必须只停sql_thread而非执行stop slave,否则io_thread停止导致binlog拉取中断、relay log断层丢数据;正确做法是stop slave sql_thread保留io_thread持续接收binlog,升级后start slave sql_thread回放,并校验gtid一致与事件解析正常。

主从滚动升级不是“不停机就能升”,而是靠“先升从、再切主、最后升原主”实现业务无感知——前提是版本差不能超一个大版本,且必须停 SQL_THREAD 而非整个复制链路。
为什么STOP SLAVE不能直接执行
直接执行 STOP SLAVE 会同时停掉 IO_THREAD 和 SQL_THREAD,导致主库新写入的 binlog 无法被拉取,一旦升级耗时较长,relay log 断层,后续追平困难甚至丢事务。真正要保的是数据不丢失、复制链不断,而不是“看起来没停”。
- 正确做法是只停 SQL_THREAD:
STOP SLAVE SQL_THREAD,让 IO_THREAD 继续运行,持续接收主库 binlog 并写入 relay log - 升级完成后,
START SLAVE SQL_THREAD启动回放;若Seconds_Behind_Master飙高或Slave_SQL_Running_State卡在 “Reading event from the relay log”,说明新版本解析旧 binlog 事件失败,需人工检查Relay_Log_File对应位置的 event 类型 - 5.7 → 8.0 升级时尤其注意:若主库未开 GTID,从库升级后默认强制启用
gtid_mode=ON,会导致CHANGE MASTER TO失败,必须先在主库补全gtid_mode = ON_PERMISSIVE等步骤
mysql_upgrade 什么时候必须执行、什么时候不能执行
mysql_upgrade 在 8.0.16+ 已被弃用,但它的替代命令 mysqld --upgrade 不是可选动作,而是 5.7 → 8.0 升级后必跑步骤——否则系统表结构不匹配,权限校验直接崩溃,典型表现是 SELECT USER() 返回空或报错 Access denied for user ''@'localhost'。
- 必须在从库停写、SQL_THREAD 停止后执行:
mysqld --defaults-file=/etc/my.cnf --upgrade=MINIMAL --skip-grant-tables --skip-networking & - 不能在主库还运行时对从库执行交互式
mysql_upgrade -u root -p(8.0.16+ 不支持),也不能跳过该步直接启动 8.0 二进制读取 5.7 数据目录,否则启动失败并报错Table 'mysql.role_edges' doesn't exist - 如果已漏掉这步且 mysqld 启动失败,不要硬重启,改用
--skip-grant-tables启动后手动修复mysql.user.authentication_string字段格式
多源复制从库升级要注意什么
多源复制的从库有多个独立通道(channel),每个通道对应一个主库,升级时不能只看整体状态,必须逐个确认通道兼容性与同步进度。
- 先查所有通道状态:
SELECT channel_name, service_state, received_transaction_set FROM performance_schema.replication_connection_status - 每个通道的主库版本都必须与目标从库版本兼容:比如从库升到 8.0.33,则所有主库不能是 5.6 或 8.4,推荐主库 ≤ 8.0.32 且 ≥ 5.7.32
- 升级前必须确保所有通道的
Retrieved_Gtid_Set = Executed_Gtid_Set,否则某个通道的 binlog 滞后会导致升级后该通道永久中断 - 升级后首次启动,用
START SLAVE FOR CHANNEL 'xxx'逐个启通道,避免因某一个通道配置错误(如MASTER_AUTO_POSITION=1但主库 GTID 不连续)拖垮全部复制
切换主库前最容易被忽略的三个验证点
很多人看到 Seconds_Behind_Master = 0 就切流量,结果几分钟后出现主键冲突或权限失效——因为这个值只表示 relay log 已读完,不等于已安全执行。
- 检查
SHOW SLAVE STATUS\G中的Executed_Gtid_Set是否完全包含Retrieved_Gtid_Set,不等价说明有事务被跳过或过滤 - 确认
binlog_format主从一致为ROW:5.7 对MIXED支持减弱,某些函数(如UUID())在 MIXED 下会导致 SQL_THREAD 中断且不报错 - 验证
sql_mode兼容性:8.0 默认启用STRICT_TRANS_TABLES,若主库 5.7 用了NO_AUTO_CREATE_USER(8.0 已移除),则从库升级后执行含该模式的语句会直接报错中断
滚动升级真正的复杂点不在操作步骤,而在于每个环节的“隐性依赖”:GTID 连续性、系统表结构迁移时机、认证插件切换顺序、auto_increment 的 offset 配置——这些不会在日志里明说,但任何一个出错,都会让复制静默失败或数据不一致。











