Aurora MySQL バージョン2からバージョン3へのアップグレード時に遭遇したエラー

[PONOS Advent Calendar 2024](https://qiita.com/advent-calendar/2024/ponos)の11日目の記事です。

# はじめに #
Aurora MySQLのメジャーアップグレード時に発生したエラーと解決した方法を紹介していきます。

# 背景：Aurora MySQLバージョン2の標準サポート終了 #
2024年10月31日をもって、Aurora MySQLバージョン2の標準サポートが終了になりました。標準サポート終了後もAurora MySQL マイナーバージョンが2.11と2.12の場合は、Amazon RDS延長サポートの対象なので、引き続きデータベースを以前のメジャーエンジンバージョンで実行することができます。

https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/Aurora.MySQL57.EOL.html

AWSのサポートメールからRDS延長サポートの料金は、2024年12月1日から発生するとのこと。
また、インスタンスサイズが小さい場合、元のインスタンス費に比べサポート費の割合が高くなりそう。

https://dev.classmethod.jp/articles/how-to-supress-amazon-rds-extended-support-cost/

# アップグレードと発生したエラー #
所持している複数のAuroraデータベースがマイナーバージョン2.11を使用していたので、料金が加算される前に何とかせねば！ということで11月中にこれらをアップグレードすることにしました。しかし、アップグレードの過程でいくつかのデータベースでエラーが発生し、結果的にアップグレードは失敗しました。問題の原因は、Aurora MySQLのメジャーバージョンがアップグレードされ、MySQLの互換性が5.7から8.0に変更されたことでした。この変更により、互換性のない変更が導入され、それが2種類のエラーを引き起こしていました。

## パーティション作成時の日付型の区切り文字でエラー ##
```:error/mysql-error.log
[ERROR] [MY-013140] [Server] Partition column values of incorrect type
```
RDSのコンソールからエラーログを見ると、パーティションを使っているテーブルでエラーが出ていることがわかりました。

```SQL:エラーになったパーティション作成SQLのイメージ
ALTER TABLE test_tables PARTITION BY RANGE COLUMNS(created_at) (
    PARTITION p202004 VALUES LESS THAN ('2020/04/01 00:00:00'),
    ...
    PARTITION p203003 VALUES LESS THAN ('2030/03/01 00:00:00')
);
```

このSQLはMySQL 5.7互換のAurora環境では動作していたので、MySQL 8.0で変更の影響かと思いリリースノートを確認してみた所、MySQL 8.0から日付型に任意の区切り文字を使用することが非推奨となっていました。

https://dev.mysql.com/doc/relnotes/mysql/8.0/en/news-8-0-29.html

リリースノートでは非推奨ですが、アップグレードする予定だったAuroraのバージョンでは既に任意の区切り文字を許容していない様子でしたので修正をしました。

```SQL:修正後のパーティション作成SQL
ALTER TABLE test_tables PARTITION BY RANGE COLUMNS(created_at) (
    PARTITION p202004 VALUES LESS THAN ('2020-04-01 00:00:00'),
    ...
    PARTITION p203003 VALUES LESS THAN ('2030-03-01 00:00:00')
);
```

スラッシュで日付型の区切り文字を書いていた部分をハイフンに変更することで、こちらのエラーは解消されました。
注意すべき点として、パーティションの変更時にテーブルロックの発生が可能性としてあるため、サービスの停止を考慮する必要があります。

## ストアドプロシージャで予約語になった単語を使っていた ##

```json:upgrade-prechecks.log
{
    "id": "routinesSyntaxCheck",
    "title": "MySQL 8.0 syntax check for routine-like objects",
    "status": "OK",
    "description": "The following objects did not pass a syntax check with the latest MySQL 8.0 grammar. A common reason is that they reference names that conflict with new reserved keywords. You must update these routine definitions and `quote` any such references before upgrading.",
    "documentationLink": "https://dev.mysql.com/doc/refman/en/keywords.html",
    "detectedProblems": [
        {
            "level": "Error",
            "dbObject": "test.test_procedure",
            "description": "at line 2,29: unexpected token 'rank'"
        }
    ]
}
```

また、別のデータベースではアップグレード前の事前チェックでエラーが出ていました。古いシステムでストアドプロシージャを設定しているデータベースがあるのですが、ログを見るとそこでMySQL 8.0から予約語になった単語を使用しているためエラーとなったようです。

https://dev.mysql.com/doc/refman/8.0/ja/keywords.html

```SQL:エラーになったストアドプロシージャのイメージ
CREATE PROCEDURE `test_procedure` (IN _rank BIGINT)
BEGIN
    INSERT INTO test_tables (rank) VALUES (_rank);
END
```

今回の場合、元々カラム名に使っていた "rank" という単語が新しく予約語として登録され、そのカラムを指定していたストアドプロシージャがエラーになっていました。
予約語をカラム名に使うことは推奨されませんが、既存システムのカラム名を簡単に変えることもできないため、カラム名をバッククォートで囲い対応しました。バッククォートを使用することで、予約語やキーワードをエスケープすることが可能です。

```SQL:修正語のストアドプロシージャ
CREATE PROCEDURE `test_procedure` (IN _rank BIGINT)
BEGIN
    INSERT INTO test_tables (`rank`) VALUES (_rank);
END
```

エスケープすることでアップグレードは成功しますが、このデータベースを使用しているサービスにおいて、エスケープなしで予約語が使用されている箇所がないかも同時に確認する必要があります。

# 終わりに
料金が加算される前に、アップグレードができて良かったです。
まだアップグレードしていない方のご参考になれば幸いです。

それでは次回は[@kerimeka](https://qiita.com/kerimeka)さんです。

# 参考・引用
[Amazon Aurora MySQL 互換エディションバージョン 2 の標準サポート終了に向けて準備する](https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/Aurora.MySQL57.EOL.html)
[安定したAWSアカウントのデータベース利用費が2024年3月から増えていたらRDS延長サポートを要チェック!](https://dev.classmethod.jp/articles/how-to-supress-amazon-rds-extended-support-cost/)
[Changes in MySQL 8.0.29 (2022-04-26, General Availability)](https://dev.mysql.com/doc/relnotes/mysql/8.0/en/news-8-0-29.html)
[9.3 キーワードと予約語](https://dev.mysql.com/doc/refman/8.0/ja/keywords.html)