Redo日志 (4)—log sequence number(六十二)

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
云数据库 RDS MySQL Serverless,价值2615元额度,1个月
简介: Redo日志 (4)—log sequence number(六十二)

前面说了redo日志的格式,刷新到磁盘后台有线程每秒运行一次,还有事务提交的时候,buffer pool不会刷新到磁盘,但是log buffer会刷新到磁盘。Log buffer会分成若干的block,吧这些block持久化到磁盘上,mysql根目录有两个log_file0和log_file1,可以增加,当存满的时候,从0循环继续存储,默认是48Mb。每个block是512个字节,前面四个block占比2048个字节是记录管理信息,2048字节后面开始记录block。

redo日志文件格式(3)—mysql进阶(六十一)


Log sequence number


自系统修改开始,就不断的修改页面,也就不断的生成redo日志。为了记录一共生成了多少日志,于是mysql设计了全局变量log sequence number,简称lsn,但不是从0开始,是从8704开始。

我们知道log buffer中写入redo日志不是一条一条写入的,而是mtr生成的一组redo日志为单位写入,实际吧内容写在log block body处,但在统计lsn增长量时,是按照实际写入日志量占用log block header和log block tralider来计算的。举个例子:

例1:系统第一次启动初始化log buffer时,buf_free会指向第一个block偏移量为12个字节大小的地方,那么lsn值也会增加12。

那么lsn值就会记录成:8704+12 = 8716

例2:如果以mtr为一组redo日志占用存储的空间比较小,则会吧mtr占用的空间加进去。

那么lsn值就会记录成8716+200 = 8916

例3:如果以mtr为一组redo日志占用的存储空间比较大,则会吧log block header 和log block trailder占用的12个字节和4个字节也算进去。假设mtr2占用了三个block,此刻里面包含两个header 和两个trailder。

那么lsn值就会记录成1000+2*12 +4 * 2 = 1032 + 8716

至于为什么开始设置为8704呢,这是mysql规定好的,从上可以指定,每一组mtr都对应一个lsn值,如果lsn值越小,则redo日志生产的越早。


Flushed_to_disk_lsn


Redo日志首先写到log buffer中,之后才会被刷新到磁盘的redo日志文件上(ib_file0和ib_file1)。所以innoDB设计了一个全局变量buf_next_to_write,这个字段前面的数据都是已经被刷新到磁盘上的。所以log buffer的组成应该是:第一部分是到buf_next_to_write表示已经持久化到磁盘的数据,buf_next_to_write之后到buf_free表示记录的数据,还未持久化,buf_free之后的数据则是空间的log buffer。

我们前面说过lsn值代表redo日志量,包括未刷新到磁盘的redo日志,相对应的,innoDB设计了从   redo日志刷新到磁盘的全局变量,称为flushed_to_disk_lsn。系统第一次启动,lsn和flushed_to_disk_lsn值是相同的,但随着redo不断持久化到磁盘,就拉开距离了。

举例场景:当有mtr1:8716~8916

Mtr2:8916~9948

Mtr3:9948~10000

这时候因为还未持久化,所以flushed_to_disk_lsn还是8716,但是lsn值已经到了10000。

当mtr1和mtr2持久化到磁盘的时候,lsn值不变,flushed_to_disk_lsn则变为9948.

由上可以知道,当有新的redo日志,lsn值会增长,fulshed_to_disk_lsn不变,当持久化数据到磁盘的时候,则lsn不变,flushed_to_disk_lsn增长。当他们值相同的时候,说明所有redo日志已经持久化到磁盘。

LSN值和redo日志文件偏移量对应关系

因为lsn值是日志增长量的和,所以偏移量可以直接用lsn值减去初始的lsn值8704,剩下的就是redo日志文件偏移量。


Flush链表中的LSN


我们知道mtr代表一次对底层页面原子的访问,每次mtr结束的时候,都会吧redo日志写入到log buffer 中。除此之外,在mtr结束还有重要的事要做,写入到buffer pool的flush 链表中。回忆一下

