PolarDB MySQL 5.6/MySQL 5.6升级PolarDB MySQL 8.0最佳实践

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云原生数据库 PolarDB MySQL 版,通用型 2核4GB 50GB
简介: 升级概述为什么选择升级到PolarDB MySQL 8.0?PolarDB MySQL 8.0.1 (基于官方MySQL 8.0.13内核版本)发布于2019-12-03和PolarDB MySQL 8.0.2(基于官方MySQL 8.0.18内核版本)发布于2020-07-22*,增强了诸多卓越的架构增强和内核能力,为业务提供更灵活的技术解决方案和强大收益的性能提升,主要包括:Serverles

升级概述

为什么选择升级到PolarDB MySQL 8.0?

PolarDB MySQL 8.0.1 (基于官方MySQL 8.0.13内核版本)发布于2019-12-03和PolarDB MySQL 8.0.2(基于官方MySQL 8.0.18内核版本)发布于2020-07-22*,增强了诸多卓越的架构增强和内核能力,为业务提供更灵活的技术解决方案和强大收益的性能提升,主要包括:

  • Serverless :Serverless数据库能够使得数据库集群资源随客户业务负载动态弹降,将客户从复杂的业务资源评估和运维工作中解放出来。
  • 多主集群(库表) :在一个集群中通过多个主节点来实现从一写多读架构到多写多读架构的升级,主要面向SaaS多租户、游戏、电商等高并发读写的应用场景。
  • 弹性并行查询(Elastic Parallel Query) :弹性并行查询(Elastic Parallel Query,ePQ)目前支持单机并行和多机并行*两种并行引擎,单机并行引擎等效于原有的并行查询,多机并行引擎支持集群内跨节点的自适应弹性调度*。
  • 列存索引(IMCI) 面向OLAP场景大数据量复杂查询。通过列存索引,PolarDB MySQL实现了一体化的实时事务处理和实时数据分析的能力,成为一站式HTAP数据库产品解决方案。通过一套数据库系统,即可满足业务的OLTP及OLAP需求。
  • 高压缩引擎(X-Engine):阿里巴巴自研的基于LSM-tree架构的存储引擎X-Engine提供了强大的数据压缩能力,满足了归档数据库低存储成本的要求。通过LSM-Tree(Log-Structured Merge-Tree)层次化架构和Zstandard(ZSTD)压缩算法实现了更高的数据压缩率,对比使用InnoDB作为存储引擎,最高可节省70%的存储空间。
  • 分区表增强:支持更多分区功能增强(全二级分区类型支持、Interval Range分区、List Default Hash分区、异构分区、部分分区索引、全局二级索引等),性能改进(分区MDL锁、动态剪枝、Partition-Wise连接等)帮助客户解决大表性能、运维和管理。
  • 冷数据归档:为了降低数据存储成本,PolarDB for MySQL支持将低频使用的冷数据归档到OSS对象存储中,支持冷热数据管理语法和存储过程方式。
  • DDL增强优化:支持并行DDL、秒级加字段、DDL预读、DDL多路归并排序、DDL异步IO、非阻塞DDL等增强了DDL的性能、稳定性和易用性。
  • 事务系统增强全新的事务系统PolarTrans, 它利用提交时间戳技术CTS对高并发在线交易场景进行了优化,可以有效提升数据库的读写性能;同时PolarTrans利用现有的网络基础设施资源,与RDMA技术深度结合,推出高性能集群强一致性读SCC功能。SCC可以确保集群任何RW和RO节点都可以提供写后读的强一致性,通过对强一致性读请求进行RO分流,有效降低了RW节点的负载。在OLTP场景下,极大的提升了集群的整体吞吐能力。
  • SQL优化 :包括利用Window Function和Group By Aggregation对子查询解关联;通过CBQT组件(Cost Based Query Transformation)实现基于代价的查询变换,从而大幅提升复杂查询的执行效率;Limit Offset下推、谓词完全下推扫描完全下推(FastTraverse)和针对 HashJoin的Bloom Filter下推能力;Partial Result Cache(简称PTRC)功能来缓存查询语句中算子的中间结果集,来减少这些复杂算子的重复计算,以此来提升查询性能。
  • 性能监控增强Performance Agent是PolarDB提供的一种更加便捷的性能数据统计方案。通过PolarDB MySQL引擎插件的方式,实现PolarDB MySQL引擎集群中的节点内部各项性能数据的采集与统计。SQL Trace功能,用于跟踪SQL语句的执行信息,如:执行计划和执行统计信息(包括扫描行数、执行时间等)。可以帮助您快速地发现因执行计划变更而引发的性能变化,并统计当前集群中占用内存最多的查询语句。

另外,PolarDB MySQL 8.0.x版本还受益于官方从各个方面带来的令人兴奋的能力,详细参考《What’s New in MySQL 8.0》

  • SQL全面增强 :支持窗口函数(Window functions), 公共表表达式( Common Table Expressions, 优化并发SELECT ... FOR UPDATE的NOWAIT和SKIP LOCKED, 降序索引(Descending Indexes), Grouping函数, 正则表达式函数(Regular Expressions), 字符集增强(Character Sets), 代价模型增强(Cost Model), 直方图(Histograms),哈希连接(Hash Join)*,横向派生表(LATERAL),[NOT] IN/EXISTS子查询转换增强*,EXPLAIN ANALYZE*, 索引级别的优化器HINT ,派生表条件下推*
  • TempTable临时表内存引擎 :代替MEMORY引擎,更高效的支持VARCHAR和VARBINARY类型。
  • 支持JSON数据* :JSON数据存储、JSON函数、改进排序和部分更新
  • 支持GIS数据 :空间数据存储、空间类型、空间函数和空间索引
  • 可靠性(Reliability) :基于InnoDB存储的元数据管理和事务性的数据字典改进,使得DDL成为操作和灾难恢复保证安全。
  • 可观测性(Observability) : 显著增强了Performance Schema,Information Schema,配置变量和错误日志。
  • 易于运维(Manageability) :支持Undo tablespace管理,支持instant DDL,极大缩短了一些常见DDL的操作。
  • 安全(Security)  改进了OpenSSL,增加了新的默认认证方式,SQL角色等等。
  • 性能(Performance)  InnoDB显著的增进了Read/Write负载、IO bound负载, 和高竞争的热点(hot spot)负载。

预检验

PolarDB MySQL 5.6/MySQL 5.6 向 8.0 升级过程中,经常遇到的问题主要是性能问题、语法兼容性问题,以及周边组件是否的支持,查询的性能问题一般是由于优化器升级导致执行计划有变,此类问题需要对性能低下的语句进行针对性的性能优化,但性能问题基本不会引发业务报错以及代码的改写问题,此类问题不在本文讨论范围之内。

本文主要讨论真实的兼容性问题,此类问题需要在数据库升级过程中,对代码做出对应的更新或环境配置的更改,引发原因主要是版本升级后一些语法的变化以及特性的更新、移除。预检验主要提供一个简要清单来帮助用户在升级前能够更好的了解升级过程中可能注意的问题,如果遇到下列问题,可以到版本升级详细说明章节进行操作和检查。

  • 确保没有使用废弃的数据类型、函数和 功能,更多信息参考   Features removed in MySQL 8.0   官方文档。
  • 确保触发器Triggers没有丢失或者空的definer或无效的内容。
  • 确保只有InnoDB引擎的分区表。
  • 确保关键字和保留关键字没有冲突,详细参考官方文档  Keywords and reserved words
  • 确保没有和MySQL 5.6的系统数据库没有和MySQL 8.0的新增INNODB_开头的词典表名冲突。
  • 确保不依赖于INFORMATION_SCHEMA下的GLOBAL|LOCAL]_[VARIABLES|STATUS]表
  • 确保sql_mode中不使用废弃的变量设置。
  • 确保表或存储过程单个ENUM或者SET 列元素的长度不得超过 255 个字符或 1020 个字节。
  • 确保表分区不在共享InnoDB tablespaces表空间。
  • 确保查询SQL中的GROUP BY不带有 ASC or DESC 。
  • 确保外键约束名字不超过64字符。
  • 为了增强Unicode的支持,考虑将使用utf8mb3字符集(已废弃)的对象改为utf8mb4字符集。另外,同样也需要考虑使用utf8mb4代替utf8,因为utf8是utf8mb3字符集的别名。更多信息参考   The utf8mb3 character set (3-byte UTF-8 unicode encoding)  

如果上述内容确保没有存在,可以跳过下面章节进行升级,请参考《PolarDB for MySQL引擎大版本一键升级》。注意:升级前一定要进行备份,以避免升级过程可能遇到的其他问题。另外,达摩院的DAS团队还推出了智能压测能力,方便客户对新升级实例进行流量回放的压力测试,详细可以了解《智能数据库DAS之智能压测技术》

版本升级详细说明

配置兼容性

引擎和分区表兼容

有关将MyISAM 表转换为 的信息InnoDB,请参阅 第“将表从 MyISAM 转换为 InnoDB”。在PolarDB MySQL 8.0中,将导致使用没有此类型支持的存储引擎分区表创建语句失败并出现错误 ( ER_CHECK_NOT_IMPLEMENTED )。

PolarDB MySQL 存储引擎现在负责提供自己的分区处理程序,并且PolarDB MySQL 服务器不再提供通用引擎分区支持。 InnoDB是唯一提供 PolarDB MySQL 8.0 支持的本机分区处理程序的存储引擎。必须在升级服务器之前InnoDB更改使用任何其他存储引擎的分区表将其转换为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引擎或删除分区:

<mysql> ALTER TABLE part ENGINE = INNODB;
Query OK, 0 rows affected (0.09 sec)
 
OR
 
<mysql> ALTER TABLE part REMOVE PARTITIONING;
Query OK, 0 rows affected (0.06 sec)

