はじめに
はじめまして。
リンクアンドモチベーションでエンジニアをしている田中です。
まだまだ若輩者のエンジニアですが
直近、データ移行タスクに挑戦する機会があり、大事な観点を特に3点学んだのでこの場でアウトプットさせていただきます。
構成
- 今回担当したデータ移行タスク
- 躓いたことと学び
- 今後の展望
今回担当したデータ移行タスク
今回担当した移行タスクは3点です。移行タスクファイルはrailsを使って作成しています。
- 社内Aアプリケーションから、社内Bアプリケーションへマイクロサービス化に伴ってDB分離するための移行
- 社内Aアプリケーションから、外部Cアプリケーションへマイクロサービス化に伴ってAPI分離するための移行
- 社内AアプリケーションのAテーブルにおいて、AカラムからBカラムへ、カラム名変更に伴う移行
躓いたことと学び
特に3点、ベテランエンジニアの方からFBいただく中で学びが大きかったので、ピックアップして書きたいと思います。
要件は正しいか 〜移行対象のデータ範囲が決まっていない〜
エンジニア側の要件定義では移行対象になっているものの、実際に使うのかわからないデータが存在していました。
本当にそのデータ範囲で過不足がないのか、移行後のユースケースを過去慣性なく設計する必要があります。
❌私の失敗例
とりあえず、要件に合致するものを全部移行して、使われないデータが新DBにも移行されてしまう
⭕️行った対策
ユースケースを使用するユーザーとすり合わせ、必要なデータだけを移行する
設計はリスクヘッジが取れているか 〜データ移行の実行手順書について、失敗のリスクが考慮されていない〜
実行手順について、フェーズごとに失敗するとどうなるのかが検討されていない点が多く存在しました。
失敗時のリスクが大きい箇所は特に、失敗するとしたら何が原因かを考え抜き、対策を打っておく必要があります。
❌私の失敗例
データ移行失敗時の復旧手順がなく、もし失敗したら復旧に時間をかけてしまう
dry run等で実行の期待値が正しいことを確認できる手段がないので、予期せぬ本番のデータ変更に対応できない
⭕️行った対策
データ移行失敗時の復旧手順を、自分以外でも行える粒度で記載する
データ変更を伴わないテスト実行(dry run)を行えるようにし、処理の最終チェックを本番実行前に行えるようにする
実装は機能・性能を満たす上で最善であるか 〜データ移行の性能に問題があり、実行完了までに時間がかかりすぎる〜
そもそもデータ量が多いにも関わらず、バルクインサートを行えていなかったので、元々の移行には30分弱かかっていました、、、
バルクインサートとは、リレーショナルデータベース(RDB)のテーブルに行を追加する際、複数の行を一回のSQL文の実行で追加すること。INSERT文に複数行のデータを列挙する。
IT用語辞典 e-Wordsより
またバルクインサートにおいてもrailsには主に2手法があり、当初railsに標準搭載しているinsert_allを用いていました。
一方、バリデーションやコールバックを用いた上でインサートしたい時に、insert_allでは実現が不可能です。
そのため、性能面ではinsert_allが優れているものの、不整合データを受け入れないためにactiverecord-importを使用しました。
以下Railsのbulk insert事情より引用
insert_allとactiverecord-importの違い
insert_all | activerecord-import | |
---|---|---|
実行速度 | ◎ | ○ |
batch size指定 | × | ○ |
自動timestamp | ○ (ver. 7 ~)*1 | ○ |
arg:hash | ○ | ○ |
arg:model objects | × | ○ |
association | ○ (ver. 6.1 ~)*2 | ○ |
validation | × | ○ |
callback | × | ○ |
*1:https://github.com/rails/rails/pull/43003
*2:https://github.com/rails/rails/pull/38899
❌私の失敗例
性能を考慮せず処理を書き、Time Out Errorを起こす
⭕️行った対策
要件を満たす実装方法+できるだけ処理が速く行える実装方法を比較検討し、機能・性能が最も充足している方法を用いる
今後の展望
データ移行タスクの設計〜実装で、要件を絞ること、設計のリスク考慮もれをなくすこと、機能・性能を満たす上でそれが最善かを検討することの大切さを学びました。
あらゆるシステムにおいて上記3点は大切ですが、リスクの大きいデータ移行というタスクで、ひしひしと大切さに気づくことができたので普段の設計、実装タスクに活かしていきます!