主从复制事务不一致的典型表现是主库写入成功但从库报error 1032或1062,根源在于binlog未完整保留事务上下文,须使用row格式+innodb引擎,并禁用不兼容gtid的语句。

主从复制中事务不一致的典型表现
主库写入成功但从库报 ERROR 1032 (HY000): Can't find record in table 或 ERROR 1062 (23000): Duplicate entry,基本可判定事务在从库回放时出错。这不是网络中断或延迟问题,而是事务上下文在 binlog 中未被完整保留——比如用了非事务引擎(MyISAM)、混合了 DML 和 DDL、或启用了 binlog_format=STATEMENT 但函数含不确定性(如 NOW()、UUID())。
必须用 ROW 格式 + 事务引擎
binlog_format=ROW 是 MySQL 主从事务同步的底线要求,它把每行变更的实际值写入 binlog,绕过 SQL 重放逻辑,避免函数不确定性导致的主从差异。同时,所有参与复制的表必须使用 InnoDB(不能是 MyISAM),否则事务原子性无法保障,BEGIN...COMMIT 范围内的多语句可能只部分同步到从库。
- 检查当前格式:
SELECT @@binlog_format;,非ROW需在主从两端配置文件中统一设为binlog_format = ROW并重启 - 确认表引擎:
SHOW CREATE TABLE t1;,发现ENGINE=MyISAM必须转为ENGINE=InnoDB - 禁止在事务中混用 DDL(如
ALTER TABLE),DDL 在 ROW 模式下会隐式提交事务,破坏原子边界
跳过错误不是修复,而是临时止损
当从库已出现事务冲突(如主库插入后从库该行已被删),SET GLOBAL sql_slave_skip_counter = 1 可跳过当前事件,但仅适用于单条语句级错误;对事务级错误(如一个 INSERT ... SELECT 批量插入失败),更稳妥的是用 gtid_next 跳过整个 GTID 事务:
STOP SLAVE; SET GTID_NEXT='aabbccdd-eeff-1111-2222-333344445555:12345'; BEGIN; COMMIT; SET GTID_NEXT='AUTOMATIC'; START SLAVE;
注意:跳过前务必确认该事务在从库确实无业务影响,且主库没后续依赖此事务的更新;跳过操作不可逆,事后需人工比对数据一致性。
GTID 模式下事务同步更可靠但有约束
启用 gtid_mode=ON 后,每个事务有唯一标识,从库能自动定位同步位点,避免传统 relay_log_file + relay_log_pos 手动定位出错。但它强制要求所有实例都开启 GTID,且禁止执行 CREATE TABLE ... SELECT、CREATE TEMPORARY TABLE 等不支持 GTID 的语句——这些语句在 GTID 模式下会直接报错 ERROR 1786 (HY000): Statement violates GTID consistency。
- 迁移前先检查:
SELECT * FROM information_schema.INNODB_TRX;确保无长事务阻塞 - 从库切换 GTID 前需先停复制、重置
RESET SLAVE ALL,再启动时指定START SLAVE UNTIL SQL_AFTER_GTIDS控制回放范围 - GTID 不解决应用层逻辑冲突(如主从同时更新同一行),只保证“相同事务”被准确传递和执行
真正难处理的从来不是复制链路本身,而是事务里藏着的隐式依赖、跨库操作、或者应用误把从库当主库写入——这些不会报错,但会让数据偏移在数小时后才暴露。










