Seconds_Behind_Master为0不代表事务未丢失,因其仅表示中继日志拉取完成,不反映SQL线程是否执行成功;常见丢事务场景包括SQL线程报错停止、IO线程因binlog缺失断连、GTID范围不匹配跳过事务等。

MySQL从库丢失事务不是“偶发故障”,而是异步复制机制下的确定性行为——主库提交即返回,从库是否执行、何时执行、是否出错,主库一概不关心。要避免丢失,必须主动启用强一致性保障机制,不能依赖默认配置。
为什么Seconds_Behind_Master为0也不代表事务没丢?
这个值只反映中继日志拉取完成的延迟,不反映SQL线程是否真正执行成功。常见漏掉事务的场景包括:
-
Slave_SQL_Running: No但被静默忽略(比如监控未覆盖该字段) - 从库执行
UPDATE时因唯一键冲突报错ERROR 1062,SQL线程停止,后续事务全部卡住 - 主库 binlog 被
expire_logs_days清理,从库请求的binlog.000123已不存在,I/O 线程断连且未告警 - GTID 模式下从库
gtid_purged范围小于主库gtid_executed,导致部分事务被跳过
开启半同步复制:让主库等至少一个从库“签收”
这是最基础的强一致性门槛,但需注意它只保证 binlog 传输成功,不保证执行成功。
- 主库执行
INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so'; - 从库执行
INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so'; - 主库设
rpl_semi_sync_master_enabled = ON,从库设rpl_semi_sync_slave_enabled = ON - 关键参数:
rpl_semi_sync_master_timeout = 1000000(单位微秒,即1秒),避免超时后退化为异步 - 验证是否生效:
SHOW VARIABLES LIKE 'rpl_semi_sync%';和SHOW STATUS LIKE 'Rpl_semi_sync%';
启用增强半同步(Loss-Less Semi-Sync)并配齐持久化
普通半同步仍可能在主库 crash 后丢失已确认但未落盘的 binlog。增强模式要求主库先刷盘再通知从库。
- 主库必须同时开启:
sync_binlog = 1(每次事务都刷 binlog 到磁盘) - 主库必须同时开启:
innodb_flush_log_at_trx_commit = 1(每次事务都刷 redo log) - 启用增强模式:
rpl_semi_sync_master_wait_point = AFTER_SYNC(MySQL 5.7+ 默认,5.6 需显式设) - 此时主库只有在收到从库 ACK 且自身 binlog 已 fsync 后,才向客户端返回 commit 成功
用 GTID + replica_preserve_commit_order = ON 锁定提交顺序
仅靠半同步无法防止从库回放乱序导致的逻辑错误(如 UPDATE 先于 INSERT)。必须组合 GTID 和提交顺序保护。
- 主从均开启:
gtid_mode = ON、enforce_gtid_consistency = ON - 从库设:
replica_parallel_type = WRITESET(MySQL 8.0.22+,比LOGICAL_CLOCK更准) - 从库设:
replica_parallel_workers = 4(建议值,非越多越好) - 最关键:
replica_preserve_commit_order = ON—— 强制 SQL 线程按主库 commit 顺序应用事务,哪怕并行回放也保序 - 注意:
WRITESET依赖binlog_format = ROW且表必须有主键或唯一非空索引,否则退化为单线程
真正难的不是配置开关,而是在写业务 SQL 时就规避隐性不一致:比如在 READ COMMITTED 下做多次 SELECT + UPDATE,从库延迟会导致中间状态被固化。这种问题任何复制参数都救不了,只能靠应用层加 SELECT ... FOR UPDATE 或升到 REPEATABLE READ 并接受锁开销。











