mysql主从复制中如何处理事务_mysql事务同步方案

来源:这里教程网 时间:2026-02-28 20:49:03 作者:

主从复制中事务不一致的典型表现

主库写入成功但从库报

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 不解决应用层逻辑冲突(如主从同时更新同一行),只保证“相同事务”被准确传递和执行

真正难处理的从来不是复制链路本身,而是事务里藏着的隐式依赖、跨库操作、或者应用误把从库当主库写入——这些不会报错,但会让数据偏移在数小时后才暴露。

相关推荐