after_sync模式让主库每条写事务变慢,因其强制在提交前阻塞等待至少一个从库ack:写binlog→刷盘→发送→等ack→提交;ack仅表示relay log缓存写入成功,不保证落盘或执行,网络抖动、从库tcp队列满或io压力均导致延迟。

为什么AFTER_SYNC模式会让主库每条写事务都变慢
因为主库必须在事务提交前,强制等待至少一个从库返回ACK。这个等待不是“发完就走”,而是阻塞式同步点:写binlog → 刷盘(若sync_binlog=1)→ 发送 → 等ACK → 才提交。哪怕网络RTT只有2ms,P99达到80ms时,主库的COMMIT就被卡在这一步,QPS直接受限。
-
rpl_semi_sync_master_wait_point = AFTER_SYNC是MySQL 5.7无损复制的唯一可靠路径,但它把网络延迟直接计入事务延迟 - ACK只表示从库已将event写入relay log buffer,不保证落盘、更不保证执行——主库却为此停住整个事务流程
- 如果从库TCP接收队列满、内核
net.ipv4.tcp_rmem过小、或正经历大查询IO压力,ACK就会延迟甚至丢包,主库只能等超时
哪些配置组合会把吞吐压到不可接受
单看半同步开关没用,真正拖垮吞吐的是参数叠加效应。几个典型“性能黑洞”配置:
-
sync_binlog=1+innodb_flush_log_at_trx_commit=1+ 半同步:三次强制刷盘(binlog、redo、relay log buffer)+ 一次网络往返,SSD高负载下单事务轻松破10ms -
rpl_semi_sync_master_wait_for_slave_count = 2:要求两个从库都ACK才提交,等于把最慢那个从库的延迟变成全局瓶颈,实际是自设单点 -
slave_parallel_workers > 0但slave_parallel_type = 'DATABASE':SQL线程未执行完就提前发ACK,主库误判成功,但后续并行冲突导致重试或卡住,间接拉长整体延迟
如何验证主库是不是真被半同步卡住
别只查rpl_semi_sync_master_enabled = ON——那只是开关开了。关键看运行时是否真在等、等谁、等多久:
- 查状态:
SHOW STATUS LIKE 'Rpl_semi_sync_master_no_times'和Rpl_semi_sync_master_off_times持续增长?说明频繁超时降级,不是配置问题,是网络或从库IO跟不上 - 抓包确认:主库dump线程发出binlog event后,是否真等到从库TCP ACK + 协议层
semi-sync reply才继续调用ha_commit_trans() - 对比指标:开半同步前后,
Com_commit的平均耗时是否明显上移?用pt-query-digest --filter '$event->{arg} =~ m/COMMIT/'抽样分析
超时值rpl_semi_sync_master_timeout该怎么设
它不是越长越安全,而是要匹配你真实网络波动区间。设错反而放大问题:
- 设成
100(毫秒):跨机房场景下几乎必降级,Rpl_semi_sync_master_off_times每小时涨几十次,等于半同步形同虚设 - 设成
10000(默认值):一个事务可能卡10秒,业务直接超时,比异步还糟 - 推荐值:
3000(3秒)覆盖99%尖峰抖动;高SLA场景可设5000,但必须配合监控告警——一旦Rpl_semi_sync_master_off_times突增,立刻查从库SHOW PROCESSLIST里I/O线程是否卡在Waiting for master to send event











