美团二面如何解决binlog与redol

刚看见这个题目的时候还是有点懵逼的,后来才反应过来其实问的就是redolog的两阶段提交

为什么说redolog具有崩溃恢复的能力

前面我们说过,MySQLServer层拥有的binlog只能用于归档,不足以实现崩溃恢复(crash-safe),需要借助InnoDB引擎的redolog才能拥有崩溃恢复的能力。所谓崩溃恢复就是:即使在数据库宕机的情况下,也不会出现操作一半的情况

至于为什么说redolog具有崩溃恢复的能力,而binlog没有,我们先来简单看一下这两种日志有哪些不同点:

1)适用对象不同:

binlog是MySQL的Server层实现的,所有引擎都可以使用而redolog是InnoDB引擎特有的

2)写入内容不同:

binlog是逻辑日志,记录的是这个语句的原始逻辑,比如“给id=1这一行的age字段加1”redolog是物理日志,记录的是“在某个数据页上做了什么修改”

3)写入方式不同:

binlog是可以追加写入的。“追加写”是指binlog文件写到一定大小后会切换到下一个,并不会覆盖以前的日志redolog是循环写的,空间固定会被用完

可以看到,redolog和binlog的一个很大的区别就是,一个是循环写,一个是追加写。也就是说redolog只会记录未刷入磁盘的日志,已经刷入磁盘的数据都会从redolog这个有限大小的日志文件里删除。

而binlog是追加日志,保存的是全量的日志。这就会导致一个问题,那就是没有标志能让InnoDB从binlog中判断哪些数据已经刷入磁盘了,哪些数据还没有。

举个例子,binlog记录了两条日志:

记录1:给id=1这一行的age字段加1记录2:给id=1这一行的age字段加1

假设在记录1刷盘后,记录2未刷盘时,数据库崩溃。重启后,只通过binlog数据库是无法判断这两条记录哪条已经写入磁盘,哪条没有写入磁盘,不管是两条都恢复至内存,还是都不恢复,对id=1这行数据来说,都是不对的。

但redolog不一样,只要刷入磁盘的数据,都会从redolog中被抹掉,数据库重启后,直接把redolog中的数据都恢复至内存就可以了。

这就是为什么说redolog具有崩溃恢复的能力,而binlog不具备。

redolog两阶段提交

前面我们介绍过一条SQL查询语句的执行过程,简单回顾:

MySQL客户端与服务器间建立连接,客户端发送一条查询给服务器;服务器先检查查询缓存,如果命中了缓存,则立刻返回存储在缓存中的结果;否则进入下一阶段;服务器端进行SQL解析、预处理,生成合法的解析树;再由优化器生成对应的执行计划;执行器根据优化器生成的执行计划,调用相应的存储引擎的API来执行,并将执行结果返回给客户端

对于更新语句来说,这套流程同样也是要走一遍的,不同的是,更新流程还涉及两个重要的日志模块binlog和redolog。

以下面这条简单的SQL语句为例,我们来解释下执行器和InnoDB存储引擎在更新时做了哪些事情:

updatetablesetage=age+1whereid=1;

执行器:找存储引擎取到id=1这一行记录

存储引擎:根据主键索引树找到这一行,如果id=1这一行所在的数据页本来就在内存池(BufferPool)中,就直接返回给执行器;否则,需要先从磁盘读入内存池,然后再返回

执行器:拿到存储引擎返回的行记录,把age字段加上1,得到一行新的记录,然后再调用存储引擎的接口写入这行新记录

存储引擎:将这行新数据更新到内存中,同时将这个更新操作记录到redolog里面,此时redolog处于prepare状态。然后告知执行器执行完成了,随时可以提交事务

注意不要把这里的提交事务和我们sql语句中的提交事务


转载请注明:http://www.aierlanlan.com/rzdk/1787.html

  • 上一篇文章:
  •   
  • 下一篇文章: