> 文档中心 > MySQL 主从GTID不一致导致主从切换报错

MySQL 主从GTID不一致导致主从切换报错

版本:

MySQL-5.7.32+GTID

问题:

        主从切换之后,新从库同步复制新主库产生报错1236,从库请求的gtid不在主库现有的binlog日志里。

问题分析:

        造成该问题的原因为,从库之前执行过命令导致产生了新的gtid,并且该gtid所在的binlog已经被清理,导致发生主从切换之后,新从库同步复制新主库时,由于master_auto_position=1模式下,从库会将当前已经执行过的gtid集合发送给主库,主库接收到从库发送的gtid集合后,会与当前已经执行的gtid求差值,并将没有执行过的gtid发送给备库,由于binlog被清理导致无法将gtid发送给从库(gtid_purged没有包含)

问题解决:

        1 在新从库手动跳过缺失的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;

2 从备份binlog里面恢复

         将binlog从备份里面恢复到原来的日志目录(需要的binlog要从第一个包含缺失的gtid日志到当前的全部日志)

        手动修改日志文件index,添加恢复的binlog,从头追加写入 

         刷新新主库binlog日志

flush binary logsshow binary logs

         重启新主库,让gtid_purged重新读取到最旧的binlog文件

        新从库重新恢复复制 

start slaveshow slave status\G

3 重置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 slaveshow slave status\G