MySQL运维——GTID模式下主从同步跳过一个事务来恢复同步的方法

故障假设:Last_SQL_Errno: 1396

1396 错误本质是「SQL 语句执行失败」(如 CREATE USER/RENAME USER/DROP USER 失败、表操作权限不足、数据插入违反约束等),在 GTID 模式下,即使事务执行失败,从库仍会记录该 GTID 为「已接收」,导致后续同步卡住 —— 因为从库认为 “这个 GTID 还没执行成功,但主库已经推进了 GTID,无法跳过”。

1、定位出错的GTID事务

performance_schema(MySQL 5.6+ 自带的性能监控库)中筛选出导致 1396 错误的同步线程,重点查看 LAST_SEEN_TRANSACTION 字段 —— 这个值就是出错的 GTID 事务编号(比如 caa383cb-f1e0-11eb-a179-2cea7fed4c41:3640563

select * from performance_schema.replication_applier_status_by_worker where LAST_ERROR_NUMBER=1396;

操作前必须确认:该 GTID 事务可跳过

只有确认该事务是「无业务影响的错误」(如创建已存在的用户、删除不存在的表),才能跳过;如果是核心业务事务(如订单插入),跳过会导致主从数据不一致,需先修复数据再同步

先在主库查看该 GTID 对应的具体 SQL(通过 mysqlbinlog 解析 binlog):

# 主库执行,找到对应GTID的SQL
mysqlbinlog --include-gtids='caa383cb-f1e0-11eb-a179-2cea7fed4c41:3640563' /var/lib/mysql/mysql-bin.000154

2、停止同步

stop slave;

3、手动标记该 GTID 事务为「已执行」

这是核心步骤,通过手动将 gtid_next 设置为出错的 GTID,然后提交一个空事务 —— 从库会把这个 GTID 标记为「已执行(Executed_Gtid_Set)」,相当于 “跳过” 了这个失败的事务,最后必须恢复 gtid_next=automatic,否则后续从库的本地事务会无法分配 GTID

-- 替换 [LAST_SEEN_TRANSACTION] 为步骤1查到的GTID(比如 caa383cb-f1e0-11eb-a179-2cea7fed4c41:3640563)
set @@session.gtid_next='caa383cb-f1e0-11eb-a179-2cea7fed4c41:3640563';
begin;  -- 开启空事务
commit; -- 提交空事务(无任何SQL操作,仅占用GTID)
set @@session.gtid_next=automatic;  -- 恢复GTID自动分配(关键!否则后续事务会报错)

4、重启从库同步并验证

start slave;
show slave status\G;
Categories: 数据库运维