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

本文涉及的产品
云原生数据库 PolarDB MySQL 版,Serverless 5000PCU 100GB
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
云数据库 RDS MySQL Serverless,价值2615元额度,1个月
简介: 升级概述为什么选择升级到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未支持,自建库升级前请参考检查器

参考文档

相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
11天前
|
SQL 关系型数据库 MySQL
【MySQL-1】理解关系型数据库&数据的数据模型
【MySQL-1】理解关系型数据库&数据的数据模型
|
13天前
|
DataWorks 关系型数据库 MySQL
DataWorks产品使用合集之在DataWorks中,如何通过PolarDB for MySQL来查看binlog日志
DataWorks作为一站式的数据开发与治理平台,提供了从数据采集、清洗、开发、调度、服务化、质量监控到安全管理的全套解决方案,帮助企业构建高效、规范、安全的大数据处理体系。以下是对DataWorks产品使用合集的概述,涵盖数据处理的各个环节。
28 1
|
13天前
|
SQL 关系型数据库 MySQL
【MySQL】:探秘主流关系型数据库管理系统及SQL语言
【MySQL】:探秘主流关系型数据库管理系统及SQL语言
26 0
|
14天前
|
关系型数据库 MySQL 测试技术
【专栏】PostgreSQL数据库向MySQL迁移的过程、挑战及策略
【4月更文挑战第29天】本文探讨了PostgreSQL数据库向MySQL迁移的过程、挑战及策略。迁移步骤包括评估规划、数据导出与转换、创建MySQL数据库、数据导入。挑战包括数据类型不匹配、函数和语法差异、数据完整性和性能问题。应对策略涉及数据类型映射、代码调整、数据校验和性能优化。迁移后需进行数据验证、性能测试和业务验证,确保顺利过渡。在数字化时代,掌握数据库迁移技能对技术人员至关重要。
|
14天前
|
关系型数据库 MySQL 分布式数据库
PolarDB产品使用合集之PolarDB MySQL标准版中带有分区功能吗
PolarDB产品使用合集涵盖了从创建与管理、数据管理、性能优化与诊断、安全与合规到生态与集成、运维与支持等全方位的功能和服务,旨在帮助企业轻松构建高可用、高性能且易于管理的数据库环境,满足不同业务场景的需求。用户可以通过阿里云控制台、API、SDK等方式便捷地使用这些功能,实现数据库的高效运维与持续优化。
|
15天前
|
关系型数据库 分布式数据库 数据库
VLDB顶会论文解读 | PolarDB MySQL高性能强一致集群核心技术详解
在VLDB2023会议上,阿里云瑶池数据库团队的论文介绍了PolarDB-SCC,这是一个创新的云原生数据库系统,确保了低延迟的全局强一致读取。PolarDB-SCC解决了传统主从架构中只读节点可能返回过期数据的问题,实现了在不影响性能的情况下提供强一致性。通过重新设计的主从信息同步机制、线性Lamport时间戳和细粒度修改跟踪,以及利用RDMA优化的日志传输,PolarDB-SCC已经在PolarDB中成功应用超过一年,成为业界首个无感知全局一致性读的云原生数据库解决方案。
66715 0
|
3天前
|
关系型数据库 MySQL 数据库
docker MySQL删除数据库时的错误(errno: 39)
docker MySQL删除数据库时的错误(errno: 39)
10 0
|
1天前
|
关系型数据库 MySQL 数据库
mysql 设置环境变量与未设置环境变量连接数据库的区别
设置与未设置MySQL环境变量在连接数据库时主要区别在于命令输入方式和系统便捷性。设置环境变量后,可直接使用`mysql -u 用户名 -p`命令连接,而无需指定完整路径,提升便利性和灵活性。未设置时,需输入完整路径如`C:\Program Files\MySQL\...`,操作繁琐且易错。为提高效率和减少错误,推荐安装后设置环境变量。[查看视频讲解](https://www.bilibili.com/video/BV1vH4y137HC/)。
17 3
mysql 设置环境变量与未设置环境变量连接数据库的区别
|
3天前
|
关系型数据库 MySQL 数据库连接
用Navicat备份Mysql演示系统数据库的时候出:Too Many Connections
用Navicat备份Mysql演示系统数据库的时候出:Too Many Connections
|
4天前
|
存储 Oracle 关系型数据库
oracle 数据库 迁移 mysql数据库
将 Oracle 数据库迁移到 MySQL 是一项复杂的任务,因为这两种数据库管理系统具有不同的架构、语法和功能。
15 0