mysql中的Redo log

news2025/1/8 4:16:16

目录标题

  • 前言
    • redolog保证持久性
    • redolog工作过程
  • redo log中的WAL(先写日志,再写磁盘【写入redo log file】)
  • 刷盘策略 重要参数innodb_flush_log_at_trx_commit
    • 如何选择
  • Redo log file日志文件
    • 日志文件组
    • redo log刷盘与数据页刷盘
    • redo log何时刷入磁盘
      • 正常关闭服务器时
      • 事务提交时(innodb_flush_log_at_trx_commit = 1 )
      • 后台线程输入(innodb_flush_log_at_trx_commit = 0 or innodb_flush_log_at_trx_commit = 2 )
      • redo log buffer 空间不足时
      • 触发checkpoint规则
  • 一条更新语句的执行步骤
    • Mysql的两阶段提交
  • 为什么要引入redolog
    • 修改数据量小,每次写入都写入磁盘造成资源浪费
    • 直接写回磁盘,是随机IO,效率低下

前言

redolog保证持久性

我们都知道,事务的四大特性里面有一个是 持久性 ,具体来说就是只要事务提交成功,那么对数据库做的修改就被永久保存下来了,不可能因为任何原因再回到原来的状态
那么 mysql是如何保证一致性的呢?最简单的做法是在每次事务提交的时候,将该事务涉及修改的数据页全部刷新到磁盘中。但是这么做会有严重的性能问题,主要体现在两个方面:
因为 Innodb 是以 页 为单位进行磁盘交互的,而一个事务很可能只修改一个数据页里面的几个字节,这个时候将完整的数据页刷到磁盘的话,太浪费资源了!
一个事务可能涉及修改多个数据页,并且这些数据页在物理上并不连续,使用随机IO写入性能太差!
因此 mysql 设计了 redo log , 具体来说就是只记录事务对数据页做了哪些修改,这样就能完美地解决性能问题了(相对而言文件更小并且是顺序IO)。

redolog工作过程

redo log(重做日志)是InnoDB存储引擎独有的,它让MySQL拥有了崩溃恢复能力。
比如MySQL实例挂了或宕机了,重启时,InnoDB存储引擎会使用redo log恢复数据,保证数据的持久性与完整性。
在这里插入图片描述
MySQL中数据是以页为单位,你查询一条记录,会从硬盘把一页的数据加载出来,加载出来的数据叫数据页,会放入到Buffer Pool中。
后续查询都是先从Buffer Pool中找,没有命中再去硬盘加载,减少硬盘IO开销,提升性能。
更新数据,也是先从Buffer Pool查找要更新的数据,就直接在Buffer Pool里更新;如果没有找到要更新的数据,则从硬盘加载到Buffer Pool。
然后会把“在某个数据页上做了什么修改”记录到重做日志缓存(redo log buffer)里,接着刷盘到redo log文件里。
在这里插入图片描述
理想情况,事务一提交就会进行刷盘操作,但实际上,刷盘的时机是根据策略来进行的。

每条redo记录由“表空间号+数据页号+偏移量+修改数据长度+具体修改的数据”组成

redo log中的WAL(先写日志,再写磁盘【写入redo log file】)

redo log 包括两部分:一个是内存中的日志缓冲( redo log buffer ),另一个是磁盘上的日志文件( redo log file )。 mysql 每执行一条 DML 语句,先将记录写入 redo log buffer ,后续某个时间点再一次性将多个操作记录写到 redo log file 。这种 先写日志,再写磁盘 的技术就是 MySQL里经常说到的 WAL(Write-Ahead Logging) 技术。

在计算机操作系统中,用户空间( user space )下的缓冲区数据一般情况下是无法直接写入磁盘的,中间必须经过操作系统内核空间( kernel space )缓冲区( OS Buffer )。因此, redo log buffer 写入redo log file 实际上是先写入 OS Buffer ,然后再通过系统调用fsync()将其刷到redo log file中,过程如下:
在这里插入图片描述

刷盘策略 重要参数innodb_flush_log_at_trx_commit

mysql 支持三种将 redo log buffer 写入 redo log file 的时机,可以通过 innodb_flush_log_at_trx_commit 参数配置,各参数值含义如下:

innodb_flush_log_at_trx_commit=0 (延迟写)事务提交时不会将 redo log buffer 中日志写入到 os buffer ,而是InnoDB存储引擎后台有一个线程,每隔1秒,就会把redo log buffer中的内容写入到os buffer 。并调用 fsync() 写入到 redo log file 中。也就是说设置为0时是(大约)每秒刷新写入到磁盘中的,当系统崩溃,会丢失1秒钟的数据。
在这里插入图片描述

innodb_flush_log_at_trx_commit=1(实时写,实时刷) 表示事务每次提交都会将 redo log buffer 中的日志写入 os buffer 并调用 fsync() 刷到 redo log file 中。只要事务提交成功,那么 redo log 就必然在磁盘里了。这种方式即使系统崩溃也不会丢失任何数据,但是因为每次提交都写入磁盘,IO的性能较差。
innodb_flush_log_at_trx_commit=2(实时写,延迟刷) 表示提交事务的时候,都仅写入到 os buffer ,然后是每秒调用 fsync() 将 os buffer 中的日志写入到 redo log file 。
在这里插入图片描述

总结:
0表示每秒将"log buffer"同步到"os buffer"且从"os buffer"刷到磁盘日志文件中。
1表示每事务提交都将"log buffer"同步到"os buffer"且从"os buffer"刷到磁盘日志文件中。
2表示每事务提交都将"log buffer"同步到"os buffer"但每秒才从"os buffer"刷到磁盘日志文件中。

如何选择

对数据丢失很敏感,设置为1,保证写到磁盘上。但性能较差。
对数据不太敏感,设置为0或2,性能较好。但可能会丢失1秒的数据。

Redo log file日志文件

MySQL默认目录中,有两个文件ib_logfile0和ib_logfile1,每次刷盘都是将数据刷新到这两个文件内
Redo日志文件有很多个,一般以日志文件组的形式出现,文件统一命名,格式是ib_logfile+数字,从0开始
日志文件组中每个文件大小相同
每次写入从0开始,然后是1,2,3…
在这里插入图片描述

日志文件组

硬盘上存储的redo log日志文件不只一个,而是以一个日志文件组的形式出现的,每个的redo日志文件大小都是一样的。
比如可以配置为一组4个文件,每个文件的大小是1GB,整个redo log日志文件组可以记录4G的内容。
它采用的是环形数组形式,从头开始写,写到末尾又回到头循环写,如下图所示。
在这里插入图片描述

redo log刷盘与数据页刷盘

同时我们很容易得知, 在innodb中,既有 redo log 需要刷盘,还有 数据页 也需要刷盘, redo log 存在的意义主要就是降低对 数据页 刷盘的要求 。
在上图中,write pos表示 redo log 当前记录的 LSN(逻辑序列号)位置, check point 表示 数据页更改记录刷盘后对应 redo log 所处的 LSN (逻辑序列号)位置。
write poscheck point 之间的部分是 redo log 空着的部分,用于记录新的记录;check pointwrite pos 之间是 redo log 待落盘的数据页更改记录。当write pos追上check point时,会先推动 check point 向前移动,空出位置再记录新的日志。

启动 innodb 的时候,不管上次是正常关闭还是异常关闭,总是会进行恢复操作。因为 redo log 记录的是数据页的物理变化,因此恢复的时候速度比逻辑日志(如 binlog )要快很多。 重启 innodb 时,首先会检查磁盘中数据页的 LSN ,如果数据页的 LSN 小于日志中的 LSN ,则会从 checkpoint 开始恢复。 还有一种情况,在宕机前正处于checkpoint 的刷盘过程,且数据页的刷盘进度超过了日志页的刷盘进度,此时会出现数据页中记录的 LSN 大于日志中的 LSN ,这时超出日志进度的部分将不会重做,因为这本身就表示已经做过的事情,无需再重做。

redo log何时刷入磁盘

正常关闭服务器时

事务提交时(innodb_flush_log_at_trx_commit = 1 )

在事务提交时,为了保证持久性,会把log buffer中的日志全部刷到磁盘。注意,这时候,除了本事务的,可能还会刷入其它事务的日志。

后台线程输入(innodb_flush_log_at_trx_commit = 0 or innodb_flush_log_at_trx_commit = 2 )

innodb_flush_log_at_trx_commit = 0:每秒写入 os buffer 并调用 fsync() 写入到 redo log file 中
innodb_flush_log_at_trx_commit = 2:每秒调用 fsync() 将 os buffer 中的日志写入到 redo log file 中

redo log buffer 空间不足时

redo log buffer 的大小是有限的,如果不停的往这个有限大小的 log buffer 里塞入日志,很快它就会被填满。如果当前写入 log buffer 的redo 日志量已经占满了 log buffer 总容量的大约一半左右,就需要把这些日志刷新到磁盘上。

触发checkpoint规则

重做日志缓存、重做日志文件都是以块(block)的方式进行保存的,称之为重做日志块(redo log block),块的大小是固定的512字节。我们的redo log它是固定大小的,可以看作是一个逻辑上的 log group,由一定数量的log block 组成。
它的写入方式是从头到尾开始写,写到末尾又回到开头循环写。
其中有两个标记位置:
write pos是当前记录的位置,一边写一边后移,写到第3号文件末尾后就回到0号文件开头。
checkpoint是当前要擦除的位置,也是往后推移并且循环的,擦除记录前要把记录更新到磁盘。
在这里插入图片描述
当write_pos追上checkpoint时,表示redo log日志已经写满。这时候就不能接着往里写数据了,需要执行checkpoint规则腾出可写空间。
所谓的checkpoint规则,就是checkpoint触发后,将buffer中日志页都刷到磁盘。

一条更新语句的执行步骤

在这里插入图片描述

  1. 执行器先找引擎取 ID=2 这一行。ID 是主键,引擎直接用树搜索找到这一行。如果 ID=2这一行所在的数据页本来就在内存中,就直接返回给执行器;否则,需要先从磁盘读入内存,然后再返回。
  2. 执行器拿到引擎给的行数据,把这个值加上1,比如原来是 N,现在就是 N+1,得到新的一行数据,再调用引擎接口写入这行新数据。
  3. 引擎将这行新数据更新到内存中,同时将这个更新操作记录到 redo log 里面,此时 redo log 处于 prepare状态。然后告知执行器执行完成了,随时可以提交事务。 【写入 redo log(处于 prepare 阶段)】
  4. 执行器生成这个操作的 binlog,并把 binlog 写入磁盘。【写 binlog】
  5. 执行器调用引擎的提交事务接口,引擎把刚刚写入的 redo log 改成提交(commit)状态,更新完成。【提交事务(处于 commit 状态)】

Mysql的两阶段提交

在这里插入图片描述

上面的流程采用了两阶段提交,那为什么要采用两阶段提交呢?是为了让 binlog 和 redo log 之间的逻辑一致。

我们假设一下上面的 update 语句在执行的每个时刻,MySQL 崩溃了,看一下两个日志间的逻辑是如何保持一致的。
假设在步骤3前,MySQL崩溃重启,那么事务提交失败,不会影响数据。虽然更新了内存,但崩溃后,内存会丢失。
假设在步骤3完成后崩溃,此时已经写入 redo log 了,重启后,发现 redo log 处于 prepare 阶段,就不恢复。
假设在步骤4完成后崩溃,此时已经写入 binlog 了,重启后,发现 binlog 已经写入了,就把对应的 redo log 改为 commit 状态。
这样就能保证 redo log 和 binlog 的逻辑一致性。

两阶段提交是跨系统维持数据逻辑一致性时常用的一个方案。
在这里插入图片描述

为什么要引入redolog

在这里插入图片描述

修改数据量小,每次写入都写入磁盘造成资源浪费

innodb是以页为单位来管理存储空间的(数据页大小是16KB),任何的增删改差操作最终都会操作完整的一个页,会将整个页加载到buffer pool中,然后对需要修改的记录进行修改,而且仅仅修改了一条记录,刷新一个完整的数据页到磁盘的话过于浪费了

直接写回磁盘,是随机IO,效率低下