如果使用 mysqldump从在 MySQL 5.6(或更早版本)中创建的转储文件将数据库导入PolarDB MySQL 8.0 服务器,则必须确保创建分区表的任何语句都不会同时指定不受支持的存储引擎,方法是删除对分区的任何引用,或通过将存储引擎指定为 InnoDB或允许将其设置为 InnoDB默认值。“为升级准备安装”中给出的过程描述了如何识别在升级到 MySQL 8.0 之前必须更改的分区表。有关详细信息,请参阅“与存储引擎相关的分区限制”

字符集&排序规则兼容

官方版本 8.0 默认字段集改为 utf8mb4,MySQL/PolarDB MySQL 8.0 默认字符集为了兼容性目前默认 character_set_server 均为 utf8,可以按业务需求调整,为了改进 Unicode 支持,请考虑将使用该字符集的对象转换utf8mb3为使用该utf8mb4字符集。不推荐使用utf8mb3字符集。另外,考虑使用utf8mb4字符集引用而不是 utf8,因为当前 utf8utf8mb3字符集的别名。有关详细信息,请参阅 utf8mb3 字符集(3 字节 UTF-8 unicode 编码)在 MySQL 文档中。

官方MySQL版本 8.0 新增了 default_collation_for_utf8mb4 参数,此参数的作用是在字符集为 utf8mb4 时,默认排序规则,默认值为 utf8mb4_0900_ai_ci,官方文档注明只是为MySQL Replication使用的内部参数,所以建议如果没有从低版本同步过程中遇到Illegal mix of collations错误前不建议修改该默认值为utf8mb4_general_ci/utf8_general_ci

utf8mb4_unicode_ci 是基于官方Unicode的规则来做通用的排序和比较,准确度高,但比对速度稍慢。

utf8mb4_general_ci 是精简集合的排序规则,目的是提供简化的一个设计来加快速度,虽然没有去遵循Unicode的规则,但是结果在相同情况下是符合预期的。

排序规则和字符集不同,它之和排序和比较有关系,其中ai指的是口音不敏感。也就是说,排序时e,è,é,ê和ë之间没有区别, ci表示不区分大小写。也就是说,排序时p和P之间没有区别。

注意事项

  • 比如在 8.0向低版本反向同步或者 dump 同步时,有可能导致脚本不支持,
  • 比较容易在 DTS 低版本与高版本双向同步场景下出现,需要使用5.6默认的排序字符集,否则DTS反向同步的时候会有异常。
  • 创建视图可能会报错Illegal 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 里面指定 column,table, db 的 collation 都不会起作用。 如果一定要用 convert,可以明确带上 collation,类似这样写 (convert(a.c1 using utf8mb4) collate utf8mb4_general_ci) = b.c1
  • 修改  default_collation_for_utf8mb4 默认值如 utf8mb4_unicode_ci,会导致SYS库无法读取及其相关函数无法读取,报错“Illegal mix of collations (utf8mb4_unicode_ci,IMPLICIT) and (utf8mb4_0900_ai_ci,IMPLICIT) for operation '='”,也会导致会导致从PolarDB 8.0.1升级到PolarDB 8.0.2失败,因为该参数是8.0的新参数,所以建议不要修改该参数,如果必须使用其他值,请升级前提工单重置为默认 utf8mb4_0900_ai_ci 升级后修改回来。

参数兼容

lower_case_table_names

从 MySQL 8.0.11 开始,禁止 lower_case_table_names 使用与服务器初始化时使用的设置不同的设置来启动服务器。该限制是必要的,因为各种数据字典表字段使用的排序规则基于 lower_case_table_names 服务器初始化时定义的设置,并且使用不同的设置重新启动服务器会在标识符的排序和比较方式方面引入不一致。实例区分大小写在 8.0 版本中,无法在初始化完成后再次更改,需要在购买PolarDB MySQL 8.0实例时选定。

sql_mode

为避免PolarDB MySQL 8.0 上的启动失败,请NO_AUTO_CREATE_USER sql_modeMySQL 选项文件中的系统变量设置中删除任何实例。sql_mode您的系统变量设置中不得定义过时的 SQL 模式,sql_mode 会引起许多行为的不同,在版本升级时需要确认对齐。取消如下配置项:

DB2, MAXDB, MSSQL, MYSQL323, MYSQL40, ORACLE, POSTGRESQL, NO_FIELD_OPTIONS , NO_KEY_OPTIONS, NO_TABLE_OPTIONS

以上配置项大多为组合配置,需要注意是否有不一致的 mode 选项,如: sql_mode=TRADITIONAL等于配置如下项:

STRICT_TRANS_TABLES, STRICT_ALL_TABLES, NO_ZERO_IN_DATE, NO_ZERO_DATE, ERROR_FOR_DIVISION_BY_ZERO, NO_ENGINE_SUBSTITUTION. 

在 5.6 默认配置时sql_mode=TRADITIONAL等于配置如下项:

STRICT_TRANS_TABLES, STRICT_ALL_TABLES, NO_ZERO_IN_DATE, NO_ZERO_DATE,
ERROR_FOR_DIVISION_BY_ZERO, NO_AUTO_CREATE_USER, and NO_ENGINE_SUBSTITUTION.

