Mysql日志系统之redolog

Mysql日志系统之redolog

redo log的作用

MySQL的InnoDB存储引擎的物理文件存储体系中,除了实际的数据文件(ibd, ibdata)之外,还有两个非常重要的日志系统,分别是redo log 和undo log。redo log又称重做日志文件,用于记录事务操作的变化,记录的是数据修改之后的值,不管事务是否提交都会记录下来。有了redo log ,InnoDB就可以保证即使数据库发生异常重启,之前提交的记录都不会丢失,这个能力称为crash-safe

redo log是如何运作的
mysql里有一个叫WAL的技术,它的全称是Write-Ahead Logging,他的关键点就是先写日志,再写磁盘,具体的意思就是当有一条记录需要更新的时候,InnoDB引擎就会先把记录写到redo log里面,并更新内存,这个时候更新就算完成了,同时,InnoDB会在适当的时机,把这个操作更新到磁盘里,而这个时机有以下几种:
1.当redo log文件写满的时候
2.当数据库空闲的时候
3.当数据库要关闭的时候

2和3两点我们就不讲了,主要来讲一下第1点:当redo log文件写满的时候
redo log文件是一个可以重复循环写的文件,而且大小是固定的,在这个文件里面,有一个点叫check point,也叫检查点,可以这么说,如果在redo log里记录的你所做的一些操作在这个check point后面,那么这些数据一定是已经被刷到磁盘里了的,而在check point前方,是write pos(当前记录的位置),我们可以把redo log理解为一个圈
Mysql日志系统之redolog_第1张图片
图中绿色的部分,就代表着这些记录操作都已经刷到磁盘里去了,可以重新使用了,而红色的部分,表示这些数据还没有刷到磁盘里,不可以重新使用,当绿色部分快用完的时候,这时候,InnoDB会停下所有的操作,去全力刷redolog,把check point往前推进。

redo log buffer
我们再来说一个知识点,那就是redo log buffer,它使用的是内存的空间,在事务执行的过程中,生成的redo log是要先写到redo log buffer里的,日志写到redo log buffer是很快的,write到文件系统的page cache里也是很快的,但是当它已经write到文件系统的page cache里之后,还有一步,就是持久化到磁盘,这一步是很占用时间的,也就是占用磁盘的IOPS,redo log 写到磁盘的时间,基本上就可以说是redo log从文件系统page cache持久化到磁盘的时间。

当内存数据页跟磁盘内容不一致的时候,我们称这个内存页为脏页,这个脏页上的数据称为脏数据,即上图的红色部分,内存数据写入到磁盘后,磁盘和内存上的数据页内容就一致了,我们把这个数据页称为干净页,如果我们的数据库偶尔稍微卡那么一下,那就可能是数据库在刷脏页。

那为什么不把绿色部分的redo log直接清除掉呢?
因为如果要查询数据,而这个数据刚好还在内存中,那这个数据一定是准确的,而且返回的时间还快,如果要找的数据不在内存中,而在磁盘上,那也可以肯定在磁盘上的数据一定是准确的。

提到脏页,这里做个小展开:
我们可以控制innodb引擎的刷脏速度,可能通过参数innodb_io_capacity去设置,一般这个参数可以设为 自己磁盘的iops值,iops值可以通过fio工具去测试。
参数innodb_max_dirty_pages_pct是设置脏页比例上限,默认值为75%,innodb会根据当前脏页比例刷脏。
innodb_flush_neighbors参数设置为1的时候,就表示在刷脏页的时候,如果相邻数据页也是脏页,会把它也一起刷了,如果参数设为0,那么只是刷自己的,在以前机械硬盘的时代,因为机械硬盘的IOPS很低,所以设置为1可以大大的减少磁盘随机写的次数,从而提升性能,在现在SSD的时代,我们基本把这个参数设为0。
在mysql 8.0中,innodb_flush_neighbors参数已经默认为0了。

redo log buffer 占用的空间即将达到innodb_log_buffer_size一半的时候,后台线程会主动写盘,但是由于事务没有提交,所以只是留在了文件系统的page cache里,没有持久化到磁盘,但是如果有另一个线程B的事务提交了,就会带上事务A的redo log buffer里的日志一起持久化到磁盘上。

我们还可能通过参数来控制redo log的写入策略,InnoDB提供了innodb_flush_log_at_trx_commit参数:
1.设置为0的时候,表示每次事务提交都只是把redo log留在redo log buffer中
2.设置为1的时候,表示每次事务提交都将redo log直接持久化到磁盘
3.设置为2的时候,表示每次事务提交都只是把redo log写到page cache中
在生产环境中,不建议把innodb_flush_log_at_trx_commit参数设为0.

还有,InnoDB有一个后台线程,每隔一秒,就会把redo log buffer中的日志,调用write写到page cache里,然后调用fsync持久化到磁盘。

redo log还有一个最主要的作用,就是当你对一条记录做操作的时候,他是先记录在redo log buffer里的,你可以想一下,几次操作一起写到磁盘和操作一次写一次磁盘,那肯定是前者的方式好,它把随机写转变成了顺序写,可以这么说,redo log提升了innodb的写入速度。

你可能感兴趣的:(mysql)