异步复制在主库崩溃时会丢数据,因为主库写入成功即返回客户端,不等待从库确认,未发送的binlog事件永久丢失。

异步复制为什么在主库崩溃时会丢数据
MySQL 默认的异步复制(AFTER_COMMIT 或 AFTER_SYNC 模式未启用)下,主库写入成功后就返回客户端 OK,不等待从库确认。此时 binlog 虽已刷盘,但 relay log 在从库可能还没开始拉取,或刚写入 OS cache 未落盘。
常见错误现象:主库宕机后切从库,发现最新几秒的事务完全丢失;监控显示 Seconds_Behind_Master 为 0,但实际仍有未应用的 event 缓存在 SQL 线程内存中。
- 主库 crash 后,未发送到从库的 binlog event 永久丢失
- 从库 IO 线程延迟(如网络抖动、磁盘慢)不会阻塞主库,但放大数据不一致窗口
-
sync_binlog=1和innodb_flush_log_at_trx_commit=1只保主库本地持久性,不解决复制级一致性
半同步复制不是“强一致”,而是“至少一个从库收到”
半同步(rpl_semi_sync_master_enabled=ON)要求主库至少收到一个从库的 ACK(收到并写入 relay log 文件),才提交事务。但它不保证该事务已被从库 SQL 线程执行,也不保证 ACK 是 fsync 到磁盘后的——取决于从库配置 rpl_semi_sync_slave_enabled 和 relay_log_info_repository=TABLE 是否开启。
使用场景:对 RPO(恢复点目标)有硬性要求(比如不能丢超过 1 个事务),且能接受主库提交延迟升高(典型增加 1–5ms)。
- 若所有从库都不可用,半同步自动降级为异步(由
rpl_semi_sync_master_timeout控制超时时间,默认 10s) - MySQL 5.7+ 支持
AFTER_SYNC模式(默认),主库 commit 前等 ACK,崩溃后可保证从库有完整事务;5.5/5.6 是AFTER_COMMIT,主库 commit 后等 ACK,崩溃仍可能丢 - 必须同时在主从两端安装插件:
INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so'和对应 slave 插件
选异步还是半同步?关键看你的 RPO 和 TP99 延迟容忍度
没有银弹。异步复制吞吐高、延迟低,适合日志类、分析类业务;半同步牺牲部分性能换确定性,适合订单、支付等核心事务。
- 如果业务能容忍分钟级数据丢失(例如离线报表库),用异步 + 定期备份更简单可靠
- 如果要求“主挂了立刻切,数据不能少”,半同步是底线,但需配合
read_only=ON、从库定期STOP SLAVE; START SLAVE;防 relay log 积压 - 不要只看复制模式:
max_allowed_packet不一致会导致半同步握手失败静默退化;从库slave_parallel_workers > 0时,ACK 时间点可能滞后于实际写入顺序
-- 检查当前半同步状态(主库) SELECT * FROM performance_schema.replication_applier_status_by_coordinator; SHOW VARIABLES LIKE 'rpl_semi_sync%'; SHOW STATUS LIKE 'Rpl_semi_sync%';-- 查看是否真正生效(Rpl_semi_sync_master_status = ON 且 Rpl_semi_sync_master_clients > 0)
半同步的“半”字很准确——它不解决故障切换逻辑、不防止脑裂、不替代备份。真正容易被忽略的是:当网络分区发生时,主库可能因超时降级,而你监控里只看到“semi sync is on”,却没盯住 Rpl_semi_sync_master_no_times 这个计数器是否在涨。










