MySQL中的redo log和checkpoint

来源:这里教程网 时间:2026-03-01 16:49:48 作者:
提到MySQ中的checkpoint就不得不提redo log了。
下面跟随笔者一起来梳理一下REDO LOG相关知识点吧!
问题点:
1.checkpoint发生的时间点是什么时候?
2.checkpoint的作用是什么?
3.为什么有那么多数据库架构选择去掉checkpoint这一机制呢?比如 AWS的Aurora(MySQL)?

1.redo log日志类型

redo log日志还是有点意思,竟然根据写入大小来划分类型, 诸如:MLOG_1BYTE、 MLOG_8BYTE等。当然,这只是简单型redo ,还有复杂一些的类型, 诸如:MLOG_COMP_REC_INSERT表示插入一条使用紧凑行格式的记录时的redo日志类型。每组redo log日志最后一条日志类型为MLOG_MULTI_REC_END,表示redo log是完整的。 对底层页面的一次原子访问称之为Mini-Transaction,一个包含多条语句的事务,每个事物含有多个原子性操作,会产生一组mini-trx。 各组mini-trx在log buffer中是交替写入的。mtr运行中产生的一组redo log会在mtr结束的时候复制到log buffer中。
注意: 在MySQL5.7之后还新增了几条redo log类型,如:MLOG_CHECKPOINT、MLOG_FILE_NAME ,其中MLOG_CHECKPOINT在MySQL8.0之后被废弃了,这里可以将MLOG_CHECKPOINT算着是MLOG_FILE_NAME的一种补充,可以简单理解为 MLOG_FILE_NAME是为了在做Crash recovery的时候将查找需要恢复的表的ibd文件的过程与数据字典解耦,通过查找MLOG_FILE_NAME类型的redo log找到后续需要恢复的space信息。MLOG_CHECKPOINT则是对MLOG_FILE_NAME的一种补充,在系统检查点之后,对当前活动的所有数据文件做一个MLOG_FILE_NAME的补全,完成之后,写入MLOG_CHECKPOINT。Crash recovery的时候,碰到MLOG_CHECKPOINT则表示在它之前,检查点之后的所有redo log和space的映射关系均已建立完成。如果没有找到MLOG_CHECKPOINT则表示系统是正常关闭,checkpoint之后无脏页。

2.redo log日志的内部结构

redo log 是以512字节大小 的block进行记录的,log文件的前2048个字节,也就是前4个block包含有file header、checkpoint1、checkpoint2,其中file header中会记录log file文件开始的LSN,checkpoint则记录有服务器做checkpoint的编号,服务器做checkpoint时候的LSN,checkpoint时候LSN值对应的日志文件的偏移量。flush链表中的脏页就是按照脏页最先修改发生时候的LSN进行连接和排序的,除此之外还记录有最近一次修改LSN。

3.log buffer 刷盘时机

容量超过log buffer的一半
每次事务提交时(innodb_flush_log_at_trx_commit)
脏页刷盘前
后台线程,大概1s一次
正常关闭服务器
checkpoint
binlog切换

4.checkpoint

buffer pool中的脏页在没有flush 到盘之前是不能进行其对应位置的redo log的覆盖使用的,checkpoint_Lsn表示可以被覆盖的redo log的位点。
checkpoint_no、checkpoint_lsn、checkpoint_offset为日志管理信息,当checkpoint_no为偶数时,写入checkpoint_1,奇数时候,写入checkpoint_2中。
checkpoint发生分为fuzzy_checkpoint和sharp_checkpoint。
fuzzy_checkpoint是在实例运行时,以一定的比例进行刷脏。
分为Master thread checkpoint
Flush_lru_list(innodb_lru_scan_depth)
Async/sync checkpoint(redo日志文件大小不够用)
脏页太多,超过innodb_max_dirty_pages_pct。
sharp_checkpoint则发生在实例关闭的时候。

 

5.崩溃恢复的两个LSN点

恢复的起点为checkpoint_lsn,崩溃恢复的终点为log block中LOG_BLOCK_HDR_DATA_LEN<>512de 块。 在这checkpoint_lsn之前的脏页肯定是被flush到磁盘的,在这之后的脏页呢?不一定没有刷到磁盘,如果某个脏页在checkpoint之后被刷盘,那么这个页面header中的FIL_PAGE_LSN一定大于checkpoint_lsn,符合这种情况的页中LSN小于该值的redo log也是不需要进行恢复的。

6.redo log 文件最大是多少?

在初次使用一个log block的时候会分配一个LOG_BLOCK_HDR_NO,记录在log block header处,计算公式为 ((lsn / 512) & 0x3FFFFFFFUL) + 1,最多产生1GB个LOG_BLOCK_HDR_NO,redo日志文件组中包含的所有文件大小不超过512G。

7.关于redo log的版本优化

7.1 To simplify InnoDB tablespace discovery during crash recovery, new redo log record types were introduced in MySQL 5.7.5. This enhancement changes the redo log format。

7.2 From MySQL 8.0.30, the [innodb_redo_log_capacity]variable controls the amount of disk space occupied by redo log files.InnoDB maintains 32 redo log files in the #innodb_redo directory in the data directory.the [innodb_log_files_in_group]and [innodb_log_file_size]variables. These two variables are now deprecated.

7.3 在高并发的环境中,mtr需要拷贝至log buffer中,MySQL8.0开始,允许不同的mtr并发的写入log buffer。

8.redo log刷盘的过程

redo log 主要为ACID中的D服务,要求其在事务提交之前,写完。写redo log的过程包括一开始由mtr_start生成的mtr。mtr中会动态维护一个动态增长的m_log,原子操作需要写的所有REDO先写到这个m_log中,原子操作结束后,mtr_commit会将m_log中的数据拷贝至Log Buffer中。 写入Log Buffer中的redo 需要进一步写入操作系统的Page Cache,由log_write来完成。(MySQL8.0并发mtr写入导致的空洞问题,由link_buffer的数据结构解决)。 写入Log Buffer之后便是flush过程,log_flusher线程会调用fsync完成刷盘,当然,这个过程还会有 innodb_flush_log_at_trx_commit参数的介入。
0 log are writen and flushed to disk once per second
1 writen and flushed to disk at each trx commit
2 log are writen afetr each trx commit and flushed to disk once per second

 

9.相关参数

9.1  innodb_redo_log_capacity 当设置了 innodb_redo_log_capacity该参数,那么 innodb_log_files_in_group    innodb_log_file_size  将会被忽略。最大512G。 innodb_log_files_in_group  *  innodb_log_file_size  =  innodb_redo_log_capacity 9.2 innodb_log_file_size  and  innodb_log_files_in_group   They are deprecated in MySQL 8.0.30。 9.3  innodb_log_group_home_dir

The directory path to the  InnoDB   redo log  files.

问题解答

1.checkpoint发生的时间点是什么时候?

分fuzzy checkpoint和sharp checkpoint两种 
2.checkpoint的作用是什么?
checkpoint其实并不像后台进程那样,会有一定的flush或者fsync的操作,只是检查buffer pool中最老的脏块的lsn是什么,并且记录。其他的工作还是依赖后台进程去做。
Makes a checkpoint. Note that this function does not flush dirty blocks from the buffer pool. It only checks what is lsn of the oldest modification

in the buffer pool, and writes information about the lsn in log files 

3.为什么有那么多数据库架构选择去掉checkpoint这一机制呢?比如 AWS的Aurora(MySQL)?
 Aurora实行的是Log is database,它的写入是没有数据页的概念的,只是redo log在流转,所以这个过程中不需要checkpoint去标识哪些页已经落盘,哪些页没有。 
参考:
[MySQL 是怎样运行的:从根儿上理解 MySQL]
庖丁解InnoDB之REDO LOG
https://cloud.tencent.com/developer/article/1506059

相关推荐