Buffer pool是由控制块+碎片+缓存页组成。

而flush链表存的是还未持久化完成的脏数据,吧这些控制块通过双向链接组成链表,头部有一个链表基节点,有总的控制块数量,及其strat位子和end位子。

当第一次修改了buffer pool中的页面,则会吧这个控制块放入这个链表里,也就是链表里的位子顺序是根据第一次修改来放入的,后面就算修改因为已经存在了,直接在flush 链表修改就好。

Oldest_modification:如果某个页面被加载到buffer pool后进行第一次修改,那么就将mtr对应的lsn值写入这个。

Newest_modification:每次修改页面都会在mtr结束时候,吧lsn值写入这个。

而且每次新增的的修改页会放在flush链表的最前面。

综上知道,当第一次修改会在flush链表新增控制块,并且放在最前面,olderst_modification写入lsn值,newest_modification则是写入mtr结束时候的lsn值。如果当前页已经存在flush链表,则不需要新增当前页,old值不需要修改,吧newest值修改成mtr结束的lsn值即可。


Checkpoint


前面我们说过,log buffer内存是优先的,当使用完毕之后,我们得从第一个文件重新循环使用,所以这样很容易追尾。那我们可以想想redo日志干嘛的,是为了防止系统崩溃,记录数据,吧数据持久化到磁盘上的,那么如果已经把这些数据持久化到磁盘了,是不是系统崩溃这些数据也不需要恢复,可以放弃了呢?

用我们上面的例子,mtr1和mtr2和mtr2,当1和2已经持久化到磁盘,但修改的脏数据仍然留在buffer pool里,所以他们生成在redo日志在磁盘里的空间是不可以覆盖的。随着系统的运行,当页已经被刷新到磁盘里,这时候控制块就会从flush链表中移除。

所以这时候innoDB设计了checkpoint_lsn全局变量来代表当前系统可以覆盖的redo日志总量,这个值默认也是8704。

比方说页a刷新到磁盘上,mtr1生成的redo日志就可以被覆盖了,我们可以进行增加一个checkpoint_lsn的操作,这个过程我们称做checkpoint。做一次checkpoint可以分为两个步骤:

步骤一:计算一下当前系统中可以覆盖的redo日志对应的lsn值是多少

Redo日志可以覆盖,意味着脏数据已经刷新到磁盘,我们只要知道最早修改的脏页对应的oldest_modification,凡是checkpoint_lsn小于这个值的,都是可以覆盖的,比如我们前面的例子,最小的oldest_ modification值是8916,这时候我们吧8916赋值给checkpoint_lsn,小于这个值的都可以覆盖。

步骤二:将checkpoint _lsn和对应的redo日志文件组偏移量以及checkpoint编号写到日志文件管理信息(就是checkpoint1和checkpoint2)中

innoDB设计了一个全局变量,checkpoint_no,每做一次point就+1,还有计算checkpoint_offset偏移量,可以通过checkpoint_lsn计算。

每个redo都有2048个管理文件的信息,当checkpoint_no是偶数的时候,就存储在checpoint1中,当checkpoint_no是奇数的时候,就存储在checkpoint2中。


批量从flush链表刷出脏页


一般情况下,后台的线程都会对flush链表和lru链表刷脏到磁盘上,主要磁盘I/O操作比较慢,不想影响用户线程的处理请求。但如果系统操作频繁,写日志频繁,系统lsn增值太快。如果后台无法及时持久化脏数据,无法checkpoint,这时候可能需要用户线程同步刷新脏数据到磁盘,这样脏数据对应的redo日志没用了,就可以去checkpoint。


查看系统中的各种LSN值


我们可以用show engine innodb status;查看lsn值

其中log_sequence_number:代表系统中的lsn值,也就是当前系统的redo日志量,包括写入log buffer中的日志