可以看到 5.6 多了 NO_AUTO_CREATE_USER 项,但其实 8.0 已经禁止使用 GRANT 语句隐式创建账号,5.6 虽然添加了NO_AUTO_CREATE_USER 选项,但在指定 identified by 时,同样可以使用 GRANT 创建账号。

如果您发现 ONLY_FULL_GROUP_BY启用导致对现有应用程序的查询被拒绝,则这些操作中的任何一个都应该恢复操作:

  • 如果可以修改有问题的查询,请这样做,以便非确定性非聚合列在功能上依赖于 GROUP BY 列,或者通过使用  ANY_VALUE() .
  • 如果无法修改有问题的查询(例如,如果它是由第三方应用程序生成的),请将 sql_mode 服务器启动时的系统变量设置为 not enable  ONLY_FULL_GROUP_BY

例如,当描述不是的一部分GROUP BY,并且没有应用聚合函数(例如MINMAX)时,就会发生这种情况。

以前的行为:

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)

PolarDB MySQL 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 nonaggregated column 'invoice_line_items.description' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by

INFORMATION_SCHEMA系统和状态变量信息的表

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

视图/表以及关键词

InnoDB相关视图

INFORMATION_SCHEMA基于InnoDB系统表的视图被数据字典表的内部系统视图取代。受影响 InnoDB INFORMATION_SCHEMA的视图已重命名:,如果系统应用中有直接访问 InnoDB 相关视图,需要确认应用中是否已经修改。

重命名的 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

在 5.6 版本中不能存在 8.0 中新增的同名视图,在 5.6 实例中执行如下语句,如果有返回则需要确认如何对此类表进行处理,此项检查建议在自建实例上云升级时执行

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',
'st_spatial_reference_systems',
'table_partition_values',
'table_partitions',
'table_stats',
'tables',
'tablespace_files',
'tablespaces',
'triggers',
'view_routine_usage',
'view_table_usage'
);

Suppose
+--------------+------------+
| TABLE_SCHEMA | TABLE_NAME |
+--------------+------------+
| mysql        | catalogs   |
+--------------+------------+
1 row in set (0.00 sec)

因此,此类用户表应在升级前重命名或删除:

mysql>ALTER TABLE catalogs RENAME user_catalogs;
Query OK, 0 rows affected (0.05 sec)
 
OR
 
mysql> DROP TABLE catalogs;
Query OK, 0 rows affected (0.06 sec)

视图兼容

在 MySQL 8.0 之前,用户可以创建具有最多 255 个字符的显式列名的视图。为遵守列名的最大长度,MySQL 8.0 不支持显式列名超过 64 个字符的视图。目前这些视图只能通过  在 MySQL 5.6 中执行SHOW CREATE VIEW来识别。

mysql> SHOW CREATE VIEW v1;
+------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+
| View | Create View                                                                                                                                                                  | character_set_client | collation_connection |
+------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+
| v1   | CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select 1 AS `a123456789012345678901234567890123456789012345678901234567890123456789` | utf8                 | utf8_general_ci      |
+------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+
1 row in set (0.00 sec

应在升级PolarDB MySQL 8.0前修改视图名字

mysql> ALTER VIEW v1(a12345678901234567890) AS SELECT 1;

系统表兼容

mysql.user系统表的 Password列 mysql.user在 MySQL 5.7.6 之后及8.0中被删除。所有凭据都存储在该 authentication_string列中,包括以前存储在该Password 列中的那些。

INNODB表兼容

DYNAMIC替换 COMPACTInnoDB表的隐式默认行格式。一个新的配置选项,innodb_default_row_format指定默认的InnoDB行格式。允许DYNAMIC的值包括(默认值)COMPACT、 和 REDUNDANT。升级到PolarDB MySQL 8.0 后,您创建的任何新表都使用定义的行格式,innodb_default_row_format 除非您明确定义行格式 ( ROW_FORMAT)。对于未显式定义 ROW_FORMAT选项或使用 的现有表ROW_FORMAT=DEFAULT,任何重建表的操作也会默默地将表的行格式更改为定义的格式 innodb_default_row_format。否则,现有表将保留其当前行格式设置。有关详细信息,请参阅定义表的行格式

类型兼容

枚举和集合类型兼容

表或存储过程的单个ENUMSET列元素的长度不得超过 255 个字符或 1020 个字节。

YEAR类型

YEAR(2) 类型废弃,需要用YEAR(4) 替换。

类型数据插入兼容

  • 将负值插入无符号列会报错

创建一个包含无符号列的表:

CREATE TABLE test (id int unsigned);

插入一个负值,以前的行为:

INSERT INTO test VALUES (-1);
Query OK, 1 row affected, 1 warning (0.01 sec)

PolarDB MySQL 8.0的行为:

INSERT INTO test VALUES (-1);  
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);  
Query OK, 1 row affected (0.01 sec)

PolarDB MySQL 8.0的行为:

INSERT INTO test2 VALUES (0/0);  
ERROR 1365 (22012): Division by 0
  • 字符超长插入报错

