升级MySQL必须做逻辑备份,禁用物理拷贝;恢复时跳过mysql系统库并初始化;GTID模式需校验gtid_purged;8.0已废弃mysql_upgrade,改由mysqld自动升级;注意默认排序规则变更。

升级前必须做完整逻辑备份,而非仅依赖物理拷贝
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 恢复,但必须提前从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 的排序行为也与旧版不一致。










