必须重启从库io线程才能激活半同步逻辑,仅设参数无效;需确认插件存在且active、防火墙放行ack、wait_point设为after_sync,并配齐sync_binlog=1等底层刷盘参数。

不能保证绝对零丢失,但能逼近 RPO=0 —— 前提是配置全对、参数协同、网络可靠。
为什么 SHOW STATUS LIKE 'Rpl_semi_sync_slave_status' 一直为 OFF
这不是“没配好”,而是从库 IO 线程压根没加载半同步逻辑。仅执行 SET GLOBAL rpl_semi_sync_slave_enabled = 1 不触发插件初始化;必须显式重启线程:STOP SLAVE IO_THREAD; START SLAVE IO_THREAD;。否则状态永远是 OFF,主库也永远收不到 ACK。
- 检查插件文件是否存在:
ls -l $(mysql -Nse "SELECT @@plugin_dir")/semisync_replica.so(MySQL 8.0.26+)或semisync_slave.so(≤8.0.25) - 确认插件已激活:
SELECT PLUGIN_NAME, PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME LIKE 'rpl_semi%';,状态必须是ACTIVE - 防火墙可能拦截 ACK 包:主库 3306 端口需允许从库 IP 的双向 TCP 流量(不只是初始连接)
rpl_semi_sync_source_wait_point 必须设为 AFTER_SYNC
这是唯一能逼近 RPO=0 的模式。它强制主库在 InnoDB 提交前,等待至少一个从库将 binlog 写入并 fsync 到 relay log 文件 —— 客户端收到成功响应时,该事务的 binlog 已确定落盘到从库磁盘,而非仅在内存或 OS 缓存中。
- 默认值在 MySQL 5.7+ 是
AFTER_SYNC,但必须显式设置:SET GLOBAL rpl_semi_sync_source_wait_point = 'AFTER_SYNC'; -
AFTER_COMMIT模式下,主库先提交再等 ACK,崩溃时已提交但未发出去的事务会丢失 - 该变量只对后续新事务生效,不影响正在执行的事务
配套参数缺一不可,否则 AFTER_SYNC 形同虚设
就算 rpl_semi_sync_source_wait_point = 'AFTER_SYNC' 生效了,如果底层日志没真正刷盘,ACK 对应的事务照样可能丢。
-
sync_binlog = 1:每次事务提交都强制fsyncbinlog 文件,防止 OS 缓存延迟写盘 -
innodb_flush_logs_at_trx_commit = 1:确保 redo log 同步刷盘,这是 InnoDB 持久化的底线 - 从库必须启用
relay_log并确保其所在磁盘支持fsync(如禁用 ext4 的barrier=0或使用某些云盘缓存策略会导致 relay log 实际未落盘) -
rpl_semi_sync_source_timeout不能设为 0(无限等待),也不宜过大(比如 60000ms);建议 10000ms 左右,平衡可靠性与业务延迟
最容易被忽略的是:半同步降级后状态仍是 ON,Rpl_semi_sync_master_status 不会变,但 Rpl_semi_sync_master_no_tx 会持续增长 —— 必须监控这个计数器,而不是只看“是否开启”。











