Azure Database for MySQL Flexible Server で 5.7 から 8.0 へのインプレースアップグレードを試してみた

2023.10.15

いわさです。

Azure Database for MySQL Flexible Server を 5.7 から 8.0 にバージョンアップさせる機会がありました。
それにあたって検証環境を用意してインプレースアップグレードを試したので紹介します。

なお MySQL 5.7 自体は、通常は今月 2023 年 10 月にコミュニティサポートの終了を迎えますが、Azure Database for MySQL の場合は Azure による 2025 年 9 月までの延長サポートを利用することが出来ます。

とはいえ、塩漬けにしておくべきようなものでも無いので移行の評価だけでも進めていきたいところです。
今回は次のような 5.7.43 を 8.0.x にアップグレードしました。

% mysql -h hoge1015mysql1.mysql.database.azure.com -u hoge -D hogedb -p
Enter password: 
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 5.7.43-log MySQL Community Server (GPL)

Copyright (c) 2000, 2023, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> select * from fuga;
+------+------+
| val1 | val2 |
+------+------+
|    1 | aaa  |
|    2 | bbb  |
|    3 | ccc  |
+------+------+
3 rows in set (0.21 sec)

いくつかアップグレード方法があるのですが、半年ほど前にメジャーバージョンアップグレード機能が GA となっており、以前まで別サーバーが作成される形だったのですが今はインプレースアップグレードも出来るようになっているようです。

今回はこちらの機能を使ってアップグレードを行ってみましたので、いくつか注意点など踏まえて機能の紹介をしたいと思います。

Burstable 以外でアップグレードメニューが表示される

アップグレード機能を使うための条件として Compute Tier の条件があります。
開発・検証用途などでよく利用される Burstable タイプの場合は本機能を利用することが出来ません。

Overview のメニューにアップグレードボタンが表示されるのですが Burstable サーバーの場合は次のように何も表示されないことがわかります。

そのため、こういったケースの場合は事前にスケールアップが必要になります。

Compute Tier が条件を満たしている場合は「Upgrade」ボタン表示されるのと、Overview の MySQL version からアップグレード機能を起動することも可能です。

上記どちらかを実行すると次のようにアップグレードダイアログが表示されます。
この画面でアップグレード先のバージョンを指定するのですが、メジャーバージョンのみ指定可能で本日時点だと 8.0 のみが指定出来ます。マイナーバージョンの指定は出来ません。

リードレプリカがある場合はレプリカサーバーから先にアップグレードする必要がある

単独のサーバーであれば問題ないのですが、リードレプリカ機能を使っている場合は少し注意する必要があります。
今回使用するアップグレード機能はサーバーごとにアップグレードが必要になるので、5.7 のプライマリに対して 5.7 のレプリカが何台かあるのであれば、レプリカに対してもそれぞれアップグレードが必要です。

また、アップグレードの順序も注意が必要で、リードレプリカがある場合は先にリードレプリカからメジャーバージョンのアップグレードを行う必要があります。

試しに 5.7 のリードレプリカが存在する状態でプライマリを 8.0 にアップグレードしようとしたところ、次のようなエラーになりました。むむ。

互換性がない状態だとエラーになる

前述のようにリードレプリカのアップグレードが先に必要なのでアップグレード操作をしてみました。

アップグレードしたところ、しばらく経つと処理が失敗したとエラーメッセージが表示されました。
リードレプリカはアップグレードされておらず 5.7 のままです。