将 20 个字符的字符串插入 10 个字符的列会报错,创建一个包含 10 个字符的列的表:

CREATE TABLE test3 (a varchar(10));

尝试插入更长的字符串,以前的行为:

INSERT INTO test3 VALUES ('abcdefghijklmnopqrstuvwxyz'); 
Query OK, 1 row affected, 1 warning (0.00 sec)

PolarDB MySQL 8.0的行为:

INSERT INTO test3 VALUES ('abcdefghijklmnopqrstuvwxyz');  
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');  
Query OK, 1 row affected, 1 warning (0.00 sec)

PolarDB MySQL 8.0的行为:

INSERT INTO test3 VALUES ('0000-00-00 00:00:00');  
ERROR 1292 (22007): Incorrect datetime value: '0000-00-00 00:00:00' for column 'a' at row 1

5.x 旧式类型兼容

旧式decimal、旧式varchar、旧式TIME/DATETIME 和 TIMESTAMP类型等数据类型分别在 MySQL 5.1 、 MySQL 5.0 和 MySQL 5.6 中已过时,由于二进制升级而一直持续到 MySQL 5.6 将不被支持在 MySQL 8.0 中。这些表可以通过在升级前在 MySQL 5.6 中运行CHECK TABLE…FOR UPGRADE 或带有check-upgrade选项的 mysqlcheck 来识别。此外,使用旧式IME/DATETIME 和 TIMESTAMP的表可以通过启用会话变量来识别,参考"How to Easily Identify Tables With Temporal Types in Old Format!"

mysql> check table 41_decimal for upgrade;
+-----------------+-------+----------+-------------------------------------------------------------------------------------+
| Table           | Op    | Msg_type | Msg_text                                                                            |
+-----------------+-------+----------+-------------------------------------------------------------------------------------+
| test.41_decimal | check | error    | Table upgrade required for `test`.`41_decimal`. Please dump/reload table to fix it! |
+-----------------+-------+----------+-------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
 
mysql> check table 55_temporal for upgrade;
+------------------+-------+----------+------------------------------------------------------------------------------------------+
| Table            | Op    | Msg_type | Msg_text                                                                                 |
+------------------+-------+----------+------------------------------------------------------------------------------------------+
| test.55_temporal | check | error    | Table upgrade required. Please do "REPAIR TABLE `55_temporal`" or dump/reload to fix it! |
+------------------+-------+----------+------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
 
nisha@nisha-PORTEGE-Z30-A:~/workspace1/mysql-5.6/dbg-5.6/client/mysqlcheck --user=root --socket=/home/nisha/workspace1/mysql-5.6/dbg-5.6/data/mysql.sock --databases test --check-upgrade
error    : Table upgrade required for `test`.`41_decimal`. Please dump/reload table to fix it!
test.55_temporal
error    : Table upgrade required. Please do "REPAIR TABLE `55_temporal`" or dump/reload to fix it!
test.child                                         OK
test.geom                                          OK
test.jemp                                          OK
test.jemp_myisam                                   OK
test.opening_lines                                 OK
test.parent                                        OK
test.t_blackhole                                   OK
test.t_blob                                        OK
test.t_blob_myisam                                 OK
test.t_compressed                                  OK
test.t_compressed2                                 OK
test.t_compressed3                                 OK
test.t_dynamic                                     OK
test.t_gen_stored                                  OK
test.t_gen_stored_myisam                           OK
test.t_gen_stored_myisam2                          OK
test.t_index                                       OK
test.t_json                                        OK
test.t_myisam_compressed                           OK
test.t_myisam_compressed2                          OK
test.t_myisam_compressed3                          OK
test.t_sc~!@#$%^&*(                                OK
test.vt2                                           OK

使用此类数据类型的表无法升级,应通过REPAIR TABLE 修复,并为旧式 varchar/旧式 decimal 转储/重新加载:

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

关键词与保留字

PolarDB MySQL 8.0 可以通过 information_schema.KEYWORDS 表查看当前版本的关键词与保留字,不得有关键字或保留字违规。PolarDB MySQL 8.0 中可能保留了一些以前未保留的关键字,有关详细信息,请参阅关键字和保留字在 MySQL 文档中。建议所有自定义内容(表名、字段名、函数 名)等等全部要规避使用。除此之外, KICKOUT 是 PolarDB MySQL 8.0 的保留关键字。因此,若您已经在 MySQL 5.6 或开源 MySQL 8.0 上使用该关键字作为对象名称(如表名、字段名、存储过程名等),在迁移到 PolarDB MySQL 8.0 前,请您先修改对象名称避免使用该关键字。否则迁移时,将会出现错误码为1064 的语法报错。

补充关键词(RDS)

有业务会使用自建序列号生成器函数 nextvalcurrval这两个关键词在 RDS MySQL 8.0 中为保留字需要改写函数名称或者直接使用 RDS 提供的 seq 功能

CREATE sequence s START WITH 1 minvalue 1 MAXVALUE 9999999 increment BY 1 CACHE 20 cycle;
SELECT nextval(s),currval(s);

SQL兼容性

