after_sync更安全是因为主库在binlog刷盘后才发日志并等待ack,事务未提交前宕机可回滚,避免“客户端收到成功但数据丢失”;虽增加一次网络等待导致更慢,但after_commit先提交再发日志,主库宕机时未同步的事务将永久丢失。

因为主库必须等至少一个从库返回 ACK 才能完成事务提交,而这个 ACK 只表示 relay log 缓冲区写入成功,不保证已刷盘或已执行——网络抖动、从库 IO 压力、TCP 接收队列积压都会让等待卡住。
为什么 rpl_semi_sync_master_wait_point = AFTER_SYNC 更慢但更安全
它强制主库在 fsync binlog 完成后才发日志、再等 ACK,最后才调用 InnoDB 提交。这意味着:事务未真正提交前,主库宕机可回滚,不会出现“客户端收到成功但数据丢了”的情况。
副作用是单事务多一次网络等待(binlog 刷盘 → 等 ACK → 提交),尤其在高并发下容易堆积 Rpl_semi_sync_master_tx_waits。别为了“快一点”切回 AFTER_COMMIT:它先提交再发日志,主库宕机后从库没收到 binlog 的事务就永久丢失了。
-
AFTER_SYNC是 MySQL 5.7+ 默认值,也是生产环境唯一推荐值 - 切到
AFTER_COMMIT不会提升吞吐,只会放大数据丢失风险 - 若观察到
Rpl_semi_sync_master_status频繁为OFF,问题不在wait_point,而在超时或从库 IO
rpl_semi_sync_master_timeout 设太小或太大都危险
单位是毫秒,不是微秒(某些旧文档写错了)。默认 10000ms(10 秒)在多数内网太保守——等 10 秒才降级,写请求早就超时了;设成 100ms 又太激进,稍有网络波动就退化为异步,半同步形同虚设。
合理值取决于你的 RTT 波动峰:内网建议 1000–3000ms;跨机房建议 5000ms 起,但必须配合监控看 Rpl_semi_sync_master_no_times 是否飙升。
- 超时后主库自动切异步,但不会自动切回——得靠从库重连触发
-
Rpl_semi_sync_master_no_tx持续增长,说明超时频繁发生,该查从库SHOW PROCESSLIST里Slave_IO_Running和磁盘负载了 - 别和
sync_binlog=1+innodb_flush_log_at_trx_commit=1叠加使用,三重刷盘会让单事务延迟突破 10ms
哪些配置组合实际在拖垮性能
看似“加强可靠性”,实则是生产环境的隐形性能黑洞:
-
rpl_semi_sync_master_wait_for_slave_count = 2:等两个从库ACK,不是高可用,是自建延迟瓶颈 - 从库开了
slave_parallel_workers > 0但没设slave_parallel_type = LOGICAL_CLOCK:SQL 线程还没执行完,IO 线程就发了ACK,主库以为 OK,其实数据还没落地 -
sync_relay_log = 0在从库上:relay log 不刷盘,ACK发得太早,主库误判安全性,故障时 relay log 丢数据
验证是否真生效,别只看 SHOW VARIABLES,要查 Rpl_semi_sync_master_yes_transactions 是否随写入递增——这才是半同步真正起作用的铁证。