{
  "code": "ServerVersionUpgradeConditionCheckFailed",
  "message": "Upgrade server version failed, check the error message for details: Find invalid server parameters, please correct before upgrade to new server version\nName: sql_mode, \nCurrent value: ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER, \nAllowed values: ,ALLOW_INVALID_DATES,ANSI_QUOTES,ERROR_FOR_DIVISION_BY_ZERO,HIGH_NOT_PRECEDENCE,IGNORE_SPACE,NO_AUTO_VALUE_ON_ZERO,NO_BACKSLASH_ESCAPES,NO_DIR_IN_CREATE,NO_ENGINE_SUBSTITUTION,NO_UNSIGNED_SUBTRACTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,PAD_CHAR_TO_FULL_LENGTH,PIPES_AS_CONCAT,REAL_AS_FLOAT,STRICT_ALL_TABLES,STRICT_TRANS_TABLES,TIME_TRUNCATE_FRACTIONAL, \nIssueed values: NO_AUTO_CREATE_USER\n"
}

エラーメッセージによると、sql_modeパラメータでNO_AUTO_CREATE_USERが 8.0 では許容されていないようです。リファレンスマニュアルの 8.0 の非推奨・削除された内容でも言及されていますね。

Using GRANT to create users. Instead, use CREATE USER. Following this practice makes the NO_AUTO_CREATE_USER SQL mode immaterial for GRANT statements, so it too is removed, and an error now is written to the server log when the presence of this value for the sql_mode option in the options file prevents mysqld from starting.

Server parameters メニューからパラメータを編集します。

パラメータ更新後に再度アップグレードを行うとアップグレードに成功しました。
次のようにリードレプリカがインプレースアップグレードされていますね。

% mysql -h hoge1015mysql2.mysql.database.azure.com -u hoge -D hogedb -p
Enter password: 
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 27
Server version: 8.0.32 Source distribution

Copyright (c) 2000, 2023, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> select * from fuga;
+------+------+
| val1 | val2 |
+------+------+
|    1 | aaa  |
|    2 | bbb  |
|    3 | ccc  |
+------+------+
3 rows in set (0.28 sec)

なお、ソースは 5.7 のままなのですが、8.0 のリードレプリカにレプリケーションがされ続けています。
プライマリサーバーで追加したレコードが、アップグレード済みのリードレプリカで参照することが出来ました。

% mysql -h hoge1015mysql1.mysql.database.azure.com -u hoge -D hogedb -p
Enter password: 
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 7
Server version: 5.7.43-log MySQL Community Server (GPL)

Copyright (c) 2000, 2023, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> insert into fuga values (4, 'ddd');
Query OK, 1 row affected (0.20 sec)

mysql> exit
Bye
% mysql -h hoge1015mysql2.mysql.database.azure.com -u hoge -D hogedb -p
Enter password: 
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 28
Server version: 8.0.32 Source distribution

Copyright (c) 2000, 2023, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> select * from fuga;
+------+------+
| val1 | val2 |
+------+------+
|    1 | aaa  |
|    2 | bbb  |
|    3 | ccc  |
|    4 | ddd  |
+------+------+
4 rows in set (0.20 sec)

Azure Database for MySQL の公式ドキュメントのみアップグレードシナリオのひとつとして記載されていましたが、ここでプライマリへの書き込みを停止して、レプリカを昇格してアップグレードされたプライマリとして使う方法もあるようです。

なお、ドキュメントでは事前に公式のアップグレードチェッカーでエラーに対処済みであることも言及されていました。
残ったプライマリサーバーに対してアップグレードチェッカーを試してみます。

macOS 上に MySQL Shell をインストールし、Azure Database for MySQL を指定してutil.checkForServerUpgrade()を実行してみました。

% mysqlsh
MySQL Shell 8.1.1

Copyright (c) 2016, 2023, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its affiliates.
Other names may be trademarks of their respective owners.

Type '\help' or '\?' for help; '\quit' to exit.
 MySQL  JS > util.checkForServerUpgrade('hoge@hoge1015mysql1.mysql.database.azure.com:3306', {"password":"********", "targetVersion":"8.0.32"})
The MySQL server at hoge1015mysql1.mysql.database.azure.com:3306, version
5.7.43-log - MySQL Community Server (GPL), will now be checked for
compatibility issues for upgrade to MySQL 8.0.32...

