mysql 块复制_与HotDB一起学习《基于MySQL复制进行高可用的避坑详解 》

提示: 此文章之前发过一篇关于如何基于MySql进行数据高可用, 各位读者大大若是还没看过的话,建议看看哦, 保证干货满满!

话不多说,直接正文:

前一篇文章只讨论了故障服务器彻底损毁的情况。但实际使用场景中,更多的时候遇到的是MySQL实例自杀\被kill -9、内核panic、服务器死机\重启等故障。在这些场景中再次启动MySQL实例时,多数情况下,MySQL会通过执行崩溃恢复流程,使自己恢复到可以运行的状态。我们来分析一下,相关的坑点,与应对方法。

基于MySQL复制进行高可用的避坑详解

场景一、从机故障

还是先看从机故障的场景,上篇文章已经明确:从机故障是不破坏“等效不丢”的。修复从机最简单直接的方法也是:故障过的从机直接放弃,然后根据现有主机中MySQL的数据,重新搭建一个新从机。在有自动化管理平台的情况下,这样的工作通常只需要点点鼠标,简单便捷,不易出错。DBA可能会出于各种不同的想法或者一些客观原因,尝试去修复从机并继续使用,但在生产环境这样做是不理性的。一方面,故障过的服务器,如果没有从根本上解决掉问题,未来可能还会继续故障;另一方面,故障对MySQL从机会造成各种千奇百怪的影响,花样繁多,防不胜防,稍不注意,就可能为未来留下隐患。

我们从探讨技术的角度出发,研究一下从机的状态。从机经历了崩溃恢复的流程,于是它的状态肯定和log_slave_updates、master_info_repository、relay_log_info_repository、relay_log_recovery等几个重要参数和复制是否基于gtid的自动位置都有关。

我们前文已经提到打开relay_log_recovery的问题,它在打开relay_log_purge(默认打开,crash-safe的复制也要求打开)时,可能导致已经接收到的relaylog在没有被SQL线程应用的情况下被删除。这样会破坏基于半同步复制做高可用所依赖的基础,考虑到这一点,笔者个人是决策放弃使用crash-safe的复制。同时,一般而言relaylog本身是不会配置持久化的(sync_relay_log不等于1),因此,出现操作系统及更底层层次的故障时,由于relaylog损坏导致出现一些复制方面的报错也是这个决策下不得不接受的缺陷。当然,这种删除relaylog破坏半同步进而导致严重后果的危险,只出现在主从机同时出现问题的场景,它本身超出我们设想的高可用方案容许的灾难级别;使用crash-safe的复制可以减轻一些处理复制故障的工作量,有一定微小的收益;但反过来思考,继续使用这个从机同时也意味着承担服务器再次故障的隐患风险;因此最终是否坚持使用crash-safe的复制,还是看DBA自己的想法。

尽管笔者放弃了crash-safe的复制,但是还是可以尽量配置好一个从机,来降低遇到故障时的损害程度:如果我们设置log_slave_updates=on、master_info_repository=TABLE、relay_log_info_repository=TABLE,那么从机在顺利执行崩溃恢复后,gtid位置信息是正确的,复制执行到的位置信息也是正确的,尽管relaylog可能损坏,但是损坏的relaylog并不会被执行。

基于上述配置的前提,在relaylog确实损坏的情况下,DBA可以短暂地取消主机半同步复制的设置,然后在从机上删除复制关系,再使用自动位置的方式,重新完整配置半同步复制关系即可。但是在重新投入生产前,应仔细核对主从数据的一致性。

场景二、主机故障

讲完从机故障,我们来说主机故障的场景。

主机故障后,如果可以恢复运行,最大的风险在于,从机的复制会自动重连。从机重连以后会尝试继续开始复制,并且很可能可以获取到少量之前没有接收到的binlog。表面上看,主机崩溃恢复以后,它的状态和binlog状态是一致的,从机接收到这些binlog以后,将它应用掉,主从数据一致,单纯从数据库的角度去看,没有什么问题。但是我们回顾一下“等效不丢”和我们的高可用切换方法,再考虑到主机崩溃恢复多少需要一些时间,一般慢于从机追复制,我们又会发现一个坑。这种场景下,特定的“少量之前没有接收到的binlog”均属于“已经发出提交操作但没有收到提交成功的事务”,根据我们上一篇文章,这样的事务是须要由应用app检查,然后根据数据状态判断事务是提交了还是回滚了,并且对它进行相应补偿处理的。

