ソーシャル経済メディア「NewsPicks」SREチームの美濃部です。
NewsPicksでは複数のサービスでAurora MySQLをメインのデータベースとして利用しています。これまでAurora MySQL 2(MySQL 5.7互換)を使用してきましたが、2024年2月から順次クラスタのアップグレードを開始し、2024年11月にすべてのクラスタをAurora MySQL 3(MySQL 8.0互換)へのアップグレードを完了しました。この記事ではそのアップグレードプロセスについて解説します。
アップグレードの背景
アップグレードを決断した主な要因は、Aurora MySQL 2のサポートが2024年10月31日で終了し、以降発生する延長サポート料金です。1vCPUあたり1年で 1,050USD ≒ 16万円 の延長サポート料金が発生します(さらに3年目以降は2倍に)。実際に使用しているvCPU数で試算したところかなりインパクトのあるコストになる事がわかったのでアップグレードしないという判断にはなりませんでした。また、延長サポート期間は最大3年間であり、その期間内には必ずアップグレードが必要となります。将来的に避けられない移行であれば現時点での実施が最適と判断しました。
影響調査
アップグレードによる影響を以下の2点から調査しました
- MySQLクライアント(JDBCドライバであるMySQL Connector/JやNode.jsのMySQLクライアントライブラリであるmysql2など)がMySQL Server 8.0をサポートしているか
- 既存クエリがMySQL Server 8.0で動作するか
また、今回のアップグレードではパフォーマンスの事前検証は実施しませんでした。この判断については後述します。
MySQLクライアントについては必要に応じてバージョンアップを実施しました。また、弊社ではMySQLに接続する際にSequel Proというデータベースクライアントを使用している開発者が多かったのですが、MySQL Server 8.0には対応していない為TablePlusに移行するように推奨しました。
クエリの動作検証は以下の手順で実施しました。
- 開発環境にてAurora MySQL 3にアップグレードし、その上で機能検証
- 本番環境にてAurora MySQL 3のクラスタを並行で稼働させ、手動でバイナリログレプリケーション(Aurora MySQL 2からAurora MySQL 3へ)を実施し、1週間程度更新系クエリの動作確認を実施
手動でバイナリログレプリケーションを行わなくてもAWSにはブルー/グリーンデプロイ機能があるのでこれを使えば簡単にレプリケーションができるのですが、この機能はブルー環境のクラスタに存在するDBインスタンスと同数のDBインスタンスがグリーン環境に作成されてしまい、コストが増大してしまいます。そのため、手動でバイナリログレプリケーションを実施しDBインスタンスを1台のみ作成することでコストを抑制しました。
なお、バイナリログレプリケーションを行うにはバイナリログを有効化する必要があったため、DBパラメータ binlog_format
を ROW
に設定し、DBインスタンスを再起動する必要がありました。
バイナリログレプリケーションで発生した問題
バイナリログレプリケーションを実施した際に以下の2つの問題が発生しました。
- リレーログスペースの枯渇
「
Waiting for the replica SQL thread to free relay log space
」というエラーが発生し、レプリケーションが全く進まなかったので、DBパラメータrelay-log-space-limit
を0
(無制限)に設定する事で対応しました。 - デフォルトのマルチスレッドレプリケーションでのエラー
「
Cannot execute the current event group in the parallel mode
」というエラーが発生し、レプリケーションが停止してしまったので、DBパラメータreplica_parallel_workers
を0
に設定する事でシングルスレッドで再度レプリケーションを実施する事で対応しました。
アップグレード手順の確立
アップグレードの具体的な実施方法について説明します。
インプレースアップグレードやスナップショットからの復元など複数の選択肢を検討した結果、以下の2つの利点からブルー/グリーンデプロイ機能を採用することにしました。
- データベースのエンドポイントを変更せずにアップグレードが可能(アプリケーション側の変更不要)
- 既存のAurora MySQL 2のクラスタ(ブルー環境)をアップグレード直前の状態で保持でき、後述する逆方向レプリケーションの実施に適している
データベースの切り戻し手順の確立
アップグレード後に以下のようなケースを想定しました。
- アプリケーションの事前の動作確認漏れ、及び動作確認完了からアップグレードまでの期間も開発とリリースは継続されるため、その間にリリースされた内容が原因で問題が発生しその解決に数日を要するケース
- 本番環境のワークロードに対するパフォーマンス検証を事前に実施していないため、アップグレード後にパフォーマンスが著しく低下しSLOを満たせなくなるケース
これらのリスクに備えアップグレード完了後、Aurora MySQL 3からAurora MySQL 2への逆方向レプリケーションを実施し、1週間程度ダウングレードが可能な状態を維持しました。
事前に本番環境でのパフォーマンス検証を行わなかった理由は、検証にコストをかけるよりも確実な切り戻し手順を確立してアップグレードを実施する方がコストを抑えつつスケジュールも短縮できると判断したためです。
簡単ですが図で表現すると以下のイメージになります。
アップグレード後に発生した問題
一時テーブルの影響
Aurora MySQL 2からAurora MySQL 3への移行に伴い、一時テーブルの動作仕様が変更されました。
https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/ams3-temptable-behavior.html
この仕様変更の結果、データ分析基盤で実行される大容量の一時テーブルを使用するクエリにおいて、一時テーブル容量の枯渇エラーが発生しました。
対象のDBインスタンスのCloudWatchメトリクス FreeableMemory
および FreeLocalStorage
でメモリとローカルディスクの空き容量を確認し、以下のDBパラメータを調整して一時テーブルの容量を拡大する事で対応しました。
- temptable_max_ram
- temptable_max_mmap
特定のAPIエンドポイントにて性能劣化
弊社では重要なAPIエンドポイントに対してそれぞれ可用性とレイテンシのSLOを設定しています。これについての詳細は以下をご参照下さい。
アップグレード後に各エンドポイントのSLOを確認したところあるAPIエンドポイントのレイテンシがかなり悪化している事に気づきました。調査したところMySQL 8.0ではSELECT COUNT(*)が遅くなる問題があり、これが原因ではないかと考えました。ちょうどアップグレードした数日後に直後にAurora MySQL 3.08.0(MySQL 8.0.39互換)がリリースされ、この問題が解決されたBugfixが取り込まれているのでアップグレードから一週間後にマイナーバージョンアップグレードを実施しました。ただ、残念な事に今回のマイナーバージョンアップグレードでは解決されませんでした。
このAPIエンドポイントは事業を左右するような重要なエンドポイントという定義ではなかった為、ダウングレードするという判断にはなりませんでした。
アップグレードしてよかった事
アップグレードによりパフォーマンス的な改善はSLOをモニタリングしている限り特に見られませんでしたが、細かい点で以下が良かったと感じています。
権限をロールで管理できるようになった
弊社では開発者のデータベースへの権限を独自の設定をもとに反映するツールがあり、アップグレード前までは各ユーザ別に設定していました。MySQL 8.0からはロール機能が使えるようになったのでツールを改修し、ロールによるシンプルな権限設定が可能になりました。
共通テーブル式(CTE)を使用できるようになった
共通テーブル式(CTE)を使用することで、分析目的等で複雑になりがちなクエリを、名前付きの一時的な結果セットとして整理し、より見やすい形で記述できるようになりました。
ふりかえり
今回のAurora MySQL 3へのアップグレードプロジェクトを振り返ると、事前の影響調査と切り戻し手順の確立が非常に重要でした。特に、ブルー/グリーンデプロイ機能の採用と逆方向レプリケーションの実施により、安全性の高いアップグレードを実現できました。一方で、一時テーブルの仕様変更やパフォーマンスの問題など、予期せぬ課題も発生しましたが、迅速な対応により大きな影響を回避することができました。
今回のアップグレードプロジェクトを通じて、事前準備と切り戻し体制の重要性を再確認できました。今後も安全性とコストのバランスを考慮しながら、インフラストラクチャの進化を継続していきたいと思います。