MySQL 主从GTID不一致导致主从切换报错
版本:
MySQL-5.7.32+GTID
问题:
主从切换之后,新从库同步复制新主库产生报错1236,从库请求的gtid不在主库现有的binlog日志里
问题分析:
造成该问题的原因为,从库之前执行过命令导致产生了新的gtid,并且该gtid所在的binlog已经被清理,导致发生主从切换之后,新从库同步复制新主库时,由于master_auto_position=1模式下,从库会将当前已经执行过的gtid集合发送给主库,主库接收到从库发送的gtid集合后,会与当前已经执行的gtid set求差值,并将没有执行过的gtid发送给备库,由于binlog被清理导致无法将gtid发送给从库(gtid_purged没有包含)
问题解决:
在新从库手动跳过缺失的gtid(注:跳过缺失的gtid,意味着不在从库执行缺失的事务,可能导致数据的丢失)
获取新主库的gtid_purged:a0a3d4b2-fff8-11eb-a420-000c29a6e7be:1-15
stop slave;
show global variables like'%gtid_purged%' ;
show global variables like'server_uuid';
获取新从库的execute_gtud:a0a3d4b2-fff8-11eb-a420-000c29a6e7be:1-11
show global variables like '%gtid_executed%';
计算出缺失的gtid:a0a3d4b2-fff8-11eb-a420-000c29a6e7be:12-15
select GTID_SUBTRACT('a0a3d4b2-fff8-11eb-a420-000c29a6e7be:1-15','a0a3d4b2-fff8-11eb-a420-000c29a6e7be:1-11');
手动跳过gtid:a0a3d4b2-fff8-11eb-a420-000c29a6e7be:12
set gtid_next='a0a3d4b2-fff8-11eb-a420-000c29a6e7be:12';
begin;
commit;
手动跳过gtid:a0a3d4b2-fff8-11eb-a420-000c29a6e7be:13
set gtid_next='a0a3d4b2-fff8-11eb-a420-000c29a6e7be:13';
begin;
commit;
手动跳过gtid:a0a3d4b2-fff8-11eb-a420-000c29a6e7be:14
set gtid_next='a0a3d4b2-fff8-11eb-a420-000c29a6e7be:14';
begin;
commit;
手动跳过gtid:a0a3d4b2-fff8-11eb-a420-000c29a6e7be:15
set gtid_next='a0a3d4b2-fff8-11eb-a420-000c29a6e7be:15';
begin;
commit;
设置gtid_next为automatic,启动复制进程恢复同步
set gtid_next='automatic';
start slave;
show slave status\G
从备份binlog里面恢复
将binlog从备份里面恢复到原来的日志目录(需要的binlog要从第一个包含缺失的gtid日志到当前的全部日志)
手动修改日志文件index,添加恢复的binlog,从头追加写入
刷新新主库binlog日志
flush binary logs
show binary logs
重启新主库,让gtid_purged重新读取到最旧的binlog文件
新从库重新恢复复制
start slave
show slave status\G
重置gtid进行恢复
通过重置新从库的execute_gtid,跳过缺失的gtid进行恢复(注:跳过缺失的gtid,意味着不在从库执行缺失的事务,可能导致数据的丢失)
备份记录当前的gtid值
show global variables like '%gtid%'
执行reset master 置空gtid (注:操作还会清空重置binlog日志)
reset master
设置gtid_purged跳过缺失的gtid,设置之后gtid_executed初始值会等于gtid_purged
如果新主库切换后还没写入,则可以直接设置为新主库的gtid_executed
set global gtid_purged=' 1b80feab-4aa6-11ec-9a60-000c29a6e7be:1-10,
2b3039c9-57fa-11eb-b504-000c29ed797a:1-8316287,
3a59d149-d4b8-11eb-8cf6-000c29a6e7b4:1-10,
a0a3d4b2-fff8-11eb-a420-000c29a6e7be:1-2'
如果新主库切换后已经开始写入,则需要将从库gtid_purged设置为备份的gtid_executed值,并将里面master_uuid对应的gtid修改为新主库gtid_purged对应master_uuid的值
获取新主库gtid_purged对应master_uuid的gtid:a0a3d4b2-fff8-11eb-a420-000c29a6e7be:1-26
新从库将备份的gtid_executed里面a0a3d4b2-fff8-11eb-a420-000c29a6e7be:1-24
替换为a0a3d4b2-fff8-11eb-a420-000c29a6e7be:1-26,并赋值给gtid_purged
set global gtid_purged='1b80feab-4aa6-11ec-9a60-000c29a6e7be:1-10,
2b3039c9-57fa-11eb-b504-000c29ed797a:1-8316287,
3a59d149-d4b8-11eb-8cf6-000c29a6e7b4:1-10,
a0a3d4b2-fff8-11eb-a420-000c29a6e7be:1-26'
新从库重新恢复复制
start slave
show slave status\G