要点: 安全なSchema変更は旧Versionと新Versionの同時稼働を前提にします。
課題
一度のDeployでRenameや厳格Constraintを行うと旧Instanceが壊れます。大規模RewriteはLockし、Backfillは顧客Trafficと競合します。
単純な対策だけでは不十分な理由
Rolling DeployではVersionが重なり、Retry中の旧Jobも考慮が必要です。
Data移動はI/OとReplicationを使うProduction Trafficです。
処理フロー
互換Schema追加→Migrate
Dual Read・Write→Verify
Backfillと照合→Contract
旧経路削除
アーキテクチャ上の判断
Additive Expand
RenameはAdd、Copy、Cutover、Removeに分解します。
再開可能Backfill
安定Key Range、小Commit、Checkpointを使います。
Constraintを別途Validate
Blockingを抑えて既存Rowを検証します。
さらに深く考える
RollbackはData問題
新形式だけのDataがある間はReverse Compatibilityを維持します。
Constraintで保証
照合後にDB Constraintで前提を強制します。
実装手順
- 現動作を変えずNullable構造を追加します。
- 互換Codeと再開可能Backfillを実行します。
- FlagでReadを切替え、観測後に旧Schemaを削除します。
技術例: 再開可能なPrimary-key Backfill
lastId = checkpoint.load('account_region_v2')
rows = SELECT id FROM accounts WHERE id > :lastId ORDER BY id LIMIT 1000
UPDATE accounts SET region_v2 = derive(region) WHERE id IN (:rows)
checkpoint.save(MAX(rows.id))
sleep(rateLimit)各Batch後にReplication LagとLock Waitを監視し、顧客影響前に自動停止します。
想定すべき障害パターン
- 旧WorkerがLegacy Fieldだけを書きます。
- Backfillが新しいOnline Writeを上書きします。
- 旧Column削除がReportを壊します。
監視すべきシグナル
| シグナル | 確認する理由 |
|---|---|
| 旧・新Read/Write数 | Compatibility利用を確認します。 |
| Backfill進捗・Mismatch | 完全性と変換精度です。 |
| Lock Wait・Replica Lag | 顧客Trafficを保護します。 |
設計の検証方法
- 旧・新Versionを同時実行します。
- 任意CheckpointでBackfillを再開します。
- 同時Updateを上書きしないか確認します。
安全なRollout計画
Expand、互換Code、Backfill、Cutover、Contractを別Releaseにします。少数Tenantで切替え、Rollback WindowとAudit後に破壊変更を行います。
本番前チェックリスト
- 実Volume相当でDDL Lockを確認します。
- BackfillにRate Limit、Checkpoint、Pauseを持たせます。
- 旧経路Usageゼロを確認してContractします。
まとめ
無停止Migrationは一つのSQLではなく、可逆なRelease列です。
