--- id: db-distributed-sql title: Distributed SQL — CockroachDB / Spanner / YugabyteDB category: Coding status: draft source_trust_level: B verification_status: conceptual created_at: 2026-05-09 updated_at: 2026-05-09 tags: [database, distributed, cockroach, spanner, vibe-coding] tech_stack: { language: "SQL", applicable_to: ["Backend"] } applied_in: [] aliases: [CockroachDB, Spanner, YugabyteDB, NewSQL, geo-distributed, strong consistency] --- # Distributed SQL > Postgres 호환 + 자동 sharding + multi-region + strong consistency. **CockroachDB / YugabyteDB (Postgres 호환), Spanner (Google)**. 비용 + 복잡도 큼 — 진짜 글로벌만. ## 📖 핵심 개념 - Strong consistency: 어느 region 읽어도 같은 답. - Multi-region write: 사용자 가까이. - Auto sharding: 사용자 데이터 라우팅 자동. - Postgres wire protocol: 기존 client 호환. ## 💻 코드 패턴 ### CockroachDB 기본 ```sql -- 일반 Postgres 와 거의 동일 CREATE TABLE orders ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID NOT NULL, region STRING NOT NULL, amount DECIMAL, created_at TIMESTAMPTZ DEFAULT now() ); CREATE INDEX orders_user ON orders(user_id); ``` ### Multi-region (CRDB) ```sql ALTER DATABASE app PRIMARY REGION 'us-east1'; ALTER DATABASE app ADD REGION 'eu-west1'; ALTER DATABASE app ADD REGION 'asia-northeast1'; -- Locality ALTER TABLE orders SET LOCALITY REGIONAL BY ROW; -- 각 row 가 region 컬럼으로 자동 가까운 곳에 저장 -- 또는 Global (모든 region 에 read replica) ALTER TABLE products SET LOCALITY GLOBAL; ``` ### Spanner ```sql CREATE TABLE Orders ( id STRING(36) NOT NULL, user_id STRING(36) NOT NULL, amount NUMERIC, created_at TIMESTAMP NOT NULL OPTIONS (allow_commit_timestamp=true), ) PRIMARY KEY (user_id, id); -- user_id 가 첫 컬럼 → 같은 user data colocated CREATE TABLE OrderItems ( user_id STRING(36) NOT NULL, order_id STRING(36) NOT NULL, ... ) PRIMARY KEY (user_id, order_id, item_id), INTERLEAVE IN PARENT Orders ON DELETE CASCADE; -- 같은 row group — fast join ``` ### YugabyteDB (Postgres-compatible) ```sql -- 거의 모든 Postgres 동작 CREATE TABLE users (id UUID PRIMARY KEY, ...) WITH (colocation_id = 100); ``` ### Trade-offs ``` 장점: - 자동 scale (TB → PB) - 자동 failover - Strong consistency - ACID 분산 단점: - 큰 비용 (Spanner 매월 $1000s) - 운영 복잡 (CRDB self-host) - Latency 증가 (consensus = quorum) - 일부 SQL 제약 (FK / trigger 제한) ``` ### Latency 특성 ``` Single region transaction: 1-5ms Cross-region transaction: 50-200ms (consensus) → Locality 으로 90% 가까이 처리하게 디자인 ``` ### Connection (Postgres driver) ```ts import { Pool } from 'pg'; // CRDB / Yugabyte = 그대로 pg client const pool = new Pool({ connectionString: 'postgresql://user:pw@cockroach.example.com:26257/app?sslmode=require', }); // Spanner = google-cloud-spanner import { Spanner } from '@google-cloud/spanner'; const spanner = new Spanner(); const db = spanner.instance('main').database('app'); ``` ### Backup / restore ```sql -- CRDB BACKUP DATABASE app INTO 's3://backup/app'; RESTORE FROM 's3://backup/app'; ``` ### Migration from Postgres ``` 대부분 호환 — 단 검증 필요: - AUTO_INCREMENT / serial 동작 차이 - FK constraint 일부 제약 - Stored procedure / trigger 제한 - LATERAL JOIN / 일부 옛 syntax - pg_extension 일부만 ``` ```bash # CRDB: Postgres dump 호환 pg_dump --schema-only mydb | cockroach sql -f - ``` ### Survive multi-region failover ```sql -- CRDB: region 전체 실패해도 OK ALTER DATABASE app SURVIVE REGION FAILURE; -- 3+ region 필요 ``` ## 🤔 의사결정 기준 | 상황 | 추천 | |---|---| | Single region + <10TB | Postgres / MySQL | | Strong consistency 글로벌 | Spanner / CRDB | | Geo-replicated read 만 | Aurora Global / pg replicas | | Migrate from Postgres | YugabyteDB / CRDB | | Heavy budget OK | Spanner | | Self-host | CRDB / YugabyteDB | | 단순 multi-AZ HA | RDS Multi-AZ 충분 | ## ❌ 안티패턴 - **Spanner / CRDB 도입 + 단일 region 사용**: 비용만 큼. - **Cross-region transaction 매번**: 200ms+. Locality 디자인. - **PG 같다고 가정 + 모든 SQL**: 일부 트리거 / FK 제약. - **Single shard 무거운 query**: 분산 의미 없음. - **Locality 안 정의**: 자동 분산 안 됨. 임의 region. - **Write hot key**: range conflict — UUID v7 등 분산 friendly. - **Test 가 dev Postgres**: 분산 동작 차이. ## 🤖 LLM 활용 힌트 - 진짜 필요할 때만 — 아니면 Postgres + read replica 충분. - Locality 디자인 = 90% 같은 region. - PG 호환 = CRDB / Yugabyte. ## 🔗 관련 문서 - [[DB_Sharding_Strategies]] - [[DB_Read_Replica_Patterns]] - [[Backend_Geo_Replication]]