【MySQL 数据宝典】【磁盘结构】- 004 redolog 重做日志

一、背景介绍

  • 持久性要求: 对于已提交的事务,即使系统发生崩溃,其对数据库的更改也不能丢失。
  • 问题:
    • 在事务提交前将所有修改的页面刷新到磁盘浪费资源。
    • 随机IO导致刷新速度慢。
  • 解决方案:
    • 【数据副本】记录事务执行过程中所做的修改,称为 Redo 日志。
    • 【顺序写入】Redo Log 就是 WAL
  • 什么是 WAL:
    • WAL 的全称是 Write-Ahead Logging,中文称为预写式日志,是一种数据安全写入机制。在 MySQL 中,redo log 就是采用了 WAL 机制。
    • 为什么使用WAL?
      • 磁盘的写操作是随机 IO,比较耗性能。通过将每一次的更新操作先写入日志中,然后再写入磁盘,就可以将随机写操作转变为顺序写操作,从而提高性能。WAL 的核心在于将随机写转变为了顺序写,降低了客户端的延迟,提升了系统的吞吐量。

二、基本概念

InnoDB 引擎对数据的更新,是先将更新记录写入 redo log 日志,然后在系统空闲的时候或者是按照设定的更新策略再将日志中的内容更新到磁盘之中。这种技术可以大大减少 IO 操作的频率,提升数据刷新的效率。

  • redo log:被称作重做日志,包括两部分:
    • 一个是内存中的日志缓冲:redo log buffer
    • 另一个是磁盘上的日志文件: redo log file
  • 当故障发生致使内存数据丢失后,InnoDB会在重启时,经过重放 redo,将Page恢复到崩溃之前的状态 通过Redo log可以实现事务的持久性 。

三、核心流程

3.1 脏页落盘流程

  • mysql 每执行一条 DML 语句,先将记录写入 redo log buffer ( redo日志记录的是事务对数据库做了哪些修改 ) 。后续某个时间点再一次性将多个操作记录写到 redo log file

22.jpg
当进行数据页的修改操作时:

  • 首先修改在缓冲池中的页,然后再以一定的频率刷新到磁盘上。
  • 页从缓冲池刷新回磁盘的操作并不是在每次页发生更新时触发,而是通过一种称为CheckPoint的机制刷新回磁盘。

3.2 CheckPoint

如果重做日志可以无限地增大,同时缓冲池也足够大,那么是不需要将缓冲池中页的新版本刷新回磁盘。因为当发生宕机时,完全可以通过重做日志来恢复整个数据库系统中的数据到宕机发生的时刻。

image.png

  • 文件结构:
    • 可以配置为一组文件,例如,4 个文件,每个文件大小为 1GB,总共可记录 4GB 的操作。
    • 写入时从头开始写,写到末尾后又回到开头,形成循环写的机制。
    • Write Position: 写入偏移量
    • Checkpoint: 检查点
  • 作用:
    • 提速: 缩短数据库的恢复时间
    • 刷脏: 缓冲池不够用时,将脏页刷新到磁盘
    • 崩溃恢复: 重做日志不可用时,刷新脏页。
  • 刷脏的时机:
    • sharp checkpoint:强制落盘。把内存中所有的脏页都执行落盘操作。只有当关闭数据库之前才会执行
    • fuzzy checkpoint:模糊落盘。把一部分脏页执行落盘操作
      • 【定期执行】Master Thrad Checkpoint 主线程定时将脏页写入磁盘 每秒或每10s执行一次脏页。
      • 【脏页淘汰】FLUSH_LRU_LIST buffer pool有脏页换出,执行落盘
      • 【redo log 满】Async/Sync Flush checkpoint 当redo log快写满的时候执行落盘
        • 当redo log超过75%小于90%会执行异步落盘
        • 当redo log超过90%,会执行同步落盘操作。会阻塞写操作。
    • 【脏页占比过高】Dirty Page too much checkpoint 如果buffer pool中脏页太多,脏页率超过75%执行落盘
  • 总结: CheckPoint机制的重要性在于确保数据库系统在发生宕机或异常情况时能够快速恢复到一个一致的状态,同时有效管理缓冲池中的脏页。

3.3 Redo Log 持久化

缓冲区数据一般情况下是无法直接写入磁盘的,中间必须经过操作系统缓冲区( OS Buffer )。因此, redo log buffer 写入 redo logfile 实际上是先写入 OS Cache,然后再通过系统调用 fsync() 将其刷到 redo log file.

23.jpg44.jpg

  1.  存在于redo log buffer 内存区域中 2.  向磁盘写入,但是没有真正写入磁盘,而是保存在文件系统缓存中 3.  持久化到磁盘 

