はじめまして、介護/障害福祉事業者向け経営支援サービス「カイポケ」エンジニアの杉浦です。
過去数回に渡り障害児支援領域のリプレースについて説明してきました。
今回は障害児支援領域のリプレースで実施した、旧システムから新システムへのドメインモデルの変更に伴うデータ移行について紹介いたします。
リプレースで行ったこと
リプレースでは新たなドメインモデルを設計・構築することを行いました。それに伴い、データモデルも新たなドメインモデルに合わせて変更を行いました。そのため、旧システムのデータを新システムに移行する必要がありました。
また、データベースサーバも変更され、旧システムではAurora MySQLを用いていましたが、新システムではAurora PostgreSQL(Serverless v2)を採用しました。PostgreSQLを採用した理由として、新システムで利用する範囲では機能面で大差がないため今後開発の規模が拡大していくカイポケリニューアルと同じサービスを採用することにしました。
上記により、異なるデータモデル、異なるデータベース間の移行について検討する必要がありました。
データ移行対象
今回のリプレースの対象は「請求機能」であり、その他の機能は旧システムを使い続けます。そのため、新システムに移行するデータは旧システムの請求業務に関わるデータのみを対象とします。請求業務に関わるデータは2015年4月から2023年12月までの8億レコード以上ありました。
次節では実際にこれらのデータをどのように移行していったかを解説します。
手法
データ移行ではいくつかの手法を検討しました。まず初めに検討したのはAWS Database Migration Serviceでした。Aurora MySQLからAurora PostgreSQLへの移行であるため、利用できるのではないかと考えました。しかしながら、新システムでは大きくテーブル構造が変わるため、元々1レコードだったものが複数のレコードに分割されるケースや、逆に削除されるケースなど、複雑な変換を行う必要があったため利用することができませんでした。
次に検討したのが新システムのコードを流用しKotlinで移行のツールを作成することでした。オンラインとバッチの両方を検討しようとしましたが、オンラインでの移行について経験が乏しく、リリースの期間が差し迫っていたため、経験があるバッチ処理での移行を検討することとしました。
当初検討したバッチ処理の流れは次の図の通りです。抽出・変換アプリでは旧DBからデータを抽出し、新DBのテーブルの形式に変換してCSVファイルに書き出します。書込アプリでは出力されたCSVファイルを新DBへ書き込みます。

データ量が多いため、抽出・変換アプリ、書込アプリそれぞれを分割して並列実行することだけ先に決め、その後、書込アプリ → 抽出・変換アプリの順に検討を進めました。
1 . 書込アプリ
まずは最もコストの重い書き込み処理について検討しました。
書込処理はPostgreSQLのCOPYコマンドを利用する方法を取りました。COPYコマンドはCSVファイルなどからデータベースに直接データをコピーする機能で、1トランザクションでファイルの内容を高速に格納することができます。
ただし、各種制約であるNOT NULL制約や主キー制約、外部キー制約はかかるため、あらかじめCSVのデータは格納するテーブルの制約を守った状態で作成しておく必要があります。なお、KotlinからはJDBCドライバのCopyManagerクラスを用いることでCOPYコマンドを扱うことができます。
2. 抽出・変換アプリ
新システムはドメインモデルに合わせてテーブル設計が行われており、旧システムとは乖離したテーブル構造になるため1対1の変換はできません。
そこで、旧テーブルの各カラムを新テーブルのどのカラムにマッピングするか、移行する際のルールはどうするかを図にまとめながら変換の設計を進めていきました。

上記の図は、前回の記事『カイポケ障害児支援領域のリプレースで実施したドメインモデリング』で説明したドメインモデルである「学校休業日」の移行の設計図になります。このような設計を各ドメインモデルに対して実施していきました。
3. 主キー採番アプリ、シーケンス更新アプリ
書込アプリでは前述したようにCSVを作成した段階で外部制約を守った状態にする必要があります。ただ、変換処理は分割して並列実行するため、主キーを重複せずに採番することが課題でした。KVSを採用することで重複せずに採番できると考えましたが、令和6年4月の法改正が控えているためリリースまで時間がなく、今回の構成ではKVSを採用していなかったことからリスクが高いと判断し見送りました。そこで、抽出後の分割されたCSVファイルを読み込み採番を行う主キー採番アプリを作成しました。
また、COPYコマンドではシーケンス番号の更新処理は行われないため最後にシーケンス番号を更新するアプリを追加しました。
最終的なバッチ処理のステップは次の図のとおりです。

移行結果の検証
リプレースではデータベースの構造が大きく変更されたため、データが正しく移行できているか検証する必要がありました。今回のリプレースは請求機能に特化していたため、過去に旧システムで計算済みの請求結果と新システムで計算した請求結果に差異がないことを確認する作業を行いました。
検証作業では、小さな不一致から大きな不一致までいくつかありましたがチームメンバーと協力し原因を究明し修正を行い、最終的に移行結果が正しいことを確認しました。
移行作業
移行は事前移行と当日移行の2ステップで行いました。リプレースを行うシステムは請求業務という特性上、一度請求を確定したデータに関しては金額の修正が発生しない限りは格納されたデータに変更はありません。そのため、金額の修正が発生しづらいデータに関しては事前に移行し、金額の修正が発生したデータに関してはリリース日に行う当日移行としました。この事前移行により当日移行のダウンタイムを最小化することができるメリットがありました。
事前移行は稼働前の新システム側のデータベースに、旧システムのデータベースのリードレプリカを作成し、10時間をかけて移行を行いました。事前に本番想定のリハーサルを何度か実施し、バッチ処理のバグ修正や移行時間の計測を行ったため、致命的な問題なく事前移行を完遂することができました。
リリース当日は移行以外にも旧システムからの切り離しなどがあることにより、システム全体を6時間停止する必要があるため、利用者が少ない休日の昼間にリリースを行うこととしました。移行は当初の見積通り2時間程度で完了し、システム全体では4時間半の停止でリリースを終えることができました。
リプレースを終えて
リプレースから1年が経過し、本記事を執筆するまでデータ移行にまつわる問題は1件も発生しませんでした。これはひとえにチームメンバーの協力があったからに他なりません。移行検証は私が中途入社して3ヶ月目から携わった内容でした。ドメイン知識はありませんでしたが、Slackで気軽に質問できる環境やドキュメントを残す文化があったおかげでキャッチアップに苦労はありませんでした。その中でもドメイン設計のドキュメントは意思決定のプロセスが図表で残っており、お客様の業務フローから考えられる最適な解をチームで検討していることがわかりました。エス・エム・エスはお客様に向けてよいプロダクトを提供したいという意思を全員が持っており、各々がメンバーの作業をフォローする意識があると感じました。
これからもチームで協力して難易度の高いお客様の課題を解消していきたいと考えています。
