Amazon RDS for MySQL 5.7系から8.0系へ!変更点への対応と実践記録
はじめに
こんにちは!
any株式会社でプロダクトチームに所属しているエンジニアの @fumiyan です!
この記事は、any Product Team Advent Calendar2024 3日目の記事になります。
弊社が提供しているナレッジ経営クラウドのQastでは、RDBMSとしてAmazon RDS for MySQL(以下、RDSと表記)を採用しています。以前、バージョンを5.7系から8.0系にアップグレードしました。本記事は前編と後編に分かれており、今回の前編では変更点への対応と実践記録について、次回の後編ではインフラ視点で見るアップグレードの舞台裏について解説します。
これからアップグレードする予定です!という方の参考になれば幸いです!
アップグレード作業が無事終わった際に、メンバーがめちゃくちゃ喜んでくれました!笑
Amazon RDS Extended Support
そもそも社内でアップグレードの必要性が議論されるようになった背景には、MySQL 5.7系のExtended Supportが2023年10月で終了することがアナウンスされていたことがあります。また、それ以前からメンバーの間では「8.0系の機能を使いたい」という声も上がっていました。
Release | GA Date | Premier Support Ends | Extended Support Ends | Sustaining Support Ends |
---|---|---|---|---|
MySQL Database 5.7 | Oct 2015 | Oct 2020 | Oct 2023 | Indefinite |
MySQL Database 8.0 | Apr 2018 | Apr 2025 | Apr 2026 | Indefinite |
MySQL Database 8.4 | Apr 2024 | Apr 2029 | Apr 2032 | Indefinite |
引用元: https://www.oracle.com/us/assets/lifetime-support-technology-069183.pdf#page=30
Extended Supportが終了すると、メンテナンスリリース、アップデート、バグ修正(エラー修正)、セキュリティアラート
などのサポートが受けられなくなります。
ただ、Sustaining Supportがあるので、既存のアップデートや修正、アラートは受けられます。
MySQL Extended Support - 3 years of extra support including error correction, beyond the Premier Support period, for specific MySQL releases. Includes MySQL maintenance releases, updates, bug fixes (error correction), and security alerts.
引用元:https://www.mysql.com/support/
実際にはRDSを使用しているため、サポート終了日は2024年2月29日に設定されていました(当初はこれよりも早い期日が設定されていました)。
当初はサポート終了日までにアップグレード作業を行わないと、自動的にアップグレードされてしまうため、変更点の確認と対応を早急に進めていました。そんな中、追加料金を支払うことで、Amazon RDS Extended Supportというサービスを利用できるようになりました。このサービスを利用することで、2024年3月1日から2027年2月28日まで延長サポートが提供され、引き続き5.7系を使用できるほか、以下のサポートも受けられるようになりました。
・Security updates for critical and high CVEs for your DB instance or DB cluster, including the database engine
・Bug fixes and patches for critical issues
・The ability to open support cases and receive troubleshooting help within the standard Amazon RDS service level agreement
引用元:https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/extended-support.html
当時、私が機能開発も担当していたため、機能開発が落ち着いてから慎重に確認をしつつアップグレード作業を進めることにしました。そのため、この延長サポートを利用することに決めました。
注意点として、先ほども述べた通り追加料金が発生します。また、プロダクト要件上、高性能なインスタンスタイプを使用していたため、料金がかなり高額になっていました・・・
以下で料金について確認できます。
アップグレード作業
主なアップグレード作業としては、以下になります。
- 5.7系から8.0系への変更点の確認と対応
- RDSのアップグレード方針 (※こちらからは後編で解説します)
- テスト環境およびステージング環境でのアップグレード検証
- 本番環境アップグレード
5.7系から8.0系への変更点の確認と対応
アップグレード前のバージョンは5.7.44で、アップグレード対象のバージョンは、当時の最新対応バージョンである8.0.36を選択しました。また、8.0系からは継続的デリバリーモデルが採用され、パッチバージョンのリリースでも新機能が含まれる、高い頻度で後方互換性が切り捨てられるようになっていました。そのため、互換性の問題を考慮し、大規模なアップグレードになると予想したため、変更点の確認と対応を慎重に進めました。
基本的には、以下のドキュメントを参考にしながら、変更点の確認や対応をしました。
確認・対応した内容の中から、いくつかを抜粋してご紹介します。
- 予約語追加
- GROUP BY句の非推奨のASCまたはDESC修飾子の削除
- アカウント管理に関する機能削除
- 認証プラグインデフォルト値変更
- 文字セットデフォルト値変更
予約語追加
前提として、予約語を使用しないというルールは既に存在していました(テーブル名やカラム名などは、単数系で管理しており、どうしても使用したい場合は、末尾に「s
」を付けるなどで対応していました)。しかし、8.0系で新しい予約語が追加されたため、既存のテーブル名やカラム名でこれらの予約語が使用されている場合、識別子として使用するには引用符(バッククォート)で囲むか、命名を変更する必要がありました。
確認したところ、いくつか該当するケースがあったため対応を進めることになり、チーム内で話し合った結果、今回は引用符で囲む対応を採用しました。これは、命名を変更する場合に大幅な工数が発生し、大規模な修正が必要になること、加えて既存の命名が適切であり、他の命名に変更するのが難しいという背景があったためです。
ただし、引用符で囲む対応にはデメリットもありました。予約語に該当しない既存のテーブル名やカラム名は引用符で囲まれておらず、これらと混在することで実装者が迷う可能性がある点でした(他にも、毎回引用符で囲む手間が少なからず発生すると考えられます)。そこで、既存にあるライブラリを拡張して、SQLが実行される際にテーブル名やカラム名がパースされ、引用符で囲まれる仕組みを開発しました。なので、実装者側は引用符のことを気にしないで良くなりました。ただ、予約語を使用しないというルールはそのまま継続してます。
GROUP BY句の非推奨のASCまたはDESC修飾子の削除
GROUP BY句で非推奨とされていたASCまたはDESC修飾子が削除されたことで、これを使用している箇所がある場合、アップグレード後に実行時の結果が異なる可能性がありました。修正方法としては、指定されたソート順序を実現するために、ORDER BY句を追加する必要があります。該当箇所がいくつか存在していたので、修正しました。
GROUP BY a ASC -- 修正前
GROUP BY a ORDER BY a ASC -- 修正後
また、GROUP BY句に関連して暗黙的にソートが行われていましたが、8.0系以降はソートが行われなくなるため、暗黙的にソートされていた箇所については明示的にソートを指定する修正が必要です。
GROUP BY implicitly sorts by default (that is, in the absence of ASC or DESC designators), but relying on implicit GROUP BY sorting in MySQL 5.7 is deprecated.
引用元:https://dev.mysql.com/doc/refman/5.7/en/mysql-nutshell.html#mysql-nutshell-deprecations
-- 修正前
SELECT a, COUNT(b) FROM dummy GROUP BY a; -- 暗黙的にソートされていた
-- 修正後
SELECT a, COUNT(b) FROM dummy GROUP BY a ORDER BY a ASC; -- 明示的にソートを指定
アカウント管理に関する機能削除
アカウント管理に関連するいくつかの機能が削除されました。その中には、GRANTステートメントを使用してユーザーアカウントの非特権特性を変更する機能も含まれていました。実際にこの機能を利用している箇所があったため、修正を行いました。
認証プラグインデフォルト値変更
8.0.4以降、セキュリティ強化のため、アカウント認証に使用されるプラグイン(default_authentication_plugin
)のデフォルト値が変更されました。
For the server, the default value of the default_authentication_plugin system variable changes from mysql_native_password to caching_sha2_password.
引用元:https://dev.mysql.com/doc/relnotes/mysql/8.0/en/news-8-0-4.html
既存のアカウントの認証プラグインは、アップグレード後に変更されません。
This change applies only to new accounts created after installing or upgrading to MySQL 8.0 or higher. For accounts already existing in an upgraded installation, their authentication plugin remains unchanged.
引用元:https://dev.mysql.com/doc/refman/8.0/en/upgrading-from-previous-series.html
今回のアップデートに伴い、既存のアカウント認証方法をcaching_sha2_password
に変更することを検討しましたが、以下の理由により、引き続き既存のmysql_native_password
を使用することにしました。
- RDS8.0のパラメータグループにおいて、
default_authentication_plugin
システム変数のデフォルト値はmysql_native_password
であり、値のタイプが変更不可となっているので変更できない - DBへのアクセスに使用している一部のMySQLクライアントが
caching_sha2_password
に対応していない- 対応する動きはあるものの、そもそも古いクライアントなので移行を検討
ただし、mysql_native_password
は8.0.34から非推奨となっており、将来的に削除される可能性があります。そのため、上記の課題が解消されたタイミングで対応を予定しています。
1点注意が必要なのは、8.0.34以降でmysql_native_password
を使用している場合、警告エラーが継続的に表示され、ログが埋め尽くされる現象が発生することです。この警告ログは実質的に機能せず、さらにログ出力にはコストがかかるため、log_error_verbosity
システム変数を1に設定し、エラーのみが出力されるように対応しました。
※ 8.0.38で、警告が一度しか表示されないように修正されたため、次回RDSのバージョンを更新した際にlog_error_verbosity
の値を元に戻す予定です。
The deprecation warning issued when authenticating with the mysql_native_password plugin is now issued only once. (Bug #35792948)
引用元:https://dev.mysql.com/doc/relnotes/mysql/8.0/en/news-8-0-38.html
文字セットデフォルト値変更
おそらく、大きな変更の一つだったと思いますが、デフォルトの文字セットがlatin1
からutf8mb4
に変更されました(照合順序もデフォルト値が変更されています)。また、8.0.x以降ではutf8mb3
がまだサポートされていますが、将来のメジャーリリースで削除される予定になっているみたいです。一部のテーブルでutf8mb3
が使用されているため、utf8mb4
に変更する対応が必要ですが、大規模な改修が見込まれるため、別タスクとして切り出して進めています。この改修についても、後日あらためて記事にする予定です。
デフォルトの文字セット変更については、今後utf8mb4
で統一する方針となったため、このデフォルト値を採用することにしました。ただし、照合順序のデフォルト値がutf8mb4_0900_ai_ci
に変更された一方で、現状ではutf8mb4_general_ci
で統一しています。デフォルトの照合順序をどちらにするか検討した結果、現時点ではutf8mb4_general_ci
を採用しています。utf8mb4_general_ci
には絵文字問題などがあるものの、utf8mb4_0900_ai_ci
に変更すると既存システムに大きな影響を与える、全体的な要件もutf8mb4_general_ci
の方が適しているため、この選択肢を採用しませんでした。ただし、要件によっては照合順序を変更する必要が生じる場合もあると考えています。
DDLでテーブルやカラム作成時にはutf8mb4
とutf8mb4_general_ci
を明示的に指定して作成するようにしています。
CREATE TABLE dummy (
dummy_id INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
PRIMARY KEY (dummy_id),
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_general_ci;
以下に照合順序について簡潔にまとめてくださっている方がいます。
上記以外にも、アップグレードによるライブラリの影響やコード自体の修正、その他の細かな修正についても確認と対応を行いました。
かなり大きなPRレビュー対応がいくつかあったため、メンバーには大きな負担をかけてしまいました・・・!
まとめ
いかがでしたでしょうか。
大規模なシステムほど、慎重に隅々まで変更点を確認し、修正を行う必要性が高まると改めて感じました。今回の変更点の確認と修正作業にも多くの時間を要しましたが、こまめな更新の重要性を再認識する良い機会となりました(もちろん、プロダクトによっては頻繁な更新が難しい場合もあるかと思います)。
また、こういった確認作業を効率化するためのツールを作成・選定し、作業時間を短縮することが最善策だと考えています。
最後までお読みいただき、ありがとうございました!!!
Discussion