Rpl_semi_sync_master_status在ON/OFF间跳变是半同步机制主动降级,主库超时未收ACK即切异步,非插件故障;需结合Rpl_semi_sync_master_off_times等指标排查网络或从库IO瓶颈。

Rpl_semi_sync_master_status 在 ON/OFF 之间跳变,不是插件坏了,而是半同步机制在主动告诉你:ACK 没按时回来。
为什么超时就会退化为异步
主库执行完事务后,会调用 rpl_semi_sync_master_timeout 设置的毫秒数等待至少一个从库发来 ACK。一旦超时,主库立刻降级为异步模式,并把 Rpl_semi_sync_master_status 设为 OFF。这不是故障恢复逻辑,而是设计行为——MySQL 半同步不追求“永远不降级”,只承诺“能稳住时才坚持”。
- 超时后不会重试,也不会阻塞后续事务,降级是瞬时、无感的
- 降级后所有事务都走异步路径,直到下一次收到有效 ACK 才重新切回 ON
-
Rpl_semi_sync_master_off_times每次降级都会 +1,它是判断抖动频率的关键指标
怎么查是不是真在半同步状态
只看 rpl_semi_sync_master_enabled = 1 没用,必须查运行时状态:
- 主库执行
SHOW STATUS LIKE 'Rpl_semi_sync%';,重点关注:Rpl_semi_sync_master_status(当前是否生效)、Rpl_semi_sync_master_clients(连上并声明支持半同步的从库数)、Rpl_semi_sync_master_no_times(累计未收到 ACK 次数) - 挨个登录每个从库,确认
rpl_semi_sync_slave_enabled = ON且Rpl_semi_sync_slave_status = ON - 如果
Rpl_semi_sync_master_no_times和Rpl_semi_sync_master_off_times每小时涨几十次,说明不是参数问题,是网络或从库 IO 已经扛不住
timeout 值设多少才合理
rpl_semi_sync_master_timeout 不是越大越安全,它必须落在真实网络与负载的波动区间内。设错反而放大风险:
- 局域网(RTT 稳定在 0.5–2ms):起点设
1000(1 秒),覆盖 99% 尖峰抖动足够 - 跨机房或高负载(RTT 偶发飙到 15ms+):可设
3000~5000,但别碰10000(默认值),否则单事务可能卡 10 秒 - 绝对不要设低于
500:UDP 小包丢包率 >0.1% 时,100ms 超时几乎必降级 - 改完立即生效:
SET GLOBAL rpl_semi_sync_master_timeout = 3000;,无需重启
光调 timeout 不够,还得盯住 ACK 是谁发的
Rpl_semi_sync_master_status = ON 只表示“至少有一个从库连上了且声称支持半同步”,不代表你业务依赖的那个从库真在参与。常见陷阱包括:
- 从库
net.ipv4.tcp_rmem过小,导致 ACK 包被内核丢弃或延迟 - 从库正在执行大查询或备份,
Seconds_Behind_Master持续上涨,relay log 写入已滞后 - 从库开了并行复制(
slave_parallel_workers > 0)但slave_parallel_type = DATABASE,SQL 线程没执行完就提前发了 ACK - 主从之间混跑备份流量,瞬时带宽打满,ACK 包压在队列尾部
真正要做的,是让半同步“稳得住”,而不是“等得久”。网络抖动和从库 IO 能力才是根因,timeout 只是暴露问题的探针。


















