sql_mode compatibility, the pit that MySQL 8.0 has stepped on

MySQL 8.0 New Features Column Directory

Double password, MySQL 8.0 innovative feature
sql_mode compatibility, MySQL 8.0 upgrade has stepped on the pit



Foreword:

It has been 4 years since MySQL 8.0 was GA, and it has been widely used by major Internet companies, and its stability has been fully verified. Recently, we are also upgrading the stock old version database to 8.0. Although a lot of inspections and verifications were done in the early stage, some pits were inevitably stepped on during the upgrade process.

sql_mode,在MySQL 5.7之前是宽松模式;在MySQL 5.7之后一直到最新的8.0.28版本,都还是严格模式。不过,在不同的数据库版本之间、不同的数据库实例之间,sql_mode总会有一些变化;升级或者迁移的过程中一不小心就会掉入坑中。


1. After MySQL is upgraded to 8.0, the business access database reports an error

After a business library was upgraded from MySQL 5.7 to 8.0, the business request reported an error, SQLSTATE[42000]: Syntax error or access violation.

# 业务侧报错信息
SQLSTATE[42000]: Syntax error or access violation: 1231 Variable 'sql_mode' can't be set to the value of 'NO_AUTO_CREATE_USER' (SQL: select `id`, `name` from `t`)

The error message here is that the syntax is wrong. The developer was confused when he saw it. This code has been running for so many years, why does it suddenly report a syntax error? And the error message shows 'sql_mode' can't be set to the value of 'NO_AUTO_CREATE_USER'that the developer confirms that such SQL has never been written.
Here we can simply locate it, open general_log, and see what statements are executed by the client session.

...
2022-03-24T20:02:40.077202+08:00     9221 Execute   set session sql_mode='ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'
2022-03-24T20:02:40.077202+08:00     9221 Execute  select `id`, `name` from `t`
...

According to the log, it can be clearly seen that the client first sets the session-level sql_mode, and then executes the corresponding business query. With this specific SQL, developers can quickly determine that this is a statement that comes with the bottom layer of the PHP framework.

Obviously, this is a standard underlying framework developed based on MySQL 5.7 version.

2. Analysis of the cause of the problem

2.1 Historical changes of sql_mode

Why can you tell at a glance that this is a framework developed based on MySQL 5.7?

Because the sql_mode setting in the error is exactly the same as the default sql_mode setting of MySQL 5.7. The default configuration of sql_mode in MySQL 5.7 is this sql_mode='ONLY_FULL_GROUP_BY, STRICT_TRANS_TABLES, NO_ZERO_IN_DATE, NO_ZERO_DATE, ERROR_FOR_DIVISION_BY_ZERO, NO_AUTO_CREATE_USER, NO_ENGINE_SUBSTITUTION'.

In MySQL 8.0.11 version, the default configuration of sql_mode has been modified to remove a sql mode. Exactly, the removed mode is the one suggested in the previous error message NO_AUTO_CREATE_USER.

2.2 The past and present of NO_AUTO_CREATE_USER

Before MySQL 5.7, DBAs often used the grant syntax to create users and grants. MySQL 5.7 still supports this syntax to create users, but in order to limit this behavior of creating users, the sql mode of NO_AUTO_CREATE_USER was introduced. [ NO_AUTO_CREATE_USER], that is, it is forbidden to create an account with an empty password in the grant statement. To create a user using the grant syntax, the "identified by" keyword must be used to set the account password, otherwise it is considered an illegal creation statement.

After the MySQL 8.0.11 version, it is officially believed that DBAs have accepted the behavior of using the create user syntax to create accounts by default, and they directly abandoned the grant syntax for creating accounts. The grant syntax is not allowed to create accounts, so the NO_AUTO_CREATE_USER mode will naturally exit the historical stage, so this mode was abandoned in 8.0.11 at the same time, and will no longer be supported in the future.

# 在MySQL 8.0.23中测试一下grant语法,直接报错。
MySQL [(none)]> grant select on test.* to 'no_user'@'100.124.43.85' identified by 'no_user';
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'identified by 'no_user'' at line 1

NOTE: The problem here is very clear. The underlying business framework sets the session-level sql_mode after connecting to the database, including the mode that has been abandoned in MySQL 8.0, NO_AUTO_CREATE_USERand MySQL directly returns an error.

2.3 Check and resolve incompatible sql_mode

In fact, sql_mode deprecated in MySQL 8.0 is not only NO_AUTO_CREATE_USER, there are also some modes that are also incompatible with 8.0. We have considered the change of sql_mode when formulating the MySQL upgrade plan, and added the check of sql_mode which is not supported by MySQL 8.0 in the pre-upgrade check. As shown in the figure below:
MySQL 8.0 pre-upgrade check
and during the upgrade process, when configuring the initial parameters of MySQL 8.0, the operating parameters of 5.7 were compared with the parameter templates of 8.0, and some parameter settings of 5.7 were merged into the parameter file of MySQL 8.0.

However, the above solutions can only ensure that the global parameter configuration before and after MySQL upgrade is OK; we cannot control the session-level parameters set by the client connection. Here, developers need to cooperate to check whether there are parameter settings in the business-side code that are incompatible with MySQL 8.0.

Summarize

So, what parameters/settings are MySQL 8.0 incompatible with previous versions?
I will share this question with you in the next article. Welcome everyone to like and follow, I will continue to make some related records and share.

Guess you like

Origin blog.csdn.net/wangzihuacool/article/details/123760798