Redo Buffer 持久化到 redo log 的策略,可通过Innodb_flush_log_at_trx_commit 设置:

参数值含义
0 (延迟写)事务提交时不会将 redo log buffer中日志写入到 os buffer,而是每秒写入 os cache并调用 fsync()写入到 redo log file中。也就是说设置为0时是(大约)每秒刷新写入到磁盘中的,当系统崩溃,会丢失1秒钟的数据。
1  (实时写,实时刷)事务每次提交都会将 redo log buffer中的日志写入 os cache并调用 fsync()刷到 redo log file中。这种方式即使系统崩溃也不会丢失任何数据,但是因为每次提交都写入磁盘,IO的性能较差。
2 (实时写, 延时刷)每次提交都仅写入到 os buffer,然后是每秒调用 fsync()os cache中的日志写入到 redo log file
  • 一般建议选择取值 1,数据不会丢
  • 这里类似于 RocketMQ 内存写成功,但是刷盘失败: rocketmq 最佳实践

这意味着在事务提交后,数据页的修改可能仍然在内存中,并没有立即刷新到磁盘上。MySQL会根据自身的策略将内存中的数据页刷新到磁盘,这个过程可能会在事务提交后的某个时间点发生。

问题: 如果事务没有提交的时候,redo log buffer中的部分日志有可能被持久化到磁盘吗 ?
回答: 以下两种场景都会触发持久化

  • redo log buffer 占用的空间即将达到 innodb_log_buffer_size 一半的时候,后台线程会主动写盘。
  • 并行的事务提交的时候,顺带将某个未提交的事务的redo log buffer 持久化到磁盘。因为redo log buffer 是共享的,因此一些正在执行中的事务的redo log信息也有可能被持久化到磁盘中。

3.3.1 Redo Log 日志格式

日志类型描述举例
物理日志记录每个页中存储的具体值及修改操作某个事物将系统表空间中的第100个页面中偏移量为1000处的那个字节的值1改为2.
逻辑日志记录数据变动的逻辑过程或SQL语句把一个page页中的一个数据从1改为2,再从2改为3,逻辑日志就会记录1->2,2->3这个数据变化的过程.

类似于 AOF & RDB 的区别,感兴趣的可以看 Redis 部分。

通用结构

image.png

  1. **type**: 该条日志的类型2. **space ID** : 表空间ID3. **page number** : 页号4. **data** : 该条redo日志的具体内容
日志类型

redo log根据在页面中写入数据的多少,将redo日志划分为几种不同的类型(MySQL5.7中有53种类型)。

  • MLOG_1BYTE (type=1) : 表示在页面的某个偏移量处写入1字节的redo日志类型。
  • MLOG_2BYTE (type=2) : 表示在页面的某个偏移量处写入2字节的redo日志类型。
  • MLOG_4BYTE (type=4) : 表示在页面的某个偏移量处写入 4字节 的redo日志类型。
  • MLOG_8BYTE (type=8) : 表示在页面的某个偏移量处写入8字节的redo日志类型。

25.jpg

  • MLOG_WRITE_STRING(type=30): 表示在页面的某个偏移量处写入一串数据,但是因为不能确定写入的具体数据占用多少字节,所以需要在日志结构中添加一个len字段。

26.jpg

3.4 组提交

  • MySQL 为了优化磁盘持久化的开销,会有一个 组提交(group commit)的机制
  • 每个InnDB存储引擎至少有1个重做日志文件组(group),每个文件组下至少有两个重做日志文件,默认的为ib_logfile0ib_logfile1
    • redo log 的组提交(group commit)是一种优化策略,用于提高数据库的性能和吞吐量。在 MySQL 中,redo log 的组提交是指将多个事务的提交操作合并成一个批量提交操作,从而减少磁盘 IO 操作的次数,提高系统的效率。
    • 具体来说,当多个事务同时提交时,MySQL 可以将它们的提交操作合并成一个组,然后一次性将这个组的提交操作写入到 redo log 文件中。这样做的好处是可以减少磁盘 IO 操作的次数,因为将多个提交操作合并成一个批量提交操作后,可以减少文件系统的写入开销和磁盘的随机写入次数,从而提高系统的性能和吞吐量。
  1. 事务日志组路径,当前目录表示MyQSL数据目录为日志组目录.
mysql> show variables like 'innodb_log_group_home_dir';
+---------------------------+-------+
| Variable_name             | Value |
+---------------------------+-------+
| innodb_log_group_home_dir | ./    |
+---------------------------+-------+
1 row in set (0.00 sec)[root@localhost mysql]# ll ib_log*
-rw-r----- 1 mysql mysql 50331648 1月  29 03:39 ib_logfile0
-rw-r----- 1 mysql mysql 50331648 7月  11 2020 ib_logfile1
  1. 事务日志组中的事务日志文件个数,默认是2个.
