本文是 Cloud Spanner overview 的 migration playbook。走 vendor-article-spec Migration Playbook 規格 + migration-playbook-methodology Type E(paradigm shift)。每階段切換用 migration gate 把關 — Evidence 段列的證據是 gate 通過條件、不是 nice-to-have。


Driver:為什麼遷、什麼條件不該遷

啟動壓力

single-region Cloud SQL PostgreSQL primary 觸到容量上限(connection、write throughput、storage IOPS、region 故障風險)、產品要求跨 region active-active write、external consistency 是契約而非 nice-to-have。讀者要先確認自己面對的是「real 跨 region write residency」、不是「想用更強的技術」 — driver 段的核心責任是排除空泛動機。

主要 driver 候選

  • Global write residency:用戶分散全球、各地寫入本地 region、跨 region 一致性是產品要求
  • External consistency 對帳契約:跨 region 交易順序錯誤會導致對帳爆炸(金融、計費、ticketing)
  • 單 primary 容量天花板:Cloud SQL 最大 instance 仍撐不住、應用層 sharding 是大工程
  • 跨 region read latency:read 從各地直接打本地 replica、Cloud SQL read replica 受 single-primary 寫入 throughput 限制

No-go condition(基礎)

流量集中單 region、跨 region 只是 DR 需求 → 維持 Cloud SQL + read replica + cross-region async DR 更便宜。這條 no-go 不複雜、但團隊常被 marketing 推著跳過 — 在自家 traffic dashboard 上 audit 一遍「write 來自哪些 region、各占比多少」、若 90%+ 來自單 region、Spanner 沒有 benefit。

No-go condition(sizing barrier)

小 / 中型 PostgreSQL workload 的成本門檻 — Spanner 早期最小單位 100 processing units(≈ 1 node)對中小負載偏貴、過去是 sizing barrier;2021+ 推出 100 pu 起跳的 granular sizing 後雖然可從小開始、但 100 pu × per-pu monthly cost 加上跨 region replication 仍可能比 Cloud SQL HA 設定貴數倍。

來源 9.C10「判讀」段第 3 點:Spanner 早期 100 pu 起跳是 sizing barrier、後來推出 granular sizing 才讓中小負載可從小開始。Dogfood 邊界明示:9.C10 case 揭露的 sizing 結構是 Google 內部 dogfood 的 capacity 規劃語言、不是 customer-facing pricing 承諾;客戶實際成本要看當期 Spanner pricing + region + replication config。

觸發 sizing no-go 的條件:

信號判讀
workload row count < 數百萬100 pu 對這個資料量過 over-provision
QPS < 1000100 pu 容量遠超實際 traffic、cost / QPS ratio 高
單 region 即可滿足合規跨 region replication cost 是純浪費
Cloud SQL HA 設定已 cover SLA升 Spanner 沒 marginal benefit

觸發任一條 → 強烈建議走 Cloud SQL HA、不升 Spanner。判讀時要把 Cloud SQL HA cost vs Spanner 100 pu cost 對比清楚、避免讀者「想用新技術」而升級。

No-go condition(應用層延遲容忍)

應用層延遲容忍 < 50ms write 的 workload 不該升 Spanner — 跨 region Spanner write 在物理光速硬限下達 100-200ms(consistency-models-comparison 的 cross-region quorum 段)。延遲敏感 workload 升級後會在 p99 直接撞牆、回退時資料已經寫進 Spanner、roll back 成本巨大。

來源 9.C10「判讀」段第 2 點 + 「策略」段第 3 點:「external consistency 必須等多區 quorum、跨洲交易延遲可達 100-200ms」。Dogfood 邊界明示:9.C10 揭露的數量級是 Google internal observation、客戶實際 latency 隨 voting region 配置變化、引用時要附條件。

觸發 latency no-go 的場景:

  • 實時報價系統(毫秒級回應)
  • 高頻交易(HFT)
  • 遊戲 leaderboard 寫入
  • 低延遲 OLTP(金融下單、支付路由)

觸發任一條 → 強烈建議走 Cloud SQL 單 region、或考慮把 跨 region 一致性需求 重新審視(是否真的需要強一致、能不能改 event-driven async reconcile)。

替代方案排除

  • Aurora DSQL:AWS 生態、若團隊在 GCP、跨雲不合
  • CockroachDB:要自管或想 PostgreSQL wire 但不選 GCP 託管時可考慮、本 playbook 不對照
  • Citus on Cloud SQL:multi-region write 不是強項、不解 cross-region external consistency 需求