GRANT授权

在 MySQL 8.0.11 中,删除了与帐户管理相关的几个已弃用的功能,例如使用 GRANT语句修改用户帐户的非特权特性。例如

GRANT REPLICATION CLIENT ON *.* TO 'odps'@'%'; You are not allowed to create a user with GRANT 需要改为两步建
create user;
grant privielges;

不支持 GROUP BY ASC/DESC 写法

从 MySQL 8.0.13 开始,已删除不推荐使用的子句ASC或 DESC限定符GROUP BY以前依赖GROUP BY排序的查询可能会产生与以前的 MySQL 版本不同的结果。要生成给定的排序顺序,请提供一个ORDER BY子句。

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

外键约束定义

在 MySQL 5.6 中,定义FOREIGN KEY定义的InnoDB 不带CONSTRAINT 的关键字或者指定外键约束名称不得超过 64 个字符。在 MySQL 8.0 之前的版本中,当用户未明确指定时,InnoDB 通过在表名后附加 '_ibfk_X' 来自动生成外键约束名称,其中 X 是一个数字。如果表名是多字节 64 个字符,例如下面示例中使用的西里尔表名 'имя_базы_в_кодировке_утф8_длиной_больше_чем_45имя_азы_в_кодировк',则自动生成的外键约束名称超过 64 个字符。应通过删除约束并通过确保外键约束名称不超过 64 个字符来添加具有显式约束名称的约束来更改这些表。

mysql> ALTER TABLE `имя_базы_в_кодировке_утф8_длиной_больше_чем_45имя_азы_в_кодировк` DROP FOREIGN KEY `имя_базы_в_кодировке_утф8_длиной_больше_чем_45имя_азы_в_кодировк_ibfk_1`;
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0
 
mysql> ALTER TABLE `имя_базы_в_кодировке_утф8_длиной_больше_чем_45имя_азы_в_кодировк` ADD CONSTRAINT FOREIGN KEY FK1 (fld2) REFERENCES t1(fld1);
Query OK, 0 rows affected (0.13 sec)
Records: 0  Duplicates: 0  Warnings: 0

触发器兼容

MySQL 5.0.17 之前的 CREATE TRIGGER 不支持 definer 属性。此类具有缺失/空定义器属性或无效创建上下文(即 character_set_client、collat​​ion_collection、数据库排序规则属性)的触发器定义 一直存在到 MySQL 5.6 无法升级。这些触发器可以通过在 MySQL 5.6 中运行带有检查升级选项的mysqlcheck或CHECK TABLE来识别。

$./client/mysqlcheck --user=root --socket=5.6/data/mysql.sock --databases triggers --check-upgrade 
triggers.t1
Warning  : No definer attribute for trigger 'triggers'.'trg_t1_before_insert'. The trigger will be activated under the authorization of the invoker, which may have insufficient privileges. Please recreate the trigger.
Warning  : No definer attribute for trigger 'triggers'.'t1_bi'. The trigger will be activated under the authorization of the invoker, which may have insufficient privileges. Please recreate the trigger.
Warning  : No definer attribute for trigger 'triggers'.'trg_t1_after_insert_1'. The trigger will be activated under the authorization of the invoker, which may have insufficient privileges. Please recreate the trigger.
Warning  : No definer attribute for trigger 'triggers'.'trg_t1_after_insert'. The trigger will be activated under the authorization of the invoker, which may have insufficient privileges. Please recreate the trigger.
Warning  : No definer attribute for trigger 'triggers'.'trg_t1_after_insert_3'. The trigger will be activated under the authorization of the invoker, which may have insufficient privileges. Please recreate the trigger.
Warning  : No definer attribute for trigger 'triggers'.'trg_t1_before_update_3'. The trigger will be activated under the authorization of the invoker, which may have insufficient privileges. Please recreate the trigger.
Warning  : No definer attribute for trigger 'triggers'.'trg_t1_before_update'. The trigger will be activated under the authorization of the invoker, which may have insufficient privileges. Please recreate the trigger.
Warning  : No definer attribute for trigger 'triggers'.'trg_t1_after_update'. The trigger will be activated under the authorization of the invoker, which may have insufficient privileges. Please recreate the trigger.
Warning  : No definer attribute for trigger 'triggers'.'trg1'. The trigger will be activated under the authorization of the invoker, which may have insufficient privileges. Please recreate the trigger.
status   : OK
triggers.t2                                        OK

 
mysql> check table t1;
+-------------+-------+----------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table       | Op    | Msg_type | Msg_text                                                                                                                                                                                                         |
+-------------+-------+----------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| triggers.t1 | check | Warning  | No definer attribute for trigger 'triggers'.'trg_t1_before_insert'. The trigger will be activated under the authorization of the invoker, which may have insufficient privileges. Please recreate the trigger.   |
| triggers.t1 | check | Warning  | No definer attribute for trigger 'triggers'.'t1_bi'. The trigger will be activated under the authorization of the invoker, which may have insufficient privileges. Please recreate the trigger.                  |
| triggers.t1 | check | Warning  | No definer attribute for trigger 'triggers'.'trg_t1_after_insert_1'. The trigger will be activated under the authorization of the invoker, which may have insufficient privileges. Please recreate the trigger.  |
| triggers.t1 | check | Warning  | No definer attribute for trigger 'triggers'.'trg_t1_after_insert'. The trigger will be activated under the authorization of the invoker, which may have insufficient privileges. Please recreate the trigger.    |
| triggers.t1 | check | Warning  | No definer attribute for trigger 'triggers'.'trg_t1_after_insert_3'. The trigger will be activated under the authorization of the invoker, which may have insufficient privileges. Please recreate the trigger.  |
| triggers.t1 | check | Warning  | No definer attribute for trigger 'triggers'.'trg_t1_before_update_3'. The trigger will be activated under the authorization of the invoker, which may have insufficient privileges. Please recreate the trigger. |
| triggers.t1 | check | Warning  | No definer attribute for trigger 'triggers'.'trg_t1_before_update'. The trigger will be activated under the authorization of the invoker, which may have insufficient privileges. Please recreate the trigger.   |
| triggers.t1 | check | Warning  | No definer attribute for trigger 'triggers'.'trg_t1_after_update'. The trigger will be activated under the authorization of the invoker, which may have insufficient privileges. Please recreate the trigger.    |
| triggers.t1 | check | Warning  | No definer attribute for trigger 'triggers'.'trg1'. The trigger will be activated under the authorization of the invoker, which may have insufficient privileges. Please recreate the trigger.                   |
| triggers.t1 | check | status   | OK                                                                                                                                                                                                               |
+-------------+-------+----------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
10 rows in set (0.01 sec)
 
 
mysql> select definer, trigger_name from INFORMATION_SCHEMA.TRIGGERS where definer='';
+---------+------------------------+
| definer | trigger_name           |
+---------+------------------------+
|         | trg_t1_before_insert   |
|         | t1_bi                  |
|         | trg_t1_after_insert_1  |
|         | trg_t1_after_insert    |
|         | trg_t1_after_insert_3  |
|         | trg_t1_before_update_3 |
|         | trg_t1_before_update   |
|         | trg_t1_after_update    |
|         | trg1                   | 
+---------+------------------------+
 9 rows in set (0.02 sec)
