All Products
Search
Document Center

PolarDB:Best practices

Last Updated:Apr 26, 2024

This topic describes the benefits, precheck items, and compatibility description for the upgrade from PolarDB for MySQL 5.6 and 5.7 and MySQL 5.6 and 5.7 to PolarDB for MySQL 8.0.

Overview of PolarDB for MySQL 8.0

  • Release dates

    • PolarDB for MySQL 8.0.1 was released on December 3, 2019.

    • PolarDB for MySQL 8.0.2 was released on July 22, 2020.

  • Benefits

    PolarDB for MySQL 8.0 enhances the architecture and kernel capabilities, brings more flexible technical solutions for business processing, and provides a significant improvement in performance. For more information, see Features in PolarDB for MySQL 8.0.

Compatibility precheck

During the upgrade from PolarDB for MySQL 5.6 and 5.7 and MySQL 5.6 and 5.7 to PolarDB for MySQL 8.0, you may encounter issues related to performance, syntax compatibility, and support for peripheral components. Query performance issues are caused by changes in the execution plans because of the optimizer upgrade. To resolve such issues, you need to optimize the specific statements with low performance. Performance issues alone do not lead to business errors or require code rewriting. Therefore, performance issues are not discussed in this topic.

This topic focuses on compatibility issues that require updates of code or environment configurations during the database upgrade. The main causes of such issues are changes in syntax and feature update or removal after the version upgrade. If no such issues exist, skip the following sections and directly perform the upgrade. For more information, see Procedure.

This section provides a brief checklist to help you better understand the issues that you must pay attention to in the upgrade process before you perform the upgrade. If issues are found based on the following checklist, resolve the issues by referring to the subsequent sections.

  • Make sure that no discontinued data types, functions, or features are in use. For more information about the list of discontinued items, see Features Removed in MySQL 8.0.

  • Make sure that the triggers are free of missing definers, empty definers, or invalid content.

  • Make sure that only partitioned tables of the InnoDB storage engine are available.

  • Make sure that no names conflict with keywords or reserved words. For more information, see Keywords and Reserved Words.

  • Make sure that no names conflict with system databases in MySQL 5.6 and 5.7 and new data dictionary tables whose names start with INNODB_ in MySQL 8.0.

  • Make sure that no items depend on the GLOBAL, LOCAL, VARIABLES, or STATUS table within INFORMATION_SCHEMA.

  • Make sure that no discontinued variable settings are used in sql_mode. For more information, see the Parameter compatibility section of this topic.

  • Make sure that a single ENUM or SET column element does not exceed 255 characters or 1,020 bytes in length in tables and stored procedures.

  • Make sure that no table partitions reside in shared InnoDB tablespaces.

  • Make sure that the GROUP BY clauses in SQL query statements do not contain ASC or DESC.

    Note

    In version 8.0.2.2.11.1 or later, you can set the loose_group_by_compatible_sorting parameter to TRUE in the PolarDB for MySQL console to enable the compatibility mode. In this mode, you can use GROUP BY clauses that contain ASC or DESC. For more information about how to configure parameters in the PolarDB for MySQL console, see Configure cluster and node parameters.

  • Make sure that the name of a foreign key constraint does not exceed 64 characters in length.

Note
  • To enhance support for Unicode, we recommended that you change the character set used by objects from utf8mb3 (discontinued) or utf8 (alias for the utf8mb3 character set) to utf8mb4. For more information, see The utf8mb3 Character Set (3-Byte UTF-8 Unicode Encoding).

  • A backup is required before the upgrade in case other issues occur during the upgrade.

Storage engine and partitioned table compatibility

If you create a MyISAM partition in version 8.0, the statement fails because this storage engine is not supported, and the ER_CHECK_NOT_IMPLEMENTED error is reported. For more information about how to convert tables from MyISAM to InnoDB, see Converting Tables from MyISAM to InnoDB.

The storage engine supports partition handlers, and the server no longer supports generic engine partitions.

InnoDB also provides native partition handlers that are supported only in version 8.0. Before you upgrade the server, you must convert partitioned tables from other storage engines to InnoDB or delete the partitioned tables. Otherwise, the partitioned tables cannot be used after the upgrade. Convert similar partitions to InnoDB in advance before the upgrade. Run the following statement to check the storage engine:

SELECT TABLE_SCHEMA, TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE ENGINE NOT IN ('innodb','ndbcluster') AND CREATE_OPTIONS LIKE '%partitioned';

You can also use the following syntax:

SELECT DISTINCT NAME,SPACE,SPACE_TYPE FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES
WHERE NAME LIKE '%#P#%' AND SPACE_TYPE NOT LIKE 'Single';

Run the following statement to change the storage engine to InnoDB:

ALTER TABLE part ENGINE = INNODB;
Query OK, 0 rows affected (0.09 sec)

Run the following statement to delete a partitioned table:

ALTER TABLE part REMOVE PARTITIONING;
Query OK, 0 raws affected (0.06 sec)

If you use mysqldump to import data from a dump file created on a MySQL 5.6 or 5.7 server to a MySQL 8.0 server, make sure that no unsupported storage engines are specified in statements for partitioned table creation. To meet this requirement, you can delete all references to partitions, specify the storage engine to InnoDB, or set the default_storage_engine parameter to InnoDB. For more information about how to identify the partitioned tables that you must change before the upgrade to MySQL 8.0, see Preparing Your Installation for Upgrade. For more information about partition limits, see Storage-related partition limits.

Character set and collation compatibility

The default character set for MySQL 8.0 is utf8mb4. For MySQL 8.0 and PolarDB for MySQL, the character_set_server parameter is set to utf8 by default. You can change the value based on your business requirements. To support Unicode, we recommend that you change the character set from utf8mb3 to utf8mb4. For more information, see The utf8mb3 Character Set (3-Byte UTF-8 Unicode Encoding).

In MySQL 8.0, the default_collation_for_utf8mb4 parameter is added, which specifies the default collation when the character set is utf8mb4. The default value of this parameter is utf8mb3_0900_ai_ci, which is an internal collation that is used by replication in MySQL.

If you have not encountered the illegal mix of collations error when you synchronize data from an earlier version to a later version, we recommend that you do not change the default value to utf8mb4_general_ci or utf8mb4_0900_ai_ci.

  • utf8mb4_0900_ai_ci: performs general sorting and comparison based on official Unicode rules. The accuracy is high, but comparison is slow.

  • utf8mb4_general_ci: provides a simplified set of sorting rules to accelerate the comparison. Although the Unicode rules are not followed, the results meet expectations under the same circumstances.

Different from character sets, collations are related only to sorting. In the name of a collation, ai indicates that the collation is not accent-sensitive. For example, e, è, é, ê, and e are considered as the same character during sorting. ci indicates that the collation is not case-sensitive. For example, p and P are considered the same character during sorting.

Note
  • Compatibility issues may occur during reverse synchronization from version 8.0 to an earlier version or synchronization in dump mode.

  • In two-way synchronization between earlier and later versions by using Data Transmission Service (DTS), exceptions are likely to occur. You must use the default sorting character set for MySQL 5.6 and 5.7 and PolarDB for MySQL 5.6 and 5.7. Otherwise, exceptions may occur during reverse synchronization.

  • Due to the collation issues, the illegal mix of collations error may be reported when you create a view. For example, when you use convert(a.c1 using utf8mb4)=b.c1, the preceding error may be reported.

  • If you use convert(exp using utf8mb4) and do not specify a collation, MySQL queries data based on utf8mb4, and the return value of charset number is 255. The collation that corresponds to 255 is the default utf8mb4_0900_ai_ci for MySQL 8.0.

  • The collation does not take effect when you modify the default_collation_for_utf8mb4 parameter or specify a column name, table name, or database name in DDL statements. If you need to use the convert function, add a collation. Example: (convert(a.c1 using utf8mb4)collate utf8mb4_general_ci)=b.c1.

  • Issues occur if you change the default value of the default_collation_for_utf8mb4 parameter. For example, if you change the default value to utf8mb4_general_ci, the following issues occur:

    • The sys database and its related functions cannot be correctly read, and the error illegal mix of collations(utf8mb4_0900_ai_ci.IMPLICIT) and (utf8mb4_general_ci.IMPLICIT) for operation'=' is reported.

    • The upgrade from 8.0.1 to 8.0.2 fails. This parameter is added in version 8.0. We recommend that you do not modify this parameter. If you must use a different value, go to the Quota Center console and click Apply in the Actions column for the default_collation_for_utf8mb4 quota to reset the default value to utf8mb4_0900_ai_ci. After the upgrade is complete, change the default value to utf8mb4_general_ci.

Parameter compatibility

lower_case_table_names

Since MySQL 8.0.11, it is prohibited to use a value of the lower_case_table_names parameter that is different from that defined during server initialization to start the server. The collations used by various data dictionaries and table fields are based on the lower_case_table_names value that is defined during server initialization. If the server is restarted with a different value, inconsistencies are introduced in the way identifiers are sorted and compared. In PolarDB for MySQL 8.0, the case sensitivity of clusters cannot be changed after initialization. You must select whether a PolarDB for MySQL 8.0 cluster is case-sensitive when you purchase the cluster. For more information about the lower_case_table_names parameter, see lower_case_table_names.

sql_mode

