AFTER_SYNC是MySQL实现RPO=0的必要条件:主库在InnoDB commit前强制等待至少一个从库将binlog写入并刷盘relay log,确保客户端收到成功响应时事务日志已落盘从库;但需插件正确安装、IO线程重启、sync_binlog=1、innodb_flush_logs_at_trx_commit=1等前提协同才真正生效。

直接说结论:rpl_semi_sync_source_wait_point = 'AFTER_SYNC' 是 MySQL 实现 RPO=0(即主库崩溃时无数据丢失)的必要条件,但不是充分条件。它只在主库事务提交前强制等待至少一个从库写入 relay log 并刷盘,前提是插件已正确安装、IO 线程重启、网络可靠、超时设置合理。
为什么 AFTER_SYNC 能逼近 RPO=0
关键在于事务可见性与 binlog 传输的顺序绑定:
-
AFTER_SYNC模式下,主库流程是:写 binlog → fsync 到磁盘 → 发送给从库 → 等 ACK → InnoDB commit → 返回客户端 - 这意味着:客户端收到“成功”响应时,该事务的 binlog 已确定落盘于至少一个从库的 relay log 中
- 即使主库在
InnoDB commit前宕机,只要从库已刷盘 relay log,故障切换后该事务不会丢失 - 对比
AFTER_COMMIT:主库先 commit 再发 binlog,宕机时 binlog 可能尚未发出,RPO > 0
INSTALL PLUGIN 和变量名在不同版本容易搞错
MySQL 5.7.6+ 与 8.0.26+ 使用新命名规范,老教程里的旧名会直接报错:
解析 MySQL 8.0 的 DDL 脚本,并将表结构导出为 Excel 格式。适用于用户需将 MySQL 的 `CREATE TABLE` 语句转换为结构化的 Excel 文件场景,导出内容包含字段名、数据类型、长度及精度等信息。支持多张表的批量处理,每张表对应 Excel 中的一个独立工作表。适用于数据库文档编写、数据字典生成及模式分析等任务。
- 主库必须执行:
INSTALL PLUGIN rpl_semi_sync_source SONAME 'semisync_source.so'(不是rpl_semi_sync_master) - 从库必须执行:
INSTALL PLUGIN rpl_semi_sync_replica SONAME 'semisync_replica.so'(不是rpl_semi_sync_slave) - 对应系统变量也变了:
rpl_semi_sync_source_enabled、rpl_semi_sync_replica_enabled、rpl_semi_sync_source_wait_point - 执行
SHOW PLUGINS LIKE '%semi%'后,Status必须为ACTIVE,Type必须为SEMISYNCHRONOUS_REPLICATION,否则后续 SET 全无效
从库启用半同步必须重启 IO 线程,SET GLOBAL 不生效
这是最常踩的坑——很多人只在从库执行了 SET GLOBAL rpl_semi_sync_replica_enabled = 1 就以为完事了,结果 SHOW STATUS LIKE 'Rpl_semi_sync_replica_status' 一直返回 OFF:
- 半同步插件在从库上依赖 IO 线程启动时加载,运行中修改变量不触发重载
- 必须显式执行:
STOP SLAVE IO_THREAD;→START SLAVE IO_THREAD; - 之后检查
Rpl_semi_sync_replica_status是否为ON;若仍是OFF,优先排查:semisync_replica.so文件是否存在、防火墙是否放行 3306 的 ACK 包(注意不是仅开放连接,TCP ACK 也要通)、relay_log是否启用
rpl_semi_sync_source_timeout 设置过大会掩盖真实故障
超时降级是半同步的保底机制,但设成 30 秒或更高,会让短暂网络抖动演变成“伪异步”,RPO 实际失效:
- 建议设为
1000(1 秒)到5000(5 秒)之间,具体取决于你的网络 RTT 和业务容忍度 - 降级后
Rpl_semi_sync_source_status会变OFF,需监控该状态变化并告警,不能只看“主从延迟” -
rpl_semi_sync_source_wait_for_slave_count默认为 1,设为 2 可提升容错,但会显著增加事务延迟,且要求两个从库都在线才满足半同步,慎用 -
sync_binlog = 1和innodb_flush_logs_at_trx_commit = 1是前提,否则 binlog 或 redo log 未落盘,AFTER_SYNC 也白搭
真正难的不是配置命令本身,而是确认从库 relay log 刷盘动作是否真实发生——这需要结合 SHOW SLAVE STATUS\G 中的 Seconds_Behind_Master、Relay_Log_Space 增长趋势,以及从库 sync_relay_log = 1 的设置来交叉验证。任何一环松动,RPO=0 就只是幻觉。

















