必须先升级从库(聚合端),因其同时消费多个主库binlog,对协议兼容性、gtid解析及中继日志格式容忍度最低;若主库先升而从库滞后,易触发gtid范围找不到、表定义变更等错误。

必须先升级从库(聚合端),且不能直接 START SLAVE 全量启动所有通道——这是最容易导致数据错乱或 GTID 冲突的一步。
为什么聚合端必须最先升级?
多源复制的聚合端(即从库)同时消费多个主库的 binlog,它对协议兼容性、GTID 解析逻辑、中继日志格式的容忍度最低。如果先升级某个主库,而聚合端仍是旧版本,可能出现:
-
STOP SLAVE FOR CHANNEL 'xxx'后无法再START SLAVE FOR CHANNEL 'xxx',报错ER_GTID_EXECUTED_RANGE_NOT_FOUND - 新主库生成的 GTID 集合(如 MySQL 8.0.29 的紧凑型
gtid_executed表结构)被旧从库错误截断或忽略 - 基于行复制(RBR)下,列顺序或元数据版本不匹配引发
Table definition has changed类错误
升级前必须确认的三项配置
聚合端升级不是替换二进制文件就完事,以下三项若未显式设置,mysql_upgrade 可能跳过关键修复,后续通道启动失败率极高:
-
master_info_repository = TABLE和relay_log_info_repository = TABLE:确保复制元数据持久化在mysql.slave_master_info和mysql.slave_relay_log_info这两张 InnoDB 表中,而非易丢失的文件 -
enforce_gtid_consistency = ON:MySQL 5.7+ 多源复制强制要求开启,否则CHANGE MASTER TO ... FOR CHANNEL会拒绝执行 -
binlog_format = ROW:虽非升级硬性前提,但若主库已用 ROW 格式,聚合端仍设为 STATEMENT,会在首次START SLAVE时因事件解析失败而卡住
升级后逐通道启动与验证的关键动作
新版 MySQL 启动后,mysql_upgrade 完成不代表复制就绪。每个通道必须独立验证,因为多源环境下各通道的位点、GTID 集合、错误状态完全隔离:
- 先执行
STOP SLAVE FOR CHANNEL 'source_a';(即使刚启动,也确保处于明确停止态) - 运行
SELECT * FROM performance_schema.replication_connection_status WHERE CHANNEL_NAME = 'source_a'\G,确认LAST_HEARTBEAT_TIMESTAMP为空、THREAD_ID为 NULL - 再执行
START SLAVE FOR CHANNEL 'source_a';,**立刻**跟查:SHOW REPLICA STATUS FOR CHANNEL 'source_a'\G - 重点盯三个字段:
Seconds_Behind_Master是否从 NULL 变为数字;Retrieved_Gtid_Set是否开始增长;Last_IO_Error是否为空——任一异常都需立即STOP SLAVE FOR CHANNEL并查错误日志
容易被忽略的 GTID 兼容性陷阱
MySQL 5.7 升级到 8.0+ 时,gtid_executed 表结构变更,但聚合端不会自动重建该表。若升级后未运行 mysql_upgrade,或运行时未加 --force 参数,SHOW REPLICA STATUS 中的 Executed_Gtid_Set 可能显示为空,实际却已应用部分事务——这种“假空集”会导致后续 RESET SLAVE ALL 或通道重建时丢数据。
真正安全的做法是:升级后首次启动,用 mysqld --upgrade=FORCE 启动,或启动后立即执行 mysql_upgrade -f,并确认输出中包含 mysql.gtid_executed 表已更新。











