必须先升从库、验证无误后再切主库,否则Seconds_Behind_Master>0时停主库会导致未同步binlog静默丢失;需确认Seconds_Behind_Master=0、GTID集合一致、read_only与super_read_only均为ON,并严格校验升级后SQL线程追平、字符集排序、事务隔离级别及执行计划。

必须先升从库、验证无误后再切主库,否则 Seconds_Behind_Master > 0 时停主库 = 数据静默丢失。
为什么不能直接停主库升级
停主库那一刻,所有未同步的 binlog 都会丢——Seconds_Behind_Master 不是 0 就代表有延迟,这部分变更永远无法追上。应用连接池(如 HikariCP)里的长连接也不会自动重连,持续报 Lost connection to MySQL server;更隐蔽的是,super_read_only=OFF 的从库若被误写,切主后立刻引发主键冲突或唯一索引报错。
- 必须确认每台待升级从库的
Seconds_Behind_Master = 0 - 用
SELECT GTID_SUBSET(@@global.gtid_executed, 'xxx')=1校验Retrieved_Gtid_Set和Executed_Gtid_Set完全一致 - 检查
read_only=ON且super_read_only=ON已生效(SHOW VARIABLES LIKE '%read_only%')
从库升级操作要点
不是简单替换二进制,而是要控制启动流程和复制恢复节奏。老版本数据目录不能直接被新版本 mysqld 启动,尤其跨大版本(如 5.7 → 8.0),系统表结构已变,强行启动可能卡在初始化阶段或损坏元数据。
- 先执行
STOP SLAVE SQL_THREAD(保留 IO 线程,避免丢 position) - 关闭 mysqld 后,用目标版本二进制替换
basedir,但datadir保持不变(前提是版本兼容,如 8.0.33 升级 8.0.39 可复用) - 重点检查配置文件:
innodb_locks_unsafe_for_binlog等废弃参数必须移除;default_authentication_plugin=caching_sha2_password若客户端不支持,需临时设为mysql_native_password - 启动后立即执行
START SLAVE,再等Seconds_Behind_Master = 0且Slave_SQL_Running_State显示Slave has read all relay log
主从切换前必须跑的三类验证
很多人只验证 SELECT 1 和 mysqld --version 就切流,结果第二天慢查询暴增、排序错乱、事务隔离异常——这些都不是“服务起来”就能发现的。
- 用业务账号执行
INSERT INTO t VALUES (1, '中文'),确认utf8mb4_0900_ai_ci排序行为没破坏搜索/去重逻辑 - 查
information_schema.INNODB_TRX,确认trx_isolation是READ-COMMITTED(MySQL 8.0 默认),不是旧版的REPEATABLE-READ - 对核心查询跑
EXPLAIN FORMAT=tree SELECT * FROM t WHERE id = ?,比对是否出现Using temporary; Using filesort——这是隐式类型转换或索引失效信号
ProxySQL / MySQL Router 灰度权重怎么调才安全
代理层不是“加一台新实例就完事”,流量切入节奏不对,监控跟不上,等于把风险从数据库转移到了中间件。
-
mysql_servers.weight初始值必须设为1(不是 0),否则健康检查通过但 SELECT 流量根本不会发过去 - HAProxy 必须配
option mysql-check user haproxy_check,且后端 MySQL 上提前建好该用户并授USAGE权限,否则 check 永远返回 UP - 权重调整间隔不能低于监控采样周期(如 Prometheus 抓取间隔是 15s,就不能每 5s 调一次),否则指标抖动无法归因
真正容易被跳过的,是升级后持续观察 30 分钟以上的 Aborted_clients 和 Threads_connected 波动——它们比慢查询更早暴露连接层兼容性问题。











