はじめに
こんにちは、マーケティングテクノロジー部 田中翔です。
Aurora2の2024年10月31日のサポート終了が迫りに迫ってきました。皆さん、対応は進んでいますでしょうか。
この記事を見ているということは、このような状態になっていることでしょう。
この記事では、Aurora MySQLのアップグレードを駆け込みでやりたい方向けに、できるだけ情報をまとめようと思います。
2024年夏...!早めのアップグレードを!!
アップグレード方式いっぱいあるやん
そうなんです、以下の方式があります。
インプレースアップグレード
- 既存のクラスタをそのままアップグレードする方法
- メリット
- 作業自体は一番簡単で、クラスターのバージョンを上げるだけ
- IaCを使っている環境であれば、バージョンを変えるだけで上がる
- アプリケーションの向き先を変える必要がない
- デメリット
- 検証した結果、ダウンタイムが約20分発生する
- 切り戻しする際には、スナップショットから復旧する必要がある
- 参考記事
スナップショットリストア
- スナップショットから新クラスタを作成する
- メリット
- 別クラスタを立てるため、問題発生時に切り戻ししやすい
- 作業的には比較的簡単
- ダウンタイムがほぼ発生しない
- デメリット
- スナップショット作成前に、書き込みを停止させる必要がある
- アプリケーションの向き先を変更する必要がある
- IaCだけで作業できない
- 参考記事
バイナリログレプリケーションを使用したアップグレード
- 新DB立ち上げ → 旧DBとバイナリログレプリケーション → DB切り替え
- メリット
- ダウンタイムを最小に抑えることができる
- Blue/Greenデプロイを使えない場面で活躍
- デメリット
- 移行作業が多い
- ダウンタイムが2回必要
- パラメータの変更(binlog_format)で1回再起動と切替時
- IaCだけで作業できない
- 参考記事
Blue/Greenデプロイ
- 本番環境とステージング環境のクラスタが立ち上がりレプリケーションされており、切り替えも簡単
- メリット
- ダウンタイムがほぼ発生しない
- エンドポイントを変えずに切り替え可能
- 作業が簡単
- デメリット
- RDS Proxyのターゲットに紐づいたクラスターは使用できない!
- パラメータの変更(binlog_format)で1回再起動が必要
- IaCだけで作業できない
- 参考記事
何選んだらいいんや...となっている方は以下を参考にしてみてください。
バイナリログレプリケーション
マーケティングテクノロジー部で使用しているAurora MySQLは、広告配信や広告効果計測で使用しています。
以下の理由からダウンタイムを許容できない状態でした。
- データベースから定期バッチでRedisに配信情報キャッシュを乗せており、TTLが切れた場合に配信情報が空になる可能性がある
- 広告効果計測をストリーミングでリアルタイム集計している
- さまざまな事業部が数百以上の広告配信枠に日々入稿設定をしている
そのためBlue/Greenデプロイでのアップグレードで進めることになりましたが、ステージング環境で問題が発生しました。
なんと、RDS Proxyに紐づいているAurora MySQLはBlue/Greenデプロイが使用できません。
このような経緯もあり、今回バイナリログレプリケーションでのアップグレードを選択しましたので、深堀って記載します。
アプリケーション事前準備
- クラスターに直接接続しているアプリケーションが紛れ込んでるかもしれません。洗い出しましょう。
レプリケーションソースでバイナリログの有効化
- クラスターパラメータグループのbinlog_formatをMIXEDに変更し、再起動適用
-- 確認
show global variables like 'binlog_format';
- バイナリログの保持期間を設定
-- 1週間に設定
CALL mysql.rds_set_configuration('binlog retention hours', 144);
-- 確認
CALL mysql.rds_show_configuration;
レプリケーションソースでレプリケーションユーザーを作成
- ユーザ作成
-- 作成、権限付与
CREATE USER 'repl_user'@'%' IDENTIFIED BY 'password';
GRANT REPLICATION CLIENT, REPLICATION SLAVE ON *.* TO 'repl_user'@'%';
-- 確認
SELECT * FROM mysql.user WHERE User = 'repl_user';
新DBクラスター作成
- クラスタースナップショットを作成し、復元
- リーダーインスタンスも追加
- ライターインスタンスの最近のイベントでレプリケーションスタート位置が出てくるので、メモ
Binlog position from crash recovery is mysql-bin-changelog.000001 1000
- Aurora3のパラメータグループを作成して、新DBクラスターをAurora3にアップグレード
レプリカターゲットでレプリケーション開始
- レプリケーションを設定
-- バイナリファイルと位置修正しレプリケーションセット
CALL mysql.rds_set_external_source ('レプリケーションソース エンドポイント', 3306, 'repl_user', 'password', 'mysql-bin-changelog.000001', 1000, 0);
-- レプリケーション開始
CALL mysql.rds_start_replication;
- レプリケーションチェック
-- Seconds_Behind_Sourceが0の場合、レプリカラグが無い
SHOW REPLICA STATUS;
-- エラークエリをスキップするとき
CALL mysql.rds_skip_repl_error;
DB切り替え
- RDS Proxyのターゲットを切り替え
- レプリケーションの設定を停止
-- 停止
CALL mysql.rds_stop_replication;
CALL mysql.rds_reset_external_source;
IaCと整合性取れなくなったぞ
ご安心ください。
Terraformで管理されている方は、対象のリソースの状態管理を外してインポートし直しましょう。
$ terraform state rm aws_rds_cluster.xxx
$ terraform state rm aws_rds_cluster_instance.xxx
$ terraform state rm aws_db_parameter_group.xxx
$ terraform state rm aws_rds_cluster_parameter_group.xxx
$ terraform state rm aws_db_proxy_target.xxx
$ terraform import aws_rds_cluster.xxx yyy
$ terraform import aws_rds_cluster_instance.xxx yyy
$ terraform import aws_db_parameter_group.xxx yyy
$ terraform import aws_rds_cluster_parameter_group.xxx yyy
$ terraform import aws_db_proxy_target.xxx yyy
ここからstateを見つつテンプレートを修正してapplyすれば、完璧です。
Cloudformationの場合は、新DBのスタックを作成してやる形になるかと思います。
ところでMySQL8.0で何が変わったの?
全て見ていくのは大変ですよね、そこで影響が大きいものを抜粋してまとめます。
DB全般関連
- 認証方式
- mysql_native_passwordからcaching_sha2_passwordに変更。Aurora3ではmysql_native_passwordプラグインが引き続き使用されるため影響が無い
- いくつかのサーバーエラーコードが削除
- アプリケーションテストで利用している場合は、影響有り
- https://dev.mysql.com/doc/refman/8.0/ja/mysql-nutshell.html#mysql-nutshell-removals
- 文字セットのデフォルトが変更
- character_set_serverおよびcharacter_set_databaseシステム変数のデフォルト値がlatin1からutf8mb4に変更
- Collationのデフォルトが変更
- collation_serverおよびcollation_databaseシステム変数のデフォルト値がlatin1_swedish_ciからutf8mb4_0900_ai_ciに変更
- InnoDB INFORMATION_SCHEMA ビューの名前が変更
クエリ関連
- GROUP BY句のASC修飾子またはDESC修飾子は削除
- 正規表現の再実装
- 既存の正規表現を使用したクエリの影響確認
- AUTO_INCREMENT
- FLOAT型およびDOUBLE型のカラム(およびシノニム)では非推奨
- クエリーキャッシュが削除
- 暗号化関連のファンクションが一部削除
- ENCODE(), DECODE(), ENCRYPT(), DES_ENCRYPT(), DES_DECRYPT()
- SQLで\NをNULLのシノニムとして処理しなくなった
- 64 文字を超える外部キーの制約名があってはいけない
- COUNT(*)が失速する可能性
- ソート時のメモリ不足発生の可能性
詳細情報は公式ページをご確認ください。
パラメータグループも変わったよね?
もちろんそうなんです。差分は以下で確認してみましょう。
- インスタンスパラメータグループ(デフォルトのパラメータ名はdefault.aurora-mysql5.7, default.aurora-mysql8.0)
$ aws rds describe-db-parameters --db-parameter-group-name xxx --profile yyy | jq --sort-keys -r '["ParameterName","ParameterValue","IsModifiable"],(.Parameters[] | [.ParameterName,.ParameterValue,.IsModifiable]) | @csv'
- クラスタパラメータグループ(デフォルトのパラメータ名はdefault.aurora-mysql5.7, default.aurora-mysql8.0)
$ aws rds describe-db-cluster-parameters --db-cluster-parameter-group-name xxx --profile yyy | jq --sort-keys -r '["ParameterName","ParameterValue","IsModifiable"],(.Parameters[] | [.ParameterName,.ParameterValue,.IsModifiable]) | @csv'
そんなのスプレッドシートにまとめて比較する時間無いよ!って方は、こちらをどうぞ。
2つのパラメータグループのsdiffを取るようになっています。awkはBSDではなく、GNU版を使ってください。(シェル芸もっと上手くなりたい)
$ echo "default.aurora-mysql5.7" "default.aurora-mysql8.0" | gawk 'BEGIN {printf "sdiff "}{for(i=1;i<=NF;i++)printf "<(aws rds describe-db-parameters --db-parameter-group-name " $i " --profile xxx | jq --sort-keys -r '\''[\"ParameterName\",\"ParameterValue\",\"IsModifiable\"],(.Parameters[] | [.ParameterName,.ParameterValue,.IsModifiable]) | @csv'\'') "}' | bash
Character, Collationの設定は変更が大きいので、確認してみてください。
おわりに
アップグレード方式、変更点、パラメータグループについてまとめてみました。
私はステージング環境のDBインスタンスを吹き飛ばすミスをしてしまいましたが(幸いにもリーダーインスタンス追加で助かりました)、皆さんのアップグレードが成功するよう祈っています。
駆け込みでもまだ時間は残っています、アップグレードを終わらせて良いシルバーウィークをお過ごしください!