1) Usage of old temporal type
  No issues found

2) MySQL 8.0 syntax check for routine-like objects
  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.
  More information:
    https://dev.mysql.com/doc/refman/en/keywords.html

  mysql.az_replication_change_master - at line 3,4208: unexpected token
    'REPLICATION'
  mysql.az_replication_change_master_with_gtid - at line 3,4213: unexpected
    token 'REPLICATION'
  mysql.az_update_replica_information - at line 3,1525: unexpected token
    'REPLICATION'

3) Usage of db objects with names conflicting with new reserved keywords
  No issues found

4) Usage of utf8mb3 charset
  No issues found

5) Table names in the mysql schema conflicting with new tables in 8.0
  No issues found

6) Partitioned tables using engines with non native partitioning
  No issues found

7) Foreign key constraint names longer than 64 characters
  No issues found

8) Usage of obsolete MAXDB sql_mode flag
  No issues found

9) Usage of obsolete sql_mode flags
  Notice: The following DB objects have obsolete options persisted for
    sql_mode, which will be cleared during upgrade to 8.0.
  More information:
    https://dev.mysql.com/doc/refman/8.0/en/mysql-nutshell.html#mysql-nutshell-removals

  mysql.az_add_action_history - PROCEDURE uses obsolete NO_AUTO_CREATE_USER
    sql_mode
  mysql.az_create_aad_user_with_password_hash - PROCEDURE uses obsolete
    NO_AUTO_CREATE_USER sql_mode
  mysql.az_create_user_with_password_hash - PROCEDURE uses obsolete
    NO_AUTO_CREATE_USER sql_mode
  mysql.az_kill - PROCEDURE uses obsolete NO_AUTO_CREATE_USER sql_mode
  mysql.az_kill_query - PROCEDURE uses obsolete NO_AUTO_CREATE_USER sql_mode
  mysql.az_load_timezone - PROCEDURE uses obsolete NO_AUTO_CREATE_USER sql_mode
  mysql.az_replication_change_master - PROCEDURE uses obsolete
    NO_AUTO_CREATE_USER sql_mode
  mysql.az_replication_change_master_with_gtid - PROCEDURE uses obsolete
    NO_AUTO_CREATE_USER sql_mode
  mysql.az_replication_remove_master - PROCEDURE uses obsolete
    NO_AUTO_CREATE_USER sql_mode
  mysql.az_replication_restart - PROCEDURE uses obsolete NO_AUTO_CREATE_USER
    sql_mode
  mysql.az_replication_skip_counter - PROCEDURE uses obsolete
    NO_AUTO_CREATE_USER sql_mode
  mysql.az_replication_skip_gtid_transaction - PROCEDURE uses obsolete
    NO_AUTO_CREATE_USER sql_mode
  mysql.az_replication_start - PROCEDURE uses obsolete NO_AUTO_CREATE_USER
    sql_mode
  mysql.az_replication_stop - PROCEDURE uses obsolete NO_AUTO_CREATE_USER
    sql_mode
  mysql.az_update_replica_information - PROCEDURE uses obsolete
    NO_AUTO_CREATE_USER sql_mode
  mysql.sp_cleanup_cloud_replica - PROCEDURE uses obsolete NO_AUTO_CREATE_USER
    sql_mode
  global system variable sql_mode - defined using obsolete NO_AUTO_CREATE_USER
    option

10) ENUM/SET column definitions containing elements longer than 255 characters
  No issues found

11) Usage of partitioned tables in shared tablespaces
  No issues found

12) Circular directory references in tablespace data file paths
  No issues found

13) Usage of removed functions
  No issues found

14) Usage of removed GROUP BY ASC/DESC syntax
  No issues found

15) Removed system variables for error logging to the system log configuration
  To run this check requires full path to MySQL server configuration file to be specified at 'configPath' key of options dictionary
  More information:
    https://dev.mysql.com/doc/relnotes/mysql/8.0/en/news-8-0-13.html#mysqld-8-0-13-logging

