本文介绍 PolarDB MySQL 版 的 5.6、5.7 版本和 MySQL 5.6、5.7 版本升级至 PolarDB MySQL 版 的 8.0 版本的优势、预检查以及兼容性说明等内容。
PolarDB MySQL 版 8.0 版本概述
-
版本发布日期
-
8.0.1 版本发布于 2019 年 12 月 3 日。
-
8.0.2 版本发布于 2020 年 7 月 22 日。
-
-
版本优势
8.0 版本增强了架构和内核能力,为用户处理业务提供了更灵活的技术解决方案,性能提升明显。详情请参见 功能特性 。
兼容性预检查
PolarDB MySQL 版 的 5.6、5.7 版本和 MySQL 5.6、5.7 版本向的 8.0 版本升级过程中,经常会遇到性能、语法兼容以及周边组件是否支持的问题。查询的性能问题一般是由于优化器升级导致执行计划有变化,此类问题需要对性能低下的语句进行针对性的性能优化,单独的性能问题基本不会引发业务报错以及代码改写的问题,此类问题不在本文讨论范围之内。
本文主要讨论兼容性问题,此类问题需要在数据库升级过程中,更新相应的代码或更改环境配置,引发此类问题的主要原因为版本升级后部分语法的变化以及特性的更新和移除。如果确保上述内容不存在问题,可以跳过下面章节进行升级,详情请参见 大版本一键升级 。
预检查功能会提供一个简要清单,帮助您在升级前更好地了解升级过程中可能需要注意的问题。如果下述内容存在对应的问题,请参考后续内容进行操作和检查。
-
确保没有使用废弃的数据类型、函数和功能,废弃清单信息请参见 Features Removed in MySQL 8.0 。
-
确保触发器(Triggers)没有丢失、空的 definer 或无效的内容。
-
确保只有 InnoDB 引擎的分区表。
-
确保关键字和保留关键字没有冲突,详情请参见 Keywords and Reserved Words 。
-
确保没有和 MySQL 5.6、5.7 版本的系统数据库、MySQL 8.0 版本新增的
INNODB_开头的词典表名冲突。 -
确保不依赖于
INFORMATION_SCHEMA下的GLOBAL、LOCAL、VARIABLES、STATUS表。 -
确保
sql_mode中没有使用废弃的变量设置,详情请参见 参数兼容性 。 -
确保表和存储过程单个
ENUM或SET列元素的长度不超过 255 个字符或 1020 个字节。 -
确保表的分区不在共享
InnoDB tablespaces表空间中。 -
确保查询 SQL 语句中的 GROUP BY 子句不带有 ASC 或 DESC。
说明8.0.2.2.11.1 版本及以上的版本,在控制台上将
loose_group_by_compatible_sorting参数的值设置为 TRUE 后可以开启兼容模式,兼容模式支持在 SQL 语句中使用带有 ASC 或 DESC 的 GROUP BY 子句。在控制台上设置参数值的操作步骤请参见 设置集群参数和节点参数 。 -
确保外键约束名称不超过 64 个字符。
-
为了增强 Unicode 的支持,推荐您将使用 utf8mb3(已废弃)或 utf8(utf8mb3 字符集的别名)字符集的对象更改为 utf8mb4 字符集。更多信息请参见 The utf8mb3 Character Set (3-Byte UTF-8 Unicode Encoding) 。
-
升级前需要进行备份,以避免升级过程中可能遇到的其他问题。
引擎和分区表兼容性
在
8.0
版本中,创建
MyISAM
类型的分区将导致使用没有此类型支持的存储引擎的分区表创建语句失败并出现错误
(ER_CHECK_NOT_IMPLEMENTED)
。有关将表从
MyISAM
转换至
InnoDB
引擎,请参见
将表从
MyISAM
转换为
InnoDB
。
存储引擎现支持分区处理程序,且服务器不再支持通用引擎分区。
InnoDB 还提供仅 8.0 版本支持的本机分区处理程序的存储引擎。您需要在升级服务器前,将其他存储引擎的分区表的存储引擎转换为 InnoDB 存储引擎,或删除对应分区表,否则后续将无法使用。如有类似分区,请您提前转换引擎后再进行升级。检查引擎语法如下:
SELECT TABLE_SCHEMA, TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE ENGINE NOT IN ('innodb','ndbcluster') AND CREATE_OPTIONS LIKE '%partitioned';
或:
SELECT DISTINCT NAME,SPACE,SPACE_TYPE FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES
WHERE NAME LIKE '%#P#%' AND SPACE_TYPE NOT LIKE 'Single';
将引擎更改为 InnoDB 引擎语法如下:
ALTER TABLE part ENGINE = INNODB;
Query OK, 0 rows affected (0.09 sec)
删除对应分区表语法如下:
ALTER TABLE part REMOVE PARTITIONING;
Query OK, 0 raws affected (0.06 sec)
如果使用
MySQLdump
从
MySQL 5.6、5.7
版本服务器创建的转储文件中将数据导入至 8.0
版本的服务器,需确保创建分区表的任何语句都没有同时指定不被支持的存储引擎,您可以通过删除对分区的全部引用、将存储引擎指定为
InnoDB
或允许将参数
default_storage_engine = InnoDB
设置为
InnoDB
的默认值的方法实现该要求。识别在升级到
MySQL 8.0
版本之前必须更改的分区表的方法请参见
为升级准备安装
。有关分区限制详细信息请参见
与存储有关的分区限制
。
字符集和排序规则兼容性
MySQL 8.0
版本的默认字符集为
utf8mb4。 MySQL 8.0
版本和
PolarDB MySQL
版
的
character_set_server
值均默认为
utf8,您可以根据业务需求进行调整。为支持
Unicode,推荐您将使用的
utf8mb3
字符集转换为使用
utf8mb4
字符集。详细信息请参见
utf8mb3
字符集
。
MySQL 8.0 版本新增 default_collation_for_utf8mb4 参数,该参数的作用为当字符集为 utf8mb4 时,根据默认排序规则排序,该参数的默认值为 utf8mb3_0900_ai_ci ,且该默认值只是 MySQL 中 replication 使用的内部参数。
若您在从低版本同步到高版本的过程中没有遇到
lllegal mix of collations
的错误,不建议您将该默认值修改为
utf8mb4_general_ci
或
utf8mb4_0900_ai_ci
。
-
utf8mb4_0900_ai_ci :基于官方 Unicode 的规则做通用的排序和比较,准确度高,但比对速度稍慢。
-
utf8mb4_general_ci :精简集合的排序规则,目的是提供简化的设计来加快比对速度,虽然没有遵循 Unicode 的规则,但在相同情况下结果符合预期。
排序规则和字符集不同,它只和排序有关,其中 ai 表示口音不敏感,即排序时 e,è,é,ê和ë之间没有区别;ci 表示不区分大小写,即排序时 p 和 P 之间没有区别。
-
在 8.0 版本向低版本反向同步或 dump 同步时,可能会存在兼容性问题。
-
在 DTS 低版本与高版本双向同步场景下容易出现异常,您需要使用 MySQL 5.6、5.7 和 PolarDB MySQL 版 5.6、5.7 版本默认的排序字符集,否则 DTS 反向同步的时候会出现异常。
-
由于排序规则问题,创建视图时可能会报错
lllegal mix of collations,例如当您使用了convert(a.c1 using utf8mb4)=b.c1时,可能会报上述错误。 -
当您使用 convert(exp using utf8mb4) 且不指定 collation 时,MySQL 会按照 utf8mb4 查询,返回的
charset number值为 255。255 对应的 collation 即为 MySQL 8.0 版本默认的utf8mb4_0900_ai_ci。 -
修改
default_collation_for_utf8mb4或在 DDL 中指定列名、表名或数据库名时, collation 都不会起作用。如果您需要使用convert函数,需要在语句中加入 collation,如(convert(a.c1 using utf8mb4)collate utf8mb4_general_ci)=b.c1。 -
修改
default_collation_for_utf8mb4参数的默认值,如将默认值修改为utf8mb4_general_ci,会导致出现如下问题:-
无法正确读取 SYS 库及其相关函数,报错
lllegal mix of collations(utf8mb4_0900_ai_ci.IMPLICIT) and (utf8mb4_general_ci.IMPLICIT) for operation'='。 -
从 8.0.1 版本升级到 8.0.2 时,升级失败。该参数是 8.0 版本新增加的参数,建议不要修改该参数,如果必须使用其他值,请在执行升级操作前,前往 配额中心 ,在配额名称为 default_collation_for_utf8mb4 的 操作 列,单击 申请 ,申请将参数的默认值重置为
utf8mb4_0900_ai_ci,升级完成后,需要将默认值再修改为utf8mb4_general_ci。
-
参数兼容性
lower_case_table_names
从
MySQL 8.0.11
版本开始,禁止
lower_case_table_names
使用与服务器初始化时不同的设置来启动服务器。各种数据字典、表字段使用的排序规则基于
lower_case_table_names
服务器初始化时定义的设置,使用不同的设置重新启动服务器时,会导致标识符的排序和比较方式引入不一致。在
PolarDB MySQL
版
8.0
版本中,集群区分大小写无法在初始化完成后再次更改,您需要在购买 8.0
版本的集群时选定集群是否区分大小写。关于
lower_case_table_names
参数详情请参见
lower_case_table_names
。
sql_mode
为避免
8.0
版本的集群启动失败,请通过
NO_AUTO_CREATE_USER
从
MySQL
选项文件的系统变量
sql_mode
设置中删除所有集群。
您的系统变量设置中不得定义过时的
SQL
模式,否则
sql_mode
会引起许多不同的行为,在版本升级时需要确认对齐。需要取消的配置项如下:
DB2, MAXDB, MSSDL, MYSQL323, MYSQL40, ORACLE, POSTGRESQL, NO_FIELD_OPTIONS, NO_KEY_OPTI
以上配置项大多为组合配置,需要注意是否有不一致的 mode 选项。例如:
-
sql_mode=TRADITIONAL等于配置如下项:STRICT_TRANS_TABLES, STRICT_ALL_TABLES, NO_ZERO_IN_DATE, NO_ZERO_DATE, ERROR_FOR_DIVISIC -
在 MySQL5.6、5.7 和 5.6、5.7 版本默认配置时,
sql_mode=TRADITIONAL等于配置如下项: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
对比上述配置项,可以看到
5.6、5.7
版本中多了
NO_AUTO_CREATE_USER
选项,在
8.0
版本已经禁止
GRANT
语句隐式创建账号,5.6、5.7
版本虽然添加了
NO_AUTO_CREATE_USER
选项,但在指定
identified by
时,可以使用
GRANT
创建账号。
如果您发现启用
ONLY_FULL_GROUP_BY
导致现有应⽤程序查询被拒绝,可以使用以下方法恢复操作:
-
如果可以修改有问题的查询,请去除
select投影列、HAVING条件或ORDER BY列表中的非聚集列,这些列既不在GROUP BY中,也不与GROUP BY列有任何函数关系。或者您可以使用ANY_VALUE()函数。 -
如果无法修改有问题的查询(例如它是由第三方应用程序生成的),请将服务器启动时的系统变量
sql_mode设置为not enable ONLY_FULL_GROUP_BY。例如,当描述不是
GROUP BY的一部分,且没有应用聚合函数(例如MIN或MAX)时,会出现如下情况: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)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
从
MySQL 8.0
开始,MySQL
官方将
explicit_defaults_for_timestamp
的默认值从
OFF
修改成
ON
。目前
PolarDB MySQL
版
8.0
中该参数的默认值仍然遵循
5.6
和
5.7
版本为
OFF
。
如果迁移过程中不希望自动添加
NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
,则需要将该参数设置成
ON
。
当
explicit_defaults_for_timestamp
为
OFF
,MySQL
对于
TIMESTAMP
类型使用了非标准行为:
-
TIMESTAMP 类型的列,如果没有显性定义 NULL 属性,将会自动添加
NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP。如果显性定义NULL属性,则保留该属性。
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)
-
表中第一个定义 TIMESTAMP 的列,要么显性指定
NULL,要么显性指定DEFAULT或者ON UPDATE属性,或者自动增加DEFAULT CURRENT_TIMESTAMP和ON UPDATE CURRENT_TIMESTAMP属性。 -
表中第二个定义 TIMESTAMP 的列,如果
sql_mode没有设置成NO_ZERO_DATE,且没有显性指定NULL或者DEFAULT属性,会自动定义成DEFAULT '0000-00-00 00:00:00'。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)如果设置成严格模式的 NO_ZERO_DATE ,则会报错:
mysql> create table t1(c1 timestamp, c2 timestamp); ERROR 1067 (42000): Invalid default value for 'c2' mysql> create table t1(c1 timestamp, c2 timestamp);
当
explicit_defaults_for_timestamp
为
ON
时,该非标准行为将会废弃,该类型和其他类型的行为一致。
视图/表/关键字兼容性
InnoDB 相关视图兼容
INFORMATION_SCHEMA
中基于
InnoDB
系统表的视图被数据字典表的内部系统视图所取代。影响
InnoDB
INFORMATION_SCHEMA
的视图已重命名,在系统应用中直接访问
InnoDB
相关视图时,需要确认应用中是否已经修改。关于参数
INFORMATION_SCHEMA
的详细信息请参见
NFORMATION_SCHEMA Tables
。
重命名的 InnoDB 信息模式视图
|
旧名称 |
新名称 |
|
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 |
在 MySQL 5.6、5.7 和 PolarDB MySQL 版 5.6、5.7 版本中不能存在 PolarDB MySQL 版 8.0 版本新增的同名视图,在 MySQL 5.7 或 PolarDB MySQL 版 5.7 版本的集群中执行如下语句,如果有返回则需要确认如何对此类表进行处理,此项检查建议您在自建集群上云升级时执行。
'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)
在 MySQL 5.6 或 5.7 版本的集群中执⾏如下语句,如果有返回则需要确认如何对此类表进⾏处理,此项检查建议您在⾃建集群上云升级时执⾏。
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',
上述出现的此类用户表应在升级前重命名或删除,重命名此类用户表语法如下:
ALTER TABLE catalogs RENAME user_catalogs;
Query OK, 0 rows affected (0.05 sec)
删除此类用户表语法如下:
DROP TABLE catalogs;
Query OK, 0 rows affected (0.06 sec)
视图兼容
在
MySQL 8.0
版本之前的版本,您最多可以创建具有
255
个字符的显示列名的视图。为遵守列名的最大长度,MySQL 8.0
版本不支持显示列名超过
64
个字符的视图,目前这些视图只能通过在
MySQL 5.6、5.7
版本中执行
SHOW CREATE VIEW
来识别。
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)
因此,您需要在升级 8.0 版本前修改视图名称。
ALTER VIEW v1(a12345678901234567890) AS SECLECT 1;
5.6 版本系统表兼容
mysql.user
系统表的
Password
列,在
MySQL 5.7.6
后的版本及
8.0
版本中被删除。所有凭据都存储在
authentication_string
列中,包括之前版本存储在该
Password
列中的数据。
5.6 版本 INFORMATION_SCHEMA 系统和状态变量信息的表兼容
MySQL 5.6
和
PolarDB MySQL
版
5.6
版本
INFORMATION_SCHEMA
中包含系统和状态变量信息的表在
8.0
版本中被废弃,废弃表如下:
INFORMATION_SCHEMA.GLOBAL_VARIABLES
INFORMATION_SCHEMA.SESSION_VARIABLES
INFORMATION_SCHEMA.GLOBAL_STATUS
INFORMATION_SCHEMA.SESSION_STATUS
8.0
版本中将上述废弃的表迁移至
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
如果您直接使用该视图,推荐使用
SHOW
命令代替,而非直接使用相应的视图。
SHOW VARIABLES
SHOW STATUS
5.6 版本 INNODB 表兼容
DYNAMIC
替换
COMPACT
为
InnoDB
表的隐式默认⾏格式。配置选项
innodb_default_row_format
指定默认的
InnoDB⾏格式,允许
DYNAMIC
的值包括
COMPACT
(默认值)和
REDUNDANT
。升级到
8.0
后,除⾮您明确定义⾏格式
(ROW_FORMAT)
,否则您创建的任何新表都需要使⽤定义的⾏格式。对于未显式定义
ROW_FORMAT
选项或使⽤的现有表
ROW_FORMAT=DEFAULT
,任何重建表的操作都会将表的⾏格式更改为定义的格式:
innodb_default_row_format
。更多详细信息请参见
表的⾏格式
。
5.6 版本 GET_LOCK 函数兼容
GET_LOCK()
功能在
MySQL 5.7.5
及之后的版本中使⽤元数据锁定(MDL)⼦系统重新实现,并且其功能已得到扩展:
-
以前版本中,
GET_LOCK()⼀次只允许获取⼀个命名锁,第⼆次调用GET_LOCK()时释放所有现有锁。8.0 版本中GET_LOCK()允许同时获取多个命名锁,并且不会释放现有锁。依赖于
GET_LOCK()释放所有先前锁的⾏为的应⽤程序必须针对新⾏为进⾏修改。 -
获取多个锁的能⼒可能会在客户端之间引⼊死锁。MDL⼦系统检测死锁且
ER_USER_LOCK_DEADLOCK在发⽣这种情况时返回错误。 -
MDL⼦系统对锁名称添加了 64 个字符的限制,因此该限制也适⽤于命名锁。之前版本没有强制执⾏⻓度限制。
-
获取的锁
GET_LOCK()现在出现在Performance Schema metadata_locks中。OBJECT_TYPE列表示USER LEVEL LOCK,OBJECT_NAME列表示锁定名称。 -
8.0 版本支持
RELEASE_ALL_LOCKS()允许⼀次释放所有获得的命名锁。
更多信息请参见 锁定功能 。
类型兼容
枚举和集合类型兼容
表或存储过程的单个
ENUM
或
SET
列元素的长度不得超过
255
个字符或
1020
个字节。
5.6 版本 YEAR 类型
废弃
YEAR(2)
类型,需要⽤
YEAR(4)
替换
YEAR(2)
。
5.6 版本类型数据插入兼容
-
将负值插⼊⽆符号列时会报错。示例如下:
-
创建⼀个包含⽆符号列的表:
CREATE TABLE test (id int unsigned); -
插⼊⼀个负值。
INSERT INTO test VALUES (-1);-
5.6 版本中显示结果如下:
Query OK, 1 row affected, 1 warning (0.01 sec) -
8.0 版本中显示结果如下:
ERROR 1264 (22003): Out of range value for column 'a' at row 1
-
-
-
数据除以零会报错。示例如下:
-
创建测试表:
CREATE TABLE test2 (id int unsigned); -
数据除以零。
INSERT INTO test2 VALUES (0/0);-
5.6 版本显示结果如下:
Query OK, 1 row affected (0.01 sec) -
8.0 版本显示结果如下:
ERROR 1365 (22012): Division by 0
-
-
-
字符超⻓插⼊报错。示例如下:
-
将 20 个字符的字符串插⼊10 个字符的列会报错。创建⼀个包含 10 个字符的列的表:
CREATE TABLE test3 (a varchar(10)); -
插⼊更⻓的字符串。
INSERT INTO test3 VALUES ('abcdefghijklmnopqrstuvwxyz');-
5.6 版本显示结果如下:
Query OK, 1 row affected, 1 warning (0.00 sec) -
8.0 版本显示结果如下:
ERROR 1406 (22001): Data too long for column 'a' at row 1
-
-
-
⾮标准零⽇期插⼊⽇期时间列会报错。示例如下:
-
创建⼀个包含⽇期时间列的表。
CREATE TABLE test3 (a datetime); -
插⼊ 0000-00-00 00:00:00 。
INSERT INTO test3 VALUES ('0000-00-00 00:00:00');-
5.6 版本显示结果如下:
Query OK, 1 row affected, 1 warning (0.00 sec) -
8.0 版本显示结果如下:
ERROR 1292 (22007): Incorrect datetime value: '0000-00-00 00:00:00' for column 'a' at ro
-
-
5.7 版本 JSON 类型中 INT 类型数据变化
JSON 中的部分 INT 类型被添加了.0 变成类似 1.0 或者 9999.0,初步确认是 5.7 和 8.0 版本对 JSON 里面双精度处理方式不同而导致,解决方案需要做 DTS 数据校验,如有需求您可以在配置 DTS 界面配置数据校验。
5.x 旧式类型兼容
旧式
decimal、旧式
varchar、旧式
TIME/DATETIME
和
TIMESTAMP
等数据类型分别在
MySQL 5.0、MySQL 5.1
和
MySQL 5.6
版本中已过时,由于二进制升级一直持续到
MySQL 5.6、5.7
版本,所以在
MySQL 8.0
版本中不被支持。这些表可以通过在升级前在
MySQL 5.6、5.7
版本中运行
CHECK TABLE...FOR UPGRADE
或使用带有
check-upgrade
选项的
mysqlcheck
来识别。此外,使用旧式
TIME/DATETIME
和
TIMESTAMP
的表还可以通过启用会话变量来识别,
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
使用此类数据类型的表无法升级,应通过
REPAIR TABLE
修复,并为旧式
varchar、旧式
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
关键词与保留字
PolarDB MySQL
版
8.0
版本可以通过
information_schema.KEYWORDS
表查看当前版本的关键词与保留字,不得有关键字或保留字违规的情况。
PolarDB MySQL
版
8.0
版本中可能保留了部分以前未保留的关键字,详情请参见
关键字和保留字
。建议所有自定义内容(表名、字段名、函数名)等全部规避使用。除此之外,
KICKOUT
是
PolarDB MySQL
版
8.0
的保留关键字。因此,若您已经在
MySQL 5.6、5.7
或原生
MySQL 8.0
版本上使用该关键字作为对象名称(如表名、字段名、存储过程名等),在迁移到
PolarDB MySQL
版
8.0
版本前,请您先修改对象名称避免使用该关键字,否则迁移时,将会出现错误码为
1064
的语法报错。
SQL 兼容性
GRANT 授权
在 MySQL 8.0.11 中,删除了部分与账户管理相关、已弃用的功能,例如使用 GRANT 语句修改用户账户的非特权特性。
GRANT REPLICATION CLIENT ON *.* TO 'odps'@'%'; You are not allowed to create a user with
create user;
grant privielges;
不支持 GROUP BY ASC/DESC
自 MySQL 8.0.13 开始,已删除不推荐使用的子句 ASC 和 DESC 限定符 GROUP BY,之前依赖 GROUP BY 排序的查询可能会产生与之前 MySQL 版本不同的结果。要生成给定的排序顺序,您需要提供一个 GROUP BY 子句。示例如下:
将 SQL 语句:
select id,count(*) from sbtest.sbtest1 where id < 10 group by id desc
改写为:
select id,count(*) from sbtest.sbtest1 where id < 10 group by id order by id
PolarDB MySQL
版
8.0.2.2.11.1
版本及以上的版本,不需要执行以上改写操作。您只需要在控制台上将
loose_group_by_compatible_sorting
参数的值设置为
TRUE
,即可直接在
SQL
语句中使用带有
ASC
或
DESC
的
GROUP BY
子句。在控制台上设置参数值的操作步骤请参见
设置集群参数和节点参数
。
外键约束定义
在
MySQL 5.6、5.7
版本中,定义
FOREIGN KEY
的
InnoDB
不得带有
CONSTRAINT
的关键字且指定外键约束名称不得超过
64
个字符。在
MySQL 8.0
之前的版本中,当您未明确指定外键约束名称时,InnoDB
会通过在表名后附加
_ibfk_X
来自动生成外键约束名称,其中
X
是一个数字。如果表名是多字节
64
字符,如下面示例中使用的⻄里尔表名
имя_базы_в_кодировке_утф8_длиной_больше_чем_45имя_азы_в_кодировк
,则自动生成的外键约束名称将超过
64
个字符。应通过删除约束并确保外键约束名称不超过
64
个字符来添加具有显式约束名称的约束来更改这些表。
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
5.7 版本空间函数
在 MySQL 5.7 中,不推荐使⽤多个名称下可⽤的部分空间函数。示例如下:
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)
由于空间函数名称更改,这些空间函数在
8.0
版本中已被删除。此更改有助于命名约定保持⼀致,即函数以
ST_
开头(精确执⾏操作情况下)或者以
MBR
开头(执⾏基于最⼩边界矩形的操作情况下),使⽤此类函数⽣成的列应在升级前更改。已删除空间函数的列表请参见
Features Removed in MySQL 8.0
。您需要更改⽣成的列以使⽤相应的
ST_
或
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
触发器兼容
MySQL 5.0.17
之前的
CREATE TRIGGER
不⽀持
definer
属性。此类具有缺失/空定义器属性或⽆效创建上下⽂(即
character_set_client
、
collation_collection
、数据库排序规则属性)的触发器定义⼀直存在导致
MySQL 5.6、5.7
版本时⽆法升级。这些触发器可以通过在
MySQL 5.6、5.7
版本中运⾏带有检查升级选项的
mysqlcheck
或
CHECK TABLE
来识别。
$./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:
$./client/mysqldump --databases triggers --socket=5.6/data/mysql.sock --user=root>trigge
Restore:
.\ triggers.sql
客户端兼容性
对于
Java
应⽤来说,MySQL Connector/J
升级到
8.0
以上版本,连接账户需要连接器/J 8.0.9
或更⾼版本的
caching_sha2_password
。如果未在数据源中将
dataworks
设置为
utf8,可能会出错,建议修改数据库名。在的连接串中增加:
characterEncoding=utf8&com.mysql.jdbc.faultInjection.serverCharsetIndex=
使
Java
客户端在连接中显性指定
session
级别字符集。
Unknown system variable 'tx_read_only'兼容性
MySQL
和 8.0
版本中已经删除
tx_read_only
环境变更,需要使⽤
transaction_read_only
代替。
即需要将:
select @@tx_read_only
改写为:
select @@transaction_read_only
常见问题
并行查询导致的排序问题
8.0
版本开始⽀持并⾏查询能⼒,并⾏扫描由于随机访问数据会导致
MySQL
默认串⾏扫描的顺序每次随机变化,尤其是涉及到分⻚的
SQL。如果您需要⽣成给定的排序顺序,请提供⼀个
ORDER BY
⼦句保证顺序。
5.6 版本子查询问题
5.6
版本子查询中的
order by
不再起作用,例如:
SELECT *
SELECT * FROM `information_schema`. TABLES
ORDER BY table_name DESC
) AS sg
GROUP BY table_name
内层的
order by
会被
5.7、8.0
版本的优化器忽略,您需要通过修改语句解决这个问题,最简单的方法是添加
limit
使排序生效,例如:
SELECT *
SELECT * FROM `information_schema`. TABLES
ORDER BY table_name DESC limit 10000 # 需要⾜够⼤的⾏数
) AS sg
GROUP BY table_name
5.6 版本派⽣表问题
优化器现在以⼀致的⽅式处理⼦句中的派⽣表和视图,使用
FROM
以更好地避免不必要的物化,并允许使⽤、产⽣更有效的执⾏计划的下推条件。但在 8.0
版本以及修改表之类的语句中,
DELETE
对
UPDATE
之前实现的派⽣表使⽤合并策略可能会导致
ER_UPDATE_TABLE_USED
错误:
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
将派⽣表合并到外部查询块中会导致从表中选择和修改表语句时发⽣错误。(物化不会导致问题,因为它实际上将派⽣表转换为了单独的表。)为避免此类错误的解决⽅法是在执⾏语句前禁⽤使用系统变量的
derived_merge
标志
optimizer_switch
:
SET optimizer_switch = 'derived_merge=off';
该
derived_merge
标志控制优化器是否尝试将
FROM
⼦句中的⼦查询和视图合并到外部查询块中。假设没有其他规则阻⽌合并,默认情况下,该标志是
on
启⽤合并。设置标志
off
阻止合并,可以避免上述描述的错误。更多信息请参见
使用合并或实现优化派生表和查看引用
。
在
UNION
语句中,要将
ORDER BY
或
LIMIT
应⽤于单独查询块
SELECT
,请将
SELECT
⼦句放在括号内 :
(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);
在 8.0 版本中,要求必须使⽤括号,MySQL 之前的版本可能允许这样的语句不带括号。
相关文档
MySQL 官方 5.6、5.7、8.0 版本差异比较: