📑

Amazon Aurora MySQL v1(5.6 互換)→ v3(8.0 互換)移行を計画する(7)パラメータ・コード確認

2022/03/12に公開

これは

の続きです。

詳細調査結果を実際のパラメータグループやアプリケーション・コード(SQL 文)などと突き合わせて確認してみます。

パラメータグループの検討

https://github.com/hmatsu47/aurora_mysql1to3diff/blob/main/aurora-mysql1_3_param.md

こちらと実際に使用しているパラメータグループ(クラスタと DB)を比較して、対応が必要な点を見付けます。

私が関わっているサービスでは、以下の点が出てきました。

innodb_strict_modeのデフォルトが 厳密モード

https://dev.mysql.com/doc/refman/8.0/ja/innodb-parameters.html#sysvar_innodb_strict_mode

これは正確には Aurora MySQL v2(MySQL 5.7)の時点でデフォルトが変わっています。

一部の SQL 文の実行で、従来は警告(Warning)で済ませていたのをエラーで止める動作に変わりました。ほぼ問題にならない見込みですが、念のため従来の設定に合わせて厳密モードを OFF にします。

innodb_autoinc_lock_modeのデフォルトが1から2

AUTO_INCREMENT 生成時のロックモードです。

https://dev.mysql.com/doc/refman/8.0/ja/innodb-parameters.html#sysvar_innodb_autoinc_lock_mode

2のほうが性能上有利なのですが、私が関わっているサービスでは、MySQL Connector/J の rewriteBatchedStatementsオプション を使ったバッチINSERTLAST_INSERT_ID() を組み合わせた処理を行っている部分があったので、動作の問題が生じる可能性を考えて従来と同じ1に戻します。

一方、以下の点については特に問題にならないことがわかりました。

tx_isolationtransaction-isolationに変わった

これはパラメータグループというよりも、アプリケーションから DB に接続する部分の実装やライブラリのオプション設定に関わる問題ですが、以前触れた サイボウズのブログ記事 ではこの変更の影響を受けていました。

私が関わっているサービスではこのパラメータをアプリケーションから変更していないので、対応は不要です。

アプリケーション・コードとテーブル定義の検討

ライブラリ

DB 接続用のライブラリ(MySQL Connector/J など)を MySQL 8.0 対応バージョンに変更します。

その際、TLS 接続(TLS バージョンが合わない、非 SSL では接続できない等)の問題が生じる可能性がある点を留意しておきます。

TLS 接続の場合

TLS バージョンの問題が生じる可能性があります(Aurora MySQL 移行より前に新しいバージョンのライブラリに更新する場合)。

https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/AuroraMySQL.Security.html#AuroraMySQL.Security.SSL.TLS_Version

非 TLS 接続の場合

ライブラリのバージョンによっては、接続パラメータにsslMode=DISABLEDが必要になる場合があります。

https://dev.mysql.com/doc/connector-j/8.0/en/connector-j-connp-props-security.html

その他

パラメータグループでデフォルトどおりexplicit_defaults_for_timestamp1(有効)を指定した状態で、

  • MySQL Connector/J のプリペアドステートメントを使って
  • NOT NULLかつDEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMPTIMESTAMPDATETIME列に対して
  • nullUPDATEしたとき

の挙動が、

  • Aurora MySQL v1・MySQL Connector/J 5.1 の組み合わせ:UPDATE時のタイムスタンプで更新
  • Aurora MySQL v3・MySQL Connector/J 8.0 の組み合わせ:「NOT NULL列にnullUPDATEすることはできない」旨のエラーが発生

のように変化するケースがあります。

同様の事象が発生した場合はnullではなくNOW()などでUPDATEする形に SQL 文(プリペアドステートメント)を書き換えます。

また、Connector/J 8.0.29 でrewriteBatchedStatements=trueのときにROW_COUNT()の結果が不正な事象も見つかっています(8.0.28 に戻して回避)。

