版本迁移前必须做一次完整逻辑备份,因mysqldump SQL文件是唯一可移植、可审查、可回滚的备份形式,物理备份跨版本不可用;导出需用目标版本客户端并设置GTID参数,排除系统库,恢复时须先建库、调sql_mode、指定字符集再导入。

版本迁移前必须做一次完整逻辑备份
MySQL 版本升级(如 5.7 → 8.0)或跨大版本降级(如 8.0 → 5.7)时,mysqldump 生成的 SQL 文件是唯一可移植、可审查、可回滚的备份形式。物理备份(如 xtrabackup)无法跨版本直接恢复,8.0 的 ibd 文件在 5.7 上会报 Tablespace has wrong space_id 错误。
实操建议:
- 用目标版本兼容的
mysqldump客户端导出(例如升到 8.0,就用 MySQL 8.0 自带的mysqldump,避免用旧版客户端导出后在新服务端执行失败) - 务必加上
--set-gtid-purged=OFF(若不启用 GTID)或--set-gtid-purged=AUTO(若启用了 GTID),否则导入时可能触发GTID_PURGED cannot be changed - 导出时排除系统库:
mysqldump --all-databases --ignore-table=mysql.user --ignore-table=mysql.db ...,避免权限表结构冲突
恢复时要先清理再导入,不能直接 source
直接在目标实例上执行 source backup.sql 很容易因字符集、SQL mode 或默认引擎差异导致中途报错中断,比如 Unknown collation: 'utf8mb4_0900_ai_ci'(MySQL 8.0 新增的校对规则,在 5.7 中不存在)。
正确做法是分步控制:
- 先创建空库:
CREATE DATABASE mydb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; - 修改目标实例的
sql_mode,临时兼容旧 dump(如去掉STRICT_TRANS_TABLES);可通过SET GLOBAL sql_mode = '...';或配置文件调整 - 用
mysql --default-character-set=utf8mb4 mydb 导入,显式指定字符集防止乱码 - 导入后手动校验
information_schema.TABLES中的ENGINE和TABLE_COLLATION是否符合预期
安全策略必须随版本演进同步更新
MySQL 5.7 默认允许空密码、匿名用户、宽松的密码策略;而 8.0 强制要求密码强度、禁用匿名用户、默认启用 caching_sha2_password 插件。如果迁移后沿用旧的安全配置,会导致应用连接失败或权限失控。
关键检查点:
- 确认
validate_password插件是否启用及策略等级:SELECT @@validate_password_policy; - 检查用户认证插件:
SELECT user, host, plugin FROM mysql.user;,将mysql_native_password用户显式重置密码以兼容老客户端 - 删除残留的匿名账户:
DELETE FROM mysql.user WHERE user = '';,然后FLUSH PRIVILEGES; - 关闭危险选项:
skip-grant-tables、local_infile=ON(除非明确需要)必须从配置中移除
不要跳过测试阶段:用生产备份在同版本环境预演
最常被忽略的一环是——把生产导出的 backup.sql 在一台干净的、与目标版本完全一致的 MySQL 实例上完整走一遍导入 + 应用连通性验证。很多问题只在这个环节暴露,比如存储过程里的 DEFINER 用户不存在、视图依赖的函数在新版本被废弃、分区表语法变更等。
建议脚本化验证流程:
- 用
mysql -e "SHOW DATABASES;"确认库存在 - 抽样查表行数:
SELECT COUNT(*) FROM mydb.orders;对比备份前快照 - 运行
mysqlcheck --all-databases --check检查表结构一致性 - 用实际应用账号连接并执行一条简单查询,验证权限和认证方式
跨版本迁移不是“dump + restore”两个命令的事,真正耗时且易出错的是字符集适配、SQL mode 差异、权限模型变更这三块。每一步都要有对应验证,而不是依赖“看起来没报错”。










