コンテンツへスキップ
DedicatedPHP 接触

元に戻せないデータ移行のためのロールバック計画の立て方

データ移行は、バックアップを復元すれば元に戻せるとは限りません。検証可能な制御を備えたうえで、再開・補正・復元のどれを選ぶべきかを解説します。

バッチとチェックポイントを使ったデータ移行と、再開・補正・復元の各経路を示す図

移行によって数百万件のレコードが変更され、稼働中のプロセスにデータが供給され、データベース外にも影響が及ぶことがあります。変換処理が途中で失敗した場合、バックアップ全体の復元が常に安全、または許容可能とは限りません。バックアップ後に新しいデータが書き込まれている可能性があり、復元に必要な時間だけシステムを停止できない場合もあります。

そのため、データ移行のロールバック計画を、単に元に戻すためのコマンドにしてはなりません。影響を受けた状態をどう特定するか、どの操作を取り消せるか、どの操作に補正が必要か、修復と再開のどちらが適切かを定める必要があります。判断基準は移行の実行前に準備し、チームが緊急時にも確認できるようにします。

バックアップの復元が常に有効なロールバックとは限らない理由

バックアップの復元が常に有効なロールバックとは限らない理由 — guía visual de DedicatedPHP

バックアップは特定のインシデントからデータを復旧するために役立ちますが、復元によって、作成後に行われた正当な変更が失われることがあります。また、サービス停止、インデックスの再構築、他のシステムに届いた書き込みの消失を伴う場合もあります。レプリケーション、キュー、エクスポート、連携機能がある場合、データベースを復元しても、それらへの影響が自動的に取り消されるわけではありません。

3つの操作を区別しましょう。復元はバックアップまたは特定時点の状態を戻すこと、ロールバックは移行による変更を取り消そうとすること、補正は影響を修正する新たな操作を適用することです。これらは同じではありません。補正によってビジネスルール上の状態を回復できても、元の状態とは異なる履歴が残ることがあります。

選択は、障害の範囲、その後に行われた書き込み、復旧目標によって異なります。開始前に、許容できるデータ損失、停止可能な時間、復旧を承認する担当者を決めてください。こうした制約が定義されていなければ、チームは運用上の判断基準を持てません。

各変換を復旧可能性に応じて分類する

移行の各ステップを記述し、想定する復旧方法に応じて分類します。

  • 可逆: 信頼できる逆操作があること。たとえば、フィールドを正規化する前の値を保持し、後続の変更を上書きせずに復元できる場合です。
  • 補正可能: 以前の状態を正確に再現できないものの、ビジネスルールに基づく新たな操作で影響を修正できること。可能な限り、補正は明示的で監査可能かつ冪等である必要があります。
  • 不可逆: 情報が破棄される、または保証をもって取り消せない影響が生じること。リスクの受容、元データの保持、追加検証について明示的な判断が必要です。

分類をSQL文の種類だけで決めてはいけません。一括更新でも、変更前の値を保存し、同時実行を制御すれば可逆になり得ます。一方、実行中に別のプロセスが同じ行を変更する場合は、可逆でないことがあります。通知、API呼び出し、課金、キューへのメッセージ送信などの副作用も考慮してください。こうした処理は、データ変換から分離する方が望ましい場合が多くあります。

初期状態と不変条件を定める

実行前に、対象エンティティ、フィルター、アプリケーションのバージョン、適用するルールなど、移行の範囲を記録します。重要な件数を基準値として定め、必要に応じて、安定したデータ集合の集計値やハッシュ値も記録します。基準時刻とデータの取得元も記録してください。範囲や背景のない数値では、復旧を検証できません。

不変条件とは、移行中も移行後も常に成立していなければならない条件です。テーブル間の関係、一意性、許容される状態、維持すべき金額、データベース内のレコードと連携システムとの対応関係などが該当します。それぞれに再現可能なクエリまたは手順と、合格基準を設定してください。実行中にデータが正当に変化する場合は、その活動と移行の影響をどう区別するかも定義します。

PHPアプリケーションでは、長時間のWebリクエストに依存するのではなく、コンソールコマンドやワーカープロセスとして変換を実装できます。ただし、選択によって同時実行のリスクやトランザクションの制約がなくなるわけではありません。どの単位をアトミックに実行できるか、2つの操作の間でプロセスが終了した場合にどうするかを決めてください。

