MySQL主从滚动升级的核心约束是主从版本差不得超过一个大版本且从库版本≥主库版本,同时需确保binlog_format、GTID行为、系统表结构等复制协议兼容。

主从架构下滚动升级的核心约束是什么
MySQL 主从滚动升级能实现业务无中断,但前提是主库和从库的版本兼容性必须满足复制协议要求。5.7 → 8.0 这类跨大版本升级不能直接跳,因为 binlog_format、GTID 行为、系统表结构(如 mysql.user)都有不兼容变更。官方明确要求:主从版本差不能超过一个大版本,且从库版本 ≥ 主库版本(仅限小版本或同一主版本内的升级)。
- 如果主库是 5.7.32,从库可先升到 5.7.40,再升到 8.0.33(需先在 5.7 上开启
show_compatibility_56=OFF并重建系统表) - 若主库已是 8.0.22,从库可直接升级到 8.0.33,但不能降级回 5.7
- 升级前必须确认
slave_type_conversions和enforce_gtid_consistency设置与目标版本兼容,否则START SLAVE会报错
怎么让从库升级时不中断复制链路
关键不是“不停止复制”,而是避免 IO_THREAD 或 SQL_THREAD 因版本切换失败而断开。实际操作中,应分三步隔离风险:
- 停掉从库的
SQL_THREAD(执行STOP SLAVE SQL_THREAD),保留IO_THREAD继续拉取 binlog,确保主库新写入不丢失 - 升级 MySQL 二进制文件 + 配置,重启 mysqld 进程(此时
IO_THREAD自动恢复,relay log 持续追加) - 等 relay log 追平后,再启
SQL_THREAD;若中途发现SHOW SLAVE STATUS中Seconds_Behind_Master飙高或Slave_SQL_Running_State卡在 “Reading event from the relay log”,说明语句在新版本解析异常,需人工检查Relay_Log_File对应位置的事件
升级后为什么 SELECT USER() 返回空或报错
这是 8.0+ 版本对账户模型重构的典型副作用。如果从库升级前没运行 mysql_upgrade(或 8.0+ 中已被移除,改用 mysqld --upgrade),系统表如 mysql.global_grants、mysql.role_edges 仍是 5.7 结构,会导致权限校验逻辑崩溃。
- 升级完必须执行
mysqld --upgrade(非交互式)或mysql_upgrade -u root -p(仅 5.7→8.0 过渡期可用,8.0.16+ 已弃用后者) - 若已跳过该步骤且出现
Access denied for user ''@'localhost',不要重启 mysqld,先用--skip-grant-tables启动,手动修复mysql.user的authentication_string字段格式 - 所有从库升级完成后,主库才能升级——否则主库创建的新角色/权限语句无法被旧从库解析
如何验证滚动升级后的数据一致性
不能只看 Seconds_Behind_Master = 0,它只表示 relay log 已读完,不保证应用成功。真实一致性要靠三重校验:
- 对比主从的
SELECT COUNT(*) FROM table_name(适合小表);大表用pt-table-checksum,注意其默认在主库执行 checksum 查询,需确保从库已启用read_only=0临时权限 - 检查
SHOW SLAVE STATUS\G中Exec_Master_Log_Pos和Read_Master_Log_Pos是否相等,且Retrieved_Gtid_Set包含Executed_Gtid_Set - 抓一段主库 binlog(如
mysqlbinlog --base64-output=DECODE-ROWS -v mysql-bin.000001 | head -n 50),在从库上用SELECT * FROM performance_schema.replication_applier_status_by_coordinator查对应 GTID 是否标记为APPLIED
跨版本滚动升级最易被忽略的是字符集继承行为变化:8.0 默认 collation_server=utf8mb4_0900_ai_ci,而 5.7 是 utf8mb4_general_ci。如果从库升级后没同步修改 my.cnf 中的 collation-server,某些 ORDER BY 或 GROUP BY 可能返回不同结果,且不会报错。