SQL 文とテーブル定義

こちらもいくつか検討事項が出てきましたが、結局、事前改修の対象は予約語とのバッティング箇所だけになりそうです。

予約語

https://github.com/hmatsu47/aurora_mysql1to3diff/blob/main/mysql57_80_reserved.md

既存コードではOFRANKのバッティングが確認されました。この結果をふまえて、今回は一旦以下の対応とします。

  • 既存コードについてはバッティング箇所のみ直す(「`」で括る)
  • 新規コードについてはバッティングの有無に関わらずデータベース(スキーマ)名・テーブル名・カラム名・インデックス名やエイリアスを「`」で括る
    • .で連結する形式で書かれている箇所は必ずしも「`」で括る必要がないが、ミス防止のため全て「`」で括る

ビルトイン関数

https://github.com/hmatsu47/aurora_mysql1to3diff/blob/main/mysql57_80_func_oper.md#ビルトイン関数

サイボウズのブログ記事 にもあった、FOUND_ROWS()(およびSQL_CALC_FOUND_ROWS)が見つかりました。

こちらはページャ機能の実装で使っていますが、

  • 先に改修してから Aurora MySQL v3 に移行すると、Aurora MySQL v1 運用中の性能低下の恐れがあること
  • 今後ページャ機能からスクロールなど別の UI に切り替える検討を進めていること

などから、移行前の改修は見送ることにします。

文字セット・照合順序

https://github.com/hmatsu47/aurora_mysql1to3diff/blob/main/mysql57_80_manual_all.md#文字セット照合順序

一部utf8utf8mb3のエイリアス)が残っていますが、現時点ではまだ「非推奨」なので、都合上今回の移行とは別のタイミングで対応します。

データ型

https://github.com/hmatsu47/aurora_mysql1to3diff/blob/main/mysql57_80_manual_all.md#データ型

DOUBLE(M,D)がありました。こちらも現時点では「非推奨」であり、一旦別タイミングでの対応とします。

その他 SQL ステートメントなど

https://github.com/hmatsu47/aurora_mysql1to3diff/blob/main/mysql57_80_manual_all.md#sql-ステートメントなど

サイボウズのブログ記事 にもあったGROUP BY 【列名】 ASC/DESCですが、 暗黙の昇順ソートASCが省略されているもの)が比較的多数見つかりました。

これは見逃しやすいので注意が必要です。

実際に動かしてみないとわからないものもある

ここまでは調査資料から判別できましたが、一部、それが難しい項目もあります。

RIGHT JOINの修正(MySQL 8.0.22)

MySQL 8.0.22 のリリースノートの Optimizer Notes に、

When using a RIGHT JOIN, some internal objects, were not converted to those suitable for use with a LEFT JOIN as intended. These included some lists of tables built at parse time, but which did not have their order reversed. This required maintaining code to handle instances in which a LEFT JOIN was originally a RIGHT JOIN as special cases, and was the source of several bugs. Now the server performs any necessary reversals at parse time, so that after parsing, a RIGHT JOIN is in fact, in all respects, a LEFT JOIN. (Bug #30887665, Bug #30964002)

References: See also: Bug #12567331, Bug #21350125.

という項目があります。RIGHT JOIN実行時、内部的にLEFT JOINに書き換える処理に不適切な部分があったのを改修したという趣旨ですが、これらのバグトラッキング番号の情報がクローズされてしまい内容が読めないので、こちらは実際に動作を確認してみる必要がありそうです。

UNIONの構文解析と動作の変更(MySQL 8.0.19 など)

マニュアルの UNION 句のページ中、

https://dev.mysql.com/doc/refman/8.0/ja/union.html#union-distinct-all

ここから下の各項目については内容を読む限りでは問題はなさそうですが、カッコの記述などが動作に影響する可能性があるため、念のため実際の動作確認の際に変化が生じないか気を付ける必要がありそうです。


に続きます。

GitHubで編集を提案

Discussion