はじめに
こんにちは、エモーションテック SREのおかざきです。
弊社プロダクト「EmotionTech」で利用しているAWS Aurora MySQLで17億レコード規模のテーブルをAmazon RDS Blue/Green Deploymentsを用いてスキーマ変更を行ないました。
*本記事で触れるプロダクト「EmotionTech」とは、直近でいくつか記事を掲載している「Google CloudでRustおよびNestJSを利用したマイクロサービスアーキテクチャのプロダクト」とは別のプロダクトです。
この記事はエモーションテック Advent Calendar 2023 の17日目の記事です。
背景
「EmotionTech」では、本施策の検討開始時点ではDBとしてAWS Aurora MySQL 2.11.1 (MySQL5.7互換)を利用しており、アプリケーションはRuby on Rails 6.0を利用していました。
各テーブルのidカラムがint型であり、一部のテーブルのidカラム値が17億に達しint型の上限である2,147,483,647
に迫っている状況でした。
上限に達してしまうとそのテーブルへのレコードの追加ができなくなってしまい、サービス停止に繋がることが見えていました。
そこで、カラムの型をint型からbigint型にして、上限を増やす必要がありました。
ただ、対象のテーブルで型変更のためにALTER TABLEをすると50時間程度かかり、その間書き込みがロックされることも分かったため 普通にALTER TABLEをした場合、サービスを長時間停止しなければなりませんでした。
停止時間を短縮する方法を模索する中でAWSのソリューションアーキテクトに相談したところ、2022年11月に発表されたRDS Blue/Green Deploymentsをbigint型化のALTER TABLEにも使えると紹介頂きました。 検証した上で本番切替まで実施し、実質数分間の書き込み停止で切替できました。(実際の切替では万全を期すため動作確認等含めて1,2時間程度サービス停止を行いましたが、ALTER TABLEをそのまま実行する場合と比較すると停止時間をかなり短縮できました。)
切替までの流れ
切替までの流れは大まかに以下の通りです。
- バイナリログの有効化:Auroraインスタンスの再起動が必要なので注意
- AuroraにAmazon RDS Blue/Green Deploymentsを有効化して、新Aurora(Green環境)を作成
- Green環境でALTER TABLEを実行して、idカラムをbigint型に変更
- レプリケーションが止まらないことを数週間確認
- 本番切替でAmazon RDS Blue/Green DeploymentsのSwitch Overを実行し、Green環境のAuroraを本番Auroraに昇格
Green環境でALTER TABLEには50時間程度かかりますが、その間は現行Aurora (Blue環境)がサービス通信のクエリを受け付けるため、長時間のサービス停止が必要ありませんでした。
バイナリログの形式について
RDS Blue/Green Deploymentsを利用するためにはバイナリログ出力を有効にしておく必要があります。
2023/12/10時点でドキュメントを確認したところ、以下のようにあり、binlog_formatにROW形式を指定することが推奨されています。
While any binlog format works, we recommend ROW to reduce the risk of replication inconsistencies.
ただ、 RDS Blue/Green Deploymentsリリース当初はMIXED形式を指定する必要があったため、今回はMIXED形式を指定しました。 MIXED形式についてはMySQLのドキュメントの以下のページ等で説明されています。
MySQL :: MySQL 5.7 Reference Manual :: 16.2.1 Replication Formats
MySQL :: MySQL 5.7 Reference Manual :: 5.4.4.3 Mixed Binary Logging Format
「5.4.4.3 Mixed Binary Logging Format」に記載があるように、MIXEDの場合はデフォルトでSTATEMENT形式のバイナリログが出力されますが、条件によってはROW形式となります。
ROW形式を利用する場合は、後述するように原則としてBlue環境とGreen環境の型が一致していることが必要になるため、int型からbigint型に変換するためにはslave_type_conversionsオプションを指定する等の対処が必要となります。
つまづいた点
MIXED形式を利用する必要があったと述べましたが、この形式起因で1点問題が発生したので、ご紹介します。
RDS Blue/Green Deployments構成を有効化し、定期的にレプリケーション状態をチェックしていました。 最初の1,2日は問題なかったのですが、3日経過後にレプリケーションが止まっていることに気がつきました。
Auroraのエラーログを確認したところ、以下のエラーが発生していました。(テーブル名はdb.table1とします。)
[ERROR] Slave SQL for channel '': Column 0 of table 'db.table1' cannot be converted from type 'int' to type 'bigint(20)', Error_code: 1677 [ERROR] Error running query, slave SQL thread aborted. Fix the problem, and restart the slave SQL thread with "SLAVE START". We stopped at log 'mysql-bin-changelog.000508' position 97584081
検証環境で再現検証をしたところ、特定の機能から以下のクエリが実行された時に該当のエラーが発生することがわかりました。
UPDATE `table1` INNER JOIN `table2` ON `table1`.`table2_id` = `table2`.`id` SET `table1`.`soft_destroyed_at` = 'yyyy-mm-dd hh:mm:ss', `table1`.`updated_at` = 'yyyy-mm-dd hh:mm:ss', WHERE `table2`.`table3` = xxxx AND `table1`.`soft_destroyed_at` IS NULL;
*クエリはActive Recordにより生成されたもの
MIXED形式の場合はデフォルトでSTATEMENT形式のバイナリログが出力されるので、Blue環境、Green環境両方のテーブルカラムの型が一致していなくてもレプリケーションは出来ていたのですが、
このクエリは、STATEMENT形式にするには安全ではないと判定されROW形式として扱われるものだったようです。
そして、このクエリによる変更がROW形式でレプリケーションされた結果、Green環境側に適用される際に、Column 0 of table 'db.table1' cannot be converted from type 'int' to type 'bigint(20)'
というように違う形に変換できない旨のエラーが出てしまったと考えられます。
対処
Green環境Auroraのクラスターパラメータにてslave_type_conversions
パラメータをALL_NON_LOSSY
にしてint > bigint型の変換は許可させるようにしました。
This mode permits conversions that do not require truncation or other special handling of the source value; that is, it permits conversions where the target type has a wider range than the source type.
とあり、今回のようにint型カラムをbigint型に変換する場合はbigint型の方が広い範囲の値を格納できる=変換に伴いデータ損失が発生しないならレプリケーションを可能とすることができます。
おわりに
Amazon RDS Blue/Green Deploymentsを用いて大規模テーブルのカラムの型を変更した事例を紹介しました。 RDS Blue/Green Deploymentsを用いることで、現行Auroraを稼働させたままGreen環境の新設Auroraに50時間程かかるALTER TABLEを実行する事ができ、サービス停止時間をSwitch Over操作のタイミングだけに限定することが出来たため、非常に助かりました。
ただ、確実に切替を行うにはMySQLのバイナリログの形式毎の特徴や要件に応じた対処法を理解する必要はあるので、 やはり入念な事前準備は必要だなと思いました。
エモーションテックでは顧客体験、従業員体験の改善をサポートし、世の中の体験を変えるプロダクトを開発しています。プロダクトに興味のある方、この記事や他の記事を見て少しでも弊社に興味をもっていただけましたら、ぜひ採用ページからご応募をお願いいたします。