亚马逊AWS官方博客

Aurora MySQL 2(兼容 MySQL 5.7)升级前检查

从传统企业到互联网系统,自单机数字化系统到生成式 AI 盛行的今天,几十年来数据库一直承载着企业的核心数据资产。而数据库运维的核心就是稳定,高效,安全。提到安全,无法回避的就是版本生命周期的结束,升级到新版本的需求。

Aurora MySQL 2(兼容 MySQL 5.7)的生命周期比社区会更长,详细信息可以参考 Aurora 版本生命周期请注意以下关键时间点:

  • 从现在开始到 2024/10/31,建议您将 Aurora MySQL 2(兼容 MySQL 5.7)升级到 Aurora MySQL 3(兼容 MySQL 8.0)
  • 2024/10/31 之后,Aurora MySQL 2 大版本的标准支持正式停止,您也可以选择 Aurora MySQL 2 扩展支持来继续停留在 Aurora 2 长达三年的时间。

注意:Aurora MySQL 2 将会从 2024 年 12月 1 开始收取扩展支持费用。

安全很重要,但是稳定也无法忽视。为保证数据库的平稳升级,及不同场景的的升级需求差异。我们推出一些列文章,每一篇记录了细分场景的完整过程。

  1. Aurora MySQL 2 升级方案
  2. Aurora MySQL 2 升级前置准备(本文)
  3. Aurora MySQL 2 升级预检查-上
  4. Aurora MySQL 2 升级预检查-下
  5. Aurora MySQL 2 升级之流量兼容性检查辅助工具
  6. Aurora MySQL 2 升级之 Global Database 处理方案
  7. Aurora MySQL 2 升级之下游 Binlog 消费处理方案 – Canal
  8. Aurora MySQL 2 升级之下游 Binlog 消费处理方案 – Flink CDC

凡事预则立,不预则废,乃对敬畏生产之明证。卓有远见,谨慎部署,精心谋划,方能铸就非凡。

《礼记·中庸》

数据库日常维护,尤其是大版本升级,如何提前规避风险,让升级过程平稳,业务影响最小呢? 希望本文的内容,对你的升级有价值。

本文内容更多从 DBA 角度出发,如何规划升级路径,升级前的静态和动态检查等步骤进行详细介绍。本文以 Aurora MySQL 为例,同时也是用其他数据库类型的升级前预检,仅具体命令有差异。

升级前准备工作列表

  • 升级环境准备
  • 静态检查
    • 客户端信息统计
    • 兼容性检查
  • 动态检查
    • SQL 可执行性,及执行性能检测
    • 确定 QPS,TPS,RDS 机型信息,以及 RDS 的业务空闲期,切换窗口的的时间,建议能预留 1 小时以上
    • 确定数据库 size,预估 replica 创建时间
    • 性能压测
  • 升级过程演练
    • 创建一个时间表,用以跟踪主从同步状态的验证
    • 完整走完升级全过程
    • 手动创建反向 replica,用以故障回退
  • 升级中验证步骤
    • 创建一个时间表,用以跟踪主从同步状态的验证。在升级前,确认数据同步正常,无数据丢失情况
    • 检查全部表的统计信息,index 状态。理论上,在升级演练过程中,已经可以发现这些问题。为安全起见,升级过程中,再次检查确认
    • 业务端链接状态测试,防止连接状态缓存,继续访问原有数据库
  • 回滚策略
    • 做好数据库回滚操作的准备。基于时间点恢复,评估是否要在蓝绿部署前,准备一个 replica(切换前,先升主),用于紧急恢复
    • 手动创建反向 replica,以备不时之需

实施步骤详解

1. 升级环境准备

从数据库集群快照还原数据库集群,用以测试升级过程。方法如下:

  1. 登录 AWS Management Console 并通过以下网址打开 Amazon RDS 控制台:https://console.aws.amazon.com/rds/
  2. 在导航窗格中,选择快照
  3. 选择要从其还原的数据库集群快照。
  4. 对于操作,选择还原快照
  5. 将显示还原快照页面。
  6. 选择您要将数据库集群还原到的数据库引擎版本。原定设置情况下,快照还原到与源数据库集群相同的数据库引擎版本(如果该版本可用)。
  7. 对于数据库实例标识符,请输入还原后的数据库集群的名称。
  8. 指定其他设置,如数据库集群存储配置。有关每项设置的信息,请参阅 Aurora 数据库集群的设置。
  9. 选择 Restore DB cluster(还原数据库集群)。

2. 静态检查

2.1 兼容性检查

使用 MySQL Shell 工具进行前置检查,需要解决每一项“Error 检查项”。

目前 MySQL 官方提供的 MySQL Shell 中有专门用作 MySQL 升级兼容性检查的函数 util.checkForServerUpgrade(),我们可以使用该检查函数在升级之前对相应实例进行初步检查,如果检查中出现升级不兼容项目,输出的日志中会有详细的信息记录,并且会在日志末尾对不兼容项目的数量按照 Error、Warnings 以及 Notices 进行分组统计其数量。

对 Amazon RDS 进行实例升级时,升级检查结果记录在 Amazon RDS 的日志记录中,日志文件名为 PrePatchCompatibility.log,当出现直接导致升级失败的错误类型时,也会同时在实例对应 Event 中出现相应的日志记录。

MySQL Shell 升级检查函数 util.checkForServerUpgrade() 具体的使用方法如下:

#wget https://dev.mysql.com/get/Downloads/MySQL-Shell/mysql-shell-8.0.32-linux-glibc2.12-x86-64bit.tar.gz
#tar -xvzf mysql-shell-8.0.32-linux-glibc2.12-x86-64bit.tar.gz
#cd mysql-shell-8.0.32-linux-glibc2.12-x86-64bit/bin
#./mysqlsh
MySQL JS > util.checkForServerUpgrade('admin@your-instance.rds.amazonaws.com:3306',{"password":"123456","targetVersion":"8.0.30"})
The MySQL server at your-instance.rds.amazonaws.com:3306,
version 5.7.38-log - Source distribution, will now be checked for compatibility
issues for upgrade to MySQL 8.0.30...

Errors: 0
Warnings: 4
Notices: 0

以下列出了常见的能直接导致升级失败的检查项,如出现其他导致升级失败的项未列示的情况,可具体分析也可联系作者进一步讨论。以下各项摘取自升级时输出的 PrePatchCompatibility.log。

1) Usage of old temporal type
4) Table names in the mysql schema conflicting with new tables in 8.0
5) Partitioned tables using engines with non native partitioning
6) Foreign key constraint names longer than 64 characters
9) ENUM/SET column definitions containing elements longer than 255 characters
10) Usage of partitioned tables in shared tablespaces
13) Usage of removed GROUP BY ASC/DESC syntax
18) Issues reported by 'check table x for upgrade' command
19) The definer column for mysql.events cannot be null or blank
20) Tables with dangling FULLTEXT index reference

更多细节,请参考文档:保驾护航 – Amazon RDS for MySQL 5.7 到 8.0 升级前置检查

2.2 客户端信息统计

统计所有需要使用这个数据库的客户端,统计客户端的目的如下:

  1. 客户端 JDBC 版本兼容性检查
  2. 客户端 JDBC 配置检查,避免使用 IP 方式访问数据库,应该使用 Endpoint 访问数据库。
  3. 客户端 JDBC 配置修改,如果通过 Replica 或者 DMS 数据迁移的方式进行迁移,就需要修改 JDBC 的连接串配置。
  4. SSL 证书检查,对于使用证书访问数据库的客户端,需要注意证书的版本。MySQL 使用 OpenSSL 来实现安全连接。Amazon RDS for MySQL 支持传输层安全性协议(TLS)版本 1.0、1.1、1.2 和 1.3。TLS 支持取决于 MySQL 版本。下表显示了支持 TLS 的 MySQL 版本。
MySQL 版本 TLS 1.0 TLS 1.1 TLS 1.2 TLS 1.3
MySQL 8.0 不支持 不支持 支持 支持
MySQL 5.7 支持 支持 支持 不支持

如何修改证书,请参考文档:https://docs.aws.amazon.com/zh_cn/AmazonRDS/latest/UserGuide/ssl-certificate-rotation-mysql.html

2.2.1 已经了解统计客户端的目的,那么我们如何统计客户端呢?

通常有两种方法:

  • 通过 AWS Performance Insight 收集信息
  • 通过 Mysql SQL 收集 Session 信息

1. 开启 performance insight,作为升级后性能对比参考

Amazon RDS Performance Insights 是一项数据库性能调优和监控功能,可帮助您迅速评估数据库负载,并确定在何时、何处采取行动。Performance Insights 使用不会影响应用程序性能的轻量级数据收集方法,可轻松查看导致负载的 SQL 语句以及相应的原因。它不需要任何配置或维护,目前可用于 Amazon Aurora(PostgreSQL 和 MySQL 兼容版本)、Amazon RDS for PostgreSQL、MySQL、MariaDB、SQL Server 和 Oracle。

由于可免费将性能历史记录保留七天,因此可轻松跟踪并解决各种问题。如果您需要长期保留,则可以选择付费购买长达两年的性能历史记录保留期。

参考文档:使用 Performance Insights 优化 Amazon RDS for MySQL

2. 通过定时任务执行 SQL 收集 Session 信息

注:建议收集 2 周以上信息,避免报表等等执行频率较低的业务被遗漏。

  • SQL 样例如下:
    mysql -h<aurora_endpoint> -u<username> -p<yourpasssword> -e 'select user,host,DB,info,now() from information_schema.processlist;' >> session_info.txt
  • 收集完 session 信息后,可以将 txt 导入 Mysql 进行统计分析,导入方式如下:
    create  database info;
    create table info.session_info as select user,host,DB,info,now() from information_schema.processlist;
    mysql -h<aurora_endpoint> -u<username> -p<yourpasssword>
    SQL> load data local infile "session_info.txt" into table info.session_info;
    
  • 统计 session 信息
    SELECT SUBSTRING_INDEX(host, ':', 1) AS ip_address,COUNT(*) AS ct
    FROM info.session_info
    GROUP BY ip_address
    ORDER BY ct DESC;
    
    参考结果:
    +--------------+----+
    | ip_address   | ct |
    +--------------+----+
    | localhost    | 31 |
    | 172.31.17.79 |  6 |
    | host         |  5 |
    +--------------+----+
    

在完成静态检查项目,并修复相关兼容性问题之后。我们可以进行升级演练操作。

3. 升级过程演练

常见升级方案如下,每个方案都有各自有缺点,可根据各自情况选择。对于维护窗口较短数据库,建议使用蓝绿部署的方案。本文也以蓝绿部署方案进行演示。

升级方法 停机时间 升级复杂度 适合数据集大小
1 原地升级到新版本 时间长 各种数据集大小
2 蓝绿部署 较低 各种数据集大小
3 DMS 迁移(全量+增量) 较小数据量

3.1 升级中的预检查机制

在升级中,Aurora 首先自动执行预检查,以查找与目标版本的任何兼容性问题,如果在该环节发现问题,将会自动停止本次升级行为,并且在 upgrade-prechecks.log 留下错误信息,您可以参考 Aurora MySQL 2 升级预检查 来排查此类问题。

3.2 升级演练的收益

在生产数据库维护的过程中,操作员的规范和熟练操作,永远是最重要的。许多重大故障,都离不开操作人员的误操作等因素。通过升级演练达到以下目的:

  1. 让操作人员熟练掌握每一步升级过程
  2. 记录每一个操作环节的耗时,便于申请升级维护时间
  3. 发现问题,解决问题。不存在侥幸心理,生产环境的维护人员,通常都会“逢赌必输”。任何没有测试过的点,都有有可能在生产环境维护窗口爆发。
  4. 操作过程脚本化,升级流程提前准备 playbook,不在升级过程中临时增加任何步骤和命令,遇到问题立即停止操作并回滚。

使用刚通过快照还原的数据库实例,创建一个蓝绿部署,具体细节请参考文档:https://docs.aws.amazon.com/zh_cn/AmazonRDS/latest/AuroraUserGuide/blue-green-deployments-creating.html

3.3 故障回退机制演练

为防止升级完成一段时间后,发现升级导致的重大异常,切无法及时解决的问题。需要回退到之前版本。一个具有实时同步数据的旧版本 Replica,是非常必要且关键的。具体创建方法,在回滚策略准备环节进行讲述。

4. 动态检查

4.1 SQL可执行性,及执行性能检测

数据库大版本升级,在安全性提升等同时,会有很多功能和性能的增强。但是老版本执行良好的 SQL,在新版本是否能顺畅运行,也是需要逐一验证的。对于语法兼容性,您可以参考 Aurora 数据库升级流量兼容性检测方案 来进行初步排查。

4.1.1 SQL文本收集方式

1. 通过 performance insight 进行收集

参考链接:https://docs.aws.amazon.com/zh_cn/AmazonRDS/latest/UserGuide/USER_PerfInsights.UsingDashboard.Components.AvgActiveSessions.TopLoadItemsTable.TopSQL.html

2. Slow log 的方式进行收集

参数修改,开启 slow log,设置查询捕获时间,根据业务场景,在磁盘空间足够的情况下,可以短期将 long_query_time 设置为 0,将全部 SQL 进行统计。

slow_query_log='ON’;
long_query_time = 0.1; (s)
log_output = table

获取 Slow log 的语句

mysql -h <your-instance>.rds.amazonaws.com -u root -p -P13306 -D mysql -s -r -e \
"SELECT CONCAT( '# Time: ', DATE_FORMAT(start_time, '%y%m%d %H%i%s'), '\n', '# User@Host: ', user_host, '\n', '# Query_time: ', TIME_TO_SEC(query_time), ' Lock_time: ', TIME_TO_SEC(lock_time), ' Rows_sent: ', rows_sent, ' Rows_examined: ', rows_examined, '\n', sql_text, ';’ ) 
FROM 
mysql.slow_log“ > /tmp/mysql_slow_log.log

使用 pt-query-digest 格式化 slow log 文件。

参考文档:使用 pt-query-digest 分析 RDS MySQL 慢查询日志

3. SQL 方式收集

SELECT 
COUNT_STAR,SCHEMA_NAME,DIGEST_TEXT,FIRST_SEEN 
FROM 
performance_schema.events_statements_summary_by_digest order by COUNT_STAR desc

4.1.2 SQL 执行计划检查

有 SQL 文本之后,需要在两个版本的数据库中,进行执行计划检查和比较。

Explain 
SELECT SUBSTRING_INDEX(host, ':', 1) AS ip_address,COUNT(*) AS ct
FROM info.session_info
GROUP BY ip_address
ORDER BY ct DESC;

4.2 索引状态信息

升级后,检查索引状态,防止由于升级导致的索引失效。

SELECT CONCAT(TABLE_SCHEMA, '.', TABLE_NAME) AS Table_Name, INDEX_NAME,
    CASE
        WHEN NON_UNIQUE = 1 THEN 'Duplicate'
        ELSE 'Unique'
    END AS Index_Type,
    CASE
        WHEN SEQ_IN_INDEX = 1 THEN 'Clustered'
        ELSE 'Non-Clustered'
    END AS Index_Type,
    CASE
        WHEN CARDINALITY > 0.1 * (SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = T.TABLE_SCHEMA AND TABLE_NAME = T.TABLE_NAME) THEN 'Effective'
        ELSE 'Not Effective'
    END AS Index_Status
FROM
    INFORMATION_SCHEMA.STATISTICS T
WHERE
    TABLE_SCHEMA NOT IN ('mysql', 'information_schema', 'performance_schema', 'sys')
ORDER BY TABLE_NAME, INDEX_NAME;

4.3 查询表的基本信息,和统计信息最后更新时间

检查升级后,表的统计信息,防止统计信息丢失,导致选择错误的 SQL 执行计划。UPDATE_TIME 记录了表定义或统计信息最后一次被更改的时间。通常来说,如果 UPDATE_TIME 较新,就意味着表的统计信息也较新。

SELECT
    TABLE_SCHEMA AS '数据库名',
    TABLE_NAME AS '表名', 
    ROUND(DATA_LENGTH / 1024 / 1024, 2) AS '数据大小(MB)',
    ROUND(INDEX_LENGTH / 1024 / 1024, 2) AS '索引大小(MB)',
    ROUND((DATA_LENGTH + INDEX_LENGTH) / 1024 / 1024, 2) AS '总大小(MB)',
    TABLE_ROWS AS '行数',
    UPDATE_TIME AS '统计信息收集时间'
FROM
    INFORMATION_SCHEMA.TABLES
WHERE
    TABLE_SCHEMA NOT IN (
        'mysql', 'information_schema', 'performance_schema', 'sys'
    )
ORDER BY
    (DATA_LENGTH + INDEX_LENGTH) DESC;

显示样例:

+--------------+--------------+------------------+------------------+---------------+--------+--------------------------+
| 数据库名     | 表名         | 数据大小(MB)     | 索引大小(MB)     | 总大小(MB)    | 行数   | 统计信息收集时间         |
+--------------+--------------+------------------+------------------+---------------+--------+--------------------------+
| info         | ss           |             0.02 |             0.00 |          0.02 |     42 | 2024-06-22 16:53:27      |
| info         | session_info |             0.02 |             0.00 |          0.02 |     42 | 2024-06-22 17:11:28      |
+--------------+--------------+------------------+------------------+---------------+--------+--------------------------+

4.4 数据库性能压测

升级后,整体系统的性能压测,也是很重要的。如果可以,建议从前段应用开始全链路压测。或者只完成数据库层面的性能压测。这样可以更好的评估数据库升级后的整体性能。这个测试除了验证升级效果之外,也可以作为数据库的 baseline,作为后续数据库扩缩容,性能分析优化的基准。

参考链接:

4.5 数据库常规信息统计

生产数据库的大小,QPS,TPS,以及数据库的硬件信息,数据库业务波峰波谷信息,维护窗口时长等信息,都需要提前统计。

这些信息不会直接影响升级,但是有个上层视角观察所有指标信息,也会在升级方式等决策方面,提供有价值的数据支撑。

5. 升级中验证步骤

5.1 数据同步状态验证

在蓝绿方式升级过程中,需要确保数据已经完全同步,再进行切换。虽然理论上,蓝绿部署升级,不会丢失数据。但是依然建议申请维护窗口,先停止业务段写入。观察数据同步状态,确认无误之后,再进行切换。常用数据同步的检测方法:

  • 通过 show slave status 监控主从同步状态
  • 创建一个时间表,定时插入时间戳,升级切换前,检查数据同步状态

5.2 统计信息&索引状态检查

检查全部表的统计信息,索引状态。理论上,在升级演练过程中,已经可以发现这些问题。为安全起见,升级过程中,再次检查确认。具体方法参考动态检查索引状态统计信息检查。

5.3 业务端链接状态测试,防止连接状态缓存,继续访问原有数据库

数据库升级完成后,进行业务端回归测试。确保所有业务端都能正常读写数据库。尤其需要注意业务端的连接信息缓存,会继续访问原有数据库 IP。如果遇到类似问题,如在短时间内无法查找到问题根源,最快捷的方式是修改/etc/hosts,直接指向升级后的数据库。后续再逐步排除问题。

6. 回滚策略

在前面的步骤都完整的完成后,通常数据库都已经顺利完成升级。那么我们是不是可以高枕无忧呢?No,由于某些因素(如触发新版本的 bug,且无法规避),不得不回退到之前版本的情况。所以,也需要将回滚策略提前定义好。

6.1 通常的回滚策略

回滚方式 前置准备 还原过程 RPO 与 RTO
快照还原(适用原地升级) 无(原地升级会自动留下升级前的数据库快照)

1. 通过快照还原旧集群

2. 应用程序停写后修改 endpoint

RPO:升级之后的增量数据

RTO:恢复快照时间 + 应用重启时间

保留旧实例(适用蓝绿升级)

1. 记录切换时 Event 事件的 Binlog 位点

2. 按需设置 Binlog 保存周期

1. 恢复蓝环境可写

2. 通过 set_external_master 或者 DMS 追齐增量数据

应用程序停写后修改 endpoint

RPO:0

RTO:应用重启时间+增量数据追齐时间

提前搭建反向 CDC 复制 通过 Binlog/DMS 搭建高版本向低版本的持续复制 应用程序停写后修改 endpoint

RPO:0

RTO:应用重启时间 + 同步延迟

6.2 这里又细分两种需要回退场景

  1. 升级后立即发现问题,需要回退。
  2. 升级后运行一段时间后,发现问题,需要回退。

第一种场景,一般情况下,在升级前测试,验证等步骤,都能发现问题,只要终止升级进程即可。或者立即将应用程序 JDBC 修改为旧版本的 Endpoint。

第二种场景,数据库运行一段时间才发现问题,已经有很多新业务数据写入。直接切换回原数据库,会丢失大量数据。使用 Mysqldump 方式将数据导回旧版本,耗时会很长。

此种场景下,如何最小化影响业务,并回退到之前版本呢?

在蓝绿方式升级完成后,立即创建反向的数据同步,以备不时之需,可以最小化业务影响的方式,进行版本回退操作。

反向数据同步通常有下面两种方式:

  1. 使用 DMS(Database Migration Service)
  2. 手动配置 Read Replica

参考链接:https://docs.aws.amazon.com/zh_cn/AmazonRDS/latest/AuroraUserGuide/AuroraMySQL.Replication.MySQL.html

通过本系列文章,希望能帮助你清晰地理解数据库升级的完整步骤,顺利地完成数据库的升级。

本篇作者

许晓亮

亚马逊云科技解决方案架构师,负责基于 AWS 云计算方案架构的咨询和设计,在国内推广 AWS 云平台技术和各种解决方案。擅长数据库和大数据领域,结合云原生特性,为客户设计高效稳定的全球化系统方案。

陈阳

亚马逊云科技数据库专家架构师,十余年数据库行业经验,主要负责基于亚马逊云计算数据库产品的解决方案与架构设计工作。