mysql>

应转储/重新加载此类触发器以解决问题:

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

并行查询导致的排序问题

PolarDB MySQL 8.0开始支持并行查询能力,并行扫描由于随机访问数据导致MySQL默认串行扫描的顺序每次会随机变化,尤其涉及到分页的SQL,需要要生成给定的排序顺序,请提供一个ORDER BY子句保证顺序。

子查询问题

子查询中的order by 不再起作用,例:

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

内层的order by 会被5.7、8.0的优化器忽略,需要修改语句,最简单是添加 limit 使排序生效,例如:

SELECT *
FROM
 (
  SELECT * FROM `information_schema`. TABLES
  ORDER BY table_name DESC limit 10000 # 需要足够大的行数
 ) AS sg
GROUP BY table_name

派生表问题

优化器现在以一致的方式处理子句中的派生表和视图, FROM以更好地避免不必要的物化,并允许使用产生更有效执行计划的下推条件。但是,在 PolarDB MySQL 8.0 中,以及对于修改表之类的语句,DELETE对 UPDATE先前实现的派生表使用合并策略可能会导致 ER_UPDATE_TABLE_USED错误:

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 clause

当将派生表合并到外部查询块中会导致从表中选择和修改表的语句时发生错误。(物化不会导致问题,因为它实际上将派生表转换为单独的表。)避免此错误的解决方法是在执行语句之前禁用系统变量的derived_merge 标志 :optimizer_switch

SET optimizer_switch = 'derived_merge=off';

derived_merge标志控制优化器是否尝试将FROM子句中的子查询和视图合并到外部查询块中,假设没有其他规则阻止合并。默认情况下,该标志是on启用合并。设置标志以off 防止合并并避免刚刚描述的错误。有关更多信息,请参阅 第 8.2.2.4 节,“使用合并或实现优化派生表和查看引用”

  • 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);

以前版本的 MySQL 可能允许这样的语句不带括号。在 PolarDB MySQL 8.0 中,强制要求使用括号。

GET_LOCK函数兼容

该 GET_LOCK()功能在 MySQL 5.7.5 中使用元数据锁定 (MDL) 子系统重新实现,并且其功能已得到扩展:

  • 以前, GET_LOCK()  一次只允许获取一个命名锁,第二次 GET_LOCK()  调用释放任何现有锁。现在 GET_LOCK() 允许同时获取多个命名锁,并且不会释放现有锁。

依赖于GET_LOCK()释放任何先前锁的行为的应用程序必须针对新行为进行修改。

  • 获取多个锁的能力会在客户端之间引入死锁的可能性。MDL 子系统检测死锁并 ER_USER_LOCK_DEADLOCK  在发生这种情况时返回错误。
  • MDL 子系统对锁名称施加了 64 个字符的限制,因此该限制现在也适用于命名锁。以前,没有强制执行长度限制。
  • 获取的锁  GET_LOCK() 现在出现在 Performance Schema  metadata_locks 表中。列  OBJECT_TYPE USER LEVEL LOCK ,  OBJECT_NAME 列表示锁名。
  • 一个新功能,  RELEASE_ALL_LOCKS()  允许一次释放所有获得的命名锁。

