外观
MySQL 升级回滚方案
概述
回滚方案的重要性
MySQL 升级是一项高风险的操作,尽管我们在升级前做了充分的准备和测试,但仍然可能遇到各种意外情况。回滚方案是升级过程中的最后一道防线,它可以在升级失败或升级后出现严重问题时,快速将系统恢复到升级前的状态,最大限度地减少业务损失。
回滚方案的目的
- 快速恢复服务:在升级失败或出现严重问题时,快速将系统恢复到升级前的状态
- 减少业务影响:最大限度地减少升级失败对业务的影响
- 保障数据安全:确保回滚过程中数据的安全性和完整性
- 降低操作风险:为升级操作提供安全保障,增强团队信心
回滚方案的原则
- 可行性:回滚方案必须经过测试,确保在实际情况下能够成功执行
- 完整性:回滚方案必须覆盖升级的所有方面,包括数据库、配置、应用等
- 及时性:回滚操作必须快速执行,减少业务 downtime
- 数据一致性:回滚过程中必须确保数据的一致性和完整性
- 可操作性:回滚步骤必须具体、清晰、易于执行
- 文档化:回滚方案必须详细记录在文档中,便于团队成员查阅和执行
回滚触发条件
在升级过程中或升级后,如果出现以下情况,应考虑执行回滚操作:
升级过程中触发回滚的条件
- MySQL 服务无法启动:升级后 MySQL 服务无法正常启动,且在规定时间内无法解决
- 数据损坏:升级过程中出现数据损坏,无法修复
- 系统崩溃:升级过程中导致系统崩溃,无法恢复
- 升级超时:升级过程超出预期时间,影响业务正常运行
- 严重错误:升级过程中出现严重错误,如系统表损坏、数据丢失等
升级后触发回滚的条件
- 应用兼容性问题:升级后应用程序无法正常工作,且在规定时间内无法解决
- 性能严重下降:升级后系统性能严重下降,影响业务正常运行
- 功能失效:升级后关键功能失效,无法正常使用
- 数据不一致:升级后出现数据不一致的情况
- 安全问题:升级后出现安全漏洞或权限问题
- 频繁崩溃:升级后系统频繁崩溃,无法稳定运行
回滚决策流程
当出现上述情况时,应按照以下流程进行决策:
- 问题评估:由技术负责人组织团队对问题进行评估,确定问题的严重程度和影响范围
- 影响分析:分析回滚操作对业务的影响,包括回滚时间、数据损失风险等
- 决策制定:根据问题评估和影响分析结果,由项目负责人或更高管理层决定是否执行回滚
- 回滚执行:如果决定执行回滚,按照回滚方案执行回滚操作
- 回滚验证:回滚完成后,对系统进行验证,确保系统恢复正常
- 总结分析:对回滚原因、过程和结果进行总结分析,提出改进措施
回滚前准备
在执行回滚操作前,需要做以下准备工作:
确认回滚范围
- 确认需要回滚的数据库实例
- 确认需要回滚的版本(回滚到哪个版本)
- 确认回滚的方式(In-place 回滚或 Logical 回滚)
备份当前状态
在执行回滚前,对当前状态进行备份,以便在回滚过程中出现问题时恢复:
- 备份当前数据目录
- 备份当前配置文件
- 备份当前日志文件
- 记录当前系统状态和关键指标
示例:
bash
# 备份当前数据目录
cp -r /var/lib/mysql /var/lib/mysql.bak.rollback.$(date +%Y%m%d_%H%M%S)
# 备份当前配置文件
cp /etc/my.cnf /etc/my.cnf.bak.rollback.$(date +%Y%m%d_%H%M%S)
# 备份当前日志文件
cp -r /var/log/mysql /var/log/mysql.bak.rollback.$(date +%Y%m%d_%H%M%S)准备回滚工具和资源
- 准备回滚所需的二进制文件(旧版本 MySQL)
- 准备回滚所需的工具,如
xtrabackup、mysqldump等 - 确保有足够的磁盘空间用于回滚操作
- 确保网络连接稳定
通知相关人员
- 通知业务部门回滚计划和预计影响时间
- 通知开发团队回滚计划
- 通知运维团队回滚计划
- 通知监控人员回滚计划,做好监控准备
停止写入流量
在执行回滚操作前,需要停止写入流量,确保数据一致性:
- 通知业务部门停止写入操作
- 或使用
read_only参数设置数据库为只读模式
示例:
sql
SET GLOBAL read_only = ON;In-place 升级的回滚步骤
In-place 升级的回滚主要是恢复旧版本的二进制文件和数据目录。
回滚步骤
- 停止当前 MySQL 服务
bash
systemctl stop mysql- 恢复旧版本的二进制文件
根据安装方式,恢复旧版本的二进制文件:
RPM/YUM 安装方式
bash
# 卸载当前版本
yum remove mysql-community-server mysql-community-client mysql-community-common mysql-community-libs
# 安装旧版本
yum install mysql-community-server-8.0.28 mysql-community-client-8.0.28 mysql-community-common-8.0.28 mysql-community-libs-8.0.28APT 安装方式
bash
# 卸载当前版本
apt-get remove --purge mysql-server mysql-client mysql-common
apt-get autoremove
apt-get autoclean
# 安装旧版本
apt-get install mysql-server=8.0.28-1debian10 mysql-client=8.0.28-1debian10 mysql-common=8.0.28-1debian10手动编译安装方式
bash
# 停止 MySQL 服务后,替换二进制文件
cp -r /usr/local/mysql.bak.8.0.28/* /usr/local/mysql/- 恢复旧版本的数据目录
bash
# 备份当前数据目录(可选,用于后续分析)
mv /var/lib/mysql /var/lib/mysql.current
# 恢复旧版本的数据目录
cp -r /var/lib/mysql.bak.8.0.28 /var/lib/mysql
# 恢复数据目录权限
chown -R mysql:mysql /var/lib/mysql- 恢复旧版本的配置文件
bash
# 恢复配置文件
cp /etc/my.cnf.bak.8.0.28 /etc/my.cnf- 启动 MySQL 服务
bash
systemctl start mysql- 验证 MySQL 版本
bash
mysql -V
mysql Ver 8.0.28 for Linux on x86_64 (MySQL Community Server - GPL)- 验证数据完整性
sql
-- 检查关键表的数据行数
SELECT COUNT(*) FROM db1.table1;
SELECT COUNT(*) FROM db1.table2;
-- 验证存储过程和触发器
CALL db1.sp_test();- 恢复写入流量
sql
SET GLOBAL read_only = OFF;Logical 升级的回滚步骤
Logical 升级的回滚主要是将应用连接切换回旧版本的数据库实例。
回滚步骤
- 确认旧版本数据库实例状态
确保旧版本数据库实例处于正常运行状态:
bash
systemctl status mysql_old- 验证旧版本数据完整性
sql
-- 检查关键表的数据行数
SELECT COUNT(*) FROM db1.table1;
SELECT COUNT(*) FROM db1.table2;
-- 验证存储过程和触发器
CALL db1.sp_test();- 切换应用连接到旧版本数据库
更新应用配置,将数据库连接指向旧版本数据库实例:
- 更新应用配置文件中的数据库连接信息
- 重启应用程序
示例:
bash
# 更新应用配置文件
sed -i 's/mysql_new/mysql_old/g' /etc/app/config.yml
# 重启应用
systemctl restart app- 验证应用连接
验证应用程序能够正常连接到旧版本数据库并执行操作:
- 执行简单的业务操作
- 检查应用日志,确保没有连接错误
- 停止新版本数据库实例
如果不需要保留新版本数据库实例,可以将其停止:
bash
systemctl stop mysql_new主从复制环境的回滚步骤
主从复制环境的回滚需要考虑主库和从库的回滚顺序和一致性。
回滚策略
主从复制环境的回滚主要有两种策略:
- 整体回滚:将主库和所有从库都回滚到升级前的版本
- 切换回滚:将业务流量切换到备用主库,然后回滚原主库
整体回滚步骤
- 停止所有从库的复制进程
在每个从库上执行:
sql
-- MySQL 5.6/5.7
STOP SLAVE;
-- MySQL 8.0
STOP REPLICA;- 停止所有从库的 MySQL 服务
bash
systemctl stop mysql_slave1
systemctl stop mysql_slave2
# ... 停止其他从库回滚所有从库(参考 In-place 升级或 Logical 升级的回滚步骤)
停止主库的 MySQL 服务
bash
systemctl stop mysql_master回滚主库(参考 In-place 升级或 Logical 升级的回滚步骤)
启动主库的 MySQL 服务
bash
systemctl start mysql_master- 重新配置主从复制
- 在主库上创建复制用户(如果需要)
- 在每个从库上重新配置复制关系
示例:
sql
-- 在主库上创建复制用户
CREATE USER 'repl'@'%' IDENTIFIED BY 'repl_password';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
-- 查看主库状态
SHOW MASTER STATUS;
-- 在从库上配置复制
-- MySQL 5.6/5.7
CHANGE MASTER TO
MASTER_HOST='master_host',
MASTER_USER='repl',
MASTER_PASSWORD='repl_password',
MASTER_LOG_FILE='binlog.000001',
MASTER_LOG_POS=154;
START SLAVE;
-- MySQL 8.0
CHANGE REPLICATION SOURCE TO
SOURCE_HOST='master_host',
SOURCE_USER='repl',
SOURCE_PASSWORD='repl_password',
SOURCE_LOG_FILE='binlog.000001',
SOURCE_LOG_POS=154;
START REPLICA;- 启动所有从库的 MySQL 服务
bash
systemctl start mysql_slave1
systemctl start mysql_slave2
# ... 启动其他从库- 验证主从复制状态
在每个从库上执行:
sql
-- MySQL 5.6/5.7
SHOW SLAVE STATUS\G
-- MySQL 8.0
SHOW REPLICA STATUS\G确保 Slave_IO_Running/Replica_IO_Running 和 Slave_SQL_Running/Replica_SQL_Running 都为 Yes,且 Seconds_Behind_Master/Seconds_Behind_Source 为 0。
- 恢复写入流量
sql
SET GLOBAL read_only = OFF;切换回滚步骤
- 将业务流量切换到备用主库
更新应用配置,将数据库连接指向备用主库:
bash
# 更新应用配置文件
sed -i 's/master_host/standby_master_host/g' /etc/app/config.yml
# 重启应用
systemctl restart app回滚原主库(参考 In-place 升级或 Logical 升级的回滚步骤)
将原主库配置为备用主库的从库
sql
-- MySQL 5.6/5.7
CHANGE MASTER TO
MASTER_HOST='standby_master_host',
MASTER_USER='repl',
MASTER_PASSWORD='repl_password',
MASTER_LOG_FILE='binlog.000001',
MASTER_LOG_POS=154;
START SLAVE;
-- MySQL 8.0
CHANGE REPLICATION SOURCE TO
SOURCE_HOST='standby_master_host',
SOURCE_USER='repl',
SOURCE_PASSWORD='repl_password',
SOURCE_LOG_FILE='binlog.000001',
SOURCE_LOG_POS=154;
START REPLICA;- 验证复制状态
sql
-- MySQL 5.6/5.7
SHOW SLAVE STATUS\G
-- MySQL 8.0
SHOW REPLICA STATUS\G回滚后的验证
回滚完成后,需要进行以下验证工作:
服务状态验证
- 验证 MySQL 服务是否正常运行
- 验证监听端口是否正常
- 验证进程是否正常
示例:
bash
# 验证 MySQL 服务状态
systemctl status mysql
# 验证监听端口
netstat -tlnp | grep 3306
# 验证进程
ps aux | grep mysqld数据完整性验证
- 验证关键表的数据行数是否与升级前一致
- 验证数据内容是否正确
- 验证存储过程、触发器、视图等对象是否正常
示例:
sql
-- 检查关键表的数据行数
SELECT COUNT(*) FROM db1.table1;
SELECT COUNT(*) FROM db1.table2;
-- 验证数据内容
SELECT * FROM db1.table1 WHERE id = 123;
-- 验证存储过程和触发器
CALL db1.sp_test();应用功能验证
- 验证应用程序能够正常连接到数据库
- 验证关键业务功能是否正常
- 验证应用性能是否正常
示例:
bash
# 执行应用健康检查
curl -i http://app_host/health
# 执行业务功能测试
curl -i -X POST http://app_host/api/test -d '{"data": "test"}'性能验证
- 验证系统性能是否恢复到升级前水平
- 验证查询响应时间是否正常
- 验证系统资源使用率是否正常
示例:
bash
# 使用 sysbench 进行性能测试
sysbench --db-driver=mysql --mysql-host=localhost --mysql-user=root --mysql-password=your_password --mysql-db=test --table_size=1000000 --tables=10 --threads=64 oltp_read_write run
# 查看系统资源使用率
top
vmstat 1日志验证
- 检查 MySQL 错误日志,确保没有错误
- 检查慢查询日志,确保没有异常慢查询
- 检查系统日志,确保没有相关错误
示例:
bash
# 检查 MySQL 错误日志
tail -n 100 /var/log/mysql/error.log
# 检查慢查询日志
tail -n 100 /var/log/mysql/mysql-slow.log
# 检查系统日志
tail -n 100 /var/log/messages版本差异考虑
MySQL 5.6 回滚注意事项
- 配置文件差异:MySQL 5.6 配置文件中某些参数在高版本中可能被废弃或重命名
- 系统表结构:MySQL 5.6 系统表结构与 5.7/8.0 差异较大,回滚时需确保系统表完整
- 复制命令:MySQL 5.6 仅支持旧版复制命令,如
STOP SLAVE、START SLAVE - 存储引擎:MySQL 5.6 中 MyISAM 存储引擎仍被广泛使用,回滚时需注意
- 性能 Schema:MySQL 5.6 中 Performance Schema 默认关闭,回滚后需根据需要开启
MySQL 5.7 回滚注意事项
- SQL_MODE 默认值:MySQL 5.7 默认 SQL_MODE 更加严格,回滚后需注意应用兼容性
- 密码策略:MySQL 5.7 默认启用
validate_password插件,回滚后需注意密码策略 - InnoDB 变化:MySQL 5.7 中 InnoDB 成为默认存储引擎,回滚后需确保 InnoDB 相关配置正确
- Performance Schema 增强:MySQL 5.7 中 Performance Schema 收集更多性能数据,回滚后需注意资源占用
MySQL 8.0 回滚注意事项
- 认证插件变化:MySQL 8.0 默认认证插件为
caching_sha2_password,回滚后需注意应用驱动兼容性 - 数据字典变化:MySQL 8.0 引入了新的数据字典,回滚时需确保数据字典完整
- 复制命令变化:MySQL 8.0 引入了新的复制命令,如
STOP REPLICA、START REPLICA - 系统变量变化:MySQL 8.0 中大量系统变量被重命名或废弃,回滚时需注意配置文件兼容性
- 错误日志格式:MySQL 8.0 错误日志格式更加结构化,回滚后需注意日志监控工具兼容性
回滚过程中的监控和问题处理
实时监控
在回滚过程中,需要实时监控以下指标:
- 系统资源:CPU、内存、磁盘 I/O、网络流量等
- MySQL 状态:连接数、QPS、TPS、锁等待等
- 复制状态:主从延迟、复制错误等(如果是主从复制环境)
- 日志信息:错误日志、慢查询日志等
常见问题和解决方案
MySQL 服务无法启动
问题现象:
systemctl start mysql
Job for mysql.service failed because the control process exited with error code.解决方案:
- 查看错误日志,定位具体问题
- 检查数据目录权限是否正确
- 检查配置文件是否有语法错误
- 检查端口是否被占用
- 尝试使用
--skip-grant-tables参数启动,修复权限问题
示例:
bash
# 查看错误日志
tail -n 100 /var/log/mysql/error.log
# 检查数据目录权限
chown -R mysql:mysql /var/lib/mysql
# 检查配置文件语法
mysqld --defaults-file=/etc/my.cnf --validate-config
# 使用 --skip-grant-tables 参数启动
mysqld_safe --skip-grant-tables --defaults-file=/etc/my.cnf &数据一致性问题
问题现象:
- 回滚后数据与升级前不一致
- 主从复制出现数据不一致
解决方案:
- 使用备份恢复数据
- 使用
pt-table-checksum和pt-table-sync工具修复主从数据不一致 - 重新初始化从库
示例:
bash
# 使用 xtrabackup 恢复数据
xtrabackup --copy-back --target-dir=/backup/mysql_full_20231201
chown -R mysql:mysql /var/lib/mysql
# 使用 pt-table-checksum 检查主从数据一致性
pt-table-checksum --host=master_host --user=root --password=your_password
# 使用 pt-table-sync 修复主从数据不一致
pt-table-sync --execute --replicate=percona.checksums master_host应用连接失败
问题现象:
ERROR 2003 (HY000): Can't connect to MySQL server on 'localhost' (111)解决方案:
- 检查 MySQL 服务是否正常运行
- 检查防火墙是否开放了 3306 端口
- 检查用户权限是否允许远程连接
- 检查密码是否正确
- 检查应用配置中的连接信息是否正确
示例:
bash
# 检查 MySQL 服务状态
systemctl status mysql
# 检查防火墙规则
iptables -L -n | grep 3306
# 检查用户权限
mysql -u root -p -e "SELECT User, Host FROM mysql.user WHERE User='app_user'"
# 检查应用配置
cat /etc/app/config.yml | grep -A 10 database最佳实践
回滚方案设计最佳实践
- 提前测试:在测试环境中测试回滚方案,确保其可行性
- 详细文档:回滚方案必须详细记录在文档中,包括步骤、命令、注意事项等
- 明确责任:明确回滚过程中各个角色的责任和分工
- 时间估算:估算回滚所需的时间,以便更好地规划和沟通
- 备份策略:确保有完整的备份,包括数据、配置和日志
- 监控机制:建立回滚过程中的监控机制,及时发现问题
回滚执行最佳实践
- 快速执行:回滚操作必须快速执行,减少业务 downtime
- 严格按照流程执行:严格按照回滚方案的步骤执行,避免出错
- 记录过程:记录回滚过程中的所有操作和事件,便于后续分析
- 及时沟通:及时向相关人员通报回滚进展和结果
- 谨慎操作:回滚过程中要谨慎操作,避免二次错误
回滚后的最佳实践
- 总结分析:对回滚原因、过程和结果进行总结分析,提出改进措施
- 更新文档:根据回滚经验,更新升级和回滚文档
- 培训学习:组织团队学习回滚经验,提高团队的故障处理能力
- 改进流程:根据回滚经验,改进升级流程和回滚方案
案例分析
案例一:In-place 升级失败回滚
案例背景:
- 当前版本:MySQL 5.7.35
- 目标版本:MySQL 8.0.33
- 升级方式:In-place 升级
- 升级过程中出现 MySQL 服务无法启动的问题
回滚过程:
- 问题发现:升级后执行
systemctl start mysql失败,查看错误日志发现系统表损坏 - 决策制定:由于问题严重且无法在短时间内解决,决定执行回滚
- 回滚执行:
- 停止 MySQL 服务
- 恢复 5.7.35 版本的二进制文件
- 恢复数据目录和配置文件
- 启动 MySQL 服务
- 回滚验证:
- 验证 MySQL 版本为 5.7.35
- 验证数据完整性
- 验证应用连接正常
- 总结分析:升级失败原因是系统表兼容性问题,改进措施是在升级前使用
mysqlcheck --check-upgrade工具检查系统表
回滚效果:
- 回滚时间:30 分钟
- 业务 downtime:45 分钟
- 数据无丢失
案例二:Logical 升级后性能下降回滚
案例背景:
- 当前版本:MySQL 8.0.28
- 目标版本:MySQL 8.0.33
- 升级方式:Logical 升级
- 升级后应用性能严重下降
回滚过程:
- 问题发现:升级后应用响应时间从 50ms 增加到 500ms,严重影响用户体验
- 决策制定:经过性能分析,确定是新版本查询优化器行为变化导致,短期内无法优化,决定执行回滚
- 回滚执行:
- 验证旧版本数据库状态正常
- 切换应用连接回旧版本数据库
- 验证应用性能恢复正常
- 回滚验证:
- 验证应用响应时间恢复到 50ms 左右
- 验证业务功能正常
- 总结分析:升级失败原因是新版本查询优化器对某些查询的处理方式发生变化,改进措施是在升级前对所有慢查询进行测试
回滚效果:
- 回滚时间:15 分钟
- 业务 downtime:20 分钟
- 数据无丢失
总结
回滚方案是 MySQL 升级过程中的重要组成部分,它可以在升级失败或出现严重问题时,快速将系统恢复到升级前的状态,最大限度地减少业务损失。
一个完善的回滚方案应该包括:
- 明确的回滚触发条件
- 详细的回滚前准备工作
- 清晰的回滚步骤
- 回滚后的验证方法
- 回滚过程中的监控和问题处理机制
- 版本差异考虑
- 最佳实践和案例分析
回滚方案需要提前测试和文档化,确保在实际情况下能够快速、可靠地执行。同时,回滚后的总结分析也是非常重要的,它可以帮助我们改进升级流程和回滚方案,提高未来升级的成功率。
作为 DBA,我们应该重视回滚方案的设计和测试,将其作为升级工作的重要组成部分,确保数据库升级的安全和可靠。
