• 参数为1时,立即fsync文件到磁盘;
  • 参数大于1时,则达到指定提交次数后,统一fsync到磁盘。 因此只有当sync_binlog参数为1时,才是最安全的,当其不为1时,都存在binlog未fsync到磁盘的风险,若此时发生断电等故障,就有可能出现此事务并未刷出到磁盘,从而故障恢复时将此事务回滚的情况。

了解了MySQL关于Innodb与Binlog的两阶段提交机制后,就可以更深入去探究MySQL在故障恢复时的处理过程。 在MySQL启动时,首先会初始化存储引擎,如本例中的InnoDB引擎,然后InnoDB引擎层会读取redolog进行InnoDB层的故障恢复,回滚未prepared和commit的事务,但对于已经prepared,但未commit的事务,暂时挂起,保存到一个链表中,等待后续读取binlog日志,然后根据binlog日志再对这部分prepared的事务进行处理。 接下来,MySQL会读取最后一个binlog文件。binlog文件通常是以固定的文件名加一组连续的编号来命名的,并且将其记录到一个binlog索引文件中,因此索引文件中的最后一个binlog文件即是MySQL将要读取的最后一个binlog文件。 读取这个binlog文件时,通过文件头上是否存在标记LOG_EVENT_BINLOG_IN_USE_F,通过这个标记可以知道上次MySQL是正常关闭还是异常关闭,如果是异常关闭,则会进入故障恢复过程。 进入故障恢复过程后,会依次读取最后一个binlog文件中的所有log event,并将所有已提交事务的binlog日志中记录的xid提取出来添加到hash表中,以备后续对前述InnoDB故障恢复后遗留的Prepared事务继续处理。另外此处还要定位最后一个完整事务的位置,防止在上次系统异常关闭时有部分binlog日志未刷到磁盘上,即存在写了一半的binlog事务日志,这部分写了一半binlog日志的事务在MySQL中会按事务未提交来处理,后续会将其在存储引擎层回滚。当此文件中的内容全部读出之后,一是得到一个已提交事务的列表,另一个是最后一个完整事务的位置。 然后检查由InnoDB层得到的Prepared事务列表,若Prepared事务在从Binlog中得到的提交事务列表中,则在InnoDB层提交此事务,否则回滚此事务。 pic 最后MySQL将最后一个完整事务位置之后的binlog清除,完成故障恢复全部过程。

基于RAFT协议的多副本架构,每一条数据都会被复制多份,通过多副本来增加系统的可用性,防止单副本失效而导致数据不可用。多副本之间基于RAFT协议来实现数据的一致性,只有数据存在于半数以上副本方可认为数据有效,而无效的副本数据系统会自动修复,从而确保系统只会提供一个统一的一致性视图。 阿里云的MySQL金融版就是基于RAFT的多副本集群,从根本上彻底解决了多副本集群故障切换后的数据不一致的问题,从而实现RPO等于0的目标,相比传统的主备集群有以下优势:

  • 消除master故障后由于切换master导致的数据不一致;
  • 不低于两节点主备集群的性能;
  • 节点故障或网络故障后自动切换master,响应及时;
  • 管理透明,用户无需额外管理及学习成本;