必须先完整备份,再停服务、再升级;mysqldump需强制加--single-transaction和--master-data=2保证一致性与复制定位,漏--routines等参数或未验证备份有效性极易导致升级失败。

必须先完整备份,再停服务、再升级,顺序错一步就可能丢数据。
mysqldump 备份时要加 --single-transaction 和 --master-data=2
这两个参数不是可选的,是跨版本升级的底线要求:
-
--single-transaction:保证 InnoDB 表在导出过程中一致性,避免锁表导致备份卡住或不完整 -
--master-data=2:把当前 binlog 位置写进 SQL 文件开头,后续恢复后能准确定位复制起点 - 漏掉
--routines --triggers --events可能导致存储过程、事件丢失,尤其是升级到 MySQL 8.0 后权限模型变化大 - 如果用
--all-databases,记得加--set-gtid-purged=OFF(MySQL 5.7.6+ 默认开启 GTID,但旧实例可能没启用,强行开启会报错)
备份后必须用 mysqlcheck --check-upgrade 验证兼容性
很多升级失败不是因为备份本身出错,而是备份前数据库里已有不兼容结构:
- 执行
mysqlcheck -u root -p --all-databases --check-upgrade,它会扫描所有表并报告是否支持目标版本 - 特别注意分区表:如果引擎不是
InnoDB或ndbcluster,MySQL 8.0 会拒绝启动,得提前改:ALTER TABLE table_name ENGINE = INNODB - 检查
sql_mode:MySQL 5.7 默认启用严格模式,而 5.6 可能是空的;备份前最好统一设为STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION,避免还原时报语法错误
不要直接覆盖二进制文件升级,mysqld --upgrade 必须在新版本启动后首次运行
原地升级不是“替换文件 + 启动”那么简单:
- 必须先用新版本的
mysqld启动服务(带--skip-grant-tables或确保 datadir 权限正确),再手动执行mysql_upgrade -u root -p -
mysql_upgrade不是脚本,它会连接正在运行的 mysqld,检查系统表结构并自动修复 —— 如果 mysqld 没起来,它就什么都做不了 - 升级完别急着切流量,先连上去跑
SELECT VERSION(), @@sql_mode;确认版本和模式已生效;再查SELECT COUNT(*) FROM mysql.user;看用户表有没有被重写乱
备份文件本身要验证可读性,不能只看 .sql 文件大小
常见翻车点:备份命令看似成功,实际导出的是空文件或报错被忽略:
- 执行完
mysqldump后立刻检查返回值:echo $?应该是 0;非零值代表失败,但 shell 脚本里常被忽略 - 用
head -n 20 backup.sql看开头是否有CREATE DATABASE或INSERT INTO,而不是一堆 warning 或 empty set - 如果用了压缩(
gzip),解压后用grep -m1 "INSERT INTO" backup.sql.gz验证内容存在 —— gzip 不报错不代表内容有效 - 真正保险的做法:挑一个测试库,用
mysql -e "DROP DATABASE IF EXISTS test_restore; CREATE DATABASE test_restore;",再导入部分备份验证流程通不通
最易被跳过的环节是备份后验证和升级后连通性检查,不是备份动作本身难,而是人容易默认“命令没报错=成功”。