数据页刷盘是随机写,因为一个数据页对应的位置可能在硬盘文件的随机位置,所以性能是很差。
如果是写redo log,一行记录可能就占几十Byte,只包含表空间号、数据页号、磁盘文件偏移 量、更新值,同时redo log是循环写入固定的文件,是顺序写入磁盘的,所以刷盘速度很快。

所以用redo log形式记录修改内容,性能会远远超过刷数据页的方式,这也让数据库的并发能力更强。

视频链接:https://www.bilibili.com/video/BV1Pv411h7Ep
文章来源:https://javaguide.cn/database/mysql/mysql-logs.html#redo-log
日志文件:https://blog.csdn.net/Merciful_Lion/article/details/124715392
https://blog.csdn.net/weixin_40449300/article/details/117927295
https://www.cnblogs.com/liang24/p/14089065.html
https://blog.csdn.net/weixin_43213517/article/details/117457184
https://www.zhihu.com/question/486105337/answer/2538190061

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

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

相关文章

Vue CLI Todo-List案例

3.7. Todo-List 案例 组件化编码流程 拆分静态组件:组件要按照功能点拆分,命名不要与html元素冲突实现动态组件:考虑好数据的存放位置,数据是一个组件在用,还是一些组件在用 一个组件在用:放在组件自身即…

Cesium入门之八:Cesium加载矢量数据

目录 一、什么是矢量数据二、Cesium支持的矢量数据格式KML格式KmlDataSource CZML格式CzmlDataSource GeoJSON格式GeoJsonDataSource 三、Cesium加载GeoJSON数据格式的中国地图示例 一、什么是矢量数据 矢量数据是用于描述地理空间几何特征的一类基于向量的地理信息数据&#…

RabbitMQ的几种通讯方式及其代码示例

文章目录 一、引言二、RabbitMQ介绍三、RabbitMQ安装四、RabbitMQ架构4.1 官方的简单架构图4.2 RabbitMQ的完整架构图4.3 RabbitMQ 通讯方式4.4 Hello-World案例演示4.5 基本原理 五、SpringBoot整合RabbitMQ的使用5.1 导入依赖5.2 在application.properties中增加配置5.3 Hell…

前端学习--Vue(2)

一、Vue简介 1.1 概念 Vue是一套用于构建用户界面的前端框架 框架:现成解决方案,遵守规范去编写业务功能 指令、组件、路由、Vuex、vue组件库 1.2 特性 数据驱动视图 vue连接页面结构和数据,监听数据变化,自动渲染页面结构…

Vue--》Vue 3 路由进阶——从基础到高级的完整指南

目录 Vue3中路由讲解与使用 路由的安装与使用 路由模式的使用 编程式路由导航 路由传参 嵌套路由 命名视图 重定向与别名 Vue3中路由讲解与使用 Vue 路由是 Vue.js 框架提供的一种机制,它用于管理网页上内容的导航。Vue 路由可以让我们在不刷新页面的情况下…

【ChatGPT】通过 ChatGPT 用文字描述来绘制插画

