Aurora for MySQL Major Upgrade

## 前段
来たる `2024年10月31日` に、`Amazon Aurora for MySQL 2 (MySQL 5.7 互換)`の AWS 標準サポートが終了し、`Aurora for MySQL 3 (MySQL 8.0 互換)`への強制メジャーアップグレードが行われる。

このまま放置すればほぼ確実にクリティカルな問題が発生すること請け合いなため、これに先んじてアップグレード作業を実施することが現職での自分の最後の大きな務めとなった。


## 事前調査
以下、まずは問題となりそうなポイントの洗い出し作業を行った！

### `DEFAULT COLLATION`の変更
- 概要
    - `MySQL 5.7`ではデフォルト照合順序が`latin1_swedish_ci`だったが、`MySQL 8.0`では`utf8mb4_0900_ai_ci`に変更となる
- 確認
    - クエリを発行し現状確認をした上で、マイグレーションファイルなどを確認し影響範囲の見定めを行った。確認の結果、デフォルトである`latin1_swedish_ci`のまま設定している箇所は見当たらず、問題無しと判断
        - DB 単位
            - `SELECT @@collation_database;`
        - テーブル単位
            - `SHOW TABLE STATUS FROM データベース名;`
- 参考
    - [Changes in MySQL 8.0.1 (2017-04-10, Development Milestone)/Character Set Support
](https://dev.mysql.com/doc/relnotes/mysql/8.0/en/news-8-0-1.html)
        - `The default value of the collation_server and collation_database system variables has changed from latin1_swedish_ci to utf8mb4_0900_ai_ci`


### クエリキャッシュ機能の削除
- 概要
    - MySQL 5.7 で有効だったクエリキャッシュ機能は、8.0 において完全に削除された。当初はパフォーマンス向上目的で導入されたが、スケーラビリティ観点で問題があり廃止される運びとなった模様
        - 広範囲にロックを取るため、複数セッションから同時にクエリを発行されると競合が起こり、高速化しないという問題があったとか
- 確認
    - これに関しては、幸い MySQL のキャッシュヒットを主眼としたチューニングや実装は行っておらず、クエリパフォーマンスに問題のある場合は`Redis`を使用してキャッシュ化などが行われていたため、問題無しと判断
        - 念のため先行してステージング環境でのアップグレードを行った上で様子見。本番でもアップグレード後、経過を見ることとした


### インスタンスクラスのサポート制限
- 概要
    - `db.r4`以下のサイズのインスタンスクラスは、`Aurora for MySQL 3`へのアップグレード後、使用できなくなる
- 確認
    - 現状の各インスタンスサイズが上記サイズを上回っていることを確認


### パラメータ変更
- 概要
    - [Aurora MySQL 設定パラメータ](https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/AuroraMySQL.Reference.ParameterGroups.html#AuroraMySQL.Reference.Parameters.Cluster) に変更が発生し、クラスター・インスタンスレベルのそれぞれにおいて、削除されるものや追加されるものが多数存在する
- 確認
    - これも幸いと言っていいのか、ゴリゴリパラメータチューニングを行うような対応は行われておらず、ほぼデフォルト設定通りであったので、以下確認により問題無しと判断
        - AWS コンソール画面上で設定しているパラメーターグループを確認し、「ソース」という項目が`Modified`となっているものはデフォルトから変更が加えられており、`System default`となっているものはデフォルト通りであると確認できる


### `AUTO_INCREMENT`値に関する注意点
- 概要
    - `Aurora for MySQL`の`Version 3`では各インスタンスの再起動時にテーブル毎の`AUTO_INCREMENT`値を保持するが、`2`では保持されない。よって、スナップショットからの復元やクラスターのクローン作成により新しいクラスターを設定する場合、各`AUTO_INCREMENT`はその時点での最大列値に基づいて初期化されてしまう
- 確認
    - 念のため現状`AUTO_INCREMENT`を使用している箇所を洗い出し。使用している場合、物理削除を許容しているかどうかを判断基準とした（最新のレコードが物理削除されている場合、その`AUTO_INCREMENT`値が失われてしまう恐れがある）。これも、現仕様で`AUTO_INCREMENT`を使用・かつ物理削除を許容している箇所が見られず、問題無しと判断


### SQL やデータ構造が一部非互換に
- 概要
    - 一例として、以下のような構文・データ構造の変更が発生した
        - `GROUP BY`句から`ASC`・`DESC`修飾子が削除された
        - `GROUP BY`句を使っていて、条件的に一意に定まらないカラムを`SELECT`句で指定している場合、エラーが発生するようになった
        - 予約語が追加された（参考：[9.3 キーワードと予約語](https://dev.mysql.com/doc/refman/8.0/ja/keywords.html)）
        - `WHERE`句において、`YYYY`や`YYYY-MM`形式での日付指定を行った場合、エラーが発生するようになった（`YYYY-MM-DD`は OK）
- 確認
    - 各発行クエリを順に見て、問題箇所が無いか確認を行った。コチラも幸い問題無かったが、念のため一部リファクタを加えた（`SELECT`句におけるテーブル名を明示的にするなど）
- 参考
    - [2.11.4 MySQL 8.0 での変更](https://dev.mysql.com/doc/refman/8.0/ja/upgrading-from-previous-series.html)


### その他
- 概要
    - その他、無数にある項目をシラミ潰しに確認。その際には、**[Aurora MySQL バージョン 2 と Aurora MySQL バージョン 3 の比較](https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/AuroraMySQL.Compare-v2-v3.html)** を重点的に確認した。特に注意が必要そうな箇所は、別途調査を行うという流れで確認を進めていった
- 確認
    - 注意が必要な項目は上述のように一つずつ確認していったが、事前の全体チェックにおいてはチェッカーも使用した
        - `util.checkForServerUpgrade() 関数`を使用（参考：[8.1 アップグレードチェッカユーティリティ](https://dev.mysql.com/doc/mysql-shell/8.0/ja/mysql-shell-utilities-upgrade.html)）



## 実アップグレード作業

### Sandbox 環境下での、Terraform による検証
- 概要
    - 対象環境に関しては元は`Terraform`管理がされ切っていなかったが、関係者と相談の上で、事前に既存スナップショットからの復元により`Terraform`化
    - その後、Snadbox 環境下にて、アップグレード作業のリハーサルを行った
- 確認
    - まず Snadbox 環境下にて既存と同等の環境を`terraform apply`
    - その状態で、`In-Place Upgrade`を実施し、検証を行った
- 注意
    - ※特に詰まったのは、`terraform plan`時には現れない、`terraform`内部での依存関係や実行順序だった
        - 例えば本ケースでは、以下の順序を経なければならない
            **1. 最初に、新しいパラメーターグループを作成**
            **2. クラスター・インスタンスを順にアップグレード**
            **3. 最後に、古いパラメーターグループを削除**
        - しかしこれが、設定や内部的な依存関係により、まだクラスターに紐付いている古いパラメーターグループを先に削除しようとしてコケるという実行時にしか確認できない問題などが発生して手間取った
- ポイント
    - パラメーターグループの`family`を`aurora-mysql8.0`とした上で、`name`を既存のものから変更（例えば末尾に`-mysql8`を付与）し、`lifecycle`に`create_before_destroy = true`を設定する
        - この`create_before_destroy`設定があることにより、パラーメーターグループを先に削除しようとするデフォルトの挙動を変更することが可能となり、エラーを防げる
    - クラスターに`allow_major_version_upgrade = true`設定を追加する
    - **内部的な依存関係・それによる実行順序に注意する**
        - ※特に自分が引っ掛かった（気付けなかった）ポイントがコレで、**特定 resource 内で他 resource の参照を行うと内部的に依存関係（`depends_on`）が発生する**
            - 例えば、`resource "rds_cluster_parameter_group"`があるとして、別`resource`内で`local.rds_cluster_parameter_group`として参照させると、依存関係が発生する
            - このせいで当初は、実施したかったクラスター・インスタンスの`In-Place Upgrade`ではなく、`Recreate`の実行計画となってしまい、中々上手くいかなかった
            - **まずパラメーターグループの設定を一番始めに持ってきて、内部で`create_before_destroy`を指定・その上で、クラスターからそのリソース名を指定してパラメーターグループとの依存関係を発生させることで、想定通りの実行計画になるようになった！**
        - （参考：[Terraformでコードを変更していないリソースが known after apply となってしまう場合にどうすればよいか](https://tech.dentsusoken.com/entry/2023/08/07/Terraform%E3%81%A7%E3%82%B3%E3%83%BC%E3%83%89%E3%82%92%E5%A4%89%E6%9B%B4%E3%81%97%E3%81%A6%E3%81%84%E3%81%AA%E3%81%84%E3%83%AA%E3%82%BD%E3%83%BC%E3%82%B9%E3%81%8C_known_after_apply_%E3%81%A8%E3%81%AA%E3%81%A3)、[Data Resource Dependencies（Terraform公式）](https://developer.hashicorp.com/terraform/language/data-sources#data-resource-dependencies)）

### ステージング・本番環境下それぞれでの、Terraform による`In-Place Upgrade`の実施
- 概要
    - Snadbox 環境下で散々試したので、あとは実行に移すのみ！
    - 入念な調査や検証の甲斐もあり、コチラは実にスムーズに完了した！🎉



## 総括
特に最初、期限が間近に迫っており放っておくと強制アップグレードされてしまうというプレッシャーの中、やたら注意書きの分量が多い公式サイトや各種調査情報と睨めっこしながら、計画を練っている時が一番しんどかった。

当初は織り込んでいなかったが、Sandbox 環境下で実際に何度も検証を繰り返したことで、Terraform にかなり馴染めたし、内部挙動や注意点にも詳しくなった。これにより、安心して本番でも作業を行えたので、事前にしっかり検証して本当に良かった！🙌

これで思い残すことなく、退職できる！👋