16) Removed system variables
  To run this check requires full path to MySQL server configuration file to be specified at 'configPath' key of options dictionary
  More information:
    https://dev.mysql.com/doc/refman/8.0/en/added-deprecated-removed.html#optvars-removed

17) System variables with new default values
  To run this check requires full path to MySQL server configuration file to be specified at 'configPath' key of options dictionary
  More information:
    https://mysqlserverteam.com/new-defaults-in-mysql-8-0/

18) Zero Date, Datetime, and Timestamp values
  No issues found

19) Schema inconsistencies resulting from file removal or corruption
  No issues found

20) Tables recognized by InnoDB that belong to a different engine
  No issues found

21) Issues reported by 'check table x for upgrade' command
  No issues found

22) New default authentication plugin considerations
  Warning: The new default authentication plugin 'caching_sha2_password' offers
    more secure password hashing than previously used 'mysql_native_password'
    (and consequent improved client connection authentication). However, it also
    has compatibility implications that may affect existing MySQL installations. 
    If your MySQL installation must serve pre-8.0 clients and you encounter
    compatibility issues after upgrading, the simplest way to address those
    issues is to reconfigure the server to revert to the previous default
    authentication plugin (mysql_native_password). For example, use these lines
    in the server option file:
    
    [mysqld]
    default_authentication_plugin=mysql_native_password
    
    However, the setting should be viewed as temporary, not as a long term or
    permanent solution, because it causes new accounts created with the setting
    in effect to forego the improved authentication security.
    If you are using replication please take time to understand how the
    authentication plugin changes may impact you.
  More information:
    https://dev.mysql.com/doc/refman/8.0/en/upgrading-from-previous-series.html#upgrade-caching-sha2-password-compatibility-issues
    https://dev.mysql.com/doc/refman/8.0/en/upgrading-from-previous-series.html#upgrade-caching-sha2-password-replication

23) Columns which cannot have default values
  No issues found

24) Check for invalid table names and schema names used in 5.7
  No issues found

25) Check for orphaned routines in 5.7
  No issues found

26) Check for deprecated usage of single dollar signs in object names
  No issues found

27) Check for indexes that are too large to work on higher versions of MySQL
Server than 5.7
  No issues found

28) Check for deprecated '.<table>' syntax used in routines.
  No issues found

Errors:   3
Warnings: 1
Notices:  17

ERROR: 3 errors were found. Please correct these issues before upgrading to avoid compatibility issues.
 MySQL  JS >

Azure Database のアップグレード機能でエラーになったパラメータNO_AUTO_CREATE_USERも出力されていますが、それ以外の Azure 固有っぽいパラメータもいくつか出力されていて、ちょっと精査に時間かかりそうですね。

リードレプリカアップグレード後にプライマリをアップグレード

リードレプリカのアップグレード後、プライマリもアップグレードしてみました。
プライマリサーバーでも事前にパラメータなど互換性のない項目は対処済みです。

プライマリサーバーの場合は次のチェックを ON にした後にアップグレードボタンを押します。

プライマリもアップグレードすることが出来ました。
インプレースアップグレード出来たので、クライアント側で使用する接続文字列は変更せずに 8.0 で使うことが出来ます。

さいごに

本日は Azure Database for MySQL Flexible Server で 5.7 から 8.0 へのインプレースアップグレードを試してみました。

インプレースアップグレード自体は出来ますし、今回の検証構成だとすぐにアップグレードすることが出来ました。
また、インプレースアップグレードを行う場合は互換性の対処が出来ていない場合にアップグレードが中断されるようになっていることも確認出来ました。

注意点としては、リードレプリカが存在している場合にサーバーごとにアップグレードが必要なのと、事前にレプリカのアップグレードが必要という点でしょうか。