半同步复制解决异步复制下主库提交后从库未收到导致的数据丢失风险;需主从同时启用插件、重启IO线程并确保relay_log启用;AFTER_SYNC比AFTER_COMMIT更安全,推荐使用;超时降级后通过Rpl_semi_sync_master_status和Rpl_semi_sync_master_no_times监控判断。

半同步复制到底解决什么问题?
它解决的是异步复制下“主库提交了,但从库还没收到”导致的数据丢失风险。比如主库刚 COMMIT 一个转账事务,立刻宕机,而 binlog 还卡在网络或从库 IO 线程缓冲区里——这时切换到从库,钱就凭空消失了。半同步强制主库多等一步:至少一个从库把 binlog 写进 relay log 并刷盘(flush),才向客户端返回成功。
为什么装插件后还无效?常见激活失败原因
半同步不是装完插件就自动生效的,必须两端同时启用且 IO 线程重启。最容易漏的三步:
-
SET GLOBAL rpl_semi_sync_master_enabled = 1(主库)和SET GLOBAL rpl_semi_sync_slave_enabled = 1(从库)必须分别执行,缺一不可 - 从库必须显式重启 IO 线程:
STOP SLAVE IO_THREAD; START SLAVE IO_THREAD;—— 单纯START SLAVE不会重载半同步逻辑 - 确认从库的
relay_log已启用(relay_log非空值),否则即使插件开启,从库也无法写 relay log,自然无法发 ACK
AFTER_SYNC 和 AFTER_COMMIT 到底差在哪?
这是 MySQL 5.7+ 的关键分水岭,默认是 AFTER_SYNC,但行为差异直接影响故障时的数据一致性:
-
AFTER_SYNC:主库写完 binlog → 等从库 ACK → 再COMMIT。好处是只要主库COMMIT成功,该事务必然已在至少一个从库的 relay log 中。坏处是主库 crash 在COMMIT前,这个事务虽已发往从库,但主库自己没提交,客户端收不到响应——需应用层幂等处理 -
AFTER_COMMIT(5.5/5.6 默认):主库写完 binlog →COMMIT→ 再等 ACK。问题在于:COMMIT后主库就认为事务完成,其他会话可见;但如果此时网络断开、从库未收到,紧接着主库宕机,failover 到从库就会丢数据
可通过 rpl_semi_sync_master_wait_point 查看或设置,生产环境强烈建议用 AFTER_SYNC。
超时降级后怎么知道它已经“变回异步”了?
半同步不是全有或全无的状态,它会动态退化。监控两个关键指标即可判断是否已降级:
-
SHOW STATUS LIKE 'Rpl_semi_sync_master_status':返回ON表示当前半同步有效;OFF表示已退为异步(常见于从库延迟 >rpl_semi_sync_master_timeout,默认 10000 毫秒) -
SHOW STATUS LIKE 'Rpl_semi_sync_master_no_times':该值持续增长,说明频繁触发超时降级,得查从库 IO 延迟、磁盘刷盘性能或网络抖动
真正容易被忽略的是:降级后主库不会报错、不中断服务,但数据保护能力已归零——你得靠监控主动发现,而不是等故障发生才意识到“原来早就不半同步了”。










