回滚必须基于已验证可用的备份,否则无法实施;需确认备份文件完整可读、含关键参数(--single-transaction等)、datadir未被覆盖,且物理备份须匹配版本兼容性。
没有合规备份,就别谈回滚——升级失败后唯一能落地的回滚,必须基于升级前已验证可用的逻辑或物理备份。
很多人卡在第一步:以为有 mysqldump 就算备好了,结果导入时报 ERROR 1932 (HY000) 或连不上 mysql.user。真正决定回滚成败的,是这三项是否全部满足:
head -n 20 backup.sql 看开头是否有 /*!40101 SET @OLD_CHARACTER_SET_CLIENT=,用 tail -n 20 backup.sql 确认末尾不是截断的 INSERT INTO
--single-transaction --routines --events --triggers 缺一不可;若导出全库,必须排除 --ignore-table=sys.sys_config --ignore-table=performance_schema.*
rsync --delete 或 cp -r,原目录大概率已损坏,此时物理备份(如 XtraBackup)也失效适用于 5GB 以下实例,但极易因认证插件或字符集不匹配失败。重点不是“怎么导入”,而是“用哪个版本、怎么启动”:
mysqld 启动空实例(例如从 8.0.46 回退,就得用 8.0.30 的二进制),不能只换配置文件default_authentication_plugin:MySQL 5.7 默认是 mysql_native_password,8.0+ 默认是 caching_sha2_password;若不一致,用户会报 Access denied
mysql -u root -e "SET FOREIGN_KEY_CHECKS=0;",否则可能因表依赖顺序报错caching_sha2_password 用户无法直接在 5.7 中使用,需手动重建或改用 mysql_native_password 导出看似“解压即用”,实际对版本极其敏感。XtraBackup 不是快照工具,它只保证备份时刻一致性,不解决跨版本数据字典兼容问题:
XtraBackup 8.0.33 备份只能用 XtraBackup 8.0.33+ 恢复,不能用于 8.0.32 实例——小版本不向下兼容InnoDB: Unsupported redo log format:因为 8.0.30 和 8.0.46 的 ib_logfile* 格式不同,绝不能手动拷贝--innodb-force-recovery=1 启动旧版 mysqld,再用 mysqldump 导出,最后导入干净旧实例——本质还是走逻辑路径--backup 而非 --prepare,恢复前必须用对应版本的 xtrabackup --apply-log 完成准备,否则启动直接失败升级失败但尚未写入任何业务数据(即新版本 mysqld 从未正常启动过),才有微弱抢救机会;一旦执行过 mysql_upgrade 或任意 INSERT,立刻放弃所有“覆盖降级”操作:
Table 'mysql.plugin' doesn't exist,说明系统库升级中断,可尝试用备份的整个 mysql/ 子目录覆盖当前同名目录(仅此库,其他库不动)Unknown table engine 'InnoDB',大概率是 ibdata1 被重写,此时不要碰 datadir,优先检查 my.cnf 是否误删了 plugin_load_add = ha_innodb.so
mysqld --skip-grant-tables 启动后修改权限表——8.0+ 的 authentication_string 字段结构与 5.7 不兼容,改完反而更难登录回滚最易被忽略的点:不是备份有没有,而是备份能不能在旧版本上跑通。很多团队备份做了,却没在测试环境验证导入流程,等线上出事才发现 mysqldump 文件里混入了 8.0 特有语法(如隐藏索引定义),或者字符集声明缺失导致中文乱码。真正的回滚能力,藏在升级前那一次最小规模的还原测试里。