停机前必须完成三道兼容性检查:mysqlcheck --check-upgrade、mysqlsh util.checkForServerUpgrade()、手动查非InnoDB表;容器升级须用逻辑备份而非docker commit;滚动升级需严格主从切换并验证GTID与错误日志。

停机前必须跑通的三道兼容性检查
直接替换二进制再启动,90% 的失败都卡在没做这三步。MySQL 不是换 App,它对表结构、SQL 模式、用户认证方式都有强约束,跳过检查等于埋雷。
-
mysqlcheck --check-upgrade:登录当前版本 MySQL 后执行,会明确报出哪些表引擎不合法(比如 MyISAM 分区表)、哪些系统表字段缺失 -
mysqlsh -uroot -p -S /tmp/mysql.sock -e "util.checkForServerUpgrade()":MySQL Shell 提供的深度扫描工具,能发现密码策略过期、废弃语法(如GRANT ... IDENTIFIED BY)、sql_mode冲突等隐藏问题 - 手动查非 InnoDB 表:
SELECT TABLE_SCHEMA, TABLE_NAME, ENGINE FROM information_schema.TABLES WHERE ENGINE NOT IN ('InnoDB') AND TABLE_SCHEMA NOT IN ('mysql', 'information_schema', 'performance_schema', 'sys');——这些表在 8.0 升级中大概率报错,得提前ALTER TABLE ... ENGINE=InnoDB
容器环境里备份不能只靠 docker commit
物理快照在容器里等于没备——docker commit 或宿主机 rsync /var/lib/mysql 无法保证 InnoDB redo log、binlog position 和 buffer pool 一致,回退时极易出现 GTID 断裂或表损坏。
- 必须用逻辑备份:
mysqldump -u root -p --all-databases --single-transaction --routines --triggers --events --master-data=2 > full_backup.sql - 备份后立刻校验:
head -n 20 full_backup.sql | grep "CREATE TABLE"确认导出头正常;mysqlcheck -c检查表结构完整性 - 别信
:latest镜像:升级时显式指定带 patch 号的标签,例如mysql:8.0.33,而非mysql:8.0或mysql:latest,避免认证插件静默变更引发连接池崩溃
滚动升级不是“换完从库再切主”,而是主从角色切换链
单节点容器强行“停旧启新”风险极高:连接中断期间未刷盘事务丢失、应用重连遭遇 Lost connection to MySQL server、连接池复用旧连接触发 caching_sha2_password 认证失败——这些都不是超时重试能解决的。
- 滚动升级只适用于有主从架构的场景,且必须走完整角色切换:先升级从库 → 停写 → 主从切换(原主变从)→ 升级原主库 → 恢复写入
- 切换前确认
SHOW SLAVE STATUS\G中Seconds_Behind_Master = 0,且Retrieved_Gtid_Set == Executed_Gtid_Set - 升级从库时,启动命令加
--skip-networking和--innodb-force-recovery=1(仅诊断),观察日志是否出现InnoDB: Upgrade is required或Unknown system variable错误
升级后第一件事不是查版本,而是看错误日志里的 Upgrading system tables
mysql -u root -p -e "SELECT VERSION();" 返回 8.0.x ≠ 升级完成。8.0.16+ 已弃用 mysql_upgrade,系统表升级由 mysqld 自动触发,但卡住时不会报错,只会静默挂起。
- 必须盯紧错误日志(默认
/var/log/mysql/error.log或docker logs):首次启动看到Upgrading system tables.→Finished upgrading system tables.才算通过 - 验证 performance_schema 是否完整:
SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'performance_schema';——8.0 应返回 87+,少于这个数说明元数据升级失败 - 检查 SQL 模式是否生效:
SELECT @@sql_mode;,若含STRICT_TRANS_TABLES和ONLY_FULL_GROUP_BY,而业务 SQL 没加GROUP BY字段,就会直接报错,得提前调SET PERSIST sql_mode = '...'降级