举一个会发生问题的例子:10:00分,T1事务提交,但是没有收到提交成功的信息,主机就崩溃了;假定T1的实际情况为成功写入binlog,但是没有发给从机(只要同时有很多事务并发处理,或者多次尝试这个场景,肯定会有这样的事务);然后在10:05分,成功切换到从机,从机中没有T1的数据;10:10分,应用app对事务的状态进行了判断,发现事务不存在,因此执行了补偿事务T2;

10:15分,主机恢复运行了,主机崩溃恢复依赖binlog,因此主机提交了T1事务;10:20分从机重连,获取到T1事务的binlog并应用。

至此,我们在从机上,发现T1和它的补偿事务T2同时存在;如果是普通主从复制,主机上存在T1,如果是双主单活复制,则主机上也是T1和T2同时存在。(还有因为主键冲突等原因导致复制报错的可能性)这个例子中,单纯从数据库的角度看,数据没错,但是业务逻辑角度则是出错了。

我们怎么解决这个问题呢,不进行补偿?

不行,会有一些事务没有成功写入binlog。

延迟补偿的时间?

我们不知道主机恢复最久要多久,也不知道多久时间以后,主机一定不会再恢复,调整应用app处理逻辑,不能从根本上解决问题。

我们仔细分析上面的例子,不难发现,其实是应用app做出正确补偿处理以后,MySQL数据库的复制机制,后续又“背着应用app偷偷篡改了”数据,导致最终结果违背业务逻辑。那解决方案也就有了,在切换到从机以后,我们要停掉从机的复制,才能开放从机给应用app访问。

关于主机的恢复,建议做法同样是放弃掉现有的内容。将现在的从机作为未来的主机,然后新搭建未来的从机,再组建、配置未来新的高可用关系等等。

从技术探讨角度出发,分析一下主机在执行崩溃恢复流程以后的数据的状态:正常而言,主机执行崩溃恢复流程以后,它的数据和binlog保持一致,但是数据可能比从机多,也可能比从机少。数据比从机多,较为容易理解,binlog没有来得及传输到从机就会发生这样的情况。数据比从机少,则往往发生在sync_binlog不等于1的场景;binlog末尾丢失\损坏,就会出现主机数据少于从机的情况。

假设出现数据比从机多的情况,基本只能采取重新搭建的方式处理。出现数据少于等于从机的情况,则需要特别注意,先修改自己的server-id(建议也修改server-uuid)以后,再通过复制的方式补全数据。

同时,经过探讨,几个问题的答案就呼之欲出了:

崩溃恢复以后的MySQL实例,不考虑故障后续再写入的数据,能否保证故障实例和现存的实例数据一致?

分析MySQL执行崩溃恢复的过程,我们可以知道,崩溃恢复处理中,决定一个事务是否存在的关键在于有没有对应的binlog。从原理上思考,半同步复制、双1等,并没有办法去保证主机上binlog有的内容,一定被从机收到;或者是保证,被从机收到的事务,其binlog一定不会丢失(即使使用双1,还有RAID卡没电等场景);以及主机崩溃恢复时,只考虑自己binlog中有没有事务,不会考虑从机的情况。因此主机崩溃恢复的场景,必然做不到保证主机崩溃恢复后,数据和从机相同。

从机崩溃恢复的场景,同样只考虑自己binlog中的内容,不会考虑主机的情况,单纯的崩溃恢复,同样是做不到保证崩溃恢复后,数据和主机相同。但是从机崩溃的场景,只会缺少事务,如果加上正确处理复制相关事项,则从机可以补足缺少的事务,后续做到一致。

MGR为什么可以保证一致?

MGR的崩溃恢复机制实际上分为MySQL实例本身在启动时的崩溃恢复,和加入集群时的“Distributed Recovery”。加入集群时的恢复处理,考虑到了集群中的数据情况,遇到真正数据有异常的情况,实例是无法加入集群的(gtid情况异常的MySQL实例可以启动运行,但是无法正常加入MGR集群),能成功重新加入集群的都是数据正常,或者缺少数据并且可以补回来的。

各位读者想了解工多干货,请点点关注我们官方微信公众号“热璞数据库”。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值