MySQL升级时主从同步中断是因binlog格式、GTID状态或复制协议版本不兼容,导致IO/SQL线程报错停止;5.7升8.0需开启enforce_gtid_consistency,8.0.23+默认启用binlog压缩,老从库无法解压;GTID模式下跳过DDL须注入空事务;切换主库前须确认旧主停写、从库GTID集完整、新主正确设置gtid_purged;从库升级应调大slave_net_timeout并避免systemctl restart;mysqldump不保证一致性,校验宜用pt-table-checksum或COUNT+MD5;隐式类型转换变化可能引发性能退化。

主从同步在MySQL升级时为什么会断?
因为升级过程里,主库或从库的binlog格式、GTID状态、复制协议版本可能不一致,IO_THREAD 或 SQL_THREAD 会直接报错停止。常见错误是 ER_MASTER_FATAL_ERROR_READING_BINLOG 或 Cannot replicate because the master version is higher than slave —— 这不是网络问题,是协议/解析层不兼容。
- 5.7 升 8.0 时,如果从库没开
enforce_gtid_consistency=ON,即使主库开了,复制也会卡在事务校验阶段 - 8.0.23+ 默认启用
binlog_transaction_compression=ON,老版本从库无法解压,SHOW SLAVE STATUS里Seconds_Behind_Master会突变为NULL,Slave_SQL_Running_State停在 “Waiting for transaction to be committed” - 跳过 DDL 的临时方案(如
SET GLOBAL sql_slave_skip_counter=1)在 GTID 模式下完全失效,必须用gtid_executed手动注入空事务
在线切换主库前必须验证的三件事
别信“升级完重启就自动同步”,主从角色切换后,新主库的 binlog position / GTID set 必须和旧主库最后一致,否则从库追不上、或者重复执行。
- 确认旧主库已停写:
FLUSH TABLES WITH READ LOCK后立刻查SHOW MASTER STATUS,记下File和Position(非 GTID 场景)或Executed_Gtid_Set(GTID 场景) - 检查所有从库的
Retrieved_Gtid_Set是否包含旧主库的完整 GTID 集;若不全,先等Seconds_Behind_Master = 0再操作 - 新主库启动后,必须执行
RESET MASTER(非 GTID)或SET GLOBAL gtid_purged = 'xxx'(GTID),否则从库连接时会因 GTID 冲突拒绝 IO 线程启动
升级从库时如何避免复制中断超时
MySQL 8.0 默认 slave_net_timeout = 60,但升级期间 mysqld 重启可能耗时超过这个值,导致从库主动断连并清空 relay log,再连上就得重传全部 binlog —— 这不是丢数据,但会拖慢恢复速度。
- 升级前在从库设大一点的超时:
SET PERSIST slave_net_timeout = 300(注意:8.0.11+ 才支持PERSIST,老版本改配置文件后 reload) - 不要用
systemctl restart mysqld,换成mysqladmin shutdown+ 手动拉起新二进制,能控制进程启停节奏 - 升级后首次
START SLAVE前,先运行CHANGE REPLICATION SOURCE TO ... SOURCE_AUTO_POSITION = 1(8.0.23+ 语法),避免因 source_host/source_port 缓存导致连错实例
为什么 mysqldump 不适合做主库升级前的数据校验
它默认不锁表、不保证一致性快照,尤其在有长事务或大 DML 时,dump 出来的数据和主库当前 SHOW MASTER STATUS 并不对应,拿它去比对从库数据,结果不可信。
- 真要校验,用
SELECT COUNT(*) FROM t1+CHECKSUM TABLE t1组合,比对主从结果是否一致(注意:CHECKSUM 在 8.0.29+ 已弃用,可用SELECT MD5(GROUP_CONCAT(...))替代) -
pt-table-checksum是更稳的选择,但它依赖replication_user有PROCESS权限,升级前记得检查权限是否继承 - 别在校验过程中执行
OPTIMIZE TABLE或ANALYZE TABLE,这些语句在 5.7 和 8.0 解析方式不同,可能导致从库 SQL 线程 crash
最麻烦的其实是升级后隐式类型转换行为变化 —— 比如 WHERE id = '123 ' 在 5.7 会命中,在 8.0 可能走全表扫描,这种不会报错,但会让业务变慢,得靠慢日志回溯,而不是靠同步状态判断。











