Before upgrading to MySQL 5.7, review the changes described in this section to identify those that apply to your current MySQL installation and applications. Perform any recommended actions.
Changes marked as Incompatible
change are incompatibilities with earlier versions of
MySQL, and may require your attention before
upgrading. Our aim is to avoid these changes, but
occasionally they are necessary to correct problems that would be
worse than an incompatibility between releases. If an upgrade
issue applicable to your installation involves an incompatibility,
follow the instructions given in the description. Sometimes this
involves dumping and reloading tables, or use of a statement such
as CHECK TABLE or
REPAIR TABLE.
For dump and reload instructions, see
Section 2.10.12, “Rebuilding or Repairing Tables or Indexes”. Any procedure that involves
REPAIR TABLE with the
USE_FRM option must be
done before upgrading. Use of this statement with a version of
MySQL different from the one used to create the table (that is,
using it after upgrading) may damage the table. See
Section 13.7.2.5, “REPAIR TABLE Statement”.
Incompatible change: In MySQL 5.7.11, the default
--early-plugin-loadvalue is the name of thekeyring_fileplugin library file, causing that plugin to be loaded by default. In MySQL 5.7.12 and higher, the default--early-plugin-loadvalue is empty; to load thekeyring_fileplugin, you must explicitly specify the option with a value naming thekeyring_fileplugin library file.InnoDBtablespace encryption requires that the keyring plugin to be used be loaded prior toInnoDBinitialization, so this change of default--early-plugin-loadvalue introduces an incompatibility for upgrades from 5.7.11 to 5.7.12 or higher. Administrators who have encryptedInnoDBtablespaces must take explicit action to ensure continued loading of the keyring plugin: Start the server with an--early-plugin-loadoption that names the plugin library file. For additional information, see Section 6.4.4.1, “Keyring Plugin Installation”.Incompatible change: The
INFORMATION_SCHEMAhas tables that contain system and status variable information (see Section 24.3.11, “The INFORMATION_SCHEMA GLOBAL_VARIABLES and SESSION_VARIABLES Tables”, and Section 24.3.10, “The INFORMATION_SCHEMA GLOBAL_STATUS and SESSION_STATUS Tables”). As of MySQL 5.7.6, the Performance Schema also contains system and status variable tables (see Section 25.12.13, “Performance Schema System Variable Tables”, and Section 25.12.14, “Performance Schema Status Variable Tables”). The Performance Schema tables are intended to replace theINFORMATION_SCHEMAtables, which are deprecated as of MySQL 5.7.6 and are removed in MySQL 8.0.For advice on migrating away from the
INFORMATION_SCHEMAtables to the Performance Schema tables, see Section 25.20, “Migrating to Performance Schema System and Status Variable Tables”. To assist in the migration, you can use theshow_compatibility_56system variable, which affects how system and status variable information is provided by theINFORMATION_SCHEMAand Performance Schema tables, and also by theSHOW VARIABLESandSHOW STATUSstatements.show_compatibility_56is enabled by default in 5.7.6 and 5.7.7, and disabled by default in MySQL 5.7.8.For details about the effects of
show_compatibility_56, see Section 5.1.7, “Server System Variables” For better understanding, it is strongly recommended that you read also these sections:Incompatible change: As of MySQL 5.7.6, data directory initialization creates only a single
rootaccount,'root'@'localhost'. (See Section 2.9.1, “Initializing the Data Directory”.) An attempt to connect to the host127.0.0.1normally resolves to thelocalhostaccount. However, this fails if the server is run withskip_name_resolveenabled. If you plan to do that, make sure that an account exists that can accept a connection. For example, to be able to connect asrootusing--host=127.0.0.1or--host=::1, create these accounts:CREATE USER 'root'@'127.0.0.1' IDENTIFIED BY 'root-password'; CREATE USER 'root'@'::1' IDENTIFIED BY 'root-password';Incompatible change: As of MySQL 5.7.6, for some Linux platforms, when MySQL is installed using RPM and Debian packages, server startup and shutdown now is managed using systemd rather than mysqld_safe, and mysqld_safe is not installed. This may require some adjustment to the manner in which you specify server options. For details, see Section 2.5.10, “Managing MySQL Server with systemd”.
Incompatible change: In MySQL 5.7.5, the executable binary version of mysql_install_db is located in the
bininstallation directory, whereas the Perl version was located in thescriptsinstallation directory. For upgrades from an older version of MySQL, you may find a version in both directories. To avoid confusion, remove the version in thescriptsdirectory. For fresh installations of MySQL 5.7.5 or later, mysql_install_db is only found in thebindirectory, and thescriptsdirectory is no longer present. Applications that expect to find mysql_install_db in thescriptsdirectory should be updated to look in thebindirectory instead.The location of mysql_install_db becomes less material as of MySQL 5.7.6 because as of that version it is deprecated in favor of mysqld --initialize (or mysqld --initialize-insecure). See Section 2.9.1, “Initializing the Data Directory”
Incompatible change: In MySQL 5.7.5, these SQL mode changes were made:
Strict SQL mode for transactional storage engines (
STRICT_TRANS_TABLES) is now enabled by default.Implementation of the
ONLY_FULL_GROUP_BYSQL mode has been made more sophisticated, to no longer reject deterministic queries that previously were rejected. In consequence,ONLY_FULL_GROUP_BYis now enabled by default, to prohibit nondeterministic queries containing expressions not guaranteed to be uniquely determined within a group.The changes to the default SQL mode result in a default
sql_modesystem variable value with these modes enabled:ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION.The
ONLY_FULL_GROUP_BYmode is also now included in the modes comprised by theANSISQL mode.
If you find that having
ONLY_FULL_GROUP_BYenabled causes queries for existing applications to be rejected, either of these actions should restore operation:If it is possible to modify an offending query, do so, either so that nondeterministic nonaggregated columns are functionally dependent on
GROUP BYcolumns, or by referring to nonaggregated columns usingANY_VALUE().If it is not possible to modify an offending query (for example, if it is generated by a third-party application), set the
sql_modesystem variable at server startup to not enableONLY_FULL_GROUP_BY.
For more information about SQL modes and
GROUP BYqueries, see Section 5.1.10, “Server SQL Modes”, and Section 12.19.3, “MySQL Handling of GROUP BY”.
Incompatible change: The
Passwordcolumn of themysql.usersystem table was removed in MySQL 5.7.6. All credentials are stored in theauthentication_stringcolumn, including those formerly stored in thePasswordcolumn. If performing an in-place upgrade to MySQL 5.7.6 or later, run mysql_upgrade as directed by the in-place upgrade procedure to migrate thePasswordcolumn contents to theauthentication_stringcolumn.If performing a logical upgrade using a mysqldump dump file from a pre-5.7.6 MySQL installation, you must observe these conditions for the mysqldump command used to generate the dump file:
You must include the
--add-drop-tableoptionYou must not include the
--flush-privilegesoption
As outlined in the logical upgrade procedure, load the pre-5.7.6 dump file into the 5.7.6 (or later) server before running mysql_upgrade.
Incompatible change: As of MySQL 5.7.5, support for passwords that use the older pre-4.1 password hashing format is removed, which involves the following changes. Applications that use any feature no longer supported must be modified.
The
mysql_old_passwordauthentication plugin that used pre-4.1 password hash values is removed. Accounts that use this plugin are disabled at startup and the server writes an “unknown plugin” message to the error log. For instructions on upgrading accounts that use this plugin, see Section 6.4.1.3, “Migrating Away from Pre-4.1 Password Hashing and the mysql_old_password Plugin”.For the
old_passwordssystem variable, a value of 1 (produce pre-4.1 hash values) is no longer permitted.The
--secure-authoption to the server and client programs is the default, but is now a no-op. It is deprecated;expect it to be removed in a future MySQL release.The
--skip-secure-authoption to the server and client programs is no longer supported and using it produces an error.The
secure_authsystem variable permits only a value of 1; a value of 0 is no longer permitted.The
OLD_PASSWORD()function is removed.
Incompatible change: In MySQL 5.6.6, the 2-digit
YEAR(2)data type was deprecated. In MySQL 5.7.5, support forYEAR(2)is removed. Once you upgrade to MySQL 5.7.5 or higher, any remaining 2-digitYEAR(2)columns must be converted to 4-digitYEARcolumns to become usable again. For conversion strategies, see Section 11.2.5, “2-Digit YEAR(2) Limitations and Migrating to 4-Digit YEAR”. Running mysql_upgrade after upgrading is one of the possible conversion strategies.As of MySQL 5.7.7,
CHECK TABLE ... FOR UPGRADEreports a table as needing a rebuild if it contains old temporal columns in pre-5.6.4 format (TIME,DATETIME, andTIMESTAMPcolumns without support for fractional seconds precision) and theavoid_temporal_upgradesystem variable is disabled. This helps mysql_upgrade to detect and upgrade tables containing old temporal columns. Ifavoid_temporal_upgradeis enabled,FOR UPGRADEignores the old temporal columns present in the table; consequently, mysql_upgrade does not upgrade them.As of MySQL 5.7.7,
REPAIR TABLEupgrades a table if it contains old temporal columns in pre-5.6.4 format and theavoid_temporal_upgradesystem variable is disabled. Ifavoid_temporal_upgradeis enabled,REPAIR TABLEignores the old temporal columns present in the table and does not upgrade them.To check for tables that contain such temporal columns and need a rebuild, disable
avoid_temporal_upgradebefore executingCHECK TABLE ... FOR UPGRADE.To upgrade tables that contain such temporal columns, disable
avoid_temporal_upgradebefore executingREPAIR TABLEor mysql_upgrade.Incompatible change: As of MySQL 5.7.2, the server requires account rows in the
mysql.usersystem table to have a nonemptyplugincolumn value and disables accounts with an empty value. This requires that you upgrade yourmysql.usertable to fill in allpluginvalues. As of MySQL 5.7.6, use this procedure:If you plan to upgrade using the data directory from your existing MySQL installation:
Stop the old (MySQL 5.6) server
Upgrade the MySQL binaries in place by replacing the old binaries with the new ones
Start the MySQL 5.7 server normally (no special options)
Run mysql_upgrade to upgrade the system tables
Restart the MySQL 5.7 server
If you plan to upgrade by reloading a dump file generated from your existing MySQL installation:
To generate the dump file, run mysqldump with the
--add-drop-tableoption and without the--flush-privilegesoptionStop the old (MySQL 5.6) server
Upgrade the MySQL binaries in place (replace the old binaries with the new ones)
Start the MySQL 5.7 server normally (no special options)
Reload the dump file (mysql <
dump_file)Run mysql_upgrade to upgrade the system tables
Restart the MySQL 5.7 server
Before MySQL 5.7.6, the procedure is more involved:
If you plan to upgrade using the data directory from your existing MySQL installation:
Stop the old (MySQL 5.6) server
Upgrade the MySQL binaries in place (replace the old binaries with the new ones)
Restart the server with the
--skip-grant-tablesoption to disable privilege checkingRun mysql_upgrade to upgrade the system tables
Restart the server normally (without
--skip-grant-tables)
If you plan to upgrade by reloading a dump file generated from your existing MySQL installation:
To generate the dump file, run mysqldump without the
--flush-privilegesoptionStop the old (MySQL 5.6) server
Upgrade the MySQL binaries in place (replace the old binaries with the new ones)
Restart the server with the
--skip-grant-tablesoption to disable privilege checkingReload the dump file (mysql <
dump_file)Run mysql_upgrade to upgrade the system tables
Restart the server normally (without
--skip-grant-tables)
mysql_upgrade runs by default as the MySQL
rootuser. For the preceding procedures, if therootpassword is expired when you run mysql_upgrade, it displays a message informing you that your password is expired and that mysql_upgrade failed as a result. To correct this, reset therootpassword and run mysql_upgrade again:$> mysql -u root -p Enter password: **** <- enter root password here mysql> ALTER USER USER() IDENTIFIED BY 'root-password'; # MySQL 5.7.6 and up mysql> SET PASSWORD = PASSWORD('root-password'); # Before MySQL 5.7.6 mysql> quit $> mysql_upgrade -p Enter password: **** <- enter root password hereThe password-resetting statement normally does not work if the server is started with
--skip-grant-tables, but the first invocation of mysql_upgrade flushes the privileges, so when you run mysql, the statement is accepted.If mysql_upgrade itself expires the
rootpassword, you must reset the password again in the same manner.After following the preceding instructions, DBAs are advised also to convert accounts that use the
mysql_old_passwordauthentication plugin to usemysql_native_passwordinstead, because support formysql_old_passwordhas been removed. For account upgrade instructions, see Section 6.4.1.3, “Migrating Away from Pre-4.1 Password Hashing and the mysql_old_password Plugin”.Incompatible change: It is possible for a column
DEFAULTvalue to be valid for thesql_modevalue at table-creation time but invalid for thesql_modevalue when rows are inserted or updated. Example:SET sql_mode = ''; CREATE TABLE t (d DATE DEFAULT 0); SET sql_mode = 'NO_ZERO_DATE,STRICT_ALL_TABLES'; INSERT INTO t (d) VALUES(DEFAULT);In this case, 0 should be accepted for the
CREATE TABLEbut rejected for theINSERT. However, previously the server did not evaluateDEFAULTvalues used for inserts or updates against the currentsql_mode. In the example, theINSERTsucceeds and inserts'0000-00-00'into theDATEcolumn.As of MySQL 5.7.2, the server applies the proper
sql_modechecks to generate a warning or error at insert or update time.A resulting incompatibility for replication if you use statement-based logging (
binlog_format=STATEMENT) is that if a replica is upgraded, a source which has not been upgraded executes the preceding example without error, whereas theINSERTfails on the replica and replication stops.To deal with this, stop all new statements on the source and wait until the replicas catch up. Then upgrade the replicas followed by the source. Alternatively, if you cannot stop new statements, temporarily change to row-based logging on the source (
binlog_format=ROW) and wait until all replicas have processed all binary logs produced up to the point of this change. Then upgrade the replicas followed by the source and change the source back to statement-based logging.Incompatible change: Several changes were made to the audit log plugin for better compatibility with Oracle Audit Vault. For upgrading purpose, the main issue is that the default format of the audit log file has changed: Information within
<AUDIT_RECORD>elements previously written using attributes now is written using subelements.Example of old
<AUDIT_RECORD>format:<AUDIT_RECORD TIMESTAMP="2013-04-15T15:27:27" NAME="Query" CONNECTION_ID="3" STATUS="0" SQLTEXT="SELECT 1" />Example of new format:
<AUDIT_RECORD> <TIMESTAMP>2013-04-15T15:27:27 UTC</TIMESTAMP> <RECORD_ID>3998_2013-04-15T15:27:27</RECORD_ID> <NAME>Query</NAME> <CONNECTION_ID>3</CONNECTION_ID> <STATUS>0</STATUS> <STATUS_CODE>0</STATUS_CODE> <USER>root[root] @ localhost [127.0.0.1]</USER> <OS_LOGIN></OS_LOGIN> <HOST>localhost</HOST> <IP>127.0.0.1</IP> <COMMAND_CLASS>select</COMMAND_CLASS> <SQLTEXT>SELECT 1</SQLTEXT> </AUDIT_RECORD>If you previously used an older version of the audit log plugin, use this procedure to avoid writing new-format log entries to an existing log file that contains old-format entries:
Stop the server.
Rename the current audit log file manually. This file contains log entries using only the old format.
Update the server and restart it. The audit log plugin creates a new log file, which contains log entries using only the new format.
For information about the audit log plugin, see Section 6.4.5, “MySQL Enterprise Audit”.
As of MySQL 5.7.7, the default connection timeout for a replica was changed from 3600 seconds (one hour) to 60 seconds (one minute). The new default is applied when a replica without a setting for the
slave_net_timeoutsystem variable is upgraded to MySQL 5.7. The default setting for the heartbeat interval, which regulates the heartbeat signal to stop the connection timeout occurring in the absence of data if the connection is still good, is calculated as half the value ofslave_net_timeout. The heartbeat interval is recorded in the replica's source info log (themysql.slave_master_infotable ormaster.infofile), and it is not changed automatically when the value or default setting ofslave_net_timeoutis changed. A MySQL 5.6 replica that used the default connection timeout and heartbeat interval, and was then upgraded to MySQL 5.7, therefore has a heartbeat interval that is much longer than the connection timeout.If the level of activity on the source is such that updates to the binary log are sent to the replica at least once every 60 seconds, this situation is not an issue. However, if no data is received from the source, because the heartbeat is not being sent, the connection timeout expires. The replica therefore thinks the connection to the source has been lost and makes multiple reconnection attempts (as controlled by the
MASTER_CONNECT_RETRYandMASTER_RETRY_COUNTsettings, which can also be seen in the source info log). The reconnection attempts spawn numerous zombie dump threads that the source must kill, causing the error log on the source to contain multiple errors of the form While initializing dump thread for slave with UUIDuuid, found a zombie dump thread with the same UUID. Master is killing the zombie dump threadthreadid. To avoid this issue, immediately before upgrading a replica to MySQL 5.7, check whether theslave_net_timeoutsystem variable is using the default setting. If so, issueCHANGE MASTER TOwith theMASTER_HEARTBEAT_PERIODoption, and set the heartbeat interval to 30 seconds, so that it works with the new connection timeout of 60 seconds that applies after the upgrade.Incompatible change: MySQL 5.6.22 and later recognized the
REFERENCESprivilege but did not entirely enforce it; a user with at least one ofSELECT,INSERT,UPDATE,DELETE, orREFERENCEScould create a foreign key constraint on a table. MySQL 5.7 (and later) requires the user to have theREFERENCESprivilege to do this. This means that if you migrate users from a MySQL 5.6 server (any version) to one running MySQL 5.7, you must make sure to grant this privilege explicitly to any users which need to be able to create foreign keys. This includes the user account employed to import dumps containing tables with foreign keys.
As of MySQL 5.7.24, the zlib library version bundled with MySQL was raised from version 1.2.3 to version 1.2.11.
The zlib
compressBound()function in zlib 1.2.11 returns a slightly higher estimate of the buffer size required to compress a given length of bytes than it did in zlib version 1.2.3. ThecompressBound()function is called byInnoDBfunctions that determine the maximum row size permitted when creating compressedInnoDBtables or inserting rows into compressedInnoDBtables. As a result,CREATE TABLE ... ROW_FORMAT=COMPRESSEDorINSERToperations with row sizes very close to the maximum row size that were successful in earlier releases could now fail.If you have compressed
InnoDBtables with large rows, it is recommended that you test compressed tableCREATE TABLEstatements on a MySQL 5.7 test instance prior to upgrading.Incompatible change: To simplify
InnoDBtablespace discovery during crash recovery, new redo log record types were introduced in MySQL 5.7.5. This enhancement changes the redo log format. Before performing an in-place upgrade, perform a clean shutdown using aninnodb_fast_shutdownsetting of0or1. A slow shutdown usinginnodb_fast_shutdown=0is a recommended step in In-Place Upgrade.Incompatible change: MySQL 5.7.8 and 5.7.9 undo logs may contain insufficient information about spatial columns, which could result in a upgrade failure (Bug #21508582). Before performing an in-place upgrade from MySQL 5.7.8 or 5.7.9 to 5.7.10 or higher, perform a slow shutdown using
innodb_fast_shutdown=0to clear the undo logs. A slow shutdown usinginnodb_fast_shutdown=0is a recommended step in In-Place Upgrade.Incompatible change: MySQL 5.7.8 undo logs may contain insufficient information about virtual columns and virtual column indexes, which could result in a upgrade failure (Bug #21869656). Before performing an in-place upgrade from MySQL 5.7.8 to MySQL 5.7.9 or higher, perform a slow shutdown using
innodb_fast_shutdown=0to clear the undo logs. A slow shutdown usinginnodb_fast_shutdown=0is a recommended step in In-Place Upgrade.Incompatible change: As of MySQL 5.7.9, the redo log header of the first redo log file (
ib_logfile0) includes a format version identifier and a text string that identifies the MySQL version that created the redo log files. This enhancement changes the redo log format, requiring that MySQL be shutdown cleanly using aninnodb_fast_shutdownsetting of0or1before performing an in-place upgrade to MySQL 5.7.9 or higher. A slow shutdown usinginnodb_fast_shutdown=0is a recommended step in In-Place Upgrade.In MySQL 5.7.9,
DYNAMICreplacesCOMPACTas the implicit default row format forInnoDBtables. A new configuration option,innodb_default_row_format, specifies the defaultInnoDBrow format. Permitted values includeDYNAMIC(the default),COMPACT, andREDUNDANT.After upgrading to 5.7.9, any new tables that you create use the row format defined by
innodb_default_row_formatunless you explicitly define a row format (ROW_FORMAT).For existing tables that do not explicitly define a
ROW_FORMAToption or that useROW_FORMAT=DEFAULT, any operation that rebuilds a table also silently changes the row format of the table to the format defined byinnodb_default_row_format. Otherwise, existing tables retain their current row format setting. For more information, see Defining the Row Format of a Table.Beginning with MySQL 5.7.6, the
InnoDBstorage engine uses its own built-in (“native”) partitioning handler for any new partitioned tables created usingInnoDB. PartitionedInnoDBtables created in previous versions of MySQL are not automatically upgraded. You can easily upgrade such tables to useInnoDBnative partitioning in MySQL 5.7.9 or later using either of the following methods:To upgrade an individual table from the generic partitioning handler to
InnoDBnative partitioning, execute the statementALTER TABLE.table_nameUPGRADE PARTITIONINGTo upgrade all
InnoDBtables that use the generic partitioning handler to use the native partitioning handler instead, run mysql_upgrade.
Incompatible change: The
GET_LOCK()function was reimplemented in MySQL 5.7.5 using the metadata locking (MDL) subsystem and its capabilities have been extended:Previously,
GET_LOCK()permitted acquisition of only one named lock at a time, and a secondGET_LOCK()call released any existing lock. NowGET_LOCK()permits acquisition of more than one simultaneous named lock and does not release existing locks.Applications that rely on the behavior of
GET_LOCK()releasing any previous lock must be modified for the new behavior.The capability of acquiring multiple locks introduces the possibility of deadlock among clients. The MDL subsystem detects deadlock and returns an
ER_USER_LOCK_DEADLOCKerror when this occurs.The MDL subsystem imposes a limit of 64 characters on lock names, so this limit now also applies to named locks. Previously, no length limit was enforced.
Locks acquired with
GET_LOCK()now appear in the Performance Schemametadata_lockstable. TheOBJECT_TYPEcolumn saysUSER LEVEL LOCKand theOBJECT_NAMEcolumn indicates the lock name.A new function,
RELEASE_ALL_LOCKS()permits release of all acquired named locks at once.
For more information, see Section 12.14, “Locking Functions”.
The optimizer now handles derived tables and views in the
FROMclause in consistent fashion to better avoid unnecessary materialization and to enable use of pushed-down conditions that produce more efficient execution plans.However in MySQL 5.7 before MySQL 5.7.11, and for statements such as
DELETEorUPDATEthat modify tables, using the merge strategy for a derived table that previously was materialized can result in anER_UPDATE_TABLE_USEDerror:mysql> DELETE FROM t1 -> WHERE id IN (SELECT id -> FROM (SELECT t1.id -> FROM t1 INNER JOIN t2 USING (id) -> WHERE t2.status = 0) AS t); ERROR 1093 (HY000): You can't specify target table 't1' for update in FROM clauseThe error occurs when merging a derived table into the outer query block results in a statement that both selects from and modifies a table. (Materialization does not cause the problem because, in effect, it converts the derived table to a separate table.) The workaround to avoid this error was to disable the
derived_mergeflag of theoptimizer_switchsystem variable before executing the statement:SET optimizer_switch = 'derived_merge=off';The
derived_mergeflag controls whether the optimizer attempts to merge subqueries and views in theFROMclause into the outer query block, assuming that no other rule prevents merging. By default, the flag isonto enable merging. Setting the flag tooffprevents merging and avoids the error just described. For more information, see Section 8.2.2.4, “Optimizing Derived Tables and View References with Merging or Materialization”.Some keywords may be reserved in MySQL 5.7 that were not reserved in MySQL 5.6. See Section 9.3, “Keywords and Reserved Words”. This can cause words previously used as identifiers to become illegal. To fix affected statements, use identifier quoting. See Section 9.2, “Schema Object Names”.
After upgrading, it is recommended that you test optimizer hints specified in application code to ensure that the hints are still required to achieve the desired optimization strategy. Optimizer enhancements can sometimes render certain optimizer hints unnecessary. In some cases, an unnecessary optimizer hint may even be counterproductive.
In
UNIONstatements, to applyORDER BYorLIMITto an individualSELECT, place the clause inside the parentheses that enclose theSELECT:(SELECT a FROM t1 WHERE a=10 AND B=1 ORDER BY a LIMIT 10) UNION (SELECT a FROM t2 WHERE a=11 AND B=2 ORDER BY a LIMIT 10);Previous versions of MySQL may permit such statements without parentheses. In MySQL 5.7, the requirement for parentheses is enforced.