MySQL通常在人们眼中就是一个低端、开源、大众化的数据库产品,它的稳定性和可用性一直被人们所置疑,被认为难登大雅之堂,只适用于互联网应用,难于应用到可用性高的场景中,比如金融、证券等行业。然而时代的变化太快,MySQL也不能再以过去的眼光来看,从MySQL金融版的诞生开始,它已经不再是那个扶不起的阿斗,它已经脱胎换骨,以一个崭新的形象出现在数据库的高端产品中。

        这一切真的难以置信,在开源数据库产品中,MySQL从来都是一枝独秀,但在表面风光的同时,却是DBA和资深用户的满心苦涩。由于硬件、网络的可用性还难以达到理想的要求,无论出现任何故障,数据库系统都必须保证其可用性。对于MySQL来说,大家所熟知的主备集群是最常见的解决方案。由于MySQL的架构设计原因,主备集群的解决方案虽然不完美,但也是其最好的解决方案了。但其中存在的可用性隐患,却是DBA和资深用户的内心无奈。

        MySQL的主备集群方案,对于大多数应用系统可以满足基本的可用性要求了,如果要求更高的话,只能去选择商业数据库,而商业数据库的成本却又难以承受。到底存在什么问题呢?

        熟悉MySQL的都知道,MySQL是采用binlog来搭建主备集群的,主机上的事务提交时,通过两阶段事务将binlog写入到磁盘,然后再将其发送给备机,备机收到后重放日志,以完成事务与主机的同步。如下图所示难以置信,MySQL也可以无损自由切换

        显而易见,主备之间会存在一些延迟,当主机已经将事务提交后,备机也许还没有收到这条事务的binlog,此时在备机上这条事务其实的缺失的。为了尽可能降低主备延迟,后来MySQL又设计了Semi-Sync,如下图所示:难以置信,MySQL也可以无损自由切换

在Master提交之前,必须保证备机已经收到binlog,并记录到本机的relay log中。这样在主机上提交的事务就一定会在备机上提交,只是可能会有些许延迟,如果应用容忍这些延迟的话,那么一切就很完美了。

         但这个看起来很完美的解决方案,在真正故障发生时,却不一定那么完美,只是隐藏的很深。

         即使使用semi-sync的同步解决方案,当主机发生故障后,系统需要切换到备机,将备机变成主机来继续提供数据库服务。如果原来的主机故障可以修复,可以做为备机,这一切看起来没有什么问题。但如果对MySQL有更深入研究的话,就会发现其实还有隐藏的更深的隐患。

         MySQL的事务处理采用两阶段提交机制,以保证事务的可靠性。当事务准备提交时,首先将事务写入binlog,然后再在存储引擎层提交事务,比如InnoDB存储引擎。正常情况下一切都没有问题,但当系统意外down机,重新启动时,MySQL首先会进入故障恢复阶段,读取redo日志,做事务恢复,但可能会发现部分事务并没有提交,那么这部分事务是应该回滚吗?MySQL的实现方法是先将这部分事务挂起,暂时既不提交也不回滚,然后读取binlog日志,如果在binlog中发现有此事务的记录,就将事务提交,若未发现此事务的记录,就将事务回滚。

         现在我们再回过头来看之前的故障切换问题。若主机上有事务准备提交,然后事务记入binlog,但在传送给备机之前主机崩溃了,那么备机是没有这些事务的,然后备机就切换成了主机。当原主机重新启动后,通过之前所述的故障恢复过程,这些事务已经记录到binlog,那么应该提交。问题出现了,新的主机和即将成为备机的原主机数据不一致了。有些事务在新主机上没有,但在原主机上已经提交。

原文链接

相关文章:

  • 2022-12-23
  • 2022-01-13
  • 2021-06-09
  • 2021-07-26
  • 2022-01-22
  • 2022-12-23
  • 2022-01-07
  • 2021-10-28
猜你喜欢
  • 2021-07-15
  • 2023-03-16
  • 2021-06-02
  • 2021-12-16
  • 2021-08-17
相关资源
相似解决方案