升级宝典!阿里云RDS MySQL助力MySQL5.7升级到8.0

本文涉及的产品
云原生数据库 PolarDB 分布式版,标准版 2核8GB
RDS PostgreSQL Serverless,0.5-4RCU 50GB 3个月
推荐场景:
对影评进行热评分析
RDS SQL Server Serverless,2-4RCU 50GB 3个月
推荐场景:
简介: 2023年10月,社区MySQL5.7停服。阿里云RDS MySQL对MySQL5.7的服务将进行到2024年10月21日,同时,并将通过有效的方案和大量的升级经验,鼓励和助力广大企业和开发者将MySQL5.7升级到MySQL8.0。

1. 前言

2015 年 10 月,Oracle 正式推出 MySQL 5.7,相比 MySQL 5.6,其具备更好的性能、更多的功能、更高的安全性,逐步成为了 MySQL 的首选版本。2018 年, MySQL 8.0 发布,相比 MySQL 5.7 有了进一步的提升 。2023 年 10 月 25 日,社区推出 MySQL 5.7.44,该版本为最后一个 5.7 版本,意味着社区将停止对 MySQL 5.7 的维护,不再进行缺陷的修复和功能的更新,同时社区也鼓励用户将 MySQL 5.7 升级到 MySQL 8.0[1-2]

图 1  MySQL 生命周期

事实上 MySQL 5.7 作为备受信赖的服务版本,现今依然拥有广大的用户群体。据 Shadowserver 数据统计[3],截止至 2022 年 5 月,在 MySQL 的使用者中,约有 47% 的人仍在坚持使用 5.7 作为主要服务版本。在阿里云 RDS MySQL 实例列表中,MySQL 5.7 的使用比例也达到了相近的数量。然而,随着生命周期结束,由于缺乏后续的更新和支持,不再维护的 MySQL 5.7 面临着种种问题,难以满足不断变化的需求。

image.png

图 2  社区MySQL主要服务版本

相对于 MySQL 5.7,MySQL 8.0 中带来了众多强大、实用的特性,如:

表 1  MySQL 8.0 部分新特性

功能

收益

DDL log

解决了 MySQL 5.7 中 DDL 中断的文件残留问题,确保了文件操作的原子性,同时解决了 Server 层和引擎层数据不一致的问题。

Instant DDL

大大缩短 DDL 执行的时长,快速完成表结构的变更,同时消除了 Binlog 复制延迟。

增强 JSON 支持

新增了多个 JSON 相关的函数,同时对 JSON 的内存使用做了优化。

隐藏索引

可设置索引对优化器不可见,避免了潜在的重复删除、重建索引的操作。

克隆插件

免去传统备份恢复 + 主从复制的方式,直接在源实例上授权、克隆,大大提高了可拓展性。


与此同时,阿里云 RDS MySQL 8.0 在社区 MySQL 8.0 的基础上做了深度优化,开发了许多高级特性[4],如 Binlog in Redo 功能通过在事务提交时将 Binlog 内容同步写入到Redo Log中以减少磁盘操作,提高了数据库性能;通用云盘 IO 加速功能通过扩展InnoDB Buffer Pool将一部分数据页和温数据缓存,在无任何成本变化和业务改动的情况下,可以获得实例 IO 性能的大幅度提升;冷热数据分离功能通过将云盘归档数据转存至 OSS 端,大幅降低用户存储成本;RTO 相关优化通过优化 REDO 应用过程和启动路径等,大幅缩短实例启动时间,提升实例的可用性。通过架构的持续演进和内核的不断优化,阿里云 RDS MySQL 相较社区版本拥有更高的稳定性和安全性、更强的性能和更多的功能,为用户提供稳定可靠、简单易用的数据库服务。

更多 RDS MySQL 自研的高级特性可参考阿里云 RDS 官方文档

作为更强大的分支,MySQL 8.0 的维护周期将会更长久,也会逐步解决现有问题。长久来看,无论是个人用户还是企业用户,都应该推动 MySQL 5.7 到 MySQL 8.0 的升级。


2. 升级前的检查

图 3  MySQL 8.0 与 MySQL 5.7 的主要差异

尽管有许多不得不升级的理由,但实际上从 MySQL 5.7 升级到 8.0 并不是一件轻而易举的事情。MySQL 8.0 与 MySQL 5.7 相比有许多跨度很大的变化,包括了数据字典、存储引擎和SQL语法等方面的改动。由于版本间的差异,在升级之前,用户需要充分评估并做好充足的准备工作。

和 MySQL 5.6 升级到 MySQL 5.7 不同,MySQL 5.7 升级到 MySQL 8.0 是通过 inplace upgrade 的方式进行的,直接使用 MySQL 8.0 的二进制文件拉起 5.7 旧实例,升级程序就会自动进行相关的检查和升级。前文所述的升级前的准备工作实际上就是去消除升级程序中无法自动处理的的“不兼容的”变化,主要工作包括[5-9]


  1. MySQL 8.0 中引入了全新的数据字典用于保存数据库中的元信息,Server 层和 InnoDB 层共享一份元数据。8.0 中的 information_schema 中的视图全部源自于数据字典表,和 InnoDB 相关的视图被重命名(INNODB_SYS_XXX 重命名为 INNODB_XXX),若用户的应用依赖于这些视图,需要确保应用上做出对应的修改;在升级前需要确认业务是否依赖于 8.0 中被删除的系统表(如 mysql.proc、mysql.event 等),若存在则需使用新的访问方式去获取所需的数据;此外,对于和 8.0 系统表同名的用户表(如 catalogs、routines 等),需要手动执行 RENAME/DROP TABLE 操作。
  2. 8.0 不再支持的旧的数据类型(如 old style decimals, old style varchar, old style TIME、DATETIME 和 TIMESTAMP 等),问题表需要在升级前通过 REPAIR TABLE 或逻辑导出 + 导入的方式做修复。
  3. 分区表的处理在 8.0 中由 Server 层下沉至引擎层,MySQL Server 不再支持通用分区。 non-native 的分区表在 8.0 中被废弃,因此需要将此类的分区表修改为 native 类型的分区表(如 InnoDB 引擎)或是删除该分区表。
  4. 较老版本的 5.7(version < 5.0.17)的 trigger 不支持 definer 属性,因此在 5.7 实例中可能会存在缺失 definer 的 trigger,这将会导致升级到 8.0 的过程失败,因此需要在升级前重新创建此类 trigger 。
  5. 8.0 中对于外键约束的长度有限制,超长的外键约束会在升级的过程中报错导致失败,因此需要在升级前将问题外键修改为小于 64 字符长度的约束;8.0 之前视图的列名长度上限是 255 字符,而 8.0 对于视图的列名长度的上限是 64 字符,因此需要在升级前将视图的超长列名修改为小于 64 字符长度的列名;8.0 中单个 ENUM 和 SET 列元素的长度不得超过 255 个字符或 1020 个字节,因此需要在升级前超出限制的 ENUM 和 SET 进行修改。
  6. 若 frm 文件和 InnoDB 数据字典表元数据信息不匹配会导致错误,这种情况需要在升级前对数据做逻辑导出和导入;若存在游离的.frm 文件(即不含.ibd 文件仅有.frm 文件),则需要做相应的清理。
  7. 8.0 废弃了部分空间函数,如果生成列中包含了此类被删除的函数(新引入的空间函数以"ST"和"MBR"开头),则需要在升级前对对应的列做修改。
  8. 升级前必须保证 5.7 实例 clean shutdown ,即需要保证升级前没有待应用的 REDO log 和等待回滚的事务。
  9. 8.0 中引入了新的保留字,大多数的保留字禁止作为表名、列名等,因此需要对 5.7 包含 8.0 引入的新保留字的部分做处理。
  10. 使用废弃的 sql_mode 变量内容(如 NO_AUTO_CREATE_USER 等)会导致 8.0 实例无法启动,因此需要在升级前修改 sql_mode 至 8.0 支持的模式。
  11. 较新版本的 8.0 实例(version >= 8.0.13),共享表空间(系统表空间和通用表空间)中不能存在 InnoDB 类型的分区表,因此在升级前需要把共享表空间移动至独立表空间。
  12. 新版本的 8.0 实例不支持GROUP BY...[ASC | DESC]的语法,因此需要在升级前修改/删除包含相应句法的存储过程。
  13. 5.7 中 lower_case_table_names 是一个可修改的值,但在 8.0 中 lower_case_table_names 是一个初始化参数,实例一旦初始化就无法在后续做修改。若在升级时修改修改该参数为 1,需要确保升级前库表名称为小写,避免出现升级错误。

   

     除了上述的准备工作外,版本间存在的驱动、错误码、参数、优化器差异等也需要业务上做适配。对于自建用户,5.7 到 8.0 的大版本升级过程前的准备可以利用 MySQL shell、mysqlcheck 工具和社区的升级检查文档进行检查。关于 5.7 到 8.0 的变化和检查细节可以参考文末的社区文档链接。


3. 为什么升级还是失败了?