To prevent startup failures for clusters of version 8.0, delete all clusters from system variable sql_mode in the MySQL option file by using the NO_AUTO_CREATE_USER option.

Do not define obsolete SQL modes in the system variable. Otherwise, sql_mode may result in many different behaviors. Confirmation and alignment are required during the version upgrade. The following options must be deleted:

DB2, MAXDB, MSSDL, MYSQL323, MYSQL40, ORACLE, POSTGRESQL, NO_FIELD_OPTIONS, NO_KEY_OPTI
Note

In most cases, the preceding options are configured in a combined way. You must pay attention to whether inconsistent mode options exist. Example:

  • sql_mode=TRADITIONAL is equivalent to the combination of the following options:

    STRICT_TRANS_TABLES, STRICT_ALL_TABLES, NO_ZERO_IN_DATE, NO_ZERO_DATE, ERROR_FOR_DIVISIC
  • When the default configurations are used for PolarDB for MySQL 5.6 and 5.7 and MySQL 5.6 and 5.7, sql_mode=TRADITIONAL is equivalent to the combination of the following options:

    STRICT_TRANS_TABLES, STRICT_ALL_TABLES, NO_ZERO_IN_DATE, NO_ZERO_DATE,
    ERROR_FOR_DIVISIC_BY_ZERO, NO_AUTO_CREATE_USER, and NO_ENGINE_SUBSTITUTION

Based on the comparison of the preceding options, the NO_AUTO_CREATE_USER option is added in versions 5.6 and 5.7. In version 8.0, you are prohibited from executing GRANT statements to implicitly create accounts. Although the NO_AUTO_CREATE_USER option is added in versions 5.6 and 5.7, you can use GRANT to create accounts when identified by is specified.

If queries of existing applications are rejected after the ONLY_FULL_GROUP_BY option is enabled, you can use the following methods to resolve the issue:

  • If you can modify the queries, remove the non-aggregate columns from the SELECT projection, HAVING condition, or ORDER BY list that are neither in GROUP BY columns nor have any functional relationship with GROUP BY columns. Alternatively, you can use the ANY_VALUE() function.

  • If you cannot modify the queries, such as the queries that are generated by third-party applications, set the system variable sql_mode to not enable ONLY_FULL_GROUP_BY during server startup.

    For example, if the description column is not specified in the GROUP BY clause and no aggregate function such as MIN or MAX is applied, the following results are returned:

    Version 5.6:

    SELECT id, invoice_id, description FROM invoice_line_items GROUP BY invoice_id;
    +----+------------+-------------+
    | id | invoice_id | description |
    +----+------------+-------------+
    | 1 | 1 | New socks |
    | 3 | 2 | Shoes |
    | 5 | 3 | Tie |
    +----+------------+-------------+
    3 rows in set (0.00 sec)

    Version 8.0:

    SELECT id, invoice_id, description FROM invoice_line_items GROUP BY invoice_id;
    ERROR 1055 (42000): Expression #3 of SELECT list is not in GROUP BY clause and contains

explicit_defaults_for_timestamp

Since MySQL 8.0, the default value of the explicit_defaults_for_timestamp parameter is changed from OFF to ON. In PolarDB for MySQL 8.0, the default value of this parameter is OFF, which is the same as that in versions 5.6 and 5.7.

If you do not want NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP to be automatically added during the migration, you must set this parameter to ON.

MySQL uses the following non-standard behavior for the TIMESTAMP type if the explicit_defaults_for_timestamp parameter is set to OFF:

  • If the NULL attribute is not explicitly defined for a column of the TIMESTAMP type, NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP is automatically added. If the NULL attribute is explicitly defined, it is retained.

mysql> set explicit_defaults_for_timestamp = OFF;
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> create table t1(c1 timestamp);
Query OK, 0 rows affected (0.01 sec)

