ナンバーナインのMySQLバージョンを8.0にアップグレードしました
こんにちは、ナンバーナインで開発アルバイトをしているtessoです。
ナンバーナインでは、本番環境のMySQLバージョンを5.7から8.0にアップグレードしました。
本記事では、MySQL 8.0へのアップグレードの実施内容やその体験から得た知見を紹介します。
バージョンアップの背景
デジタル配信サービス「ナンバーナイン」では、データベースとしてMySQL 5.7を採用していました。
私たちのサービスでは、Amazon RDS for MySQLを利用しており、MySQL 5.7の標準サポートは2024年2月29日で終了でした。
標準サポート以降は、延長サポートという形になります。
そのため、RDSの延長サポートには追加コストがかかり、MySQL 8.0へのアップグレードが必要という状況でした。
アップグレード方法の選定
アップグレード方法としては、以下の2つが考えられました。
1. リードレプリカを使用したアップグレード
現在のDBインスタンスに対してリードレプリカを作成し、リードレプリカに対してMySQL 8.0にアップグレードを行う方法です。
リードレプリカが正常に動作することを確認した後、リードレプリカをプライマリに昇格させることでアップグレードを完了します。
アプリ側の接続先を変更するだけでアップグレード作業を完了できるため、ダウンタイムを最小限に抑えることができます。
また、リードレプリカに対してアップグレードを行うため、問題が発生した場合でも、接続先を元のプライマリに戻すことで簡単にダウングレードが可能です。
しかし、この方法は全てのアプリケーションの接続先を変更する必要があります。
そのため、事前に接続状況を把握し、接続情報を切り替える工数が発生します。
2. Blue-Greenデプロイメント
先ほどのリードレプリカを使用したアップグレードと似ているアップグレード方法です。
この方法では、新しいバージョン(Green環境)と現在のバージョン(Blue環境)を用意し、ロードバランサーで接続先を切り替えます。
AWSでは、既存の接続先がロードバランサーに切り替わり、環境の切り替えはロードバランサが変更してくれます。
そのため、アプリケーション側の接続情報を変更する必要はありません。
こちらもリードレプリカを利用した方法と同様に、2つの環境を切り替えるだけなので、ダウンタイムが少なくダウングレードも容易です。
今回は、Blue-Greenデプロイメントを採用しました。
ダウンタイムが少ないことと、ダウングレードが容易なことなどが魅力的でした。
さらに、DBインスタンス切り替え時に接続情報を書き換える必要がないこと、AWS側のサポートも充実しておりUI上から簡単に行えたことも大きいです。
事前準備
メジャーバージョンが切り替わるため、バージョンアップを行う前に事前準備が必要です。
ナンバーナインのDBで管理している書籍のデータはもちろん、支払い情報などの重要なデータがあるため、データの不整合や巻き戻りが発生しないことを第一に行いました。
1. アップグレード内容の把握
MySQL 8.0には5.7との互換性がないため、アップグレードによって動作しないSQL文やDBの設定があります。
具体的にどのような変更があるのかを把握するために、公式ドキュメントや他のアップグレード記事を参考にしました。
他の移行記事を読み込むことで、公式ドキュメントには書かれていない注意点を把握でき、大変助かりました。
Redashがとまるらしい
ナンバーナインでは、DBのデータを可視化するためにRedashを利用しています。
新しい施策をするためにも、あると嬉しい社内ツールです。
MySQLアップグレードに関するRedash への影響を調べていると、Redash v7においてTLSv1.1が原因で動作しない事例を見つけました。
そこで、AWSにおけるMySQLのTLSサポート状況を確認したところ、MySQL 8.0ではTLSv1.1のサポートをしないことが発覚しました。
ナンバーナインではRedash v5を利用しているため、アップグレードすると動作しなくなります。
いい機会なので、Redash v10までアップグレードし、Redashを動かしているインスタンスをUbuntu 22.04にアップグレードしました。
Redashはセットアップスクリプトを変更し、OSの方はdo-release-upgrade
コマンドを利用しました。
かなりバージョンが変わるので苦戦すると思いましたが、意外とすんなりいきました。
do-release-upgrade
とRedashの詳しいアップグレードガイドに感謝です。
2. ローカル環境でのテスト
ナンバーナインのシステムはDockerを用いてローカル環境でも構築できるようにしています。
とりあえず、ローカル環境からテストということで、DBのコンテナをMySQL 8.0に変更し、アプリケーションの動作を確認しました。
既存のテストの実行や、実際にアプリケーションを動作させることで、いくつかの問題を発見できました。
1. foreign_keyの設定
MySQL 8.0.16より、FOREIGN_KEY {index_name}
は無視されるようになりました。
それまでは、ALTER TABLE {table_name} ADD FOREIGN KEY `{index_name} ({column_name})`
のように設定していたため、外部キーの名前が無視されていました。
そこで、ALTER TABLE {table_name} ADD CONSTRAINT `{index_name}` FOREIGN KEY ({column_name})
と変更しました。
2. local_infileの設定
MySQL 8.0より、local_infile
がデフォルトで0になりました。
そのため、LOAD DATA LOCAL INFILE
を使用できなくなっています。
ナンバーナインでは、sqlc
を導入しています。
sqlc
でバルクインサートを行うと、内部ではLOAD DATA LOCAL INFILE
を使用しているため、エラーが発生しました。
そこで、local_infile
を1に変更しました。
別途、RDS側でも設定が必要なので注意です。
3. アップグレードチェッカーの実行
MySQL Shell ユーティリティを利用することで、MySQLメジャーバージョンのアップグレードの準備ができているかを確認できます。
ナンバーナインでは、そこまでMySQLの設定を大幅に変更していなかったためか、特にアップグレードチェッカーに検知される問題はありませんでした。
4. 開発環境でBlue-Greenデプロイメントのテスト
ローカル環境でのテストが終わった後、開発環境でBlue-Greenデプロイメントを行いました。
Blue-Greenデプロイを試すことで、実際のダウンタイムやダウングレードの時間、手順などの確認しました。
開発環境でのテストを通して以下の知見を得られました。
- 環境の構築に30分ほど必要
- ダウンタイムはほとんどない
- ダウングレードには30分ほど必要
- Blue環境への書き込みはGreen環境に共有される
アップグレード作業
以上の事前準備を踏まえて、実際に作業をします。
1. Blue-Green環境の構築
AWSコンソールからBlue-Greenデプロイ環境を構築します。
DBのパラメータグループを変更する必要がありますが、コンソールのボタンを押していくだけで簡単に作成ができます。
2. 各環境の調査
Green環境が正しく作成されているかをDBクライアントを手元から接続して確認します。
ついでに、クエリを流してバージョンやレプリカ設定が正しく行われているかを確認します。
3. 経過観察
Blue環境への書き込みは、Green環境へも共有されます。
1週間ほど、2つの環境を共存させて、エラーが発生しないかを監視しました。
特に問題は発生しませんでした。
4. 環境の切り替え
Blue環境からGreen環境への切り替えを行います。
こちらもコンソールからボタンを押すだけで完了しました。
切り替えてから数時間はログを観察していましたが、こちらも問題は発生しませんでした。
よかったね。
5. Blue環境を削除
環境切り替えから1週間ほど、ダウングレードを行うためにBlue環境も残したままにしていました。
環境を切り替えてからも問題が発生しなかったため、Blue環境を削除しました。
これで、MySQL 8.0へのアップグレード作業は完了です!
おわり
今回は、MySQLのバージョンアップについてまとめました。
バージョンアップのタスクを渡されたときは、重要なデータをいくつも扱うため、とても緊張しました。
絶対にデータの巻き戻りや不整合が起きないことを目標に、いつもより気を引き締めて入念に事前調査とテストを行いました。
そのおかげもあって、ナンバーナインのシステムを止めることもなく、巻き戻りや不整合なども起こすことなくバージョンアップができました。
大きな問題が起きなくてよかった。
参考記事
今回の移行作業にあたり、以下の記事を参考にしました。
Discussion