https://juejin.cn/post/6895265596985114638
在介绍Buffer Pool
相关内容时我们知道,当有数据页被修改时(变成了脏页dirty page),Innodb引擎会把对应的缓存页添加到Buffer Pool的flush list当中,并没有实时的将脏页同步到磁盘,而是在将来的某个时机才将脏页同步到磁盘。Mysql数据库是可以保证数据的持久性的,在脏页没有从内存同步到磁盘时,如果数据库宕机,内存数据就会丢失,这个时候得有一种机制能将丢失的脏页数据给恢复过来,才能保证Mysql数据库再次启动的时候脏页还能恢复成原来的样子,Innodb引擎提供的Redo log就是为了完成这项工作而设计的!
中国古代兵法有云:“兵马未到,粮草先行”。这句话应用到数据库设计上同样有用,不过得改一下说法:“数据未同步到磁盘,日志先行!”,意思就是说:当Buffer Pool中的脏页还没有同步到磁盘上的时候,先将缓存页做了哪些修改的操作以日志的形式先记录下来,这样即使某个时间点数据库宕机了,等数据库再次启动时,也可以将数据页再重新加载到Buffer Pool中来,再根据修改日志将数据页恢复成原来的样子。我们这里提到的记录数据页修改的日志就是本节要详细介绍的Redo log,我们所谓的日志先行的说法其实就是所谓的WAL技术(Write-Ahead Logging)。
我们再来回顾一下Innodb引擎的架构图:
我们看到,Innodb引擎在数据交互过程中产生的redo log
通过内存中Log Buffer
持久化到磁盘文件上的一组日志文件中(ib\_logfile0、iblogfile1)。本节我们会详细介绍一下redo log
的存储结构,主要包括:
此外,通过本文读者还会对Innodb引擎中的Mini-Transaction
、redo log block
有更加深入的认识,话不多说,下边就开始我们的redo log学习之旅吧~
我们现在知道了Redo log记录了用户对数据做了哪些更改,对数据进行修改的场景有很多,我们常用的增、删、改可能修改一个数据页,也可能修改多个数据页,这些数据页还不一定都是数据库中的同一张表,所以Redo log有很多种格式。结合我们前边讲到的数据页的结构,我们可以抽象出一种比较通用Redo log日志类型,即我们对哪个空间下的哪个数据页做了哪些具体的修改,下边就是比较通用的Redo log日志类型结构示意图:
其中type表示Redo log的日志类型,Innodb引擎针对不同场景对数据页的修改,制定了几十种不同类型的Redo日志。Space ID
和Page Number
是前边我们反复提到的表空间id和数据页id,根据它们能唯一标示一个数据页,再然后的data就是对该数据页到底做了哪些修改了。我们下边介绍几种简单些的redo log
日志类型,然后再看一下稍复杂些的redo log
日志类型是如何设计的。
redo log
日志类型我们先考虑一种最简单的场景,假如我们只简单更新了一个数据页中一条记录的某个字段的值。这个时候我们只需要记录下在这个页面从某个偏移量修改了几个字节的值,将这几个字节的具体内容也记录一下就好了,我们将这种极其简单的redo log
日志我们称之为物理日志。Innodb引擎根据具体在数据页中修改了数据的多少划分了划分了几种不同类型的redo log
:
MLOG_1BYTE
(type字段对应的十进制数字为1):表示在页面的某个偏移量处写入1个字节的redo日志类型。
MLOG_2BYTE
(type字段对应的十进制数字为2):表示在页面的某个偏移量处写入2个字节的redo日志类型。