BASEプロダクトチームブログ

ネットショップ作成サービス「BASE ( https://thebase.in )」、ショッピングアプリ「BASE ( https://thebase.in/sp )」のプロダクトチームによるブログです。

AWSのDMSやブルー/グリーンデプロイを使ってMySQL8.0へ移行した話

はじめに

Data Strategyチーム(以下、DSチーム)でDWHやBIツールの運用をしている@shota.imazekiと不正検知やAWS基盤運用をしている@tawamuraです。

Aurora MySQL v2(MySQL5.7互換)が2024/10/31に標準サポート終了となるため、DSチームでは2024年6月にAurora MySQL v3(MySQL8.0互換)へのアップグレードを実施しました。

その際に得られた課題や知見について紹介していきます。主にAWS DMSAmazon RDS ブルー/グリーンデプロイを用いたアップグレード方法の話になります。

DSチームのインフラ構成

DSチームはBASEの機械学習基盤を構築・運用しており、APIなどを介してプロダクト側へ機械学習モデルの推論結果などを返しています。学習・推論のために使うプロダクト側のデータはDMSを用いて、DS環境にレプリケーションしています。

具体的には、本番環境にあるレプリカDBをDMSタスクのソースに指定し、DS環境で使用するDBへと同期を行っています。

また、DMSで同期したDBをさらにソースとして指定し、DMSの変更検知(CDC)によって取得した差分をAmaon MSKに流しています。これによって特定のテーブルにデータが挿入/更新されたというイベントを取得することができ、それをトリガーにworkerで他の処理を行っています。そういったworkerや、定期実行されるバッチによる処理結果を保存しておくためのDBも同じDBクラスター内に存在しています。

今回アップグレード対象となったのは、図で赤枠で示した「DS DBクラスタ」部分になります。

事前検証

DSチームのDB(以下、DS DB)では上述した通り、DMSを用いてプロダクト側のデータをレプリケーションさせています。DSチームの方がアップグレードを早めに実施するスケジュールで動いていたため、メジャーバージョン単位でのバージョン差異があってもDMSによる同期が可能なのかを事前に検証しました。できない場合はアップグレードのタイミングをプロダクト側と合わせる必要があるためです。

検証方法としては3つのDBクラスターA(MySQL5.7), B(MySQL5.7), C(MySQL8.0)を用意し、以下のような形でDMS連携を行いました。

その後、BをMySQL8.0にアップグレードさせることで2つの事象を同時に見ることができます。

  • A(MySQL5.7)→B(MySQL8.0): DMS連携先(DS DB)がアップグレードした時の挙動
    • ここについては特に問題は発生しませんでした
  • B(MySQL5.7)→C(MySQL8.0): DMS連携元(プロダクト側のDB)がアップグレードした時の挙動
    • BをMySQL8.0にアップグレードさせると、B→CへのDMSタスクが失敗していました。
    • DMS連携の際にONにしておく必要のあるシステム変数log_binがOFFになっていたためでした。こちらを参考に再起動したところ、エラーは解消されました。

一部エラーは発生しましたが、メジャーバージョン単位でのバージョン差異があってもDMS連携は問題ないと判断しました。またDMS連携元(プロダクト側のDB)をアップグレードする際にはlog_binの値に注意する必要があることも分かりました。

アップグレード方法の検討

Amazon Aurora MySQL バージョン 3(MySQL 8.0 互換)へのアップグレードを参考に以下3つの選択肢からアップグレード方法を検討しました。

  • インプレースアップグレード
  • ブルー/グリーンデプロイ
  • スナップショットからの復元

アップグレード後に問題が発生しても、旧バージョンに戻す古いクラスターに切り替えることが可能な点やダウンタイムを最小限に抑えられる点からブルー/グリーンデプロイを選択しました。

ブルー/グリーンデプロイは、ブルー環境(稼働中のDB)とは別でグリーン環境(MySQL8.0にアップグレードされたDB)を構築しておき、任意のタイミングで本番環境をブルー環境からグリーン環境に切り替えるものです。データはブルー環境からグリーン環境にレプリケーションされているため、差分が生じることはありません。

次にAWSのブルー/グリーンデプロイ機能を使うか、グリーン環境をDMSを用いて自前で構築するかの検討を行いました。後者は準備に時間がかかるのですが、AWSのブルー/グリーンデプロイ機能でロールバックが行えるか、など不明な点が当初いくつかあり、反面DMSの環境構築に関しては既に知見がありあまり困ることがなさそうだったので自前で構築することにしました。

DMSを用いたグリーン環境の構築

DMSを用いてブルー環境のデータをレプリケーションする準備をしていましたが、その作業を行なっていくうちに一つの課題にぶつかりました。

カラムのデータサイズが大きすぎるとDMSタスクがタイムアウトになる

まず、DMSでDS DBのデータをグリーン環境に同期して、全く同じ状態のDBを構築することにしました。

DS DBには、プロダクトからDMSで同期しているテーブルに加えて、DSチームで動かしているリソースが新規保存・更新を行なっているDBやテーブルが含まれています。このテーブルの一部で、MEDIUMTEXTなど大きめのデータ(LOB: ラージバイナリオブジェクト)を保存しているカラムが存在しています。

DMSでこれらのLOB列を含むテーブルのレプリケーションを行う際、通常のバイナリログによる同期ではなく、選択可能なLOBモードによる処理方法を適用することになります。

AWS DMS タスクでのソースデータベースの LOB サポートの設定

グリーン環境へレプリケーションを行うDMSタスクを実行していると、以下のようなエラーが発生しました。

Table 'db_test'.'table_test' was errored/suspended (subtask 1 thread 1). Failed (retcode -1) to execute statement; RetCode: SQL_ERROR  SqlState: HY000 NativeError: 3024 Message: [MySQL][ODBC 8.0(w) Driver][mysqld-5.7.12-log]Query execution was interrupted, maximum statement execution time exceeded  (replicationtask.c:3066)

LOB列に対しては、ステートメントを発行して別途データを取得するようなのですが、そこでタイムアウトが発生したものかと思われます。

AWSにてサポートケースを作成し、状況を共有しつつ以下のような項目を実施しました。

  • 自主的に検証(DMSタスク設定)
    • CommitRateを1000から100に
    • TransactionConsistencyTimeout を60から600に
    • HistoryTimeslotInMinutesを5から60に
  • サポートから共有を受け実施(DMSエンドポイント設定)
    • ExecuteTimeoutを60から3600に

しかしこれらの変更を行なっても改善がみられませんでした。

続けていくつかの対応方針も提供していただいたのですが、これ以上時間をかけて対策を進めるより、AWSのブルー/グリーンデプロイ機能を試した方が良いかもと思う点がいくつか発生してきました。

  • DS DBのデータは小さくないので、DMSによる同期もかなり時間がかかることが想定される
  • 自前でブルー/グリーンデプロイを行うとしても、書き込みを行なっているリソースがあるために、データの不整合なくロールバックを行うことはほぼ不可能
  • 今後もアップグレードの機会はあるので、公式機能で楽に対応できることがわかっていればそれに越したことはない
  • ブルー/グリーンデプロイ機能でも想定しているテストや切り戻しができそう

以上からDMSを用いたブルー/グリーンデプロイは断念し、AWSのブルー/グリーンデプロイ機能を使う方針に変更しました。

AWSブルー/グリーンデプロイ

事前確認

準備についてはブルー/グリーンデプロイの作成を参考に進めていきました。ブルー/グリーンデプロイ作成時に考慮すべき点を列挙しておきます。

ブルー/グリーンデプロイでサポートされていない機能を利用しているか

以下の機能はブルー/グリーンデプロイでサポートされていないため、利用している場合は一時的に接続を切るなどの検討が必要になります。DS DBでは利用していなかったため特に困ることはありませんでした。

  • Amazon RDS Proxy
  • カスケードリードレプリカ
  • クロスリージョンリードレプリカ
  • AWS CloudFormation
  • マルチ AZ DB クラスターのデプロイ

ブルー環境のDBクラスターのbinary loggingがONになっているか

ブルー環境からグリーン環境へのレプリケーションを行うためにバイナリログが必要になるため、パラメータグループのbinlog_format を確認する必要があります。フォーマットは複数あり、どれでもレプリケーションできるそうですが推奨はROWでした。DS DBでは元々、DMSを利用している点から元々、ROWに設定していたのでこちらも特に問題なかったです。

ブルー/グリーンデプロイの作成

作成自体はグリーン環境のエンジンバージョンの設定や事前に作成しておいたパラメータグループを指定するだけだったので簡単でした。

https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/blue-green-deployments-creating.html#blue-green-deployments-creating-preparing-mysql

作成開始後、まずブルー環境のDBクラスターを複製後にアップグレードをしてグリーン環境を構築します。複製自体は数十分程度で終わったのですが、アップグレード時にエラーになりました。

Database cluster is in a state that cannot be upgraded: Upgrade prechecks failed. For more details, see the upgrade-prechecks.log file

upgrade-prechecks.logファイルを確認したところ、とあるテーブルのパーティションをアップグレードする必要があるようです。

Partitioning upgrade required. Please dump/reload to fix it or do: ALTER TABLE `database`.`table` UPGRADE PARTITIONING"

対象のテーブルはDSチームで現在利用していないものだったため、今回は削除することにしましたが必要な場合はエラーの案内に従って更新をかけることで解消できたと思います。

再度作成作業を行い、グリーン環境の構築が完了しました。構築する時間は大体1時間程度でした。

検証

グリーン環境の構築が終わったため、DS DB周りで動いているバッチやAPIを動かしてみて、動作に問題がないかできる限り確認を行いました。

ブルー/グリーンデプロイ機能では、グリーン環境構築後にグリーン環境に接続を行えるエンドポイントが作成されます(データはブルー環境のものが論理レプリケーションされており、基本的に同じものを扱える)。これにより、テストしたいリソースの向き先をグリーンのエンドポイントに向けて実行してみることで、切り替え後の問題が発生しないかを事前に確認することができます。

https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/blue-green-deployments-overview.html

確認の中で、書き込み処理のテストを行おうとしたところ、パラメータグループのread_onlyは0になっているが、グリーン環境側ではONの状態になっていることに気づきました。

  • パラメータグループ

  • MySQL
MySQL [(none)]> show variables like 'read_only';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| read_only     | ON    |
+---------------+-------+

AWSのドキュメントで、グリーン環境は読み取り専用に保つことを勧めているため、このような差異が生まれているのかと推測しています。なお、スイッチオーバーした際にはread_onlyパラメータはOFFになっていましたので、気にする必要があるのはテスト時のみでした。

テスト中は、グリーン環境のデータベースを読み取り専用に保つことをお勧めします。グリーン環境ではレプリケーションの競合が発生する可能性があるため、書き込み操作を有効にする場合は注意してください。また、スイッチオーバー後に本稼働データベースに意図しないデータが発生する可能性もあります。Aurora MySQL の書き込み操作を有効にするには、read_only パラメータを 0 に設定し、DB インスタンスを再起動します。

実施

メンテナンス当日、DMS, CDCタスクを停止後にグリーン環境への切り替えを実施しました。ダウンタイムは3分程度で終わり、この切り替え自体は特に問題が発生しませんでした。

ただ、DMS、CDCタスクを再開した後、DS DB→Amazon MSKへのCDCタスクがエラーとなっていました。確認したところ、log_binがOFFになっていたことがわかりました。

show global variables like "log_bin";
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| log_bin       | OFF   |
+---------------+-------+

DMSの事前検証の時点で同様の現象が起きていたため、ライターインスタンスを再起動してみたところ、ライターインスタンスでlog_bin=ONになってCDCタスクも動くようになりました。再起動自体は1分程度で完了しました。

おわりに

AWSのブルー/グリーンデプロイ機能は、パラメータ周りには少し悩まされましたが大した問題にはならなかったですし、簡単に利用できて実施もすぐに終えられたので非常によかったです。今後のDS DB関連のメンテナンス方法において有力な候補になると思いました。

最後となりますが、弊社ではデータエンジニアを募集しています。ご興味のある方は気軽にご応募ください!

open.talentio.com