如果主从的GTID的差异,可能导致主从切换失败,新的从库在change master后无法追平数据,这种一般就是GTID不一致导致的(准确的讲是曾经的从库也就是现在的主库上曾经被误写入了数据,并且对应的binlog已经被清理了)。
对于这种情况,可以如下思路操作:
1、事中,在从库注入相关的GTID先跳过这个GTID,让主库复制恢复正常,然后使用pt工具对主从的数据进行校验
2、事前,增加巡检机制,使用GTID_SUBTRACT函数将不一致的GTID情况找出来
这里主要演示下GTID_SUBTRACT的巡检:
代码语言:txt复制假设这里是一套主从复制环境(1主2从架构)
GTID的值的获取,可以是 select @@gtid_executed G 方法得到。
主库GTID值:
[test]> SET @master = '00019201-1111-1111-1111-111111111111:1-37';
Query OK, 0 rows affected (0.00 sec)
2个从库的GTID值:
[test]> -- 假设这里的slave_1节点误操作被写了数据,导致gtid比master的大
[test]> SET @slave_1 = '00019201-1111-1111-1111-111111111111:1-37,00019202-2222-2222-2222-222222222222:1-2';
Query OK, 0 rows affected (0.00 sec)
[test]> -- slave_2节点没有被误操作,但是复制存在延迟,gtid比master的差一点
[test]> SET @slave_2 = '00019201-1111-1111-1111-111111111111:1-33';
Query OK, 0 rows affected (0.00 sec)
然后,计算gtid差集
[test]> SELECT GTID_SUBTRACT(@slave_1, @master);
------------------------------------------
| GTID_SUBTRACT(@slave_1, @master) |
------------------------------------------
| 00019202-2222-2222-2222-222222222222:1-2 |
------------------------------------------
1 row in set (0.01 sec)
[test]> SELECT GTID_SUBTRACT(@slave_2, @master);
----------------------------------
| GTID_SUBTRACT(@slave_2, @master) |
----------------------------------
| |
----------------------------------
1 row in set (0.00 sec)
可以看到GTID_SUBTRACT(@slave_1, @master)的结果集非空,也就是说slave_1的GTID值比master的还要大,肯定是被写了数据了,需要DBA及时介入看下到底是写了什么进了binlog。然后再根据情况进行处理,进行处理。
如果dba分析了相关的binlog后,发现这个数据并不重要(例如非业务数据,只是运维类指令),可以在业务低峰期使用下面2种修复方式:
1、摘从库流量,然后停止从库复制,在从库重置下GTID(这个操作需要先清掉binlog,因此如果有canal类CDC组件连接到这个从库实例则不建议这样搞)。
2、在主库注入空事务,操作如下:
代码语言:txt复制-- 注入一个gtid
master [localhost:19201] {root} ((none)) > set gtid_next='00019202-2222-2222-2222-222222222222:1';
master [localhost:19201] {root} ((none)) > begin; commit;
master [localhost:19201] {root} ((none)) > set gtid_next='AUTOMATIC';
-- 再注入一个gtid
master [localhost:19201] {root} ((none)) > set gtid_next='00019202-2222-2222-2222-222222222222:2';
master [localhost:19201] {root} ((none)) > begin; commit;
master [localhost:19201] {root} ((none)) > set gtid_next='AUTOMATIC';
-- 查看当前gtid值
master [localhost:19201] {root} ((none)) > select @@gtid_executed G
*************************** 1. row ***************************
@@gtid_executed: 00019201-1111-1111-1111-111111111111:1-38,
00019202-2222-2222-2222-222222222222:1-2
这样,缺失的2个gtid就被补齐了。
关于主从数据不一致的原因,恩墨的崔老师这里有篇总结: https://www.modb.pro/db/500145