尽管社区提供了相应的检查工具和帮助文档去帮助用户做升级前的检查和问题的解决,然而常常会发现升级过程还是失败了,抛出了各式各样的错误,难以从日志信息中去逐一分析升级失败的原因。分析困难的原因包括但不局限于以下几点:

  1. 报错不明确,不同原因导致的错误可能会在日志中记录相同/相似的错误。用户需要花费大量的时间和精力来排查错误的根本原因,增加了升级的困难度。
  2. 报错不完整,当问题出现时,针对性解决后发现重复的问题再次导致失败,原因是升级程序在首次检测到某一类错误时就提前退出了,相同问题无法被一次性全部检测。用户需要进行多次尝试和排查,增加了升级的复杂性和时间成本。
  3. 部分错误只给出错误提示,却没有对应的解法。用户需要自行查找解决方案或向社区寻求帮助,增加了升级过程中的困惑和不确定性。
  4. 部分 5.7 或更老版本存在的问题被修复,但依旧缺少对存量实例的处理。

笔者在解决大版本升级问题中发现,由于版本差异,加上存在更老的 5.x 版本信息残留,大版本升级涉及的问题琐碎繁多,升级失败的根源大多集中在数据字典上。


4. 轻松升级到阿里云 RDS MySQL 8.0

阿里云 RDS MySQL 拥有国内乃至亚洲最大规模的 MySQL 实例,每月有数十个的实例进行 5.7 到 8.0 的大版本升级。在此过程中,我们积累了大量的经验,搭建了完备的预检查逻辑并对多个大版本升级相关 Bug 进行了分析和修复。

笔者所在的阿里云 RDS MySQL 团队所做的 5.7 升级 8.0 的专项治理,旨在提前发现问题、平滑升级过程,提升大版本升级的成功率,让用户拥有更舒适的大版本升级体验,享受到阿里云 RDS MySQL 8.0 提供的高性能和可靠性。此外,RDS 将对 MySQL 各个版本提供更长期的支持[10],给用户留下更长的缓冲期。


表 2 社区 MySQL 和 阿里云 RDS MySQL EOF

数据库大版本

社区发布时间

RDS发布时间

社区生命周期结束时间

RDS停止支持时间

MySQL 8.0

2018年04月19日

2019年05月

预计2026年04月

预计2027年04月19日

MySQL 5.7

2015年10月21日

2016年11月

预计2023年10月25 日

预计2024年10月21日


在自建 MySQL 5.7 升级 8.0 的过程中,除去前期繁复的检查工作外,根据报错信息逐步进行修复的过程可能会持续多次,并且还存在问题难以修复导致无法升级的情况。整个升级过程停机时间长、返工次数多、耗费时间精力。

图 4  自建 MySQL 5.7 和阿里云 RDS MySQL 5.7 升级到 8.0 流程对比


针对线上常见大版本升级失败问题,阿里云 RDS MySQL 内核侧做了修复工作,当用户的实例存在修复覆盖下的问题时,升级过程将不会失败,可实现无感升级;对于内核侧无法直接修复的问题,阿里云 RDS MySQL 管控侧主动进行多项兼容性检测,在实例触发大版本升级动作前提前发现问题并做出提示,用户在无需重复启停的情况下就能够解决大部分问题,同时对于升级失败的节点会自动回滚到升级前的状态,不影响业务。相比自建用户的升级,用户在进行阿里云 RDS MySQL 的大版本升级时,无需复杂的检查、无需反复核查错误日志并逐一解决问题,仅仅需要点击控制台的升级按钮,一切的升级动作都将在后台完成。经过系列的治理,2023 ~ 2024 年阿里云 RDS MySQL 5.7 升级 8.0 的成功率达到了 97.3% 以上。


表 3 阿里云 RDS MySQL 5.7 升级 8.0 的部分治理工作

导致升级失败的问题

治理

是否需要用户进一步干预

Server与InnoDB字段、索引大小写不一致[11]

在升级过程主动检测并修复 Server 层和 InnoDB 的不一致问题,用户无需手动干预即可直接实现升级。

无需用户操作

表、字段、索引和存储过程包含乱码[12]

在升级过程中主动检测并清除无效的乱码信息,用户无需手动检查和处理;在预检查逻辑中定位涉及到数据的乱码信息,并向用户告知错误信息。

需要用户处理有效数据的乱码信息

5.x 老版本临时表残留[13]

在升级过程中主动清除系统表中临时表残留的元信息,解决用户无法升级的问题。

无需用户操作

外键分区表不兼容[14]

在预检查逻辑中定位包含外键和分区表冲突的表信息,方便用户提前处理。

需要用户解决表中外键和分区表的冲突

空间列和 B-tree 索引不兼容[15]

在预检查逻辑中定位包含空间列和 B-tree 索引冲突的表信息,方便用户提前处理。

需要用户解决表中空间列和 B-tree 索引的冲突

外键约束、视图列名、enum/set 长度超限制

在预检查逻辑定位不满足长度要求的外键约束、视图列名和 enum/set 字段,方便用户提前处理

需要用户修改超出限制的长度

包含 discard 表空间

在预检查逻辑定位 discard 的表空间,方便用户提前处理

需要用户导入表空间或删除表信息。

包含待 repair 的表

在预检查逻辑定位 待 repair 的表,方便用户提前处理

需要用户执行 repair 的操作。


案例 1:Server与InnoDB字段、索引大小写不一致导致升级失败

自建 MySQL 升级失败:

[ERROR] [MY-013140] [Server] Comment for table 'test.t4' contains an invalid utf8mb3 character string: '\xF0\x9F\x90'.
[ERROR] [MY-010022] [Server] Failed to Populate DD tables.
[ERROR] [MY-010119] [Server] Aborting

RDS MySQL 自动修正引擎元数据,升级成功:

[Warning] [MY-012071] [InnoDB] Column name case mismatch: From InnoDB: id_c From Server: Id_c, DD will be consistent with Server one.
[Note] [MY-011088] [Server] Data dictionary initializing version '80023'.


案例 2:表、字段、索引和存储过程包含乱码导致升级失败

自建 MySQL 升级失败:

[ERROR] [MY-013140] [Server] Comment for table 'test.t4' contains an invalid utf8mb3 character string: '\xF0\x9F\x90'.
[ERROR] [MY-010022] [Server] Failed to Populate DD tables.
[ERROR] [MY-010119] [Server] Aborting

RDS MySQL 自动清除表、字段和索引注释的乱码,升级成功:

[Warning] [MY-025076] [Server] Clear utf8mb3 character strings: '\xF0\x9F\x90' in comment of table 'test.t4'.
[Note] [MY-011088] [Server] Data dictionary initializing version '80023'.


案例 3:5.x 老版本临时表残留导致升级失败

自建 MySQL 升级失败:

[ERROR] [MY-012216] [InnoDB] Cannot open datafile for read-only: '/tmp/#sql1dc6f_2_0.ibd' OS error: 71
[ERROR] [MY-010020] [Server] Data Dictionary initialization failed.
[ERROR] [MY-010119] [Server] Aborting

RDS MySQL 自动清理残留的元信息,升级成功:

[ERROR] [MY-012216] [InnoDB] Cannot open datafile for read-only: '/tmp/#sql8947_1_0.ibd' OS error: 71
[Warning] [MY-025078] [InnoDB] Skip orphaned tablespace during upgrade, space_id: 7, filepath: /tmp/#sql8947_1_0.ibd.
[Note] [MY-011088] [Server] Data dictionary initializing version '80023'.


当然,阿里云 RDS MySQL 团队并不是完全根解了 MySQL 5.7 升级到 8.0 过程的所有问题,在场景上、方案上都有需要完善之处。当前大版本升级过程为了保证用户实例不受影响,升级过程首先会在源实例的克隆实例上进行,当克隆实例完成升级后再将用户实例做切换,并释放旧版本实例,这个过程难免会有更多的时间和资源的消耗,更好、更快的方案值得探索;当前的治理手段无法覆盖到所有的升级失败场景,无法保证 100%的升级成功率,同时用户行为和升级冲突的情形往往也需要用户介入去做进一步的处理,无法做到完全的全自动升级,进一步降低用户干预占比是需要持续努力的方向。

关于 RDS MySQL 的升级,更多的细节可以参考官方的升级帮助文档[16]


5. 总结

升级前详细的检查、升级中逐步解决引发失败的问题、升级后做好验证和测试工作,这些都是大版本升级必须要关注的问题。大版本升级失败问题的解决不是一蹴而就的,阿里云 RDS MySQL 团队持续在进行相关问题的修复和建设,同时随着 8.0 版本走向稳定,相信大版本升级的问题会逐步收敛,直至完全解决。


6. 参考文档

[1] https://www.mysql.com/support/

[2] https://dev.mysql.com/doc/relnotes/mysql/5.7/en/news-5-7-44.html

[3] https://www.shadowserver.org/news/over-3-6m-exposed-mysql-servers-on-ipv4-and-ipv6/

[4] https://help.aliyun.com/zh/rds/apsaradb-rds-for-mysql/overview-of-alisql-features

