Aurora MySQL2クラスタをAurora MySQL 3(serverless v2に移行する)

移行しました

https://zenn.dev/k5trismegistus/articles/922715b2ad4e13

## 背景

これまで利用してきたAurora MySQL 2(MySQL5.7互換)クラスタを利用中でしたが、暗号化設定がされていませんでした。
サービス的に求められるようになり、暗号化を導入することになりました。
Auroraクラスタは設定をコンソールからぽちぽち変えるだけで暗号化できるのだろうと思ってたんですが、実はそんなことはなく新規にクラスターを作る必要があるということがわかりました。
https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/Overview.Encryption.html#Overview.Encryption.Limitations
> - 暗号化されていない DB クラスターを暗号化された DB クラスターに変換することはできません。ただし、暗号化されていないスナップショットを暗号化された Aurora DB クラスターに復元することはできます。それを行うには、暗号化されていないスナップショットから復元するときに、KMS キーを指定します。
> - 暗号化されていない Aurora DB クラスターから、暗号化された Aurora レプリカを作成することはできません。暗号化された Aurora DB クラスターから、暗号化されていない Aurora レプリカを作成することはできません。

どうせクラスタを新しく作り直す必要があるなら、ついでに次のようなこともやってしまおうと、RDB周りの変更を一気に行うこととしました。
### ついでに実施する変更
- Aurora MySQL 2が2024/10にEOLにもなるということで、Aurora MySQL 3への移行(Aurora serverless v2はAurora MySQL 3、ちょっとややこしい)
- マイクロサービスが別々に専用クラスタを持っているのを、一つのAurora serverless v2クラスタにまとめることで費用とと今後のアップデートの際の手間の削減
- バックトラックを有効化
### 考慮したこと
- Auroraクラスタを後から暗号化する際はスナップショットを使う方法がよく取られるようですが、今回は複数のクラスタを一件にまとめるということでスナップショットからの復元ではなく、それぞれのクラスタをダンプしてインポートするという形をとりました。
スナップショットから復元で良いなら↓のように簡単に終わります。
https://qiita.com/k-yamada-github/items/8b00d03f99033cbc98be
- Aurora MySQL 3はMySQL8.0互換のため、デフォルトのCOLLATIONが`utf8mb4_0900_ai_ci`になってしまいます。既存のデータベースでは基本的に`utf8mb4_general_ci`としており、移行先でも`utfmb4_general_ci`である必要があります。
### 考慮しなかったこと
- RDBを利用しているのは全てRailsアプリケーションでした。なんでMySQLのバージョン違いはActiveRecordが吸収してくれるだろうということで、性能に対する影響等細かい調査は省いています。今の所非常に重いバッチ処理などもないので。
- サービスを停止してのメンテナンスとするので、無停止での移行する方法は検討しませんでした。。
## 実施手順
これらを踏まえて、以下のように移行を実施しました。
### 1. 作業準備
#### 作業用EC2インスタンスの用意
次に踏み台となるEC2インスタンスを立てます。MySQL Clientのインストールが面倒なため、Amazon Linux 2023ではなくAmazon Linux2を利用します。
このインスタンスからは移行元DB・移行先DBどちらにも通信できるようにセキュリティグループを設定しておきます。
#### 作業用インスタンスに必要なツールを追加
EC2インスタンスに入り、mysql-clientをインストール。Amazon Linux2だと以下だけでインストールできますが、Amazon Linux 2023だとライブラリ類が足りないのか入らず、、。なのでAmazon Linux2を使うことをお勧めします。どうせ使い捨てのサーバーなので、ここに時間をかける必要はないかと。
```bash
$ sudo yum install -y https://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpm
$ sudo rpm --import https://repo.mysql.com/RPM-GPG-KEY-mysql-2022
$ sudo yum install -y mysql-community-client --enablerepo=mysql80-community
```
### 2. 移行元データベースからのダンプ取得
#### ダンプの取得       
     
mysqldumpを使って、移行元DBからデータベースを取り出します。
        
```bash
$ mysqldump -u <ユーザー名> -p -h <移行元dbクラスターホスト> <db名> --set-gtid-purged=OFF --opt > dump.sql
```
        
※GTIDというのはよくわかってないんですが、全てのトランザクションに固有のIDをふる機能です。ダンプを復元するときにGTIDを含んでいると、強い権限がないと復元できないようです。なので、それを含まずにダンプします。
#### ダンプファイルの編集
mysqldump でダンプされたファイルは、
    
```sql
CREATE TABLE `hoge` (
  ...
) ENGINE=InnoDB AUTO_INCREMENT=223 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
```
    
とDEFAULT CHARSETが書かれています。
    
DEFAULT CHARSETの指定だけがありCOLLATEの指定がないと、MySQL8.0は勝手にCOLLATIONをデフォルトのutf8mb4_0900_ai_ciにしてくれます。
https://gihyo.jp/dev/serial/01/mysql-road-construction-news/0157
> つまり、CREATE TABLE文にDEFAULT CHARSET=utf8mb4のみ記述すると、collation_serverシステム変数に設定されているサーバーのデフォルトcollationでもデータベースレベルのcollationでもない、MySQLのデフォルトcollationが設定されてしまうのです。CREATE TABLE文を実行するときは予期せぬトラブルを避けるため、DEFAULT CHARSET=xx COLLATE=xxを省略せずに記述するのが良いでしょう。
sedでダンプファイルにCOLLATEを加えます。
        
```bash
$ sed 's/DEFAULT CHARSET=utf8mb4/DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci/' dump.sql > dump-new.sql
```
これを実行すると、ダンプしたものは
```sql
CREATE TABLE `hoge` (
  ...
) ENGINE=InnoDB AUTO_INCREMENT=223 DEFAULT CHARSET=utf8mb4  COLLATE utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
```
となっているはずです。
### 3. 移行先データベースへのデータインポート
#### Aurora MySQL 3 (serverless v2)クラスタの用意
https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/aurora-serverless-v2.create-cluster.html
ドキュメントを参考に。
この時に暗号化やバックトラックの設定を有効化しておく必要があります。
    
#### 移行先クラスタにデータベース
    
```bash
$ mysql -u <ユーザー名> -p -h <移行先dbクラスターホスト>
> CREATE DATABASE <db名> DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;    
```
    
※ここでDEFAULT CHARACTER SETやCOLLATEを書いても結果あまり意味なさそうなんですが、、一応書いときます。
    
#### ダンプをインポートする
    
```bash
$ mysql -h <移行先dbクラスターホスト> -u <ユーザー名> -p <db名> < dump-new.sql
```
    
あとはアプリ側のDBの向き先を変えれば、移行完了です。
適宜スナップショットを取るなり経過観察期間をとるなり安全を確認したら、古いクラスタを削除しましょう。
https://zenn.dev/k5trismegistus/articles/922715b2ad4e13

移行しました