前情提要

在执行增删改操作的时候,是基于Buffer Pool中的缓存页中的数据的。更新了缓存页中的数据后,会写入一条数据到Redo Log中。在提交事务的时候,会立马把Redo Log刷入磁盘(推荐方式),然后在RedoLog中写入binlog信息和一个commit标记,事务至此提交完毕。

FAQ

官网:
https://dev.mysql.com/doc/refman/8.0/en/innodb-redo-log.html
https://dev.mysql.com/doc/refman/8.0/en/optimizing-innodb-logging.html

RedoLog 保障了什么

当更新了缓存中的数据页后,缓存页还没有刷到磁盘上。MYSQL宕机,那么MYSQL重启后,会直接读取RedoLog中的内容,重做到Buffer Pool中,然后在刷到磁盘。因为 RedoLog 是顺序读写,所以效率很高。并且为了保证数据的不丢失,RedoLog也要设置成不经过OS Cache。

为什么要写入 RedoLog,直接刷到磁盘的缺点在哪里?

  1. 一个缓存页是16KB,刷盘比较耗时。而且你可能只修改了几个字节的数据。
  2. 缓存页刷入磁盘是随机读写。效率很低。而 RedoLog 是顺序读写,效率高

详细介绍

RedoLog的类型

根据数据页修改的字节数划分了不同的类型

  • MLOG_1BYTE:修改了1个字节
  • MLOG_2BYTE:修改了2个字节
  • MLOG_4BYTE:修改了4个字节
  • MLOG_WRITE_STRING:修改了一大串的值

RedoLog 的大致内容

MLOG_NBYTE,表空间ID,数据页号,数据页中的偏移量,具体修改的值
MLOG_WRITE_STRING,表空间ID,数据页号,数据页中的偏移量,修改的长度,具体修改的值

RedoLog 的写入方式

我们知道RedoLog的目的,是去保证我的数据页在内存,但是还没有同步到磁盘的时候,宕机导致的数据丢失。

所以在sql语句提交之前,肯定会保存改动的 Redolog 到 redolog file文件。当改动数据还在内存,没有同步到磁盘就宕机的时候,会通过 RedoLog 文件里面找到改动点,进行同步到磁盘。

但是 RedoLogFile 的大小是固定的,写入的日志数量是有限制的,并且它的目的只是去保证数据不丢失,数据落盘了,这些日志就没有用了,所以RedoLog采用的是循环覆盖写的方式。

当 RedoLog 空间的大小满了的时候,会对以前数据进行覆盖。为了保证被覆盖的数据不会丢失,在Redolog快满的时候,也会去进行刷脏,刷脏后,对应的 Redolog 日志就无效可以被覆盖,所以RedoLog的写是循环写的方式。

当数据同步到磁盘后,RedoLog就会进行删除。

简单一句话,当32个文件被写满后,又会从第一个文件开始进行循环写入。

RedoLog Block

RedoLog中,包含着多个RedoLog Block。每个RedoLog大小是512KB;
在写入Redolog之前先写入内存中的RedoLog Block,然后再把RedoLog Block写入磁盘文件。具体的结构见图。

RedoLog buffer

好比Buffer Pool,基于内存中的一块连续空间。里面分配了多个空的RedoLog block。用来存放redolog。

  • 在一个事务中,多个操作对应多个redo Log,对应着一组redolog,现在别的地方暂存,执行完了再把一组的redolog写入到内存中的redolog buffer中的block中
  • 如果一个事务对应的redoLog太多,就会放到两个甚至多个redolog block中。
  • 如果一个redolog group比较小,也可能会把多个redolog group合并在一个redolog block中。

刷盘时机

  1. 写入redolog buffer的日志占用了总容量(innodb_log_buffer_size)的50%。
  2. 事务提交的时候
  3. 后台线程定时刷新
  4. MYSQL关闭的时候

RedoLog的一些默认处理

  • 版本 8.0.30 之前
    磁盘上默认redolog数量:2个(innodb_log_files_in_group)
    磁盘上默认redolog大小:48MB(innodb_log_file_size)
    磁盘上的默认名:ib_logfile0,ib_logfile1
    一般情况是向一个redolog中写,写满了就换下一个。所以redolog最多保存96MB的redolog,如果第二个写满了,就覆盖第一个日志文件里面原来的redolog
  • 版本 8.0.30 之后
磁盘文件的大小由 innodb_redo_log_capacity 配置,
InnoDB尝试维护32个相同大小的重做日志文件,
每个文件等于1/32 * innodb_redo_log_capacity

我们去磁盘发现,InnoDB维护了32个大小为104857600/32=3276800 的 redo 文件

我们发现有的文件是 _tmp,代表这些文件是备用文件,还没有写入 RedoLog。

禁用 RedoLog

redoLog虽然尽可能的去保证了我们数据的一致性,但是,如果为了性能考虑,而不需要保证一致性也可以对RedoLog进行关闭。

查看RedoLog是否开启

-- 查看RedoLog是否开启
SHOW GLOBAL STATUS LIKE 'Innodb_redo_log_enabled';

从8.0.21开始,可以使用指令

-- 禁用RedoLog 
ALTER INSTANCE disable INNODB REDO_LOG;
最后修改:2024 年 01 月 10 日
如果觉得我的文章对你有用,请点个赞吧~