[5] https://dev.mysql.com/doc/refman/8.0/en/upgrading-from-previous-series.html

[6] https://dev.mysql.com/doc/refman/8.0/en/mysql-nutshell.html

[7] https://dev.mysql.com/doc/refman/8.0/en/added-deprecated-removed.html

[8] https://dev.mysql.com/blog-archive/upgrading-to-mysql-8-0-here-is-what-you-need-to-know/

[9] https://dev.mysql.com/doc/refman/8.0/en/upgrade-prerequisites.html

[10]https://help.aliyun.com/zh/rds/apsaradb-rds-for-mysql/major-version-lifecycle-description

[11] https://dev.mysql.com/doc/relnotes/mysql/5.7/en/news-5-7-6.html

[12] https://bugs.mysql.com/bug.php?id=110177

[13] https://bugs.mysql.com/bug.php?id=110722

[14] https://bugs.mysql.com/bug.php?id=111134

[15] https://bugs.mysql.com/bug.php?id=111616

[16] https://help.aliyun.com/zh/rds/apsaradb-rds-for-mysql/upgrade-the-major-engine-version-of-an-apsaradb-rds-for-mysql-instance

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
25天前
|
监控 关系型数据库 MySQL
如何升级MySQL数据库?
【10月更文挑战第16天】如何升级MySQL数据库?
|
2月前
|
监控 关系型数据库 MySQL
如何升级mysql的版本
如何升级mysql的版本
455 2
|
2月前
|
存储 监控 关系型数据库
如何升级MySQL版本?
如何升级MySQL版本?
127 2
|
4月前
|
关系型数据库 MySQL Serverless
函数计算产品使用问题之调用RDS MySQL的步骤是怎样的
函数计算产品作为一种事件驱动的全托管计算服务,让用户能够专注于业务逻辑的编写,而无需关心底层服务器的管理与运维。你可以有效地利用函数计算产品来支撑各类应用场景,从简单的数据处理到复杂的业务逻辑,实现快速、高效、低成本的云上部署与运维。以下是一些关于使用函数计算产品的合集和要点,帮助你更好地理解和应用这一服务。
|
3月前
|
SQL 存储 Oracle
MySQL 项目中 SQL 脚本更新、升级方式,防止多次重复执行
MySQL 项目中 SQL 脚本更新、升级方式,防止多次重复执行
64 0
|
8天前
|
SQL 关系型数据库 MySQL
go语言数据库中mysql驱动安装
【11月更文挑战第2天】
22 4
|
6天前
|
SQL 关系型数据库 MySQL
12 PHP配置数据库MySQL
路老师分享了PHP操作MySQL数据库的方法,包括安装并连接MySQL服务器、选择数据库、执行SQL语句(如插入、更新、删除和查询),以及将结果集返回到数组。通过具体示例代码,详细介绍了每一步的操作流程,帮助读者快速入门PHP与MySQL的交互。
19 1
|
1月前
|
存储 关系型数据库 MySQL
Mysql(4)—数据库索引
数据库索引是用于提高数据检索效率的数据结构,类似于书籍中的索引。它允许用户快速找到数据,而无需扫描整个表。MySQL中的索引可以显著提升查询速度,使数据库操作更加高效。索引的发展经历了从无索引、简单索引到B-树、哈希索引、位图索引、全文索引等多个阶段。
61 3
Mysql(4)—数据库索引
|
15天前
|
监控 关系型数据库 MySQL
数据库优化:MySQL索引策略与查询性能调优实战
【10月更文挑战第27天】本文深入探讨了MySQL的索引策略和查询性能调优技巧。通过介绍B-Tree索引、哈希索引和全文索引等不同类型,以及如何创建和维护索引,结合实战案例分析查询执行计划,帮助读者掌握提升查询性能的方法。定期优化索引和调整查询语句是提高数据库性能的关键。
76 1
|
17天前
|
关系型数据库 MySQL Linux
在 CentOS 7 中通过编译源码方式安装 MySQL 数据库的详细步骤,包括准备工作、下载源码、编译安装、配置 MySQL 服务、登录设置等。
本文介绍了在 CentOS 7 中通过编译源码方式安装 MySQL 数据库的详细步骤,包括准备工作、下载源码、编译安装、配置 MySQL 服务、登录设置等。同时,文章还对比了编译源码安装与使用 RPM 包安装的优缺点,帮助读者根据需求选择最合适的方法。通过具体案例,展示了编译源码安装的灵活性和定制性。
59 2

相关产品

  • 云数据库 RDS MySQL 版
  • 云数据库 RDS