Log_flushed_up_to:代表flushed_to_disk_lsn的值,代表已经写入的磁盘的redo日志字节量。

Page flushed up to:代表fulsh链表中最早修改那个页面对应的oldest_modification属性。

Last checkpoint at:当前系统的checkpoint_lsn值。

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
3天前
|
XML Java Maven
Springboot整合与使用log4j2日志框架【详解版】
该文介绍了如何在Spring Boot中切换默认的LogBack日志系统至Log4j2。首先,需要在Maven依赖中排除`spring-boot-starter-logging`并引入`spring-boot-starter-log4j2`。其次,创建`log4j2-spring.xml`配置文件放在`src/main/resources`下,配置包括控制台和文件的日志输出、日志格式和文件切分策略。此外,可通过在不同环境的`application.yml`中指定不同的log4j2配置文件。最后,文章提到通过示例代码解释了日志格式中的各种占位符含义。
|
3天前
|
运维 监控 Go
Golang深入浅出之-Go语言中的日志记录:log与logrus库
【4月更文挑战第27天】本文比较了Go语言中标准库`log`与第三方库`logrus`的日志功能。`log`简单但不支持日志级别配置和多样化格式,而`logrus`提供更丰富的功能,如日志级别控制、自定义格式和钩子。文章指出了使用`logrus`时可能遇到的问题,如全局logger滥用、日志级别设置不当和过度依赖字段,并给出了避免错误的建议,强调理解日志级别、合理利用结构化日志、模块化日志管理和定期审查日志配置的重要性。通过这些实践,开发者能提高应用监控和故障排查能力。
8 1
|
5天前
|
弹性计算 运维 Shell
|
11天前
|
Java
log4j异常日志过滤规则配置
log4j异常日志过滤规则配置
16 0
|
14天前
|
SQL 存储 监控
SLS 查询新范式:使用 SPL 对日志进行交互式探索
像 Unix 命令一样支持多级管道级联,像加工预览一样实时处理查询结果,更便捷的交互,更丰富的算子,更灵活的探索半结构化日志,快来试试使用 SPL 语言查询日志数据吧~
|
15天前
|
Apache
web服务器(Apache)访问日志(access_log)详细解释
web服务器(Apache)访问日志(access_log)详细解释
|
21天前
|
Java Spring
日志精准记录:Spring与Log4j完美整合的实战指南
日志精准记录:Spring与Log4j完美整合的实战指南
18 0
日志精准记录:Spring与Log4j完美整合的实战指南
|
SQL 数据采集 监控
基于日志服务数据加工分析Java异常日志
采集并脱敏了整个5月份的项目异常日志,准备使用日志服务数据加工做数据清洗以及分析。本案例是基于使用阿里云相关产品(OSS,RDS,SLS等)的SDK展开自身业务。需要对异常日志做解析,将原始日志中时间、错误码、错误信息、状态码、产品信息、请求方法、出错行号提取出来。然后根据提取出来的不同产品信息做多目标分发处理。对清洗后的数据做异常日志数据分析。
717 0
基于日志服务数据加工分析Java异常日志
|
25天前
|
安全 Linux 网络安全
/var/log/secure日志详解
Linux系统的 `/var/log/secure` 文件记录安全相关消息,包括身份验证和授权尝试。它涵盖用户登录(成功或失败)、`sudo` 使用、账户锁定解锁及其他安全事件和PAM错误。例如,SSH登录成功会显示"Accepted password",失败则显示"Failed password"。查看此文件可使用 `tail -f /var/log/secure`,但通常只有root用户有权访问。
70 4
|
26天前
|
运维 监控 数据可视化
日志服务 HarmonyOS NEXT 日志采集最佳实践
鸿蒙操作系统(HarmonyOS)上的日志服务(SLS)SDK 提供了针对 IoT、移动端到服务端的全场景日志采集、处理和分析能力,旨在满足万物互联时代下应用的多元化设备接入、高效协同和安全可靠运行的需求。
116758 10