前言MySQL采用两阶段提交机制来保证redolog和binlog的逻辑一致性,从而保证数据不丢失,主从数据库中的数据是一致的。说到两阶段提交,就不得不先介绍一下redolog和binlog。RedologRedolog即重做日志,是InnoDB引擎特有的一种日志(有些面试官经常会问到这一点)。重做日志主要做什么?以更新数据为例,我们知道MySQL的数据是存储在磁盘上的。如果每次更新数据都去磁盘查找要更新的数据,更新操作的IO成本非常高。如果是固态硬盘还好,但是如果是机械硬盘,那么MySQL的更新性能就完全不能满足我们的业务需求。因此,MySQL使用了一种叫做WAL,Write-AheadLogging的技术。更新数据时,先将更新操作(即对某个数据页做了什么修改)写入redolog,然后更新内存,更新操作完成。MySQL会在服务器空闲时将redolog操作记录刷新到磁盘,以保持数据的一致性。需要注意的是,虽然重做日志也是磁盘上的一个文件,但是由于是顺序写入操作,所以性能非常高。当然redolog也是有上限的,不可能无限写。以上图为例,配置了4条redolog,writepos代表当前记录写入到哪里,checkpoint代表一个push点,会不断向前,进行数据擦除操作,保证redolog可以连续写入.当然,在擦除数据之前,重做日志记录会被刷新到磁盘。通过重做日志,可以保证即使MySQL异常重启,数据也不会丢失(因为重做日志是物理日志,可以重放),这个特性叫做crash-safe。binlogbinlog是MySQLServer提供的一种日志,称为archivelog,所有引擎都可以使用binlog。binlog和redolog有什么区别?1、这两种日志的提供者不同:bin日志由MySQLServer提供,redo日志是InnoDB引擎独有的。2、redolog主要记录某个数据页发生了哪些变化,binlog记录了语句的原始逻辑,比如更新某行的某个字段。3、redolog是循环写入的,数据会被覆盖。binlog是用来追加写入的。当文件已满时,将写入一个文件。两阶段提交介绍完redolog和binlog,我们来看看它们是如何配合完成两阶段提交的。上图是一个更新数据的过程。可以看出,在更新一条数据之前,MySQL会先将数据加载到内存中,然后更新内存,并开始写入redolog。此时redolog处于prepare状态。binlog写入后,提交事务,完成这条记录的更新操作。Redologprepare->writebinlog->redologcommit,这个过程称为两阶段提交。我们来分析一下使用两阶段提交的好处。场景一:当redolog处于prepare状态时,如果写入binlog失败,则update失败。此时redolog中没有commit,binlog中也没有记录。两人的状态一致,没有任何问题。场景二:当redolog处于prepare状态时,binlog写入成功,但是由于宕机导致commit失败。此时binlog已经产生记录,但是redolog还没有写入成功,数据暂时不一致。不过不用担心,当MySQL重启时,它会检查redolog中prepare状态的记录。在redolog中,记录了一个叫做XID的字段。binlog中也会记录这个字段。MySQL将传递此XID。如果在binlog中找到,则提交redolog。如果没有找到,说明是binlog其实写入不成功,就放弃提交。通过这样的机制,保证了redolog和binlog的一致性。总结MySQL之所以同时拥有redolog和binlog,是因为binlog是MySQLServer提供的归档日志,本身不具备crash-safe能力。redolog本身不具备归档能力,它是一种循环写入的日志。MySQL通过整合这两个日志,通过两阶段提交机制来保证数据的一致性。
