🐘

MySQLからPostgreSQLへ 〜移行の全貌解説〜

2024/03/08に公開

はじめに

こんにちは!株式会社CastingONEでHR領域のSaaS開発を行っている@hiroakiです。
最近サウナの聖地と言われている『サウナ しきじ』に行ってきました!聖地と言われるだけあって、クオリティは高く良い体験ができました。特に薬草サウナは最高でしたね!

さて、今回はCastingONEのデータベースについて、MySQLからPostgreSQLに移行した話を書いていきます。
この記事では、その移行プロセスの背景、実施方法や躓くポイント等をまとめています。
データベースの移行を検討している方の参考になれば幸いです!

移行背景

CastingONEはアプリケーションのデータ管理にMySQLを使用し、全てのデータを単一のスキーマに格納してきました。しかしクライアント企業が増えるにつれて、単一スキーマでのデータ管理ではセキュリティ上のリスクが伴うと考え、データの分割を決定しました。

PostgreSQLには、RLS(Row Level Security)という、データを論理的に分割する仕組みがあります。RLSを利用することで、各クライアント企業のデータを論理的に分割し、アクセス制御を行うことが可能となりセキュリティを強化することができます。
この機能を活用するために、PostgreSQLへの移行を決定しました。

移行方法の検討

当初は以下のようにDual Writerの構成を採用し、MySQLとPostgreSQLに同時にデータを書き込む方法を検討しました。

このアプローチでは、データの参照はMySQLからのみを維持しながら、移行期間中のアプリケーションへの影響を最小化し、同時にPostgreSQLの運用に関する課題を特定できると考えました。

しかし、この方法はデータの整合性の問題から断念しました。弊社ではPrimary KeyにAuto Incrementを用いていますが、この値がPostgreSQLとMySQLで異なる可能性があるためです。例えば、並行処理を用いて保存処理を行った際にデータのInsert順が異なると、Auto Incrementの値が異なる可能性があります。
この問題を解決するためには、PostgreSQLのAuto Incrementの値をMySQLと同期させる必要がありますが、そのための仕組みを作ることは厳しいと判断しました。
結論として、移行は一度の切り替えで行うことにしました。
運用面はやや不安が残りますが、QA期間に入念にテストを行うことと、永続化層のテストを強化することで対応することにしました。

移行作業

移行作業の全体像

移行作業は普段の開発と並行して取り組みました。以下は移行に際して必要となった対応事項の概要です。

  • アプリケーションコードの修正
  • インフラ環境の整備
    • Terraformの実装
    • スキーマの作成
  • データ移行

アプリケーションコードの変更

バックエンドのアーキテクチャにクリーンアーキテクチャを採用しているため、移行にあたって主にPostgresRepositoryの導入とDIの更新が必要となりました。
PostgresRepositoryは実装もテストもMySQLRepositoryの実装を踏襲しました。
PostgresRepositoryのテストを実行して、PostgreSQLの構文の違いによる問題が発生した場合は、PostgresRepositoryのコードを適宜修正し、テストが通るまで調整を行いました。

PostgreSQLが導入されるまで、MySQLを使用して開発が行われます。そのため、MySQLRepositoryに変更があった際には、go generate コマンドを用いてPostgresRepositoryも自動的に更新されるよう仕組みを整えました。

インフラ環境の整備

Terraformの実装

MySQLにはGCPのCloud SQLを使用していましたが、PostgreSQLにはAlloyDBを選択しました。
AlloyDBはPostgreSQLと完全互換性があり、Cloud SQLと比較してパフォーマンスとコスト面で優れていると判断しました。このため、AlloyDB用のTerraformコードを作成し、GCP上に新たな環境を構築しました。

スキーマの作成

MySQLからPostgreSQLへのスキーマ移行には、DDLをPostgreSQL用に変換する必要があります。
この変換作業には、pgloaderを使用しましたが、細かい部分では手動の調整が必要でした。
例えばインデックス名は、MySQLではテーブル内で一意ですが、PostgreSQLではスキーマ内で一意である必要があります。このような違いに対応するために、要所要所で専用のスクリプトを作成して対応しました。
また、Sequenceもpgloaderの対応外であったため、スクリプトによる変換で対応しました。
※ SequenceとはPostgreSQLでAuto Incrementを実現するための仕組みです。

