mysql升级过程中的数据备份与恢复策略

来源:这里教程网 时间:2026-02-28 20:44:59 作者:

升级前必须做完整逻辑备份,而非仅依赖物理拷贝

MySQL 升级(尤其是跨大版本,如 5.7 → 8.0)时,

mysqldump
mydumper
生成的逻辑备份是唯一可验证、可移植、兼容性可控的备份方式。直接拷贝
datadir
在多数情况下不可靠:InnoDB 表空间格式可能变更(如 8.0 默认启用
innodb_file_per_table=ON
且引入数据字典表),且 MySQL 8.0 的
mysql
系统库结构与 5.7 不兼容,强行复用会导致启动失败或权限异常。

实操建议:

使用
mysqldump --all-databases --single-transaction --routines --events --triggers --set-gtid-purged=OFF
(若未启用 GTID)或
--set-gtid-purged=ON
(若已启用 GTID)导出全量数据
避免使用
--skip-lock-tables
,它在多事务场景下可能破坏一致性
对大库(>100 GB),优先选用
mydumper
并配合
myloader
,支持并行导出/导入,且默认按表粒度加锁,影响更小
务必校验导出文件末尾是否含
EOF
或成功退出码(
$?
为 0),常见错误如磁盘满、连接中断会导致 dump 截断但无明显报错

升级后恢复时需跳过系统库,手动初始化 mysql 数据库

MySQL 8.0 将原

mysql
库中的权限表(
user
db
等)替换为数据字典表(存于
mysql.ibd
ibdata1
中),且结构完全不向下兼容。若在 8.0 实例中直接导入 5.7 的
mysqldump
全库备份,会因
mysql
库冲突导致恢复失败,甚至损坏新实例的数据字典。

正确做法是分两步:

先用
mysqld --initialize --user=mysql
初始化 8.0 实例,生成全新的
mysql
系统库和 root 密码(记录在 error log 中)
再用
mysql -u root -p  恢复,但必须提前从 <code>backup.sql
中剔除
CREATE DATABASE `mysql`
及其所有
INSERT INTO `mysql`.*
语句;可用
sed '/^CREATE DATABASE `mysql`/,/^\/\*/d' backup.sql > app_backup.sql
快速过滤(注意匹配实际注释结尾)
若备份中含自定义函数/存储过程,需确认其语法兼容性(如 8.0 移除了
DEFINER
的部分宽松校验,可能报
ERROR 1449 (HY000): The user specified as a definer ('xxx'@'%') does not exist
),应提前用
SHOW CREATE FUNCTION
检查并重写
DEFINER

GTID 模式下升级必须保持 gtid_mode=ON + enforce_gtid_consistency=ON 且校验 gtid_purged

若原实例启用了 GTID(

gtid_mode=ON
),升级后若未正确继承
gtid_purged
值,会导致主从复制断裂或新实例拒绝执行任何事务。MySQL 8.0 要求
gtid_mode
enforce_gtid_consistency
必须同时为
ON
才允许启动,而 5.7 的 dump 默认不包含
SET @@GLOBAL.GTID_PURGED
语句(除非显式加
--set-gtid-purged=ON
)。

关键检查点:

导出前确认源库
SELECT @@GLOBAL.gtid_purged;
返回非空值;若为空,需先执行
FLUSH LOGS
RESET MASTER
(仅限测试环境,生产慎用)
dump 文件开头应含类似
SET @@GLOBAL.GTID_PURGED='aaa-bbb-ccc:1-100';
的语句;若缺失,需手动追加(值来自上一步查询结果)
恢复后立即执行
SELECT @@GLOBAL.gtid_executed, @@GLOBAL.gtid_purged;
,确保二者一致且覆盖 dump 中声明的范围,否则后续开启复制会报
Could not execute Write_rows event on table

升级后必须运行 mysql_upgrade 吗?8.0 已废弃该工具

MySQL 5.7 及更早版本要求升级后运行

mysql_upgrade
来更新系统表结构、修复权限视图。但该工具在 MySQL 8.0 中已被彻底移除——所有系统库升级操作由 mysqld 启动时自动完成。若在 8.0 中误执行
mysql_upgrade
,会提示
Unknown suffix '.' encountered
或直接报错退出。

替代方案只有两个:

确保以
mysqld --upgrade=FORCE
启动(仅首次启动必需,后续无需重复);该参数会触发内部数据字典升级流程
观察 error log,确认出现类似
Server upgraded from version '50732' to '80033'
Created new data dictionary with version ...
的日志条目,即表示升级成功
切勿手动修改
mysql
库下的任何表(如
innodb_index_stats
),8.0 的统计信息已转为数据字典内建表,直接 DML 会引发崩溃

最易被忽略的是字符集与排序规则的隐式变更:MySQL 8.0 默认

collation_server=utf8mb4_0900_ai_ci
,而 5.7 是
utf8mb4_general_ci
。即使备份恢复成功,应用若未显式指定
COLLATE
,ORDER BY、GROUP BY 结果可能不同,且
utf8mb4_0900_ai_ci
对某些 emoji 的排序行为也与旧版不一致。

相关推荐