必须用after_sync确保主库宕机可安全回滚,因其要求主库先fsync binlog、再发日志、等ack、最后提交;误切after_commit会放大数据丢失风险且不提升吞吐。

半同步复制在高并发下变慢,核心不是“要不要开”,而是“怎么让它不拖垮主库提交路径”——关键参数配错、等待点选错、超时设太死,都会让延迟从毫秒级跳到百毫秒甚至秒级。
rpl_semi_sync_master_wait_point = AFTER_SYNC 为什么必须用,但又不能乱调
AFTER_SYNC 模式下,主库必须 fsync binlog 后才发日志、等 ACK、最后才调 InnoDB 提交。这多了一次网络等待,但换来的是主库宕机后事务可安全回滚;换成 AFTER_COMMIT,主库先提交再发日志,崩溃即丢数据,客户端已收到成功响应却没同步出去。
容易踩的坑:
- 误以为
AFTER_COMMIT更快就切过去——它不提升吞吐,只放大丢失风险 - 和
sync_binlog = 1+innodb_flush_log_at_trx_commit = 1叠加,触发三重刷盘,单事务延迟轻松破 10ms - 没确认从库 relay log 是否真正
fsync:如果从库sync_relay_log = 0,ACK 只代表写入缓冲区,故障时中继日志可能丢失
rpl_semi_sync_master_timeout 设多少才不卡又不退化
单位是毫秒,不是微秒。默认 10000(10 秒)在内网完全不合理——写请求早超时了;设成 100 又太激进,一次网络抖动就退化为异步,半同步形同虚设。
实操建议:
- 内网部署:设为
1000~3000,略高于实测 RTT 波动峰值(可用ping或mtr观察),再留 1~2 倍缓冲 - 跨机房部署:从
5000起,但必须监控Rpl_semi_sync_master_no_times是否飙升——持续超时说明网络或从库 IO 已成瓶颈 - 超时后主库自动降级为异步,但不会自动切回;得靠从库重连或手动
SET GLOBAL rpl_semi_sync_master_enabled = ON触发
slave_parallel_workers > 0 为什么不起作用
MySQL 5.7 的并行复制不是设了线程数就自动跑起来的。常见现象是 SHOW SLAVE STATUS\G 里 Seconds_Behind_Master 居高不下,但 performance_schema.replication_applier_status_by_worker 只显示 1 个 worker 在干活。
必须满足三个前提:
- 执行
STOP SLAVE后再改slave_parallel_workers,否则不生效 -
slave_parallel_type必须显式设为'logical_clock'(默认DATABASE在单库场景下完全无效) - 主库
binlog_format必须为ROW,且建议binlog_transaction_dependency_tracking = WRITESET(5.7 支持,比默认的 COMMIT_ORDER 更细粒度)
哪些“加强可靠性”的配置反而让半同步更慢
这些组合看似稳妥,实则是生产高频踩坑点:
-
rpl_semi_sync_master_wait_for_slave_count = 2:等两个从库 ACK,不是高可用,是人为制造延迟瓶颈 - 从库开了
slave_parallel_workers > 0但没配slave_parallel_type = LOGICAL_CLOCK:SQL 线程还没执行完,IO 线程就发了 ACK,主库误判“已接收”,实际数据根本没落地 - 从库
sync_relay_log = 0:relay log 只写缓冲区不刷盘,ACK 不可靠,主库误判“已接收”,故障时可能丢中继日志
真正影响延迟的,往往不是半同步本身,而是这些配置叠加后形成的隐性阻塞链——比如主库刷 binlog、从库不刷 relay log、SQL 线程串行回放,三者叠在一起,延迟就从几十毫秒跳到几百毫秒。











