戻せるデータ移行スクリプトを書く
移行・ロールバック・検証を一度にそろえ、少量データで先に確かめる
あなたは本番データ移行を担当するバックエンドエンジニアです。以下のテーブル定義と変更目的をもとに、三つを出力してください:1)移行スクリプト——分割実行でき、再実行可能で、1 バッチあたりの件数に上限を設けて長時間のロックを避ける;2)ロールバックスクリプト——取り消せない操作と、戻した後の確認方法を明記する;3)検証 SQL——各チェックポイント(バックフィル後、切り替え前、ロールバック前)で実行し、期待結果と合格条件を示す。スクリプトより先に、データを失う可能性が最も高い手順を指摘してください。停止時間がある前提にはしないでください。 [テーブル定義/変更目的/データ量]
使い方
まずシャドウテーブルか全体の 1% で実行し、再実行とロールバックの両方を確認してからリリース枠を確保します。
向いている場面
- 1,000 万行の orders テーブルに NOT NULL カラムを追加し、バックフィルも必要な状況です。停止できるのは数分だけです。
- テーブル名の変更や分割など、元に戻せない操作の前に、ロールバック手順とデータの突合方法を決めておきたいときです。
向いていない場面
- NULL を許すカラムを追加するだけでバックフィルも不要なら、DDL 1 文で足ります。移行スクリプトは要りません。
- カラムの意味がまだ固まっていない、テーブル定義が毎日変わるという段階では、まずモデルを決めます。スクリプトは必ず作り直しになります。
例
入力
-- orders:約 1,200 万行、MySQL 8.0 ALTER TABLE orders ADD COLUMN region_code VARCHAR(8) NOT NULL DEFAULT ''; UPDATE orders SET region_code = ...;
得られるもの
全件 UPDATE はバックフィルの間ずっとロックを保持し、停止時間を超えます。主キー順に 5,000 件ずつのバッチへ書き換え、各バッチを再実行可能にしてください。ロールバックは対称ではなく、カラムを削除すると埋めたデータも消えるため、各バッチの後に `region_code = ''` の件数を検証し、ロールバック前に基準値を記録します。
よくある誤用
- データ量の少ないステージングで全件 UPDATE を先に試すことです。あっという間に終わるため、本番テーブルのロック時間は何も分かりません。
- 移行の成功だけを確認し、ロールバックを試さないことです。いざというときに DROP COLUMN で埋めたデータまで消えます。
こう変えると効く
- 「停止は 5 分だけ」と加えると、1 本の巨大な UPDATE ではなく、分割と二重書きを選ぶようになります。
- 「途中で失敗したらどの手順から再開するか」を求めると、再実行できないスクリプトをレビュー前に弾けます。