有关更多信息,请参阅 第 12.15 节,“锁定功能”

其他

客户端兼容

对于 java 应用来说,MySQL Connector/J 升级到 5.1.46 以上版本 到 8.0.8 能够连接到 MySQL 8.0 服务器,但使用 caching_sha2_password. (连接帐户需要连接器/J 8.0.9 或更高版本 caching_sha2_password。)。

dataworks由于未在数据源中设置utf8可能出错,建议修改数据库名,并和RDS的设置一致。在PolarDB MySQL的连接串增加:characterEncoding=utf8&com.mysql.jdbc.faultInjection.serverCharsetIndex=

Unknown system variable 'tx_read_only'

8.0 中已经删除 tx_read_only 环境变更,需要使用 transaction_read_only 代替

select @@tx_read_only

需要改为

select @@transaction_read_only

升级检查器

官方目前提供了8.0升级检查器,目前PolarDB MySQL未支持,自建库升级前请参考检查器

参考文档

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
17天前
|
监控 关系型数据库 MySQL
如何升级MySQL数据库?
【10月更文挑战第16天】如何升级MySQL数据库?
|
2月前
|
监控 关系型数据库 MySQL
如何升级mysql的版本
如何升级mysql的版本
386 2
|
2月前
|
存储 监控 关系型数据库
如何升级MySQL版本?
如何升级MySQL版本?
110 2
|
22天前
|
关系型数据库 MySQL 分布式数据库
零基础教你用云数据库PolarDB搭建企业网站,完成就送桌面收纳桶!
零基础教你用云数据库PolarDB搭建企业网站,完成就送桌面收纳桶,邀请好友完成更有机会获得​小米Watch S3、小米体重称​等诸多好礼!
零基础教你用云数据库PolarDB搭建企业网站,完成就送桌面收纳桶!
|
2月前
|
关系型数据库 MySQL Serverless
探索PolarDB MySQL版:Serverless数据库的灵活性与性能
本文介绍了个人开发者对阿里云PolarDB MySQL版,特别是其Serverless特性的详细评测体验。评测涵盖了产品初体验、性能观测、Serverless特性深度评测及成本效益分析等方面。尽管试用过程中遇到一些小问题,但总体而言,PolarDB MySQL版表现出色,提供了高性能、高可用性和灵活的资源管理,是个人开发者和企业用户的优秀选择。
|
3月前
|
关系型数据库 MySQL 分布式数据库
PolarDB 与传统数据库的性能对比分析
【8月更文第27天】随着云计算技术的发展,越来越多的企业开始将数据管理和存储迁移到云端。阿里云的 PolarDB 作为一款兼容 MySQL 和 PostgreSQL 的关系型数据库服务,提供了高性能、高可用和弹性伸缩的能力。本文将从不同角度对比 PolarDB 与本地部署的传统数据库(如 MySQL、PostgreSQL)在性能上的差异。
209 1
|
5天前
|
关系型数据库 分布式数据库 数据库
锦鲤附体 | PolarDB数据库创新设计赛,好礼不停!
锦鲤附体 | PolarDB数据库创新设计赛,好礼不停!
|
1月前
|
关系型数据库 分布式数据库 数据库
PolarDB 开源:推动数据库技术新变革
在数字化时代,数据成为核心资产,数据库的性能和可靠性至关重要。阿里云的PolarDB作为新一代云原生数据库,凭借卓越性能和创新技术脱颖而出。其开源不仅让开发者深入了解内部架构,还促进了数据库生态共建,提升了稳定性与可靠性。PolarDB采用云原生架构,支持快速弹性扩展和高并发访问,具备强大的事务处理能力及数据一致性保证,并且与多种应用无缝兼容。开源PolarDB为国内数据库产业注入新活力,打破国外垄断,推动国产数据库崛起,降低企业成本与风险。未来,PolarDB将在生态建设中持续壮大,助力企业数字化转型。
78 2
|
2月前
|
关系型数据库 分布式数据库 数据库
2024年全国大学生计算机系统能力大赛PolarDB数据库创新设计赛(天池杯)等你来战!
2024年全国大学生计算机系统能力大赛PolarDB数据库创新设计赛(天池杯)等你来战!
223 10
2024年全国大学生计算机系统能力大赛PolarDB数据库创新设计赛(天池杯)等你来战!
|
2月前
|
关系型数据库 分布式数据库 数据库
来!跟通义灵码一起参加PolarDB 数据库创新设计赛,突破传统,探索人机协作
无论你是数据库新手,还是技术大咖,通义灵码邀请你参加2024 年全国大学生计算机系统能力大赛 PolarDB 数据库创新设计赛(天池杯),新参赛模式启动,挑战极限!
103 11