mysql> show variables like 'innodb_log_files_in_group';
+---------------------------+-------+
| Variable_name             | Value |
+---------------------------+-------+
| innodb_log_files_in_group | 2     |
+---------------------------+-------+
1 row in set (0.01 sec)
  1. 日志组中每个重做日志的大小一致,并循环使用;
mysql> show variables like 'innodb_log_file_size';
+----------------------+----------+
| Variable_name        | Value    |
+----------------------+----------+
| innodb_log_file_size | 50331648 |
+----------------------+----------+
1 row in set (0.00 sec)

image.png
InnoDB 以环型方式(circular fashion)写入数据到重做日志文件,当文件满了的时候,会自动切换到日志文件2,当重做日志文件2也写满时,会再切换到重做日志文件1

  • write pos: 表示日志当前记录的位置,当ib_logfile_4写满后,会从ib_logfile_1从头开始记录;
  • check point: 表示将日志记录的修改写进磁盘,完成数据落盘,数据落盘后checkpoint会将日志上的相关记录擦除掉,即 write pos -> checkpoint  之间的部分是redo log空着的部分,用于记录新的记录,checkpoint -> write pos 之间是redo log 待落盘的数据修改记录
  • 如果 write pos 追上 checkpoint,表示写满,这时候不能再执行新的更新,得停下来先擦掉一些记录,把 checkpoint 推进一下。

Redo log 记录了事务对数据库做了哪些修改,属于物理日志,包括不同类型的日志记录,如 MLOG_1BYTE、MLOG_2BYTE、MLOG_4BYTE、MLOG_8BYTE 和 MLOG_WRITE_STRING。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/2211.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux信号机制分析

概念 信号递达:实际执行信号的处理动作就是信号递达 信号未决:信号从产生到递达之间的状态就是信号未决(未决就是没有解决) 收到某信号后,把未决信号集中的此信号置为1(1表示未解决的信号)&a…

【Camera Sensor Driver笔记】四、点亮指南之EEPROM配置

很久之前写的一版&#xff1a; 【Qcom Camera】微距eeprom调试_cam_vio-supply <&l7p>-CSDN博客 <slaveInfo> EEPROMName cat24c64_imx585 eeprom型_sensor名字 slaveAddress 0xa0 i2c write address regAddrType …

国产PLC有哪些,哪个牌子比较好用?

你知道国产PLC有哪些吗,哪个牌子更好用吗&#xff1f; 今天拿出国产先锋的汇川与台达对比&#xff0c;注&#xff1a;视频后方有各品牌学习资料免费送&#xff0c;需要的移步自取。话说回来&#xff0c;只要基于Codesys开发的都比较好用&#xff0c;只是使用底层芯片不同&…

国产软件不背黑锅:4款功能强大的黑科技软件,且用且珍惜

国内软件常被冠以“流氓软件、需要额外付费、广告繁多”等负面标签&#xff0c;但实际上&#xff0c;其中不乏一些小众却功能强大、用户体验极佳的软件。 布丁扫描——免费专业的扫描APP&#xff08;安卓、ios&#xff09; 布丁扫描&#xff0c;无疑是我今年的最爱&#xff0…

服务器还在长期泄密,保护数据IPSSL证书必不可少

IP SSL&#xff0c;或称为安全套接层协议&#xff08;Secure Sockets Layer&#xff09;&#xff0c;是一种用于在互联网上进行通信加密的技术标准&#xff0c;它通过为数据提供加密服务&#xff0c;确保了数据在传输过程中的安全与完整。其工作方式是在客户端和服务器之间建立…

你们项目日志是如何处理的???

ELK日志采集系统 1.什么是ELK ELK 是一套流行的数据搜索、分析和可视化解决方案&#xff0c;由三个开源项目组成&#xff0c;每个项目的首字母合起来形成了“ELK”这一术语&#xff1a; Elasticsearch (ES): Elasticsearch 是一个基于 Apache Lucene 构建的分布式、实时搜索与…

Java 字符

Java 字符 Java教程 - Java字符 在Java中&#xff0c;char存储字符。Java使用Unicode来表示字符。Unicode可以表示在所有人类语言中找到的所有字符。 Java char是16位类型。 字符的范围是 0 到 65,536 。没有负字符。 Char文字 Java中的字符是Unicode字符集的索引。字符表…

OpenHarmony实战开发-减小应用包大小。

简介 减小应用包大小是提升应用下载、安装体验的重要方式之一。通过压缩、精简或者复用应用中的代码或资源&#xff0c;可以有效降低应用的大小&#xff0c;提升应用下载和安装速度&#xff0c;减少系统空间占用。 开发者可以参考下面三种方法减小应用包大小&#xff1a; 配…