バッチ、チェックポイント、再開可能な実行を設計する

安定した順序付きキーなどを使い、明確な境界を持つバッチに処理を分割します。処理中に行が変化または消失する可能性がある場合は、オフセットによるページネーションを避けてください。キーに基づく継続位置の方が、一般に予測しやすくなります。バッチサイズは、トランザクション時間、データベース負荷、障害検出の容易さのバランスを考慮して決めます。

各バッチの後に、ジョブID、処理範囲、状態、時刻、検証結果を含むチェックポイントを保存します。データの更新とチェックポイントの進行を連携させ、未確定のバッチを処理済みと記録しないようにします。両方の操作を1つのトランザクションにできない場合は、中間状態を検出するための照合処理を設計してください。

再開可能な移行では、変更を無条件に再適用してはいけません。各操作は再試行に耐えられるようにするか、すでに効果が適用されているかを確認する必要があります。PHPでは、データベースエンジンやデータモデルに応じて、トランザクション、一意制約、冪等な操作を活用できます。意図的な中断もテストしてください。デプロイ、例外、接続切断が発生しても、既知の方法で処理を続行できる必要があります。

影響の特定と判断の監査に必要な変更を記録する

実行ごとに一意のIDを割り当て、最低限、変換内容、対象範囲、バッチ、影響を受けた行、エラー、復旧時の判断を記録します。補正可能な変更については、必要な変更前データまたはそのデータへの安全な参照を保持します。機密情報をログに無差別に記録してはいけません。復旧と監査に必要な範囲に内容を限定し、アクセス権と保存期間を制限してください。

記録から、どの行を処理しようとしたか、どの行の処理が確定したか、どの行が失敗したか、その後どの操作で変更されたかを確認できる必要があります。必要に応じて、技術ログとビジネス上の変更履歴を組み合わせてください。追跡記録をバックアップと混同してはいけません。記録には目的に十分な詳細が必要であり、紛失や改ざんから保護する必要もあります。

再開・補正・復元のどれを選ぶか

エラー発生時に直感だけで判断するのではなく、あらかじめ兆候と対応を定めてください。

  • 再開: 障害が一時的で、不変条件が維持され、確定済みのバッチを特定できる場合。回数を限定して再試行し、エラーと負荷を監視します。
  • 補正: 適用済みの変更を把握でき、検証済みの修正操作がある場合。まず、両立しない新たな書き込みを停止し、補正によって有効な変更が上書きされないことを確認します。
  • 復元: 広範囲に破損があり、バックアップからの復旧が検証済みで、後続の変更を失う、または再構築する影響を許容できる場合。レプリカや連携システムと調整して復旧します。
  • 停止してエスカレーション: 状態を特定できない、件数の不一致を説明できない、または補正によって被害が拡大するおそれがある場合。介入する前に証跡を保全します。

許容値を超えるエラー率、不変条件の違反、件数の乖離など、処理を一時停止するしきい値を設定してください。再開を承認できる担当者と、復元を決定する担当者も定めます。調査中は、影響を受けた処理フローを隔離し、システムを制御された状態に保つ方が安全な場合もあります。

チェックリストを使って移行を検証し完了する

チェックリストを使って移行を検証し完了する — guía visual de DedicatedPHP

処理の完了だけでは、データが正しいことの証明にはなりません。想定した範囲について移行前後の件数を比較し、ビジネスルールを実行して、関係性や極端な値を確認します。特定のケースを調べるにはサンプリングを使えますが、全件検証が可能な場合にその代わりとして使ってはいけません。外部の利用者やシステムがある場合は、その状態も確認し、差異の照合方法を合意してください。

実行前: 変換を分類し、バックアップと復旧手段を確認します。代表的なデータでバッチと再試行をテストし、不変条件、停止基準、担当者、運用時間枠を定めてください。チームが変更記録を参照できること、補正または復元の手順がテスト済みであることを確認します。

実行後: 件数とルールを検証し、エラーと外部への影響を確認して、実行記録を保管し、例外があれば文書化します。合意した期間は復旧情報を利用できる状態に保ち、不要になったら安全に削除します。結果を検証でき、未解決の差異について明示的な判断がなされて初めて、移行は完了となります。

これらのアイデアをあなたのプロジェクトに活用してみませんか?あなたのPHPプラットフォームについて話し合いましょう。
関連サービスを見る