不能直接原地升级主库,因mysql 8.0数据字典重构为innodb表(mysql.ibd),与5.7的myisam系统表不兼容,导致binlog事件、gtid行为及系统表结构突变,从库sql线程无法解析,引发同步中断、权限失效和gtid混乱。

主从环境不能直接原地升级主库,必须先切走流量、停写、再升级;否则从库同步会中断甚至数据错乱。
为什么不能对运行中的主库直接 in-place 升级
MySQL 8.0 的数据字典彻底重构为 InnoDB 表(mysql.ibd),与 5.7 的 MYISAM 系统表不兼容。主库升级后,binlog event 格式、GTID 行为、系统表结构都会突变,从库用 5.7 的 SQL 线程根本解析不了,常见报错:ERROR 1236 (HY000): Could not parse relay log event entry 或 Slave SQL thread retried transaction 后卡死。
即使强行启动,也会出现:
- 从库
SHOW SLAVE STATUS中Seconds_Behind_Master持续增长,实际已不同步 - 系统表(如
mysql.user)字段缺失或类型变更,导致权限失效 - GTID 集合混乱,
SELECT @@gtid_executed在主从间不一致
滚动升级前必须做的三件事
不是“能不能升”,而是“有没有准备好升”。漏掉任意一项,后续回滚成本极高。
- 用
mysqlsh运行util.checkForServerUpgrade(),重点看utf8mb3字符集、NO_AUTO_CREATE_USER(8.0 已移除)、MyISAM系统表残留这三类 ERROR 级别问题 - 确认所有业务连接字符串已适配:JDBC 必须用
mysql-connector-java:8.0.28+,且含?serverTimezone=UTC&allowPublicKeyRetrieval=true;PHP mysqli 扩展需 ≥ 8.0.0 - 主从都执行
SET GLOBAL binlog_format = 'ROW'并重启,确保升级期间 binlog 兼容性——5.7 默认 MIXED,8.0 对 STATEMENT 格式支持更弱
主从滚动升级实操顺序(无停机窗口场景)
核心逻辑:先升从,再切主,最后升旧主为新从。全程保持至少一个节点可读可写。
- 停止从库 IO 线程:
STOP SLAVE IO_THREAD;,等Seconds_Behind_Master = 0 - 将该从库停机,用 8.0 二进制替换,启动时加
--upgrade=FORCE参数(强制升级系统表) - 启动后立即执行:
ALTER USER 'repl'@'%' IDENTIFIED WITH mysql_native_password BY 'xxx';,避免认证插件不兼容导致主库连不上 - 在主库上执行
CHANGE MASTER TO ... MASTER_HOST='new_80_slave_ip' ...,把它变成新主库的从库;验证START SLAVE;成功 - 业务层切 DNS 或 VIP 到新主库,确认写入正常;旧主库降级为从库后,再按同样流程升级
升级后最容易被忽略的校验点
很多人跑完 START SLAVE 就以为完了,但以下几处不查,上线后必出问题:
- 检查
SELECT @@default_authentication_plugin;是否为mysql_native_password(除非你确认所有客户端都支持caching_sha2_password) - 对比主从的
SELECT COUNT(*) FROM mysql.innodb_table_stats;,8.0 新增了 7 张统计表,若数量不一致说明系统表升级失败 - 执行
SELECT * FROM performance_schema.replication_applier_status_by_coordinator;,确认APPLIER_STATUS是ACTIVE,不是ERROR - 用
mysqldump --no-data --skip-triggers导出一张业务表结构,比对主从输出是否完全一致——字符集、排序规则、自增起始值都可能悄悄变化











