mysql+redo的两个阶段_MySQL事务日志Redo_Log之Crash_Safe原理和事务两阶段提交原理

MySQL的崩溃恢复crash_safe能力依赖于Redo

Log事务日志。当MySQL更改数据的时候,它的设计思想是先对内存中的数据进行修改,并且写Redo

Log,即更改数据,总是遵循WAL日志先行机制。

问题:为什么不直接更改磁盘中的数据,而是要在内存中修改,并且写Redo

Log日志,最后再落盘这么复杂呢?

其实要回答这个问题并不难。MySQL更新数据的时候,之所以不直接写磁盘,最主要的就是性能问题。因为直接写磁盘是随机写,开销大性能差,所以才会设计成现在内存中对数据进行更改,后续再落盘。但是内存并不总是可靠的,万一MySQL进程挂了或者操作系统崩溃,buffer_pool中的数据也就丢失了,而这些数据还没有落盘。所以就引入了Redo

Log,通过先写日志,当发生了断点重启之后,可以通过重放Redo Log来达到恢复数据。

当然,写Redo

Log本质上也是写磁盘文件,Redo Log是物理日志,记录的是“某个数据页做了什么修改”。写Redo

Log是顺序写,相比在直接写磁盘数据,找到不同的数据页对数据进行更新这种随机写,性能要好很多。

那么我们来看看,当MySQL更新数据的时候,其内部流程是怎么实现的呢?

假设我要执行一条SQL:update T set c=c+1 where

ID=2,那么内部执行流程为:

1、执行器找存储引擎取出ID=2这一行,如果ID=2这一行记录所在的数据页本身就在内存当中,那么就直接返回给执行器;否则需要从磁盘读取到内存当中,然后再返回给执行器;

2、执行器拿到行数据之后,会对内存中的数据页进行修改,同时将这个更新操作记录到Redo

Log。此时Redo Log处于perpare状态,然后告知执行器已经完成了,可以随时提交事务;

3、接下来执行器会生成这个更新操作的binlog;

4、执行器调用存储引擎的提交事务的接口,将刚刚写入的Redo

Log改成commit状态;

Update语句的执行流程图为:

a4c26d1e5885305701be709a3d33442f.png

从上图我们可以看到,Redo

Log写入之后,分成了两个阶段,分别是prepare阶段和commit阶段,这里其实就是MySQL事务的两阶段提交。

为什么需要两阶段提交呢?我们假设Redo

Log不需要两阶段提交,要么就是先写完Redo Log,再写binlog,要么就是先写完binlog再写Redo

Log。

1、假设是先写Redo

Log,后写binlog。如果这个时候MySQL发生了进程的异常重启,由于Redo

Log已经写完,MySQL崩溃之后通过crash_safe能力,能够把数据恢复回来。但是由于binlog还没写完就crash了,所以binlog里面并没有记录该SQL语句,所以使用binlog回档数据的时候,恢复出来的数据其实是少了一次更新操作的,这样就造成了灾难恢复出来的库和原库数据不一致;

2、假设是先写binlog,后写Redo

Log。Binlog写完之后发生了crash,由于Redo

Log还没有写,崩溃恢复之后这个事务的更新是无效的。但是binlog里面记录了这条更新的语句,所以使用binlog回档的时候就多了一条事务的更新。造成回档出来的数据和原库的数据不一致。

上图我标注了红色的“1”、“2”、“3”,分别代表的是Redo

Log的prepare阶段、生成binlog阶段、以及事务提交阶段。

1)、当MySQL在“1”,即Redo Log

prepare阶段的时候发生了crash,结合binlog记录来做仲裁,由于binlog还没有写入,所以crash_safe的时候,该事务会被回滚;

2)、当MySQL在“1”和“2”之间发生了crash,binlog还没有写入,同样事务会回滚;

3)、当MySQL在“2”,即写完binlog之后发生了crash,结合binlog记录做仲裁,满足Redo

Log

prepare状态和binlog记录的完整性,crash_safe的时候会自动commit事务;

4)、当MySQL在“2”和“3”之间发生了crash,结合binlog记录做仲裁,同样crash_safe的时候该事务会自动提交。

其实当我们开启一个事务,如:

begin;

xxxx

commit;

执行了commit指令之后,会写入binlog,以及将Redo

Log的状态改成commit状态。

那么两阶段提交就是:

1、prepare阶段,写redo log;

2、commit阶段,写binlog并且将redo

log的状态改成commit状态;

mysql发生崩溃恢复的过程中,会根据redo

log日志,结合binlog记录来做仲裁:

1、如果redo

log和binlog都存在,逻辑上一致,那么提交事务;

2、如果redo

log存在而binlog不存在,逻辑上不一致,那么回滚事务;

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值