当前位置: 首页 > 科技观察

说说什么是RedoLog?

时间:2023-03-20 12:37:54 科技观察

本文转载自微信公众号“程序猿之星”,作者程序猿阿星。转载本文,请联系程序员阿星公众号。前言说到MySQL,有两种日志是必须避免的,一种是InnoDB存储引擎的重做日志(redolog),一种是MySQLServce层的binlog(归档日志)。只要是数据更新操作,他们就一定会参与进来。今天就来说说重做日志(redolog)。重做日志重做日志(redolog)是InnoDB存储引擎特有的,它让MySQL拥有崩溃恢复能力。例如,如果MySQL实例挂掉或宕机,当重启时,InnoDB存储引擎会使用redolog来恢复数据,以保证数据的持久性和完整性。阿星在之前的文章中说过,MySQL中的数据是以页为单位的。查询一条记录时,会从硬盘中加载一页的数据。加载的数据称为数据页,将放入缓冲池中。后续的查询都是先从BufferPool中查找,没有命中则上传到硬盘,减少了硬盘的IO开销,提高了性能。更新表数据时也是如此。如果发现BufferPool中有需要更新的数据,可以直接在BufferPool中进行更新。然后它会把“某个数据页做了什么修改”记录到重做日志缓冲区(redologbuffer)中,然后刷盘到重做日志文件中。理想情况下,事务一提交就执行刷新操作,但实际上,刷新的时机是根据策略来执行的。Tips:每条重做记录由“表空间号+数据页号+偏移量+修改数据长度+具体修改数据”组成。何时刷盘,InnoDB存储引擎为redolog的刷盘策略提供了innodb_flush_log_at_trx_commit参数。它支持三种策略。当设置为0时,表示每次提交事务时都不会进行磁盘操作。当设置为1时,表示每次提交事务都会进行磁盘操作(默认值)。表示每次提交事务时只将重做日志缓冲区的内容写入页面缓存。另外,InnoDB存储引擎有一个后台线程,每1秒将redologbuffer的内容写入文件系统缓存(pagecache)。然后调用fsync擦除磁盘。换句话说,还没有提交事务的重做日志记录也可能被刷新。为什么?因为重做日志记录在事务执行过程中会被写入重做日志缓冲区,而这些重做日志记录会被后台线程刷新。除了后台线程每秒进行一次轮询操作外,还有一种情况。当redologbuffer占用的空间即将达到innodb_log_buffer_size的一半时,后台线程会主动刷盘。下面是不同刷盘策略的流程图。当innodb_flush_log_at_trx_commit=0为0时,如果MySQL挂了或者崩溃了,可能会有1秒的数据丢失。当innodb_flush_log_at_trx_commit=1为1时,只要事务提交成功,redolog记录一定在硬盘中,不会有数据丢失。如果MySQL在事务执行过程中挂了或者宕机了,这部分日志丢失了,但是事务没有提交,所以日志丢了也不会丢失。当innodb_flush_log_at_trx_commit=2为2时,只要事务提交成功,redologbuffer中的内容只写入文件系统缓存(pagecache)。如果只有mysql挂掉,不会有数据丢失,但是当它挂掉的时候可能会有1秒的数据丢失。日志文件组硬盘上并不是只有一个重做日志文件,而是以日志文件组的形式存在,每个重做日志文件的大小都是一样的。比如可以配置为4个文件为一组,每个文件的大小为1GB,整个redolog日志文件组可以记录4G的内容。它采用环形数组的形式,从头开始写,写到尾再回到头开始循环写,如下图所示。日志文件组中有两个重要的属性,即writepos和checkpoint。writepos为当前记录位置,checkpoint为当前写入时要擦除的位置。redolog记录在logfilegroup中,writepos位置会后移更新。MySQL每次加载日志文件组恢复数据时,都会清除加载的重做日志记录,并将检查点移回更新。writepos和checkpoint之间的空白部分可以用来写入新的redolog记录。如果writepos赶上了checkpoint,说明日志文件组已满,此时不能写入新的redolog记录。MySQL必须停止,清除一些记录,并推进检查点。本篇到此结束,下一篇会讲binlog(归档日志)。总结相信大家都知道redolog的作用及其定时和存储形式。现在我们想一个问题,只要每次直接刷出修改过的数据页就可以了,redolog也没什么问题。不都是刷盘的吗?有什么不同?1Byte=8bit1KB=1024Byte1MB=1024KB1GB=1024MB1TB=1024GB其实数据页的大小是16KB,刷盘比较耗时。它可能会修改数据页中的几个字节的数据。是否需要刷入完整的数据页?而且datapageflashing是随机写,因为一个datapage对应的位置可能在硬盘文件的一个随机位置,所以性能很差。如果是写重做日志,一行记录可能会占用几十个Bytes,而且只包括表空间号、数据页号、磁盘文件偏移量和更新值。另外,它们是顺序写入的,所以刷盘速度非常快。所以使用redolog来记录修改的内容会远胜于刷新数据页的方式,也使得数据库的并发性更高。事实上,内存中的数据页也会在一定时间刷新。我们称之为页面合并。当我们讲到BufferPool的时候,我们会详细解释这个,站在巨人的肩膀上。