暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

关于MySQL GTID的一次深刻学习

一森咖记 2019-12-19
1943

  最近因为一个特别的操作需求,需要临时配置一下双主复制模式。

在这个过程中让我从开始的悲观,无助到理解后的喜悦,GTID的使用模式确实给了我很多的意外惊喜,也让我对这个特性的过程有了进一步的理解。

我在书中对于GTID的特性使用了如下的图来表达。

现在的场景是一个一主一从的数据库,已经配置了从库。

在上线前进行了模拟演练,做过主从切换,然后快速验证后又恢复了回来。现在想要实现的是一个双主的配置,即需要Slave->Master做一个反向的复制配置。

我在检查的时候,发现主从都存在两个GTID属主。 

类似这样:

    Executed_Gtid_Set: 
    74a1e34b-8204-11e9-b7dd-005056b73821:1-20352047366,
    99fbf089-9266-11e9-9a38-005056b70e42:1-5046391

    其实这是因为在数据库运行过程中确实发生了两次切换导致,也通过这种方式能够清晰的记录下来GTID的变更历史,这本来没什么好说的,在配置反向关系的时候抛出了错误。 

      Last_IO_Errno: 1236
      Last_IO_Error: Got fatal error 1236 from master when reading data from binary log: 'The slave is connecting using CHANGE MASTER TO MASTER_AUTO_POSITION = 1, but the master has purged binary logs containing GTIDs that the slave requires.'

      从错误信息来看,Master切换之后,Slave变成了主库,这个时候数据写入就在Slave端了,然后业务再次切换后数据开始在Master写入。这个过程中的切换会导致一部分的binlog写入是在Slave端生成,而这部分的binlog显然随着时间的变化会自动被服务清理掉。如果报出这样的错误,实在是比较尴尬和无奈的事情了,换句话说,我们要关注当前的状态和后续的改变,binlog我们不可能自始至终保留,而且就算保留拿来恢复也不显示,所以在这个过程中一定有什么特别的地方。

      我把主从关于GTID的信息都整理出来,可以参考梳理后的结果。

                  


      在Master和Slave的UUID分别是以21和42结尾,仔细对比发现了端倪。

      Master端:

      Gtid_purged:

      74a1e34b-8204-11e9-b7dd-005056b73821:1-20294065566,

      99fbf089-9266-11e9-9a38-005056b70e42:1-5046391


      Slave端

      Executed_Gtid_Set: 

      74a1e34b-8204-11e9-b7dd-005056b73821:1-20354149730,

      99fbf089-9266-11e9-9a38-005056b70e42:1-5046473

      gtid_purged:

      74a1e34b-8204-11e9-b7dd-005056b73821:1-20295253841,

      99fbf089-9266-11e9-9a38-005056b70e42:1-5046473


      42结尾的Slave端是做过一次故障切换的,切换后的状态应该是 

      1-5046391左右,而在Slave变为主库后写入了数据,状态应该是

      1-5046473,总之在那之后基于这个GTID再无数据写入,具体在那个时间段里发生了什么已经无法知晓,但是一个值得考虑的点就是基于MHA的健康监测是使用了ping insert的方式,在没有业务数据干扰的情况下,很可能是这个潜在的原因写入了数据,但是至于为什么没有把这些变更都同步过去,这是一个问题。当然对我们解决这个问题不是最重要的。 


      我们可能需要理解一下这个问题的根本原因,其实不在于是不是存在两个GTID,而是根本在于Slave端的GTID(不变化的GTID)在两端不一致。 

      可以举个例子,比如夫妻两个人(类似于Master,Slave两个节点,为了便于理解,我就以媳妇(Master),丈夫(Slave)来简称了),先是媳妇管账,GTID以媳妇(Master)的变化为准,然后过了一段时间发生了转换,该丈夫管账,数据变化以Slave为主,结果管得不好,很快又换过来了,于是又以媳妇的(Master)为准。


      隔了很久,夫妻两人要共同管账(配置双主模式),需要把之前的消费情况理一理。 结果发现丈夫(Slave)管账的时候有一部分的账目不一样,即媳妇(Master端)看到的账目和丈夫(Slave端)看到的不一样,媳妇这边是5046391笔交易,丈夫这边记录的是5046473笔交易,结果丈夫也记不得这个过程的消费记录,所以这种情况下就需要做一些修正和稽核。


      这个情况有些类似,我们的思路是先修正两边的GTID(不变化的部分),然后再重新建立双向复制关系。



      修复过程


         

      修复过程其实比较清晰,那就是现在是以Master端的GTID为准,那么我们就不能在Master端做任何reset master的操作,所以记录的修正应该是以Master为准,所有的操作应该是在Slave端完成。

      Slave端修复的步骤如下:

      1)stop slave;

      2)show slave status\G

      记录下来得到的Executed_Gtid_Set值,这是截止stop slave时最新的GTID状态信息。

      3)reset master;

      切记是在Slave端执行,这个阶段的目的就是要重新配置GTID的校准值。这个时候mysql.gtid_executed应该就是空的了。

      4)重置GTID_purged值

          这个步骤是关键所在。我们需要配置为最新的SET的GTID值,这样就不用重复消费哪些事务数据了,而原来的GTID从5046473修改为5046391

      SET @@GLOBAL.GTID_PURGED='74a1e34b-8204-11e9-b7dd-005056b73821:1-20363492180,99fbf089-9266-11e9-9a38-005056b70e42:1-5046391';

      5)删除从库的复制配置

      reset slave all;

      6)配置复制关系

      CHANGE MASTER TO MASTER_USER='dba_repl', MASTER_PASSWORD='xxxx' , MASTER_HOST='xxxxx',MASTER_PORT=4307,MASTER_AUTO_POSITION = 1;

      7)重启Slave节点,查看状态

      start slave;

      show slave status\G

      修复完成后,再次建立复制关系就是水到渠成的事情了,当然也可以随建随删。

      转文至此。

      以下为个人公众号“一森咖记”,欢迎关注。

                     

         

      近期热文

      你可能也会对以下话题感兴趣。点击链接就可以查看。




      最后修改时间:2019-12-20 09:39:25
      文章转载自一森咖记,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

      评论