不能。半同步复制仅保证至少一个从库收到并刷盘binlog,不保证事务已在从库执行完毕,无法确保主从实时一致,且受超时退化、未提交事务、ddl、非事务引擎及主从持久化配置等因素影响。

半同步复制到底能不能保证主从完全一致
不能。它只保证至少一个从库收到了事务的 binlog 并写入 relay log(或已刷盘),不保证该事务已在从库执行完毕。也就是说,semi-sync 解决的是“主库崩溃时丢事务”的问题,不是“主从实时一致”的问题。
常见错误现象:SHOW SLAVE STATUS 显示 Seconds_Behind_Master: 0,但实际查询从库却查不到刚在主库插入的数据——这是因为事务还没 apply,只完成了接收和落盘。
- 启用半同步后,主库
INSERT会阻塞,直到至少一个从库返回 ACK(收到并刷盘 relay log) - 如果所有从库都超时或断开,主库自动退化为异步模式(由
rpl_semi_sync_master_timeout控制),此时一致性保障失效 -
rpl_semi_sync_master_wait_for_slave_count默认为 1,设为更高值会加剧主库延迟,但提升可靠性下限
如何确认半同步是否真正生效
光看 INSTALL PLUGIN 成功或变量开启不等于运行中有效。必须检查运行时状态。
使用场景:主库切流、高可用切换前,或发现数据不一致时快速验证链路是否“真半同步”。
- 查主库:
SELECT @@rpl_semi_sync_master_status;—— 必须为ON,且SELECT @@rpl_semi_sync_master_clients;> 0 - 查从库:
SELECT @@rpl_semi_sync_slave_status;—— 必须为ON,且SHOW PROCESSLIST中有semi sync相关线程 - 关键陷阱:
rpl_semi_sync_master_enabled和rpl_semi_sync_slave_enabled是启动参数,但运行中可能因网络抖动、从库 IO 延迟等被动态置OFF,需定期监控
配置半同步必须改的三个参数
MySQL 自带的半同步插件(rpl_semi_sync_master / rpl_semi_sync_slave)不依赖额外组件,但默认全关,且超时设置极不友好。
性能影响:主库每个事务多一次网络 round-trip + 从库刷盘耗时,QPS 高时延迟明显上升;兼容性上,5.7+ 原生支持,5.6 需手动安装插件,8.0.2 开始支持 WAIT_AFTER_SYNC 和 WAIT_AFTER_COMMIT 两种模式。
- 主库:
SET GLOBAL rpl_semi_sync_master_enabled = 1;、SET GLOBAL rpl_semi_sync_master_timeout = 1000000;(单位微秒,即 1 秒,太小容易频繁退化) - 从库:
SET GLOBAL rpl_semi_sync_slave_enabled = 1;,并执行STOP SLAVE; START SLAVE;让插件接管 IO 线程 - 务必在 my.cnf 里固化:否则重启后失效,且注意 5.7+ 的
plugin_load_add要显式加载,如plugin_load_add = 'semisync_master.so;semisync_slave.so'
为什么开了半同步还是丢了数据
最常被忽略的一点:半同步只保护主库 commit 的事务,不保护未 commit 的事务、DDL、或非事务引擎(如 MyISAM)的操作。
典型场景:应用层用 BEGIN; INSERT; ... 但没 COMMIT 就断连;或主库 crash 发生在事务已写 binlog 但尚未到达从库 ACK 阶段(即 timeout 触发前崩溃)。
- DDL 操作(
ALTER TABLE)在 GTID 模式下可能被跳过同步,尤其跨版本升级时 - 从库
relay_log_recovery = ON时,重启可能丢部分 relay log,导致半同步 ACK 了但后续无法执行 - 主库
sync_binlog = 0或innodb_flush_log_at_trx_commit = 0时,即使半同步成功,主库 crash 仍可能丢失 binlog 或 redo,造成主从不可逆不一致
复杂点在于:半同步是“链路级”保障,不是“数据级”保障。它减少风险,但要把控住 binlog 持久化、从库应用位点、以及业务层事务边界,才算真正靠近“完全同步”。











