MySQL:从库明明回放了某事务但是 SQL 线程报错

接到客户反馈:主库执行 drop了一张表,从库没有对应的表,就报错了:'Unknown table '%-.100s' error code=1051'
提供了 show slave status 结果,确实是报错在 drop table 那里。
MySQL 版本:5.6.21

现场排查过程:

1. show slave status 确认错误位置:
binlog file name:binlog.056429
position:682219
gtid_excuted_set: 636d6b66-xxxx:1-769622000:769622017:769622035-769622037:xxxx:xxx-xxx (有很多空洞,原因是开启了并行复制)

2. 解析主库 binlog.056429,发现在报错 position:682219 确实是 drop table ,但是这个位置的事务的 gtid 为 636d6b66-xxxx:769621968 ,与从库 gtid_excuted_set 不匹配:意味这从库已经回放过 636d6b66-xxxx:769621968 这个事务,但是sql 线程却报错在这个事务

3. 解析从库当前的 binlog,发现确实已经回放了 636d6b66-xxxx:769621968 事务。为什么 sql 线程会报错在一个已经回放过的事务?

4. 重启复制,报同样的报错

5. 相信科学,再看一遍错误日志,重新思考下面这个信息。启动复制时,初始化 slave sql thread,位置确实是 binlog.056429:682219

6. 问题出在哪?初始化 slave sql thread 时,读取的是 sql thread 回放的位置:slave_relay_log_info,保存在 mysql.slave_relay_log_info 表中,查看结果确实是 binlog.056429:682219,与 error log 中一致:

7. slave_relay_log_info 表应该在每次事务提交时更新(当事务涉及表为 innodb 表时),但是这里显然没有更新。所以当启动复制时,slave sql thread 会从错误的位置开始回放事务,但是这个事务对应的表已经删除了,所以报错

8. 直接原因已经定位到,reset slave 清空复制位点信息、relay log,再 start slave,问题解决

疑问

虽然这里解决了问题,但是为什么 slave_relay_log_info 表中的复制位点信息没有更新呢?对此我进行了一些资料查找,设计了一些测试,得到了更细致的认识,但最终还是没能解决这个疑问。可以看另外两篇文章:
《slave_relay_log_info 表认知的一些展开》https://www.jianshu.com/p/6506bf3c883e
《关于 slave_relay_log_info 表的一些测试》https://www.jianshu.com/p/65c8caf01dd8

提示

之前一直对 master_auto_position 比较模糊,潜意识里一直觉得 GTID 取代了 position,排查错误时解析 binlog 找的是 gtid 位置,实际上还是得靠 position,这才是复制的真实位置。

你可能感兴趣的:(MySQL:从库明明回放了某事务但是 SQL 线程报错)