
はじめに
こんにちは、リテールハブ開発部でバックエンドエンジニアをしているホシと申します。
現在、Laravel などを利用しながら小売アプリ開発に取り組んでいます。
先日、サービスのリリースに伴い、旧サービスの外部システムから当社のMySQL DBへユーザーデータ移行を行う機会がありました。 ただ今回、今まで行ったデータ移行と大きく違うのは、ユーザーの個人情報を含んだデータ移行でした。 データ移行自体はこれまでも経験していましたが、個人情報を含む移行は前提が異なり、多くの学びと反省点がありました。
そこで本記事では以下の点についてお話できればと思います。
- 実データを自由に扱えない状況での事前準備の進め方
- リハーサルの重要性と、実施できる場合の考え方
- 今回採用した移行方式と「変換できたのに正しく入っていない」問題と確認点
- 移行当日に意識しておくべき判断と心構え
- 次回のデータ移行に向けた改善点
それぞれの中で経験したことや反省点を記載しながら、今後に向けた改善点などを記載しています。 また、個別の移行内容というよりは、データ移行を進める際の準備・検証・判断の考え方に焦点を当てています。
1. 実データを自由に扱えない状況での事前準備の進め方
個人情報を含むデータは「自由に触れない」
個人情報が含まれる場合の制約
- 開発環境・検証環境に簡単に持ち込めない
- ログ出力、スクリーンショット、共有方法にも制限がある
- データ配置・保管場所にも慎重な判断が必要
- 事前確認が十分にできない
- 「本番で初めて見るデータ」が発生しがち
など通常とは異なる制約がある中で行う必要がありました。 この部分をもっと考慮した上で、事前準備が必要であったところは大きな反省点でした。
「できないから仕方ない」で済ませると危険
事前にできることはできる限りやり、仕様書・IF定義だけで満足しないことが大事です。
とはいえ対応できる範囲も限界はあるので以下の点を特に注意できればと思っています。
- NULL / 空文字 / 不正値の扱いは各項目でどうなっているのかを明確にする。
- 桁数・文字種・フォーマットのばらつきがあることを前提とした考慮をする。
- 仕様上はOKでも、実データでは違う可能性を考える。
(ここは正直難しいですが、データパターンを確認し、できる限り考慮したいです。)
あるあるの話ですが、通常は仕様に基づいて対応するのが当たり前ですが、 こういった大量データになるとおかしなデータはほぼ混ざっているのが逆に普通かと思っています。
2. リハーサルの重要性と、実施できる場合の考え方
今回は事前にリハーサルが実施できる状況でした。 しかし、以下の点でしか検証を行えていませんでした。
- データ移行手順が問題ないこと(スムーズに移行作業が完了できる)
- 個人情報データの取り扱いに問題がないこと
- データ変換がエラーなく行われ、正常にDBへ投入できること(想定通りのフォーマットであること)
- 実際に移行したデータを使用して簡単な動作確認を実施し問題ないこと
上記はどれもリハーサルで行う必要な項目で、どれも大事なのですが、 ただ、本番データを想定した観点としては以下の点でもっと時間をかけて行うべきでした。
- DBに入った内容に想定していないデータが入っていないか
- データパターンを各項目で洗い出し、システム上問題ない値であること
- 想定していないパターンの場合、どう対処するかを事前に明確にすること
しかし、これも個人情報のデータとなると、あまり時間をかけてのリハーサルや ローカルに保存して後ほど詳細に確認もしにくいのもあり、簡単な確認で済ませてしまっていました。
元データを最大限に利用する
一番確実なのはやはり元データを使用できることです。 当日のデータ移行の検証という意味では、これを利用した検証が一番確実だと思います。
リハーサル当日だけで出来ない部分は、別日に詳細にできればと良いと思います。 しかし、今回のような個人情報データは自由に扱えないことを理由にうまく利用できていなかったのも反省点です。
いかにここでそのファイルを活用したダミーデータを作れるかも非常に有効だったのではと思っています。
3. 今回採用した移行方式と「変換できたのに正しく入っていない」問題と確認点
どうやって移行を行おうとしたか
今回は以下の方法で行いました。
移行元データ ↓ phpでデータを読み込み、MySQLのLoadData用TSVファイルにコンバートするコードを作成 ↓ Load DataでTSVデータをDBへ投入 ↓ データ移行完了
特別な処理は特になく、シンプルな変換処理でした。
「変換できたのに正しく入っていない」問題と確認点
コンバートまでは特に問題なく変換できて、件数・エラーチェックは行えていましたが、 以下の点が見落としポイントでした。
- データ投入できていて、かつ全件「自動変換」など発生なく投入できているか?
- Load時にWarningなどが発生していないか?(投入はできていても実は正常に入っていないケースがある)
- カラム定義上は問題なく入っているが、値が想定していないものではないか?
Load Data はデータ投入時に非常に便利ですが、上記の点をしっかりと考慮した上で使用しないとデータ移行時の確認内容としては不十分になってしまいます。
特に日付はNULLの場合と「0000-00-00」で入る場合で全く挙動が異なります。 MySQLでは「0000-00-00」はNULLではなく「値」として扱われます。 そのためアプリケーション側では未設定ではなく異常値として存在してしまうことになり、 日付計算・バリデーション・ORM変換で後から問題を引き起こす可能性があるので特に注意が必要です。
今回の移行処理の責務を分離して考える
本来は以下のようにそれぞれのフェーズの責務を明確にして、対応をしていく必要がありました。
| フェーズ | 役割 | 保証すること | 保証できないこと |
|---|---|---|---|
| コンバーター | 生データをLoad Data用形式へ変換 | TSV構造・文字コード・基本的な値変換 | DBがどう解釈するか、業務的な正しさ |
| Load Data | DBへ高速に一括投入 | 指定件数の取り込み、物理的な格納 | 型変換の影響、暗黙変換、Warningの発生 |
| DB格納後の確認 | 実データの妥当性検証 | 業務的に正しい値であることの確認 | この確認を行わないと移行成功とは言えない |
特に今回は、Load Data の部分とDB格納後の確認が混在した確認になっていたと反省しています。
実際のデータパターンの検証例
パターンは膨大にあるようで、実はシンプルなものをいくつか用意しておくだけでも違うと思っています。
-- 不正日付確認 SELECT COUNT(*) FROM users WHERE birthday = '0000-00-00'; -- NULL発生率確認 SELECT COUNT(*), SUM(email IS NULL) FROM users; -- 想定外形式確認(都道府県以外のパターン確認) SELECT prefecture, COUNT(*) FROM users GROUP BY prefecture;
AIを活用したパターン洗い出し・事前テストの試み
今回、AIをうまく使いこなせていなかった点も反省点だったと思っています。 まさにAIをうまく活用できる点として、
- 前述したデータパターンを様々な観点で出すことができる
- 個人情報部分は適当なパターンデータに変換して検証することもできる
当時は本番データをそのまま使用できないことで、ちょっとしたサンプルデータ、パターンデータで行い、 十分な事前検証も不足していました。
4. 移行当日に意識しておくべき判断と心構え
今までいくつか事前準備と慎重な検証が必要と記載をしていますが、 当日は必ず想定外が起きると思って計画を立てた方が良いかと思っています。 特に膨大なデータや内容が多いほど顕著になるかと思います。
以下の点に注意して当日は望めるようにしておきたいです。
- 1つ1つの作業完了条件を明確にしておくこと。
- ロジックや仕様変更をその場でする修正は原則しないこと。
- 移行を中止、延期する、または後日対応でOKかなどの判断が当日できる人がいること。
- 移行がもし出来ない場合のリカバリ方法があること。
また、時間も想定しているよりも掛かってしまうことが多いと思います。 なるべく余裕をもった計画にしたいです。
今回は投入データの件数確認でさえ、すぐに終わるつもりが件数の正解を事前に用意していなかったため、 非常に大きく時間をかけてしまったのも今回の反省点でした。(完了条件が明確になっていない)
5. 次回のデータ移行に向けた改善点
今回の経験から以下の点を意識し改善できるようにしていきたいです。
- 一連の手順、動作確認は事前リハーサルでできる限り行うこと。
- 本番当日に向けた事前準備はしっかり時間を確保して対応する。(当日は必ず何か起きる前提)
- 当日の作業の完了基準の明確化(データ件数、エラー有無、動作確認など)
- Load Dataなどデータ投入後の部分が一番大事かつ明確にする部分であること。
- 仕様通りに作成しても、不正データは必ずある前提で行い、それらも考慮すること。
- 個人情報を扱うデータの場合は、同等のダミーデータを用意できると検証時に非常に有効。
- 検証パターン、データ生成などはAIも活用し、検証精度やコスト減に役立てる。
6. まとめ
通常、データ移行は当日一度きりの作業で、 同じ内容で再度実施するケースは少なく、個別のノウハウは蓄積しにくいところもありますが、
共通の考え方、対応として、
- 事前準備の重要性
- 検証設計の明確化
- 当日の判断基準
- 何かあった時のリカバリ方法
これらを意識することで、当日の障害確率は下げられると思っています。 改めて今回を通じて、データ移行は技術作業というより、検証設計と判断設計の仕事だったと感じています。
正直、完璧に準備をして全てスムーズに完了させることはなかなか難しいところですが、 もし今後データ移行などの作業をする際に本記事が少しでも参考になれば幸いです。
最後までお読みいただきありがとうございました。