マイグレーションの基本原則

スキーマ変更は、アプリの新旧バージョン、データ、バックアップ、運用手順を同時に扱う作業です。本番では「down migrationを必ず実行して戻す」より、後方互換な段階を作り、必要なら前向きの修正(roll-forward)で回復する方が安全な場合があります。
Expand / Contract
安全な変更は、追加して互換性を保つExpandと、旧要素を削除するContractに分けます。
- 新しいカラムやテーブルを追加する(Expand)
- 新旧どちらでも読めるアプリを出す
- 既存データを小さく移す、または両方へ書く
- データ量・エラー・ロックを観測する
- 旧版がなくなった後に旧カラムや旧コードを削除する(Contract)
例えばカラム名を変える場合、先に新カラムを追加し、読み書きを移行してから旧カラムを削除します。追加と削除を一回のリリースで行うと、旧アプリが動いている間に壊れます。
危険な操作は環境ごとに検証する
NOT NULLの追加、インデックス作成、型変更、大量更新は、データベースの種類・版・テーブルの大きさでロックや実行時間が変わります。「オンラインで安全」と決めつけず、同じ規模に近い検証環境で実行計画と所要時間を確認します。
大きなデータ移行は、全行を一度に更新せず、小さな単位で進め、途中から再開できるようにします。
ロールバックとロールフォワード
データを削除・変換した後は、単純なdown migrationで元の意味へ戻せないことがあります。事前バックアップ、復旧手順、変更の停止条件を用意します。アプリに問題が出た時は、互換性のある旧版へ戻すか、追加の修正マイグレーションを出すかを、データ状態を見て選びます。
実施前の確認
- 変更中に新旧アプリが同時に動いても壊れないか
- 本番相当のデータ量で時間とロックを確認したか
- バックアップと復旧手順を実際に試したか
- 監視するエラー、遅延、失敗時の停止条件を決めたか
- 削除は、旧版と旧データを使わない確認後まで待てるか
まとめ
安全なマイグレーションは、戻すSQLを書くことだけでは実現しません。Expand/Contractで互換性を保ち、観測と復旧計画を用意して、削除を最後に行います。