半同步复制频繁切换根本原因是主库未在rpl_semi_sync_master_timeout内收到从库ack,导致自动降级又恢复。常见原因包括timeout值过小(如设为10ms)、网络抖动、从库响应慢或配置不一致,需逐项排查。

为什么半同步复制总在 ON/OFF 之间反复切换
根本原因是主库没能在 rpl_semi_sync_master_timeout 设定时间内收到从库的 ACK。一旦超时,MySQL 自动降级为异步复制;稍后若网络或负载恢复,又可能重新升回半同步——于是状态来回跳变。
这不是“故障”,而是半同步机制的保护行为。但频繁切换说明底层条件不稳定,需定位到底是网络、参数,还是从库响应能力的问题。
检查 rpl_semi_sync_master_timeout 是否过小
这是最常见也最容易被忽略的配置陷阱。默认值是 10000 毫秒(10 秒),但很多线上环境被误设为 10 或 50 毫秒,导致只要网络有轻微抖动或从库 IO 延迟几十毫秒就触发超时。
- 用
SHOW VARIABLES LIKE 'rpl_semi_sync_master_timeout';查当前值 - 若结果是
10或50,基本可以确定是它引起的频繁 OFF - 合理值取决于你的网络 RTT 和从库负载:局域网建议设为
1000(1 秒)起步;跨机房或高负载场景建议3000–5000 - 修改后需执行
SET GLOBAL rpl_semi_sync_master_timeout = 3000;生效,无需重启
验证主从间是否存在网络抖动
即使平均延迟很低,突发丢包或瞬时延迟尖峰也会让 ACK 丢失或迟到,直接导致超时。不能只看 ping 的 avg,要看 max 和丢包率。
- 在主库服务器上运行:
ping -c 100 从库IP,重点关注max值是否偶尔飙到 20ms+,以及是否有packet loss - 用
iperf -c 从库IP -t 30 -u测 UDP 丢包(更贴近 ACK 包行为),丢包 >0.1% 就值得警惕 - 检查中间设备(防火墙、安全组、交换机 ACL)是否对小包(如 ACK)做了限速或过滤
- 避免把半同步和业务流量跑在同一条链路上,尤其当存在备份、ETL 等大流量任务时
确认从库是否真正以半同步模式连接
主库显示 Rpl_semi_sync_master_status=ON 并不保证某个从库就是半同步的——它只反映“至少有一个从库”满足条件。而那个“幸运从库”可能刚好是延迟最低、网络最好的一个,掩盖了其他从库的真实问题。
- 查主库变量:
SHOW STATUS LIKE 'Rpl_semi_sync_master_clients';,看实际参与半同步的从库数量 - 登录每个从库,执行:
SHOW VARIABLES LIKE 'rpl_semi_sync_slave_enabled';和SHOW STATUS LIKE 'Rpl_semi_sync_slave_status';,确认两者都为ON - 注意:
rpl_semi_sync_slave_timeout是从库侧参数,控制其自身处理请求的超时,一般不用调,但若设为 0 或极小值,也可能干扰 ACK 发送
真正麻烦的是那种“看起来都配对了、日志也没报错、但就是隔几分钟切一次”的情况——往往卡在某台从库的磁盘写入延迟、relay log 刷盘策略,或者 MySQL 内部 ACK 接收线程(ack_receiver)被阻塞。这时候得开 trace 日志,而不是只盯着 timeout 参数改来改去。











