システム移行のプロジェクトで本番事故が最も起きやすいのが、カットオーバー当日のデータ移行です。設計やコーディングがどれだけ順調でも、移行したデータが 1 件でも壊れていれば業務は止まり、最悪はロールバックに追い込まれます。本記事では、刷新プロジェクトの中でも特に難所であるデータ移行に絞り、ETL スクリプトの設計、エッジケース対策、差分の自動検証、そして業務停止枠から逆算したリハーサル回数の決め方までを、実案件の知見をもとに解説します。移行を含む刷新全体の進め方は システム移行の進め方|段階移行のステップ解説 で扱っているので、本記事はその中の「データ移行」だけを深掘りします。

結論: データ移行の事故は「リハーサル回数」でほぼ防げる

先に結論を書きます。データ移行の本番事故は、ETL スクリプトの巧拙よりも、本番相当のデータで何回リハーサルを回したか でほぼ決まります。

私たちが担当した卸売・流通業界向けのリプレイス案件では、業務停止枠が 4 時間しかありませんでした。この枠内で旧 DB から新 DB への完全移行を成功させるために、ETL のリハーサルを合計 23 回実施しています。結果として、本番カットオーバーは停止枠内に収まり、データの欠損や文字化けは一件も出ませんでした。この事例の全体像は レガシー業務システムを通常の半分の期間で刷新した事例 で公開しています。

逆に、リハーサルを 5 回程度で済ませようとした場合、ほぼ確実に本番で事故が起きます。理由は単純で、本番データには開発時には想像もしなかったパターンが必ず眠っているからです。20 年前に登録された全角スペースだけの氏名、システムの仕様変更前に作られた不正な日付、複数の文字コードが混在したテキスト。こうしたデータは、本番相当の全件データを通してみて初めて表面化します。リハーサルとは、本番でしか出ないバグを本番前に出し切る作業に他なりません。

データ移行で本番事故が起きる典型パターン

実際に事故につながりやすいパターンを整理しておきます。どれも「移行スクリプトのロジックは正しいのに、データ側の事情で壊れる」類のものです。

まず多いのが 文字化けと文字コードの不整合 です。レガシーシステムは SJIS やその亜種で動いていることが多く、新システムの UTF-8 へ変換する過程で機種依存文字や丸数字、全角チルダが化けます。テスト環境のきれいなデータでは再現せず、本番の古いレコードで初めて顕在化するのが厄介な点です。

次に NULL と空文字、ゼロの取り違え です。旧システムでは「未入力」を NULL で表していたカラムが、新システムでは空文字を期待している、あるいはその逆、というケースは頻発します。NOT NULL 制約に弾かれて投入そのものが失敗するか、業務ロジックが想定外の挙動を起こします。

3 つ目が 件数の不一致 です。重複データの除去ルール、論理削除済みレコードの扱い、親子関係の参照整合性。これらの解釈がずれると、移行後の件数が旧システムとわずかに合いません。1 件でも合わなければ、どこかでデータを落としているか余計に作っているということなので、原因を特定するまでカットオーバーは判定できません。

4 つ目が 所要時間の見積もり不足 です。テスト環境の少量データでは数分で終わった ETL が、本番の全件データでは数時間かかり、業務停止枠を超過する。これは机上の見積もりだけでリハーサルを省くと必ず踏む地雷です。

これらの共通点は、いずれも 本番相当のデータを通さない限り検出できない ことです。だからこそリハーサルが効きます。

ETL 設計の基本(抽出・変換・投入と業務ルールの落とし込み)

ETL は Extract(抽出)、Transform(変換)、Load(投入)の三段階です。それぞれで何を設計するかを押さえます。

抽出は、旧 DB からどのデータをどの文字コードで取り出すかを決める工程です。ここで重要なのは、抽出時点の文字コードを明示的に固定すること。曖昧なまま進めると、後段の変換で化けの原因を追えなくなります。また、論理削除フラグや有効期限といった「移行対象を絞り込む条件」も抽出側で明確に定義します。

変換は、旧システムのデータ構造を新システムのスキーマに合わせて作り替える工程で、ここに 業務ルール が集中します。たとえば旧システムで 1 つのカラムにカンマ区切りで詰め込まれていた値を、新システムでは正規化して別テーブルに分割する、といった変換です。業務ルールを文章で明文化してから変換ロジックに落とすのが鉄則で、ここを口頭やコード読みだけで進めると、後から「この変換ルールはどういう根拠だったか」が誰にも分からなくなります。