点击上方“独立开发者杂谈” 喜欢本文,请置顶或星标 使用文字描述绘制插画具有以下好处 无需绘画技巧,体验与AI结合,创意灵活性,节省时间。 使用 Figma 工具 Figma (https://www.figma.com)是一款流行的设计…

Linux:iptables防火墙

Linux:iptables防火墙 一、iptables防火墙概述1.1 iptables防火墙1.2 netfilter/iptables 关系 二、Linux防火墙基础2.1 iptables的表、链结构2.2 数据包控制的匹配流程 三、编写防火墙规则3.1 基本语法、控制类型3.2 添加、查看、删除规则等3.3 规则的匹配条件3.3.…

黑马Redis原理篇

黑马Redis原理篇 1、数据结构1.1、动态字符串SDS1.2、IntSet1.3、Dict1.4、ZipList1.5、QuickList1.6、SkipList1.7、RedisObject1.8、五种数据结构1. String(小EMBSTR,大RAW (SDS),少量整数INT)2. List(Redis3.2之后使用QuickList实现&#…

CSDN周赛52期及53期浅析

好久没写题解了,没办法,C站的题目更新的速度太慢了,重复考过去的老题已经不能再进步了。52期还混了个名次,总要写篇文章完成一下任务。而53期就惨了去了,三道选择题全蒙错了。 反正我个人觉得在现在C站的OJ环境里考选…

手撸鉴权系统——SpringBoot2+Vue2(一定惊喜满满,万字长文)

初衷: 一直不太理解整个前后端的鉴权,跨域等问题,抽空两个晚上整理出万字文章,也是对于自己的一个交代,现在共享出来,希望大家也能受益,将使用过程在这里一一详述,还是多说一句&…

【图论(1)】图的存储、遍历与拓扑排序

5月16-5月18日学习内容 文章目录 一、图是什么二、图的存储1、直接存边法2、邻接矩阵法3、邻接表法4、链式前向星时间复杂度分析 三、图的遍历DFSBFS 四、拓扑排序(今天实在没时间写了,明天写) 一、图是什么 这是oi.wiki给的定义 简而言之…

ENVI制图——土地利用专题图

ENVI制图 0 前言1 数据准备2 数据预处理2.1 先在arcmap中把数据导出为tif格式,然后加入envi(别问我为什么要先用arcmap处理,因为这是envi制图教程 :( )2.2 直接把tif格式的数据拖进envi,此时看不到数据类别&#xff0c…

低代码+AI:助力企业数字化转型,揭示未来发展趋势

问个问题:你有没有亲自去了解、使用近期爆火的生成式人工智能——ChatGPT? 如果答案是否定的,作为企业数字化转型的前沿先锋小Z,建议你一定要去亲自尝试它。虽然人工智能技术已经发展多年,但OpenAI所发布的ChatGPT&…

瑞吉外卖 - 新增菜品功能(16)

某马瑞吉外卖单体架构项目完整开发文档,基于 Spring Boot 2.7.11 JDK 11。预计 5 月 20 日前更新完成,有需要的胖友记得一键三连,关注主页 “瑞吉外卖” 专栏获取最新文章。 相关资料:https://pan.baidu.com/s/1rO1Vytcp67mcw-PD…

(十)Spring源码阅读:finishBeanFactoryInitialization方法

一、概述 该方法是实例化bean的主要方法,它实现的主要流程如下图所示。 这是方法执行的主要流程图。 具体执行流程如下图,我们将按照具体执行流程一个个介绍具体的方法。 二、主要方法 finishBeanFactoryInitialization内部调用了getBean方法。 getBea…

AIGC+机器人=具身智能?硅谷最酷的两个男人不谋而合预演“下个浪潮”

收集整理|小鱼新的AI题材层出不穷,这次轮到“机器人AI"融合而成的具身智能概念。 “硅谷钢铁侠"马斯克和热爱黑色皮衣的"显卡教父”黄仁勋均作出积极表态,可谓不谋而合。 当地时间5月16日,特斯拉2023年年度股东大会召开&…

unity DoTween动画插件的使用(最全)

DOTween是最常用的动画插件之一,比使用Unity自带脚本写动画,方便很多。 插件获取 untiy商店插件地址 https://assetstore.unity.com/packages/tools/animation/dotween-hotween-v2-27676 DOTween商城地址,开发文档 http://dotween.demigiant.com 导入和设置 DOTween首次使…

离散数学_九章:关系 —— 拓扑排序

拓扑排序 背景知识相容一个引理什么是拓扑排序 拓扑排序算法(伪代码)几个实例例1例2 假设一个项目由20个不同的任务构成。某些任务只能在其他任务结束之后完成。如何找到关于这些任务的顺序? 为了对这个问题建模,我们在任务的集合…

mysql强制修改mysql数据库密码(无需原密码)

1.创建新记事本new_password.txt 定位到记事本绝对路径,我直接放桌面 C:\Users\bao123\Desktop 为用户为 root 新密码 123456为例 ALTER user rootlocalhost identified by 123456; 为用户为 mytest 新密码 88888888为例 ALTER user mytestlocalhost identifi…

opencv_c++学习(十三)

一、创建滑动条 createTrackbar(const String & trackbarname, const String & winname, int* value, int count, onChange , TrackbarCallback 0, void * userdata 0)trackbarname:滑动条的名称。 winname:创建滑动条窗口的名称。 value:指向整数变量的指针&#xff0…