介绍TCP三次握手、传输数据、四次挥手标志为确认号变化规律

TCP协议的三次握手是一个关键过程&#xff0c;用于在客户端和服务器之间建立可靠的连接。以下是三次握手的详细过程&#xff0c;包括标志位、序列号以及ACK的变化规律&#xff1a; 第一次握手&#xff1a; 客户端&#xff1a; 标志位&#xff1a;SYN1&#xff08;表示请求建立…

【行为型模型】迭代器模式

一、迭代器模式概述 迭代器模式定义&#xff1a;提供一种方法顺序访问一个聚合对象中的各个元素&#xff0c;而又不暴露其内部的表示。把游走的任务放在送代器上&#xff0c;而不是聚合上。这样简化了聚含的接口和实现,也让责任各得其所。(对象行为型) 迭代器模式的优缺点&…

数据结构之顺序表的实现(C语言版)

Hello, 大家好&#xff0c;我是一代&#xff0c;今天给大家带来有关顺序表的有关知识 所属专栏&#xff1a;数据结构 创作不易&#xff0c;望得到各位佬们的互三呦 一.前言 1.首先在讲顺序表之前我们先来了解什么是数据结构 数据结构是由“数据”和“结构”两词组合⽽来。 什…

C语言—深度剖析函数指针,函数指针数组

我们先来看一段代码 #include <stdio.h> void test() {printf("hehe\n"); } int main() {printf("%p\n", test);printf("%p\n", &test);return 0; }输出的是两个地址&#xff0c;这两个地址是 test 函数的地址。 那我们的函数的地址…

Electron 30.0.0 发布,升级 Node 和 V8 引擎

近日&#xff0c;Electron 30.0.0 正式发布&#xff01;你可以通过 npm install electronlatest 进行安装&#xff0c;或者从 Electron 的发布网站下载&#xff0c;继续阅读了解此版本的详细信息。 &#x1f525; 主要更新 Windows 上支持 ASAR 完整性融合。如果未正确配置&am…

软件测试——Postman Script脚本功能

Postman作为软件测试里一款非常流行的调试工具&#xff0c;给我们提供了一个执行JavaScript脚本的环境&#xff0c;所以我们可以使用js语言编写脚本来解决一些接口自动化的问题&#xff0c;比如接口依赖、接口断言等等。Postman有Pre-RequestScript和Tests两个编写js脚本的模块…

Jenkins 哲学 - 插件初始化安装失败

到Jenkins官网查找最新的LST版本 最后的版本号一定要带&#xff0c;指定下载具体的版本号 docker pull jenkins/jenkins:2.426.1 自定义挂载目录&#xff0c;修改权限 mkdir /jenkins/jenkins_homechmod 777 /data/jenkins

Ansible安装基本原理及操作(初识)

作者主页&#xff1a;点击&#xff01; Ansible专栏&#xff1a;点击&#xff01; 创作时间&#xff1a;2024年4月23日15点18分 Ansible 是一款功能强大且易于使用的IT自动化工具&#xff0c;可用于配置管理、应用程序部署和云端管理。它使用无代理模式&#xff08;agentles…

谈谈mysql中的各个关键字

1.为什么学习mysql mysql是当今最主流且开放源码的关系型数据库&#xff0c;开发者为瑞典 MySQL AB 公司。目前 MySQL 被广泛地应用在 Internet 上的中小型网站中。由于其体积小、速度快、总体拥有成本低&#xff0c;尤其是开放源码这一特点&#xff0c;许多中小型网站为了降低…

【C语言】每日一题,快速提升(10)!

&#x1f525;博客主页&#x1f525;&#xff1a;【 坊钰_CSDN博客 】 欢迎各位点赞&#x1f44d;评论✍收藏⭐ 题目&#xff1a;圣诞树 输入&#xff1a; 1输出&#xff1a; * * * * * **说明&#xff1a; 输入&#xff1a; 2输出&#xff1a; * * * * * * * …

C++:基础语法

一、命名空间 在C/C中&#xff0c;变量、函数和后面要学到的类都是大量存在的&#xff0c;这些变量、函数和类的名称将都存在于全局作用域中&#xff0c;可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化&#xff0c; 以避免命名冲突或名字污染&#xff0c;n…

【C++】一篇文章带你深入了解list

目录 一、list的介绍二、 标准库中的list类2.1 list的常见接口说明2.1.1 list对象的常见构造2.1.1.1 [无参构造函数](https://legacy.cplusplus.com/reference/list/list/list/)2.1.1.2 [有参构造函数(构造并初始化n个val)](https://legacy.cplusplus.com/reference/list/list/…