MySQL中的REDO LOG和checkpoint

394 阅读4分钟

提到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中。

2.redo log日志的内部结构

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

3.log buffer 刷盘时机

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

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

参考: [MySQL 是怎样运行的:从根儿上理解 MySQL]

庖丁解InnoDB之REDO LOG - CatKang的文章 - 知乎 zhuanlan.zhihu.com/p/109417488