Mysql中的Redo Log解析(二)

  • 2019 年 11 月 6 日
  • 笔记

昨天介绍了redo log的概念,关于redo log的写入方法没有很详细的讲解,今天接着说一下。

mysql中的redo log解析(二)

01

redo log写入方法详解

昨天我们说到了mtr的概念,也就是最小事务组,当我们向一个表里面插入一条记录的时候,这个操作就是一个最小事务组,因为它不可以再被分割。只有插入成功和插入失败两种结果。这个mtr操作中,包含了很多条redo log,例如需要记录数据页分裂的redo log,记录剩余数据空闲空间的redo log,记录数据也内链表指针改变的redo log,在Innodb存储引擎中,这些记录都会被存在一个专门放置redo log的数据页里面,这个redo log的数据页和我们之前立即的不同,它的大小只有512个字节,而不是16k,我们用block来代替这种512字节的数据页,16k的数据页使用page来代替,这个512字节的数据页包含三个部分,分别是header ,body 和tailer,header包含12个字节,body包含496个字节,tailer包含4个字节,其中,header和tailer包含的是一些头信息和尾信息,我们暂时不用关注。画成图就是:

上图是单个redo log的数据页,我们知道,申请buffer pool的时候,我们说过,buffer pool中也包含redo log buffer,顾名思义,也就是说,redo log也是不能直接写在磁盘上了,而是写在redo log的缓冲区中,我们用下面的图来代替一下redo log buffer的样子,这样大家有一个直观的概念:

这个redo log buffer的大小值可以使用innodb_log_buffer_size来表示,默认值是16M.

当有redo log保存在redo log buffer中的时候,redo log buffer的样子将会变成:

图中,粉色部分,就是写入了redo log的部分。黄色部分是空的redo log的部分。

这里需要注意的是,粉色部分是一个一个mtr的redo日志堆积而成的,这些日志在buffer pool中的顺序是随机的,加入有两个mtr ,分别是mtr1和mtr2,那么这两个mtr的redo log是交替保存在redo log buffer中的。

02

刷盘操作

log buffer的大小是有限的,当mtr结束的时候,会将redo log保存在redo log buffer中,在下面几种情况下,innodb会将redo log buffer中的内容刷入到磁盘里面:

1、log buffer空间不足时

一般情况下,当redo log 占用了redo log buffer的一半时,将会进行redo log 的刷盘操作

2、事务提交时。

事务一旦提交,事务所做的修改将会保存在buffer pool中,那么要想保证事务的一致性,就必须将redo log刷入到磁盘里面。

3、后台线程每一秒都进行一次刷盘操作

4、正常关闭MySQL服务的时候,会进行刷盘。

刚才我们说了,redo log是保存在一个一个的block数据页里面的,然后这些block会被刷入到磁盘中,也就是我们的ib_logfile文件中,这里有一点需要注意,就是ib_logfile中的前4个block是保存了一些通用信息,所以ib_logfile从第2048个字节开始,其中的内容才是redo log,化成图就是:

前4个数据页里面保存的是一些通用信息,后面的数据页保存的才是redo log的信息,画成图就是:

到这里,我们已经知道了ib_logfile的大概内容,当MySQL服务启动的时候,随着时间的推移,将会发生很多变更动作,每一个动作将会生成不同的redo log,这些redo log 将会从block的body处开始往后连续的写,写满一个block,然后再去写下一个。例如上图中,ib_logfile0中redo log写了2个block,其中第二个block写了一半,为了标记目前block写到的位置,innodb中使用一个叫做LSN(Log Sequence Number)的全局量来保存这个位置,翻译过来就是日志序列。这个日志序列是用来描述当前内存中的日志写到了redo log buffer的哪个位置。

前面我们说过,redo log buffer中不可能一直存储redo log ,一定是有一个redo log的刷盘动作的,我们用另外一个参数:buf_next_to_write来表示下一个将要被刷盘的位置,这样,画出ib_logfile的图来看,就是:

途中,绿色部分是已经刷到磁盘的block数据页,而粉色部分是在内存还没有刷到磁盘中的redo log页,橙色部分是还没有被使用的block 数据页。

在MySQL服务刚开始启动的时候,buf_next_to_write和lsn是在同一个位置的,随着时间的推移,redo日志不断的写入block,lsn的位置超过buf_next_to_write的位置,二者拉开了一点差距。

到这里,我们已经理解了redo log写入磁盘的方法,下篇文章中将会引入checkpoint的概念,来讲述redo log是如何保证一致性的。今天的内容就先到这里吧。