Case anchor + dogfood 邊界

無強 customer case。9.C10 是 Google 內部 dogfood、不是公開遷移 case;本 playbook 用 Spanner overview 的 PostgreSQL dialect 路徑 + 官方 migration guide + 通用 pattern。引用時必須明示「9.C10 揭露的線性 scaling / line-rate 設計目標是 Spanner 設計依據、不等於客戶遷移後可獲得的 capacity」。

對照 case:9.C14 Standard Chartered Aurora 受監管 banking — 雖然是 Aurora、不是 Spanner、但揭露「受監管 OLTP 遷移要算合規 lead time」「資料駐留限制 = 容量規劃 per-市場」這兩條結論在 Spanner 遷移同樣適用。讀者若是受監管產業、跨 region instance config 還要疊上 voting region 是否落在合規市場的 audit。

Diff Audit(6 規格面 + sizing / cost 第 7 面)

Schema diff

PostgreSQL DDL → Spanner PostgreSQL dialect 對照:

PostgreSQL 特性Spanner 對應動作
SERIALbit-reversed sequence改 primary key 策略、避免 hot split
JSONBJSON type大部分相容、複雜 path query 重寫
ARRAYARRAYOK
PARTITION BY不直接支援改成 interleaved table 或單表
FOREIGN KEY保留 FK constraint + 考慮 Interleaved Tableparent-child access pattern 改 interleaved
B-tree INDEXOK直接遷
GIN / GiST INDEX不支援STORING column 取代部分需求、其餘改應用層
CHECK constraint部分支援(time-sensitive、查最新文件)audit 每條 constraint
UDF / stored procedure少數支援改應用層或 client-side compute
TRIGGER不支援改 application 層或 Spanner change streams

interleaved table 設計參考 schema-migration-interleaved-tables。讀者要在 schema audit 階段就決定哪些 parent-child 該 interleave、避免後悔成本。

Operational diff

維度Cloud SQLSpanner
基礎架構VM-basedAPI-based
認證postgres user / roleIAM role / service account
備份pg_dump / pgBackRestpoint-in-time backup(PITR)
監控postgres-flavor(pg_stat_*)Cloud Monitoring spanner.*
Connection poolPgBouncerSDK 內 gRPC pool
Vacuum必要不存在(MVCC 機制不同)
Replication lag需監控不存在 single-primary 概念

不再需要的 Cloud SQL 責任:vacuum、autovacuum tuning、connection pool(PgBouncer)、replication lag 監控、Patroni HA。

新增 Spanner 責任:processing unit capacity 預測、TrueTime ε 觀測(truetime-api-depth)、long-running schema operation 跟蹤、IAM 細粒度權限。

Paradigm diff

從 single-primary OLTP → 跨 region distributed SQL:

  • transaction commit latency:< 5ms → 50-200ms(跨洲、含 Commit Wait + cross-region quorum)
  • external consistency 是 default(不再是 isolation level 選擇題)
  • transaction 上限:Cloud SQL 無硬限 → Spanner 10s timeout、要重構成短交易
  • read consistency:default eventual → default strong、需顯式選 bounded staleness

詳細 consistency model 差異看 consistency-models-comparison

Component diff

退役:

  • PgBouncer / pgcat(connection pool)
  • Cloud SQL HA / Patroni cluster
  • pgBackRest(備份外掛)
  • Citus extension(若有用)
  • 各種 postgres extension(時間敏感、逐個 audit 是否 Spanner 支援等效)

新增:

  • Spanner client library(Go / Java / Node / Python)
  • Dataflow(用於 bulk export-import)
  • Datastream / Database Migration Service(用於 CDC catch-up)
  • Spanner Studio(query UI)

Application diff

維度Cloud SQL(PostgreSQL client)Spanner
ORM全 PG ORM 相容PostgreSQL dialect 相容部分 ORM、查最新 dialect 支援列表
Connection modelprocess-per-connection(postgres)stateless gRPC client(SDK 內 pool)
Transaction model可長交易10s timeout、需短交易
Timestamp 使用app 內 now() / CURRENT_TIMESTAMP改用 PENDING_COMMIT_TIMESTAMP sentinel
Cursor / prepared statement全支援部分支援、查 SDK 文件
Stored procedure全支援少數支援、業務邏輯改應用層

ORM 兼容性是 time-sensitive claim — JPA / Hibernate / SQLAlchemy 在 Spanner PostgreSQL dialect 上的行為隨 dialect 版本演進、實作前查最新 vendor docs。讀者要把 ORM 兼容測試放 Phase 0、不能假設「PostgreSQL ORM 直接搬到 Spanner」。

Data topology diff

  • Single primary(write)+ read replica → multi-region voting + read-only replica
  • Primary key 設計:避免單調遞增(SERIAL)造成 hot split、改 UUID 或 bit-reversed
  • Partition:PostgreSQL declarative partition → Spanner 不需要顯式 partition(自動 split)

Sizing / cost diff(第 7 規格面)

維度Cloud SQLSpanner
計費單位instance class(vCPU / RAM)+ storage IOPS + HA add-on100 processing units 起跳 ≈ 1 node
起跳成本小型 instance 月成本可控(小型 HA $50-200/月)100 pu × per-pu monthly rate、月成本是 Cloud SQL 小型 HA 的數倍
Storage獨立計費(GB / month)含在 node count 內、無單獨 storage charge
Throughput cap隨 instance class隨 pu 線性擴展
跨 region replication額外 read replica cost含在 multi-region instance config 內
Egress跨 region 額外跨 region 額外

觸發 sizing audit 的時機:workload 行數、QPS、跨 region 需求都明確後、把「Cloud SQL HA monthly bill」對「Spanner 100 pu × monthly rate + egress」做 cost crossover 分析、無法 cost crossover 證明 → 不升。

Cost crossover 不是「Spanner 成本必須低於 Cloud SQL」、是「Spanner 多付的成本要對應到具體 benefit」:

  • 若 benefit 是 multi-region write residency、Spanner 多付的 cost 換得跨 region 一致性 — 對齊
  • 若 benefit 只是「更新的技術」、Spanner 多付的 cost 沒對應產品價值 — 不升

Type 判定

Type E(paradigm shift)、不是 drop-in。schema / app / operation / data topology / cost 五軸都動、不能用 Type B(drop-in)思路規劃 phase。詳細 type 判定方法看 migration-playbook-methodology

Phase Plan:9 段、每段有驗證門檻

Phase 0 — Compatibility audit + sizing audit

跑 schema-converter(pgloader / Spanner migration tool)、列出 incompatible feature、決定哪些改 schema、哪些改 app。hot key 風險評估(SERIAL primary key、單調遞增 timestamp)。

同時跑 sizing audit:

  • 估 target Spanner pu 數(基於 QPS、storage size、cross-region replication factor)
  • 做 Cloud SQL HA cost vs Spanner cost crossover 分析
  • 若 cost crossover 證明不出來 → halt migration、回到 driver 段重審

Phase 0 是 migration 的決策閘門 — 不過閘門就停、不浪費 Phase 1+ 的 engineering effort。

Phase 1 — Target schema design

  • interleaved table 設計(base on Phase 0 access pattern audit)
  • Index 重寫(GIN / GiST 用 STORING column 替代、其他用 B-tree)
  • Primary key 反序(避免 hot split)
  • Storing column 選擇(trade-off:query latency vs index size)

Output 是 target DDL、跟原 PostgreSQL schema 並排 diff 文件、給 application 團隊審。

Phase 2 — Application dual-target preparation

  • 抽象 DB layer(repository pattern、避免直接呼 SQL)
  • SDK 並存(go-pg + Spanner client)
  • Feature flag 控制讀寫路徑(read-from-pg / read-from-spanner / dual-write)
  • Transaction 模式 audit(長交易拆短)

Phase 3 — Bulk initial load

Cloud SQL → Cloud Storage(CSV / Avro)→ Dataflow → Spanner。Row count + checksum 驗證、column-level diff sample。

Phase 4 — CDC catch-up

Datastream from Cloud SQL → Dataflow → Spanner。Replication lag < 1s 為前進門檻、sustained 24h。

Phase 5 — Shadow read

Production read 同時打 Cloud SQL 跟 Spanner、diff log 異常。至少 7 天觀察、divergence rate < 0.1%、p99 latency Spanner < 1.5x Cloud SQL。

Phase 6 — Dual write

Cloud SQL 為 source-of-truth、Spanner 為 mirror。偵測 dual write divergence、評估是否提早升 source-of-truth。

Phase 7 — Cutover

read-only window(< 5 min)→ 最後 catch-up → switch source-of-truth → cutover application write。

Phase 8 — Cleanup

退役 Cloud SQL primary、保留 backup、清 PgBouncer / Patroni / 監控 dashboard。