mysql> show create table t1;
+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| t1 | CREATE TABLE `t1` (
 `c1` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci |
+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> drop table t1;
Query OK, 0 rows affected (0.01 sec)

mysql> create table t1(c1 int, c2 timestamp null);
Query OK, 0 rows affected (0.01 sec)

mysql> show create table t1;
+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------+
| t1 | CREATE TABLE `t1` (
 `c1` int(11) DEFAULT NULL,
 `c2` timestamp NULL DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci |
+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
  • For the first column of the TIMESTAMP type that is defined in a table, either the NULL, DEFAULT, or ON UPDATE attribute is explicitly defined, or the DEFAULT CURRENT_TIMESTAMP and ON UPDATE CURRENT_TIMESTAMP attributes are automatically added.

  • For the second column of the TIMESTAMP type that is defined in a table, if the sql_mode parameter is not set to NO_ZERO_DATE and the NULL or DEFAULT attribute is not explicitly defined, DEFAULT '0000-00-00 00:00:00' is automatically defined.

    mysql> set sql_mode = '';
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> create table t1(c1 timestamp, c2 timestamp);
    Query OK, 0 rows affected (0.01 sec)
    
    mysql> show create table t1;
    +-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | Table | Create Table |
    +-------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | t1 | CREATE TABLE `t1` (
     `c1` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
     `c2` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00'
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci |
    +-------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    1 row in set (0.00 sec)

    If the sql_mode parameter is set to NO_ZERO_DATE to enable the strict mode, the following error is reported:

    mysql> create table t1(c1 timestamp, c2 timestamp);
    ERROR 1067 (42000): Invalid default value for 'c2'
    mysql> create table t1(c1 timestamp, c2 timestamp);

If the explicit_defaults_for_timestamp parameter is set to ON, the preceding non-standard behavior is discontinued, and the behavior for the TIMESTAMP type is the same as that for other types.

View, table, and keyword compatibility

Compatibility with InnoDB-related views

The views based on InnoDB system tables in INFORMATION_SCHEMA are replaced with internal system views on data dictionary tables. The views that affect INFORMATION_SCHEMA of InnoDB are renamed. If you access the InnoDB-related views in a system application, check whether the views have been modified in the application. For more information about INFORMATION_SCHEMA, see INFORMATION_SCHEMA Tables.

Renamed InnoDB information schema views

Old name

New name

INNODB_SYS_COLUMNS

INNODB_COLUMNS

INNODB_SYS_DATAFILES

INNODB_DATAFILES

INNODB_SYS_FIELDS

INNODB_FIELDS

INNODB_SYS_FOREIGN

INNODB_FOREIGN

INNODB_SYS_FOREIGN_COLS

INNODB_FOREIGN_COLS

INNODB_SYS_INDEXES

INNODB_INDEXES

INNODB_SYS_TABLES

INNODB_TABLES

INNODB_SYS_TABLESPACES

INNODB_TABLESPACES

INNODB_SYS_TABLESTATS

INNODB_TABLESTATS

INNODB_SYS_VIRTUAL

INNODB_VIRTUAL

Make sure that no views in MySQL 5.6 and 5.7 or PolarDB for MySQL 5.6 and 5.7 use the same names as the views that are added in PolarDB for MySQL 8.0. Execute the following statement in a MySQL 5.7 or PolarDB for MySQL 5.7 cluster. If any information is returned, determine how to process such tables. We recommend that you perform this check when you migrate a self-managed cluster to the cloud for upgrade.

'indexes',
'parameter_type_elements',
'parameters',
'resource_groups',
'routines',
'schemate',
'st_spatial_reference_systems',
'table_partition_systems',
'table_partition_values',
'table_partitions',
'table_states',
'tables',
'tablespace_files',
'tablespaces',
'triggers',
'view_routine_usage'
);

suppose
+--------------+--------------+
| TABLE_SCHEMA |  TABLE_NAME  |
+--------------+--------------+
|     mysql    |   catalogs   |
+--------------+--------------+
1 rows in set (0.00 sec)

Execute the following statement in a MySQL 5.6 or 5.7 cluster. If any information is returned, determine how to process such tables. We recommend that you perform this check when you migrate a self-managed cluster to the cloud for upgrade.

SELECT TABLE_SCHEMA, TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE LOWER(TABLE_SCHEMA) = 'mysql'
and LOWER(TABLE_NAME) IN
(
'catalogs',
'character_sets',
'check_constraints',
'collations',
'column_statistics',
'column_type_elements',
'columns',
'dd_properties',
'events',
'foreign_key_column_usage',
'foreign_keys',
'index_column_usage',
'index_partitions',
'index_stats',
'indexes',
'parameter_type_elements',
'parameters',
'resource_groups',
'routines',
'schemata',

The user tables that are returned must be renamed or deleted before the upgrade. Execute the following statement to rename a user table:

ALTER TABLE catalogs RENAME user_catalogs;
Query OK, 0 rows affected (0.05 sec)

Execute the following statement to delete a user table:

DROP TABLE catalogs;
Query OK, 0 rows affected (0.06 sec)

View compatibility

In versions earlier than MySQL 8.0, the name of a display column in a view can contain up to 255 characters. To comply with the requirements for the maximum length of a column name, MySQL 8.0 does not support views in which the name of a display column exceeds 64 characters. You can identify these views only by executing the SHOW CREATE VIEW statement in MySQL 5.6 and 5.7.

SHOW CREATE VIEW v1;
+------+------------------------------------------------------------------------------------------------
| View | Create View
+------+------------------------------------------------------------------------------------------------
|  v1  | CREATE ALGORITHM=UNDEFINED DEFINER='root'@'localhost' SQL SECURITY DEFINER VIEW
+------+------------------------------------------------------------------------------------------------
1 row in set (0.00 sec)

You must rename the views before the upgrade to version 8.0.

ALTER VIEW v1(a12345678901234567890) AS SECLECT 1;

Compatibility with system tables in version 5.6

The Password column is deleted from the mysql.user system table in versions later than MySQL 5.7.6 and 8.0. All credentials are stored in the authentication_string column, including data that was stored in the Password column in earlier versions.

Compatibility with tables that contain system and status variables in INFORMATION_SCHEMA of version 5.6

Tables that contain system and status variables in INFORMATION_SCHEMA of MySQL 5.6 and PolarDB for MySQL 5.6 are discontinued in version 8.0. The following tables are discontinued:

INFORMATION_SCHEMA.GLOBAL_VARIABLES
INFORMATION_SCHEMA.SESSION_VARIABLES
INFORMATION_SCHEMA.GLOBAL_STATUS
INFORMATION_SCHEMA.SESSION_STATUS

In version 8.0, the preceding discontinued tables are migrated to PERFORMANCE_SCHEMA.

performance_schema.global_variables
performance_schema.session_variables
performance_schema.variables_by_thread
performance_schema.global_status
performance_schema.session_status
performance_schema.status_by_thread
performance_schema.status_by_account
performance_schema.status_by_host
performance_schema.status_by_user

We recommend you run the SHOW command instead of directly using the corresponding views.

SHOW VARIABLES
SHOW STATUS

Compatibility with InnoDB tables in version 5.6

The implicit default row format for InnoDB tables is changed to DYNAMIC from COMPACT. The innodb_default_row_format parameter specifies the default InnoDB row format. The COMPACT (default) and REDUNDANT values can be changed to DYNAMIC. After the upgrade to version 8.0, any new tables that you create use the defined row format unless you explicitly specify the ROW_FORMAT option. If the ROW_FORMAT option is not explicitly specified or ROW_FORMAT=DEFAULT is used, an operation that rebuilds a table changes the row format of the table to the format specified by the innodb_default_row_format parameter. For more information, see Defining the Row Format of a Table.

Compatibility with the GET_LOCK function in version 5.6

The GET_LOCK() function is re-implemented by using the metadata locking (MDL) subsystem in MySQL 5.7.5 or later, and its features have been extended.

  • In earlier versions, the GET_LOCK() function can be called to obtain only one named lock at a time, and all existing locks are released when the GET_LOCK() function is called the second time. In version 8.0, you can call the GET_LOCK() function to obtain multiple named locks at a time and no existing locks are released.

    Modification is required to any application that depends on the GET_LOCK() function to release all previous locks.

  • The capability of obtaining multiple locks may introduce deadlocks among clients. The MDL subsystem checks for deadlocks and reports the ER_USER_LOCK_DEADLOCK error if a deadlock is detected.

  • The MDL subsystem enforces a maximum length of 64 characters on lock names. This restriction also applies to named locks. This length restriction is not enforced in earlier versions.

  • The locks obtained by using the GET_LOCK() function now appear in Performance Schema metadata_locks. The value of the OBJECT_TYPE column is USER LEVEL LOCK, and the OBJECT_NAME column indicates the lock name.

  • In version 8.0, you can call the RELEASE_ALL_LOCKS() function to release all the obtained named locks at a time.

For more information, see Locking Functions.

Type compatibility

ENUM and SET types

A single ENUM or SET column element in tables or stored procedures cannot exceed 255 characters or 1,020 bytes in length.

YEAR type in version 5.6

The YEAR(2) type is discontinued. You must replace YEAR(2) with YEAR(4).

Type data insertion in version 5.6

  • If a negative value is inserted into an unsigned column, an error is reported. Example:

    1. Create a table that contains an unsigned column.

       CREATE TABLE test (id int unsigned);
    2. Insert a negative value.

      INSERT INTO test VALUES (-1);
      • The following result is returned in version 5.6:

        Query OK, 1 row affected, 1 warning (0.01 sec)
      • The following result is returned in version 8.0:

        ERROR 1264 (22003): Out of range value for column 'a' at row 1
  • If a value is divided by zero, an error is reported. Example:

    1. Create a test table.

      CREATE TABLE test2 (id int unsigned);
    2. Divide a value by zero.

      INSERT INTO test2 VALUES (0/0);
      • The following result is returned in version 5.6:

        Query OK, 1 row affected (0.01 sec)
      • The following result is returned in version 8.0:

        ERROR 1365 (22012): Division by 0
  • If the number of characters that are inserted into a column exceeds the upper limit, an error is reported. Example:

    1. If you insert a string that contains 20 characters into a 10-character column, an error is reported. Create a table that contains a 10-character column.

      CREATE TABLE test3 (a varchar(10));
    2. Insert a string that contains more than 10 characters.

      INSERT INTO test3 VALUES ('abcdefghijklmnopqrstuvwxyz');
      • The following result is returned in version 5.6:

        Query OK, 1 row affected, 1 warning (0.00 sec)
      • The following result is returned in version 8.0:

        ERROR 1406 (22001): Data too long for column 'a' at row 1
  • If a non-standard zero date is inserted into a datetime column, an error is reported. Example:

    1. Create a table that contains a datetime column.

      CREATE TABLE test3 (a datetime);
    2. Insert 0000-00-00 00:00:00.

      INSERT INTO test3 VALUES ('0000-00-00 00:00:00');
      • The following result is returned in version 5.6:

        Query OK, 1 row affected, 1 warning (0.00 sec)
      • The following result is returned in version 8.0:

        ERROR 1292 (22007): Incorrect datetime value: '0000-00-00 00:00:00' for column 'a' at ro

Changes to data of the INT type in JSON of version 5.7

The .0 suffix is added to some values of the INT type. Examples: 1.0 and 9999.0. It is preliminarily confirmed that it is because version 5.7 and version 8.0 use different methods of double-precision processing for the data in JSON. DTS data verification is required to resolve this issue. You can configure data verification on the DTS task configuration page if necessary.

Legacy types in version 5.x

Data types such as legacy DECIMAL, legacy VARCHAR, and legacy TIME/DATETIME and TIMESTAMP are obsolete in MySQL 5.0, 5.1, and 5.6. Binary upgrades are only available in MySQL 5.6 and 5.7 and are not supported in MySQL 8.0. You can identify these tables by running the CHECK TABLE...FOR UPGRADE command in MySQL 5.6 and 5.7 before the upgrade or by using mysqlcheck with the check-upgrade option. In addition, you can identify the tables that use legacy TIME/DATETIME and TIMESTAMP by enabling session variables.

check table 41_decimal for upgrade;
+-----------------+-------+----------+------------------------------------------------
| Table           | Op    | Msg_type | Msg_text                                         
+-----------------+-------+----------+------------------------------------------------
| test.41_decimal | check | error    | Table upgrade required for `test`.`41_decimal`. 
+-----------------+-------+----------+-------------------------------------------------
1 row in set (0.00 sec) 
check table 55_temporal for upgrade;
+------------------+-------+----------+------------------------------------------------
| Table            | Op    | Msg_type | Msg_text                                        
+------------------+-------+----------+------------------------------------------------
| test.55_temporal | check | error    | Table upgrade required. Please do "REPAIR TABLE 
1 row in set (0.00 sec) 
nisha@nisha-PORTEGE-Z30-A:~/workspace1/mysql-5.7/dbg-5.7/client/mysqlcheck --user=root 
error    : Table upgrade required for `test`.`41_decimal`. Please dump/reload table to 
test.55_temporal
error    : Table upgrade required. Please do "REPAIR TABLE `55_temporal`" or dump/reloa
test.child                                         OK
test.geom                                          OK
test.jemp                                          OK
test.jemp_myisam                                   OK
test.opening_lines                                 OK

Tables that use such data types cannot be upgraded. In this case, execute the REPAIR TABLE statement to repair the tables and perform dumping and reloading for legacy VARCHAR and legacy DECIMAL.

REPAIR TABLE 55_temporal; 
+------------------+--------+----------+---------------------------------------------------
| Table            | Op     | Msg_type | Msg_text                                          
+------------------+--------+----------+---------------------------------------------------
| test.55_temporal | repair | Note     | TIME/TIMESTAMP/DATETIME columns of old format have
| test.55_temporal | repair | status   | OK                                                
+------------------+--------+----------+---------------------------------------------------
2 rows in set (0.01)
Dump:
$./client/mysqldump --databases test --socket=5.6/data/mysql.sock --user=root>test.sql
Restore:
.\ test.sql

Keywords and reserved words

In PolarDB for MySQL 8.0, you can view the keywords and reserved words that are used in the current version in the information_schema.KEYWORDS table. Make sure that no names conflict with these keywords or reserved words. Some previously unreserved keywords may be reserved in PolarDB for MySQL 8.0. For more information, see Keywords and Reserved Words. We recommend that you do not use keywords or reserved words in all custom content, such as table names, field names, and function names. In addition, KICKOUT is a reserved keyword in PolarDB for MySQL 8.0. If you have used this keyword as an object name, such as a table name, field name, or stored procedure name, in MySQL 5.6, MySQL 5.7, or native MySQL 8.0, we recommend that you change the object name before the migration to PolarDB for MySQL 8.0. Otherwise, a syntax error with error code 1064 is reported.

SQL compatibility

GRANT authorization

In MySQL 8.0.11, some discontinued features related to account management are deleted, such as the feature for using the GRANT statement to modify non-privileged features of user accounts.

GRANT REPLICATION CLIENT ON *.* TO 'odps'@'%'; You are not allowed to create a user with
create user;
grant privielges;

GROUP BY clauses that contain ASC or DESC

Since MySQL 8.0.13, the ASC or DESC qualifiers that are not recommended for GROUP BY clauses have been deleted. Queries that previously relied on GROUP BY sorting may produce results that differ from those in previous MySQL versions. To produce a given sort order, you must rewrite GROUP BY clauses. Example:

Original SQL statement:

select id,count(*) from sbtest.sbtest1 where id < 10 group by id desc

Rewritten SQL statement:

select id,count(*) from sbtest.sbtest1 where id < 10 group by id order by id
Note

In PolarDB for MySQL 8.0.2.2.11.1 or later, you do not need to rewrite GROUP BY clauses. To use GROUP BY clauses that contain ASC or DESC, you need to only set the loose_group_by_compatible_sorting parameter to TRUE in the PolarDB for MySQL console. For more information about how to configure parameters in the PolarDB for MySQL console, see Configure cluster and node parameters.

Foreign key constraint definition

In MySQL 5.6 and 5.7, the definition of InnoDB FOREIGN KEY cannot contain the CONSTRAINT keyword, and the name of a foreign key constraint cannot exceed 64 characters in length. In versions earlier than MySQL 8.0, if you do not explicitly specify a name for a foreign key constraint, InnoDB automatically generates a foreign key constraint name by appending _ibfk_X to the table name, in which X is a number. For a multi-byte 64-character table name, such as the Silil table name имя_базы_в_кодировке_утф8_длиной_больше_чем_45имя_азы_в_кодировк that is used in the following example, the automatically generated name of the foreign key constraint will consist of more than 64 characters in length. To change these tables, add a constraint with an explicit constraint name that does not exceed 64 characters in length.

ALTER TABLE `имя_базы_в_кодировке_утф8_длиной_больше_чем_45имя_азы_в_кодировк` DR
Query OK, 0 rows affected (0.01 sec)
Records: 0 Duplicates: 0 Warnings: 0
ALTER TABLE `имя_базы_в_кодировке_утф8_длиной_больше_чем_45имя_азы_в_кодировк` AD
Query OK, 0 rows affected (0.13 sec)
Records: 0 Duplicates: 0 Warnings: 0

Spatial functions in version 5.7

In MySQL 5.7, we recommend that you do not use spatial functions that are available under multiple names. Example:

CREATE TABLE t_gcol_dep (fid INTEGER NOT NULL PRIMARY KEY, g POINT GENERATED ALWA
Query OK, 0 rows affected, 1 warning (0.07 sec)
show warnings;
+---------+------+---------------------------------------------------------------------
| Level | Code | Message
+---------+------+---------------------------------------------------------------------
| Warning | 1287 | 'POINTFROMTEXT' is deprecated and will be removed in a future releas
+---------+------+---------------------------------------------------------------------
1 row in set (0.00 sec)

These spatial functions have been removed in version 8.0 because of the change to spatial function names. This change helps maintain the consistency of the naming convention. The functions whose names start with ST_ perform exact operations, whereas the functions whose names start with MBR perform operations based on minimum bounding rectangles. The columns that are generated by using these functions must be changed before the upgrade. For more information about the removed spatial functions, see Features Removed in MySQL 8.0. You need to change the columns to use functions whose names start with ST_ or MBR.

ALTER TABLE t_gcol_dep MODIFY g POINT GENERATED ALWAYS AS (ST_POINTFROMTEXT(POINT
Query OK, 0 rows affected (0.03 sec)
Records: 0 Duplicates: 0 Warnings: 0

Trigger compatibility

In versions earlier than MySQL 5.0.17, the CREATE TRIGGER statement does not support the definer attribute. This type of trigger definition with missing or empty definer attribute or invalid context, including character_set_client, collation_collection, and database collation attributes, causes an upgrade failure from MySQL 5.6 and 5.7. You can identify these triggers by running mysqlcheck with the check-upgrade option or the CHECK TABLE statement in MySQL 5.6 and 5.7.

$./client/mysqlcheck --user=root --socket=5.7/data/mysql.sock --databases triggers --ch
triggers.t1
Warning : No definer attribute for trigger 'triggers'.'trg_t1_before_insert'. The trig
Warning : No definer attribute for trigger 'triggers'.'t1_bi'. The trigger will be act
Warning : No definer attribute for trigger 'triggers'.'trg_t1_after_insert_1'. The tri
Warning : No definer attribute for trigger 'triggers'.'trg_t1_after_insert'. The trigg
Warning : No definer attribute for trigger 'triggers'.'trg_t1_after_insert_3'. The tri
Warning : No definer attribute for trigger 'triggers'.'trg_t1_before_update_3'. The tr
Warning : No definer attribute for trigger 'triggers'.'trg_t1_before_update'. The trig
Warning : No definer attribute for trigger 'triggers'.'trg_t1_after_update'. The trigg
Warning : No definer attribute for trigger 'triggers'.'trg1'. The trigger will be acti
status : OK
triggers.t2 OK
check table t1;
+-------------+-------+----------+-----------------------------------------------------
| Table | Op | Msg_type | Msg_text
+-------------+-------+----------+-----------------------------------------------------
| triggers.t1 | check | Warning | No definer attribute for trigger 'triggers'.'trg_t1_
| triggers.t1 | check | Warning | No definer attribute for trigger 'triggers'.'t1_bi'.
| triggers.t1 | check | Warning | No definer attribute for trigger 'triggers'.'trg_t1_
| triggers.t1 | check | Warning | No definer attribute for trigger 'triggers'.'trg_t1_
| triggers.t1 | check | Warning | No definer attribute for trigger 'triggers'.'trg_t1_
| triggers.t1 | check | Warning | No definer attribute for trigger 'triggers'.'trg_t1_

Dump or reload such triggers to resolve the issue.

Dump:
$./client/mysqldump --databases triggers --socket=5.6/data/mysql.sock --user=root>trigge
Restore:
.\ triggers.sql

Client compatibility

For Java applications, if MySQL Connector/J is upgraded to 8.0 or later, caching_sha2_password of MySQL Connector/J 8.0.9 or later is required for the connection accounts. If dataworks is not set to utf8 in the data source, an error may occur. We recommend that you change the database name. Add characterEncoding=utf8&com.mysql.jdbc.faultInjection.serverCharsetIndex= to the connection string to allow a Java client to explicitly specify a session-level character set in connections.

Compatibility with the unknown system variable tx_read_only

In MySQL and PolarDB for MySQL 8.0, the environment variable tx_read_only has been deleted. Use transaction_read_only instead.

Original statement:

 select @@tx_read_only

Rewritten statement:

select @@transaction_read_only

Common issues

Sorting issue caused by parallel queries

In version 8.0 or later, parallel queries are supported. Parallel scanning results in random change of the default order of MySQL serial scans each time because of random access to data, especially for the SQL statements for paged queries. To produce a given sort order, add an ORDER BY clause.

Issue related to subqueries in version 5.6

The ORDER BY clauses in subqueries in version 5.6 no longer work. Example:

SELECT *
FROM
(
SELECT * FROM `information_schema`. TABLES
ORDER BY table_name DESC
) AS sg
GROUP BY table_name

The ORDER BY clause at the inner layer will be ignored by the optimizer of versions 5.7 and 8.0. You need to modify the statement to resolve this issue. The simplest way is to add limit for the sorting to take effect. Example:

SELECT *
FROM
(
SELECT * FROM `information_schema`. TABLES
ORDER BY table_name DESC limit 10000 # The number of rows must be insufficient.
) AS sg
GROUP BY table_name

Issue related to derived tables inversion 5.6

The optimizer handles derived tables and views in clauses in the same way. It uses FROM to better prevent unnecessary materialization, which allows pushdown conditions and produces more efficient execution plans. However, in version 8.0 and table modification statements, the use of the merge policy in a DELETE statement on a derived table that was generated by using UPDATE may result in an ER_UPDATE_TABLE_USED error.

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 clause

If you merge derived tables into an outer query block, errors occur when you query or modify the tables. This issue is not caused by materialization because it actually converts a derived table into a separate table. A workaround to prevent this issue is to disable the derived_merge flag by using the optimizer_switch system variable before statement execution.

SET optimizer_switch = 'derived_merge=off';

The derived_merge flag specifies whether the optimizer attempts to merge the queries and views in FROM clauses into the outer query block. If no other rules block merging, this flag is set to on by default to enable merging. You can set the flag to off to block merging, which prevents the preceding issue. For more information, see Optimizing Derived Tables, View References, and Common Table Expressions with Merging or Materialization.

In a UNION statement, to apply ORDER BY or LIMIT to the separate SELECT query block, place the SELECT clause in parentheses (()):

(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);
Note

In version 8.0, parentheses (()) are required. Earlier MySQL versions may allow such statements without parentheses (()).

References

What Is New in MySQL 8.0

Changes in MySQL 8.0

Preparing Your Installation for Upgrade

Upgrading to MySQL 8.0? Here is what you need to know...

Differences among MySQL 5.6, MySQL 5.7, and MySQL 8.0: