コンテンツにスキップ

データマイグレーション失敗時のロールバック戦略と予防策

問題

データマイグレーションが8時間かけて実行された。しかし5万件のレコードが破損した。ロールバックが必要だが、最新バックアップは12時間前のものだ。データを失うことはできない。

回答すべき問い: 1. リカバリ戦略は何か? 2. 今後このような事態をどう防ぐか?

解答

リカバリ戦略

Step 1: 被害範囲を特定する - どの5万件が破損しているかを特定する(マイグレーション前後の状態を比較) - マイグレーションのログ・変更ログ(binlog / WAL)が残っているか確認する

Step 2: バックアップ + 差分ログで復元する

12時間前のバックアップ
  + バックアップ〜マイグレーション開始までのbinlog/WALを適用
  = マイグレーション直前の状態
MySQLならbinlog、PostgreSQLならWAL(Write-Ahead Log)を使ってPoint-in-Time Recovery(PITR)を実施する。

Step 3: 破損レコードを特定して選択的に復元する - 5万件全体をロールバックするのではなく、破損レコードのIDリストを特定し、古いDBから個別にリストア - 正常なレコードには影響を与えない

Step 4: 整合性チェック - 外部キー制約・インデックス整合性を確認 - アプリ側のバリデーションで正常性を再確認

予防策

1. Dry run(ステージング環境でテスト) - 本番と同等のデータ量でマイグレーションをリハーサルする - 実行時間・リソース消費・ロールバック手順を事前に確認

2. バックアップタイミングの見直し - 大規模マイグレーション直前に手動バックアップを取得する - 自動バックアップサイクルに依存しない

3. ダウンタイムなしのマイグレーション設計

① 新カラム/テーブルを追加(既存には触らない)
② デュアルライト(新旧両方に書き込む)
③ バックフィル(古いデータを新構造にコピー)
④ 切り替え(新構造を使用開始)
⑤ 旧構造を削除
このようなexpand/contract(ブルーグリーンマイグレーション)パターンを使えば、問題発生時にすぐ旧構造に戻せる。

4. チェックポイント付き分割実行 - 5万件を一括処理せず、バッチ処理(例:1000件ずつ)で実行 - 各バッチ後に整合性チェックを入れ、問題があれば途中停止

5. フィーチャーフラグで段階的切り替え - 新スキーマを使う機能をフラグで制御し、一部ユーザーのみに先行適用

面接でのポイント

  • PITRを知っているか: バックアップ + binlog/WALで任意時点に戻せることを説明できる
  • ロールバック計画をマイグレーション前に立てるか: 「ロールバック手順を書いてからマイグレーションを実行する」文化を持っているか
  • expand/contractパターンを知っているか: ゼロダウンタイムマイグレーションの定番パターン
  • バッチ処理で分割するか: 一括実行はリスクが高い。失敗した場合のコストが大きい
  • ステージング環境での検証: 本番前にリハーサルするか否か

「本番マイグレーション直前にバックアップを取る」「ロールバック手順を書いてから実行する」の2つだけでも多くの障害を防げる。