アプローチPDCA機能開発に伴うデータ移行について

はじめに

こんにちは!Baseconnectエンジニアの文です。 前回、弊社テックリードの朱に『MusubuのアプリケーションのRailsからGoへの移行』 として新たなプロジェクトへのアプリケーション側の移行について紹介してもらいました。

techblog.baseconnect.in

この新たなプロジェクト(『アプローチPDCA』と命名された)については、もう一つ大きな課題がありました。 記事中でも紹介がありましたが、DBの変更を行う必要があり、そしてそこには”データ移行”という大きな壁があったのです。

稼働中のシステム(以下:『rev1』と表記)はNeo4jというグラフ指向のデータベースをメインで使用しております。 プロジェクトで新たに開発するシステム(以下:『rev2』と表記)ではMySQLを採用するので、これまで蓄積されていたデータを移行する必要が出てきたというわけです。

本記事では、アプローチPDCAプロジェクトにおいて、Neo4j からMySQLにデータ移行を行うにあたって、どのように設計・実装・実行を進めたかということを紹介させていただければと思います。

移行対象データのサマリー

  • データ移行するテーブル数
    • 31
  • データ移行するレコード数
    • 約 5千万件
  • 参照するデータソース
    • Neo4j
    • Elasticsearch
    • DynamoDB

要件・実装上の制約など

当然、rev1 で蓄積した Neo4j の データをそっくりそのまま MySQL へ移行して rev2 で使用できるというわけには行きません。 データベースの性質の違いや、新システムrev2 を実装する仕様に合わせて一部データを追加、加工する必要があります。

中間テーブル問題

案件にタグを複数割り当てることができ、当然タグも複数の案件に割り当てることが出来ます。 いわゆる多対多の関係に該当するわけですが、Neo4jはグラフ指向のデータベースであり、データはノードとリレーションという形で表現されます。 MySQLなどのリレーションナルデータベースで多対多の関係を表現する際によく用いる中間テーブルが存在しません。 Neo4j上のリレーション構造を維持したままMySQL上に移植する必要があります。

仕様上のデータ移行要件

rev2 を新たに実装するにあたり、既存システムの rev1 とは仕様が異なりデータ構成のレベルで対応が必要になる部分も存在します。 取引先に保存していた住所のデータは基本的に都道府県を含む形で保存していましたが、都道府県の絞り込み検索を実現する関係で別プロパティとして都道府県データを保持していました。

これはデータの2重管理に近いような状態になってしまっており、rev2 の住所データからは都道府県を排除し市区町村以降の住所を保存するように仕様が定義されました。

それに伴い、データ移行を行う際にもそれに合わせて、データの加工を行う必要が出てきます。

テーブル名及びカラム名の変更

これは、要件的に必須というわけではなかったのですが、過去に定義したデータの名前がわかりにくかったり、運用を続ける中で実態と乖離が発生しているデータが存在します。 これをデータ移行することを機に、より明確で実態に合わせてテーブル名やカラム名を変更しておきたいというわけです。

その他データ以降を実施するにあたっての課題

データの依存関係

移行先のデータベースをMySQLを採用したことで、外部キー制約によるデータ依存関係が発生します。 データ移行を実行する順序についても設計が必要になります。

不正データへの対応

サービス運用開始当初から蓄積された rev1 のデータの中には、バリデーションが不十分な状態で作成された不正データや、不具合によって発生した不整合データなども存在します。 それらの不正データは直接データ移行が出来ないので、データ移行スクリプトを実装する際に考慮するもしくは、データ移行の実行前に不整合データの解消を行っておく必要がありました。

データ移行仕様書の作成

上記の通りデータ以降を実施するには多数の課題があります。 そのためデータ移行の要件を細かく記載したデータ移行仕様書の作成を行うことにしました。

仕様書の項目はだいたい以下を網羅する内容にしました。

▽データ移行仕様書の中の大まかな項目

  • 検討事項
  • 概要
  • 移行先テーブル
  • 参照データ
  • 移行するデータ
  • 依存関係

また、データの依存関係を考慮するとデータ移行を実行する順序についても検討しておく必要があります。 しかしながら、移行対象データの数も非常に多いので、データ移行手順書という形で、こちらについても細かく定義しておくことにします。

実装

データ移行の仕様書や手順書の作成が一通り完了してようやく実装開始です。 スクリプトPythonで実装しましたが、深い理由はないですが実装開始当初、実装担当者のアサインが定まっておらず、プロダクト開発メンバー以外でも着手できるようキャッチアップコストの少ない技術スタックを採用しました。

実装概要

データ移行の処理は大まかに分けて3ステップです。

  1. Neo4j等のデータソースからデータを読み取り、仕様書の内容に従って、データを加工し、CSVにエクスポートする
  2. エクスポートしたCSVファイルをS3へアップロードする
  3. LOAD CSV にてMySQLデータの読み込む

構成図

データ移行実行の冪等性の担保

運用前のデータベースに移行するということで、冪等性に関して気にする部分は少なかったですが、何度でもデータ移行を実行が行えるよう、移行元のデータに破壊的変更を加えることが無いように意識して実装しました。

動作確認と改善

ステージング環境は、過去のテストデータが大量に作成されており正しくデータ移行されている検証するのは困難で、運用中の本番環境に負荷をかけるわけには行きません。

そのためデータ移行の動作確認は、本番環境のスナップショットからデータベースを立ち上げて、新たに専用の環境を用意して実施しました。 いざ、データ移行を通して実行してみると想定以上に実行に時間がかかることがわかりました。

取引先のエクスポート処理だけで16時間 ...。インポートに4時間 ...。 これでは、2日確保したメンテンスの時間を使い切ってしまいそうな勢いです。

データ移行のパフォーマンス改善を行う必要がありました。 一番ボトルネックとなっていたデータ量の多いエクスポート処理については、並列実行する様に改善し、インポート処理の改善には、一時的にデータベースのスペックをあげることで対応しました。

本番実行

データ移行のパフォーマンス改善を実施したものの本番環境のデータ移行には想定以上に時間がかかりました。 動作確認用に作成したクローンのデータベースから移行テストを行っていましたが、作成から本番データ移行を実施するまでに5ヶ月程度あり、その間に増加したデータが想定以上に多かったことが原因でした。

また、データ移行後のアプリケーションからの動作確認で、不備が見つかる場面もありましたが、データ移行実行に関しては冪等性を担保出来ていたので、スクリプトの修正を行い再度実行することが出来ました。

成果とまとめ

データ移行の検討を始めた当初は、どのようにすすめて行けばよいかイメージしづらかったのですが、大規模で複雑なデータ移行を実施するにあたっても、一つひとつ手順を分解して明確化していくことが重要であると痛感しました。

データ移行仕様書や、手順書を定義していくことに注力する中でかなり手順を明確化することができ、実装に着手する段階ではすでに勝負が決していたような感じでした。

実際の動作確認してみるパフォーマンス問題に直面しましたが、処理の並列化などの対応をしていく中でも、仕様書に定義された要件を満たすことに集中すればよかったので、テストも行いやすかったですね。

今回はアプローチPDCAのデータプロジェクト内で実施したデータ移行の設計や実装、改善といったプロセスを中心に紹介してみました。 本記事内で実装の詳細な技術的な部分に触れた部分は少なかったですが、複雑なデータ移行を実施する際の参考にしていただければ幸いです。