//
MySQL中的Redo Log(三)
//
关于MySQL的redo log,之前写过两篇文章,都比较简短易懂,开始今天的内容之前,先贴一下前两篇的链接:
为了便于理解,我们将第二篇文章中的redo log buffer的图拷贝过来:
在本图中,buf_next_to_write左侧的绿色部分,为log buffer pool中已经刷新到磁盘上的redo log,右侧的粉色部分,为写入到log buffer,但是还没有刷新到磁盘上的redo log。
当我们使用show engine innodb status\G的方法来显示当前innodb存储引擎状态的时候,我们会看到一部分下面的内容:
---
LOG
---
Log sequence number 2633475
Log flushed up to 2633475
Pages flushed up to 2633475
Last checkpoint at 2633466
其中,
Log sequence number:代表系统中的lsn值,也就是当前系统已经写入的redo日志量,包括写入log buffer中的日志,第二篇文章中有做过解释。
Log flushed up to:代表flushed_to_disk_lsn的值,也就是当前系统已经写入磁盘的redo日志量。
前两个参数比较容易理解,第三个参数比较难理解。要理解这个参数,我们需要先了解flush链表。在innodb存储引擎中,buffer pool中维护了2个重要的链表,其中一个是free链表,另外一个是flush链表,其中free链表记录了当前buffer pool中空闲的数据页,flush链表记录了当前buffer pool中被污染的数据也,这些数据也即将被刷新到磁盘中。
我们知道,当我们提交一个mtr时,可能被该mtr修改的数据页,会被添加在buffer pool中的flush链表中,代表该数据页即将被刷新到磁盘。假设我们的页面提交顺序是a,b,c,那么flush链表中的页面顺序用图来表示就是:
可以看到,flush链表采用的是头插法。而且,假设有mtr1和mtr2,都对页面b进行了修改,则页面b只在该链表中被加载一次,假设mtr1早于mtr2提交,mtr1影响页面b的时间我们称之为old,mtr2影响页面b的时间我们称之为new,如果此时mtr3也影响了页面b,则更新new的值为mtr3影响页面b的时间点。
这样,我们得到的链表就是按照old这个时间排序的:
其中old3>old2>old1
到这里,上述Pages flushed up to的值就可以解释了:
Pages flushed up to:代表flush链表中被最早修改的那个页面对应的oldest_modification属性值。
再来看最后一个参数:last checkpoint at。
我们知道,redo log的日志文件ib_logfile0和ib_logfile1的容量是有限的,而且他们是循环利用的,当redo log记录到一定程度时,一定会出现"追尾“的现象。而redo日志只是为了系统崩溃后恢复脏页用的,如果对应的脏页已经刷新到了磁盘,也就是说即使现在系统崩溃,那么在重启后也用不着使用redo日志恢复该页面了,所以该redo日志也就没有存在的必要了,那么它占用的磁盘空间就可以被后续的redo日志所重用。也就是说:判断某些redo日志占用的磁盘空间是否可以覆盖的依据就是它对应的脏页是否已经刷新到磁盘里。
我们知道,redo log会被刷新到磁盘上的ib_logfile日志文件组中,但是,redo log落盘后,并不能直接覆盖该ib_logfile所占据的空间,因为这些redo log可能被用在后续的回滚操作或者恢复操作中。如下图所示,蓝色部分指的是将redo log刷入了磁盘上的ib_logfile0中。
那么什么时候,ib_logfile中的redo log部分占用的空间才能被循环利用呢?
随着系统的运行,当事务被提交的时候,这些redo log影响的数据页会被刷新到磁盘上,也就是将数据页从flush 链表中的页面刷新到磁盘上,例如我们把数据页a刷新到磁盘上,那么flush 链表会变成:
那么此时,因为事务提交后具有持久性,ib_logfile0文件示意图中蓝色部分的redo log就没有意义了,就可以将ib_logfile中的可用位置移动了,如下:
innodb把这个过程叫做checkpoint,checkpoint过后的新空闲区域最后的位置,叫做checkpoint_lsn。
到这里,我们就能解释第四个参数的值了,如下:
Last checkpoint at:当前系统的checkpoint_lsn值。
其中,lsn、log flushed up to、last checkpoint at的相对位置,画成图就是:
最后,再提一点,如果lsn的值和checkpoint_lsn的值相差很远,说明系统当前可能磁盘IO的压力比较大。
时间原因,今天的内容就到这里吧。