投入は、変換済みデータを新 DB に書き込む工程です。外部キー制約や一意制約を満たす順序で投入する必要があり、親テーブルから子テーブルへ、依存関係を踏まえた順番を組みます。投入は冪等であること、つまり何度流しても同じ結果になることが望ましく、リハーサルを繰り返す前提なら必須の性質です。

私たちの案件では、旧 DB から新 DB への ETL を、業務ルールを文章で渡すと SQL と TypeScript の移行スクリプトが生成される形にしました。生成されたスクリプトはそのまま信用せず、後述する差分の自動検証で必ず裏を取ります。AI 生成コードをテストで縛るこの進め方は、AI 駆動 TDD|テストを先に書かせる開発フロー の考え方をデータ移行に応用したものです。

エッジケース対策(NULL 許容/半角全角混在/SJIS 由来の文字化け)

ETL 設計で最も時間を割くべきがエッジケースの洗い出しです。実案件で必ず問題になる 3 つを挙げます。

NULL 許容カラムの扱い は、旧システムと新システムで「未入力」の表現が一致しているかを一カラムずつ確認します。NULL なのか、空文字なのか、ゼロなのか、特定のデフォルト値なのか。新システムの NOT NULL 制約に弾かれないかも含め、テストケースに落とし込みます。判断に迷うカラムは、業務担当者に「このデータが空のとき、業務上は何を意味するか」を確認するのが確実です。

半角全角の混在 は、氏名や住所、商品名でよく起きます。「フィクジット」と「フィクジット」が同一顧客として登録されているような状態です。新システムで正規化するのか、原文のまま保持するのかを業務ルールとして先に決めます。検索や名寄せに影響するため、移行後にまとめて直すのは現実的でなく、移行時に方針を確定させておくべきです。

SJIS 由来の文字化け は最も油断できません。機種依存文字(丸数字やローマ数字、特殊な記号)、全角チルダと波ダッシュの取り違え、外字。これらは UTF-8 への変換で化けます。対策は、過去データから機種依存文字を含むレコードを抜き出して専用のテストケースにし、変換ライブラリと変換テーブルを固定したうえでリハーサルで実データを通すこと。本番で初めて気づいても修正が間に合わないため、必ず事前に出し切ります。

これらのエッジケースは、私たちの案件でも NULL 許容のカラム、半角全角の混在、SJIS 由来の文字化けをすべて専用のテストで担保しました。エッジケース一覧をチームで共有する「移行データの落とし穴台帳」を作り、新しいパターンが見つかるたびに追記してテストを足していくと、漏れが減ります。

移行差分を自動テストで検証する仕組み

リハーサルを何 10 回も回すなら、毎回の検証を手作業でやってはいけません。差分検証は必ず自動化します。検証は大きく三層で組み立てます。

第一層は 件数の突合 です。旧 DB の各テーブルと新 DB の対応するテーブルで、移行対象条件を揃えたうえでレコード件数を照合します。重複除去や論理削除のルールを考慮した「あるべき件数」を計算し、実際の投入件数と一致するかを確認します。ここがずれていれば、後続の検証に進む前に原因を潰します。

第二層は 値の突合 です。主キーで旧データと新データを突き合わせ、変換ルールを適用した期待値と実際の投入値が一致するかをレコード単位で比較します。全件比較が時間的に厳しい場合は、リスクの高いカラムや業務上重要なテーブルに絞り、サンプリングと全件のハイブリッドにします。

第三層は 業務不変条件のチェック です。たとえば「受注金額の合計は移行前後で一致する」「在庫数の総和は変わらない」といった、業務として絶対に守られるべき集計値を移行前後で比較します。個々のレコードが正しくても、集計レベルで合わなければどこかに歪みがあるということなので、これは強力な安全網になります。

私たちはこの差分検証を移行スクリプトと一体で自動テストとして実装し、リハーサルのたびに自動で走らせました。差分が出たレコードだけがレポートに上がるので、23 回のリハーサルを現実的な工数で回せたのは、この自動化があったからです。検証を自動化していなければ、回数を増やすほど人手がかかり、結局リハーサルを削る圧力がかかります。

業務停止枠から逆算したリハーサル回数の決め方

リハーサルは「何回やれば十分か」を回数の絶対値で決めるのではなく、業務停止枠と達成条件から逆算 して決めます。

まず、本番カットオーバーの業務停止枠を確認します。私たちの案件は 4 時間でした。この枠の中に、ETL の全工程に加えて、最終の差分検証、業務担当者による疎通確認、何かあったときのロールバック判断の時間まで収める必要があります。つまり ETL 本体に使える時間は停止枠より短く、その時間内に全件移行が完了するかをリハーサルで実測します。

そのうえで、カットオーバー判定の達成条件を先に定義します。私たちが使うのは「直近 3 回連続で、差分ゼロかつ停止枠内に所要時間が収まる」という条件です。1 回成功しただけでは、偶然うまくいった可能性を排除できません。連続して安定再現することを確認して初めて、本番に進めます。

リハーサルの中身は段階的に変えていきます。序盤の数回は ETL スクリプトのバグ出しで、少量データでロジックを固めます。中盤は差分検証の精度を上げる作業で、検出した差分を 1 つずつ潰しながらエッジケースのテストを足します。終盤は本番相当の全件データを使った計測リハーサルで、所要時間とリソースを実測し、停止枠に収まることを確認します。この段階を踏むと、合計回数は自然と 20 回前後に落ち着きます。

業務停止枠が短すぎて全件移行が収まらない場合は、移行方式そのものを見直します。静的データを事前に先行移行しておき、停止枠中はトランザクションデータの差分だけを流す方式や、新旧 DB を並走させて差分を継続同期し切り替え時点の残差分だけを反映する方式です。ここでも、選んだ方式が本当に枠内に収まるかをリハーサルで実測する点は変わりません。

AI に移行スクリプトを生成・検証させる進め方

ETL スクリプトの作成と差分検証は、AI と相性の良い領域です。ただし丸投げではなく、人間が枠組みを設計したうえで AI に手を動かさせる形が安全です。

私たちの進め方は次のとおりです。まず業務ルールと変換仕様を文章で明文化します。「このカラムはこういう条件で分割する」「未入力はこう扱う」といったルールを言語化しておくことが、AI に正しいスクリプトを書かせる前提になります。次に、その仕様を渡して SQL と TypeScript の移行スクリプトを生成させます。同時に、前述の三層の差分検証を自動テストとして用意し、生成スクリプトを必ずテストで裏取りします。

AI は典型的な変換を速く正確に書きますが、NULL 許容カラムの扱いや文字化けのようなエッジケースは、指示が曖昧だと取りこぼします。だからこそ、エッジケースを人間が洗い出してテストケースとして与え、AI 生成コードをテストで縛ることが重要です。テストが赤くなれば AI に修正させ、緑になるまで回す。この AI 駆動 TDD の進め方をデータ移行に適用すると、リハーサルのたびに見つかる新しいデータパターンへも素早く対応できます。

注意点として、AI が出力した変換ロジックを「動いているから正しい」と判断しないことです。件数突合と業務不変条件のチェックで、移行前後の集計が合うことまで確認して初めて、その変換は信頼できます。AI を使うほど、検証の枠組みを人間が握る重要性が増すと考えてください。

まとめ

データ移行の本番事故は、ETL スクリプトの技巧ではなく、本番相当のデータでリハーサルを十分に回したかで決まります。抽出・変換・投入の各工程で業務ルールを明文化し、NULL 許容や半角全角混在、SJIS 由来の文字化けといったエッジケースを事前に洗い出してテスト化する。件数・値・業務不変条件の三層で差分を自動検証し、停止枠から逆算した達成条件を満たすまでリハーサルを繰り返す。AI には人間が設計した枠組みの中でスクリプト生成と検証を担わせる。この型を守れば、業務停止枠 4 時間のような厳しい条件でも、データ移行は安全に完了できます。なお、データ移行の難易度は刷新全体の費用を大きく左右します。規模別の費用と期間のレンジは レガシー刷新の費用と期間 にまとめています。

レガシーシステムの刷新やデータ移行を検討していて、移行設計やリハーサル計画に不安がある場合は、お問い合わせ からご相談ください。実案件でリハーサル 23 回を回した知見をもとに、移行を含む刷新全体を AI 駆動開発のクリエイティブスタジオが伴走します。サービスの詳細は システム刷新・リプレイス でも紹介しています。