こちらもアプリケーションコード同様に、MySQLのMigrationファイルが変更されたら、合わせてPostgreSQLのMigrationファイルを更新するような仕組みを整備しました。

データ移行

データ移行方法検討

データ移行について、いくつかの方法を検討しました。

  • ☑️ pgloader
    • pgloaderを用いたデータ移行は理論上可能でしたが、実際にはエラーが頻発し、成功に至りませんでした。
    • オンラインで他のユーザーからも同様の報告があり、最終的にはこの方法を断念しました。
  • ☑️ DMS(Database Migration Service)
    • GCPのDMSは2024年3月現在、様々なデータベース間の移行をサポートしています。
      • MySQLの移行
      • PostgreSQLの移行
      • PostgreSQLからAlloyDBへの移行
      • OracleからPostgreSQLへの移行
    • しかし、CloudSQL(MySQL)からAlloyDB(PostgreSQL)への移行はサポート外であったため断念しました。
  • ✅ CSVを用いたデータ移行
    • MySQLのデータをCSVにエクスポートし、PostgreSQLにインポートする方法です。
    • 上記2つの方法が厳しかったため、今回はこちらを採用しました。

弊社ではリリース時はサービスを停止しているため、データ移行作業はリリース作業時に実施しました。
リリース作業の限られた時間内に移行作業を完了させる必要があったため、作業時間の効率化が課題でした。
移行作業の流れは以下の通りです。

移行処理の詳細

csv export

MySQLのデータをCSVにエクスポートしてGCSにアップロードします。
こちらのexport処理は非常に時間がかかるため、並行処理を行うことで時間を短縮を試みました。
1つのインスタンスにつき1つのエクスポートジョブしか実行できないため、read replicaを複数用意して並行処理を行いました。

🕐 実行時間:約1時間

csv download

データ容量が非常に大きいため、GCE上に十分なスペックのサーバーを立ててCSVをダウンロードしました。
通常の永続ディスクを使用するとデータのダウンロードに非常に時間がかかるため、ローカルSSDを使用しました。

🕐 実行時間:約7分

csv convert

MySQLのCSVデータをPostgreSQL用に変換しました。
基本的にはデータに大きな違いはありませんが、少し微調整を行う必要があります。
例えばMySQLの0000-00-00timestampはPostgreSQLでは許容されないため、1971-01-01に変換するなどの微調整が必要でした。
こちらもテーブルごとに並行処理を行い、時間を短縮しました。

🕐 実行時間:約7分

insert all data

変換したデータをPostgreSQLにインポートしました。
foreign key制約があると、インポート順序等考慮する必要があり、また処理自体にも時間がかかってしまいます。そのため、データインポート前にforeign key制約を一時的に外す対応を行いました。
インポート処理も並行処理を行い、時間を短縮しました。

🕐 実行時間:約1時間

導入後のお話

PostgreSQLを実務で使用するのが初めてだったため、導入前後でPostgreSQLの勉強会を開催しました。チーム全員で特定の参考書を読み進めることから始め、その過程で発見した点や、当社の運用面での考え方について議論を行いました。

MySQLとの挙動の違いで稼働当初少しエラーが発生しましたが、現在は基本安定して稼働しています。
本記事では割愛しましたが、無事RLSの導入も完了し、各クライアント企業のデータを論理的に分割することができました。
今後はPostgreSQLの機能を活用し、セキュリティを強化していく予定です。

おわりに

この記事では、MySQLからPostgreSQLへの移行プロセスについて、背景や移行作業の全体概要を共有しました。このプロジェクトには約6人のエンジニアが関わり、約半年かけて慎重に進められました。意向については不具合の発生を避けるために4回のリハーサルを実施し、その甲斐あって移行当日はスムーズに作業を完了することができました。
もし同じようなデータベース移行を検討している方がいれば、この記事が役立つことを願っています。

最後までお読みいただき、ありがとうございました!
CastingONEの開発チームに少しでも興味を持った方は是非カジュアルにお話をさせてください!

https://www.wantedly.com/projects/1283256
https://www.wantedly.com/projects/836878

Discussion