Stage 0 variant 規劃

若 read-only window 不可接受(24/7 不能停機的金融 / 醫療系統)、Phase 6 dual write 期間做 conflict resolution(last-writer-wins + manual reconcile)、進入 fail-forward 模式、不走 read-only cutover。

Evidence:每階段驗證材料

PhaseEvidence
Phase 0incompatible feature 清單、預估改動 SP、hot key 風險 row count、sizing audit 報告(target pu 數估算 + Cloud SQL HA vs Spanner cost crossover 月 / 年成本對比)
Phase 1DDL diff report、預估 backfill 時間(基於 row count + Spanner 文件)
Phase 3row count 對齊、column-level checksum、payload sample diff
Phase 4CDC lag < 1s sustained 24h、error rate < 0.01%
Phase 5shadow read divergence rate < 0.1%、p99 latency Spanner < 1.5x Cloud SQL
Phase 6dual write divergence < 0.01%、reconcile queue 不積壓
Phase 7cutover window 內 write 一致性、回到 Phase 6 的條件(rollback path)

Cost crossover 報告(Phase 0 必交付):

 1Item                          | Cloud SQL HA | Spanner 100 pu | Delta
 2------------------------------|--------------|----------------|------
 3Compute monthly               | $X           | $Y             | $Y-X
 4Storage monthly               | $A           | (included)     | -$A
 5Cross-region replication      | $B           | (included)     | -$B
 6Egress (est)                  | $C           | $C             | $0
 7Total monthly                 | $X+A+B+C     | $Y+C           | $Y-X-A-B
 8Annual                        | 12*above     | 12*above       | -
 9Benefit (qualitative)         | -            | multi-region write residency / external consistency | -
10Crossover verdict             | -            | proceed / halt | -

Verdict = proceed 才進 Phase 1;halt → 回到 Driver 段重審 driver 是否成立。

所有 evidence 進 incident decision log、回 4.20 Observability Evidence Package

Cutover:決策與 rollback

Cutover window

選用戶最低流量時段、< 5 min read-only freeze、預先通知。受監管產業(對照 9.C14 Standard Chartered)要算合規 lead time、每市場各自審。

Decision owner

DB lead + product lead + on-call SRE 共同 sign-off。受監管產業多加合規 owner。

Rollback condition

  • cutover 後 30 min 內 p99 write latency 持續 > SLA 2x → rollback
  • error rate > 1% sustained 5 min → rollback
  • 對帳系統發現 divergence > 0.1% → rollback

Rollback 機制

保留 Cloud SQL 為 read-only mirror 14 天、Spanner 改 read-only、reverse CDC(Spanner → Cloud SQL)需事先準備。Reverse CDC 在 Phase 4-6 期間就要 dry-run 過、不能 cutover 才第一次試。

連結 rollback-windowrollback-condition

Cleanup:退役清單跟保留責任

退役清單

  • Cloud SQL primary instance
  • PgBouncer 配置
  • Patroni cluster
  • pgBackRest backup job(保留歸檔 90 天、依產業合規)
  • Datastream pipeline
  • Dataflow job

監控清理

postgres-specific dashboard(exporter / wal lag / autovacuum)改成 Spanner dashboard(commit_latencies / clock_skew_ms / cpu_utilization_by_priority)。

文件 / runbook 更新

postgres operation runbook 標記 deprecated、Spanner runbook 上線。新 runbook 含:

  • DDL long-running operation 監控
  • TrueTime ε 異常處理
  • Cross-region instance failover drill
  • Cost monitoring alert

稽核 / 合規

保留 final pg_dump 7 年(依產業)、incident write-back 完成、合規市場各自留檔(對照 Standard Chartered case 的 per-市場合規 lead time)。

邊界與整合:sibling、對照、anti-recommendation

Sibling deep articles

跟其他 migration 對照

跟 case 對照

Anti-recommendation

讀者讀完本文應該能判斷:

  • 若 driver 只是「想用新技術」→ 回 Cloud SQL
  • 若 workload 小(QPS < 1000、行數 < 數百萬)→ Cloud SQL HA 更划算
  • 若應用層延遲容忍 < 50ms write → Cloud SQL 單 region
  • 若 cost crossover 證明不出來 → halt migration、不升

Driver 是真正跨 region write residency / external consistency 對帳契約 / 單 primary 容量天花板 → 才升。Migration playbook 的目標不是把所有 Cloud SQL workload 升到 Spanner、是把「適合升」的部分用低風險路徑遷過去。