【MySQL进阶之路 | 高级篇】简谈redo日志

news2025/2/23 17:37:45

1. 前言

事务有四种特性:原子性,一致性,隔离性和持久性。那么事务的四种特性到底是基于什么机制实现呢?

  • 事务的隔离性由锁机制实现。
  • 而事务的原子性,一致性和持久性由事务的redo日志和undo日志来保证。

REDO LOG称为重做日志,提供再写入操作,恢复提交事务修改的页操作,用来保证事务的持久性。

UNDO LOG称为回滚日志,回滚行记录到某个特定版本,用来保证事务的原子性,一致性。

REDO和UNDO都可以视为一种恢复操作但是

  • redo log:是存储引擎层生成的日志,记录的是物理级别上的页修改操作,比如页号xxx,偏移量yyy写入了'zzz'数据。主要是为了保证数据的可靠性。
  • undo log:是存储引擎层生成的日志,记录的是逻辑操作的日志,比如对某一行数据进行了INSERT语句操作,那么undo log就记录一条与之相反的DELETE操作。主要用于事务的回滚(undo log记录的是每个修改操作的逆操作)和一致性非锁定读(undo log回滚行记录到某种特定的版本--MVCC,即多版本并发控制)。

2. redo日志

InnoDB存储引擎是以页为单位来管理存储空间的。在真正访问到页面之前,需要把在磁盘上的页缓存到内存中的Buffer Pool之后才可以访问。所有的变更都必须先更新缓冲池中的数据,然后缓冲池的脏页会会以一定频率被刷入磁盘(checkPoint机制),通过缓冲池来优化CPU和磁盘之间的鸿沟,这样就可以保证整体的性能不会下降的太快。

2.1 为什么需要REDO日志

一方面,缓冲池可以帮助我们消除CPU和磁盘之间的鸿沟,checkPoint机制可以保证数据的最终落盘,然而由于checkPoint机制并不是每次变更的时候就触发的,而是master线程隔一段时间去处理的。所以最坏的情况就是事务提交后,刚写完缓冲池,数据库宕机,那么这段数据就是丢失的,无法恢复。

另一方面,事务包含持久性的特性,就是说对于一个已经提交的事务,在事务提交后即使系统发生了崩溃,这个事务对数据库中所作的更改也不能丢失。

那么如何保证这个持久性呢?一个简单的做法:在事务提交完成之前把事务所修改的所有页面都刷新到磁盘上,但这个简单粗暴的做法有一些问题:

  • 修改量与刷新磁盘工作量严重不成比例:有时候我们仅仅修改了某个页面的一个字节,但是我们知道在InnoDB中是以页为单位来进行磁盘IO的,页就是说我们在该事务提交时不得不将一个完整的页面从内存中刷新到磁盘上,我们又知道一个页面的默认是16KB大小,只修改一个字节就要刷新16KB的数据到内存上显然是大题小作。
  • 随机IO刷新较慢:一个事务可能包含很多语句,即使是一条语句也可能修改很多页面,假如该事务修改的这些页面可能并不相邻,这就意味着在将某个事务修改的buffer pool中的页面刷新到磁盘上时,需要进行很多的随机IO,随机IO比顺序IO要慢。

另一个解决的思路:我们只是想让已经提交了的事务对数据库中数据所做的修改永远生效,即使后来系统崩溃,在重启后也能把这种修改恢复出来。所以我们其实也没必要在每次事务提交时就把改事务在内存中修改的全部页面刷新到磁盘上,只需要把修改了哪些东西记录一下就好了。比如,某个事物将系统表空间中第10号页面中偏移量为100处的那个字节的值1改成值2,我们只需要记录一下:将第0号表空间的第10个页面的偏移量为100处的值更新为2。

InnoDB引擎的事物采用了WAL技术(Write-Ahead Logging),这种技术的思想就是先写日志,再写磁盘,只有日志写入成功,才算事务提交成功,这里的日志就是redo log。当发生宕机且数据未刷到磁盘的时候,可以通过redo log来恢复,保证ACID中的D,这就是redo log的作用。

94f5c0a8402b4b8e907f06ac69a55ec9.png

2.2 REDO日志的好处,特性

1). 好处

  • redo日志降低了刷盘频率。
  • redo日志占用的空间非常小。

存储表空间ID,页号,偏移量以及需要更新的值,所需的存储空间是很小的,刷盘快。

2). 特点

  • redo日志是顺序写入磁盘的。

在执行事务的过程,每执行一条语句,就可能产生若干条redo日志,这些日志是按照产生的顺序写入磁盘的。也就是使用顺序IO,效率比随机IO快。

  • 事务执行过程中,redo log不断记录

redo log跟bin log的区别,redo log是存储引擎层产生的,而bin log是数据库层产生的。假设一个事务,对表做10万行记录插入,在这个过程中,一直不断的往redo log顺序记录,而bin log不会记录,直到这个事务被提交,才会一次写入到bin log文件中。

2.3 redo的组成

redo log可以简单分为以下两个部分:

  • 重做日志的缓冲(redo log buffer),保存在内存中,是易失的。

在服务器启动时就向操作系统申请了一大片空间称之为redo log buffer的连续内存空间,翻译成中文就是redo日志缓冲区。这片内存空间被划分为若干个连续的redo log block。一个redo log block占用512字节大小。66d574614d5a4d8ebc42be1ff8e13d29.png

参数设置:innodb_log_buffer_size:默认大小16M,最大值是4096M,最小为1M。

  • 重做日志文件(redo log file),保存在硬盘中,是持久的。ib_logfile0和ib_logfile1是REDO日志。

2.4 redo的整体流程

以一个更新事务为例,redo log流转流程,如下:

01921766c8524159be3360047c2a4344.png

  1. 先将原始数据从磁盘中读入内存中来,修改数据的内存拷贝。

  2. 生成一条重做日志并写入redo log buffer,记录的是数据被修改后的值。

  3. 当事务commit时,将redo log buffer中的内容刷新到redo log file,对redo log file采用追加写的方式。

  4. 定期将内存中修改的数据刷新到磁盘中。

2.5 redo的刷盘策略

注意,redo log buffer刷盘到redo log file的过程并不是真正的刷到磁盘中去,只是刷入到文件系统缓存(page cache)中去(这是现代操作系统为了提高文件写入效率做的一个优化),真正的写入会交给系统自己来决定(比如page cache足够大了)。那么对于InnoDB来说就存在一个问题,如果 交给系统来同步,同样如果系统宕机了,那么数据也丢失了。

针对这种情况,InnoDB给出了innodb_flush_log_at_trx_commit参数,该参数控制commit提交事务时,如何将redo log buffer中的日志刷新到redo log file中。它支持三种策略:

  • 设置为0:表示每次事务提交时不进行刷盘操作,(xito默认master thread每隔1s进行一次重做日志的同步)
  • 设置为1:表示每次事务提交的时都将进行同步,刷盘操作(默认值)
  • 设置为2:表示每次事务提交时都只把redo log buffer内容写入到page cache中,不进行同步。由os自己决定什么时候同步到磁盘文件。

查看变量:show variables like 'innodb_flush_log_at_trx_commit';

另外,InnoDB存储引擎有一个后台线程,每隔1s,就会把redo log buffer中的内容写到文件系统缓存(page cache),然后调用刷盘操作。

2.6 不同刷盘策略演示

1). innodb_flush_log_at_trx_commit=1

c04bc8f921104613be49657a3da62e97.png

  • 这种情况只要是1,redo log记录就一定在硬盘里,不会有任何数据的丢失。
  • 如果事务执行期间MySQL挂了或宕机,在部分日志丢了,但事务并没有提交,所以日志丢了也不会有损失。可以保证ACID的D,数据绝对不会丢失,但是效率最差的。
  • 建议使用默认值,虽然操作系统宕机的概率理论小于数据库宕机的概率,但是一般使用的事务,那么数据库的安全相对来说重要一些。

2). innodb_flush_log_at_trx_commit=2;

9514956752a14f37ac86f4b6dd4b0470.png

当innodb_flush_log_at_trx_commit=2时,只要事务提交成功,redo log buffer的内容只是写入到文系统缓存(page cache)。如果仅仅是MySQL挂了不会有任何数据的丢失,但是操作系统宕机肯恩那个会有1s数据的丢失。这种情况 无法满足ACID中的D。但是数值2肯定是效率最高的。

3). innodb_flush_log_at_trx_commit=0

当innodb_flush_log_at_trx_commit=0时,master thread中每一秒进行一个重做日志的fsync的操作,因此实例crash最多丢失1s内的事务。(master thread是负责将缓冲池中的数据异步刷新到磁盘,保证数据的一致性)。

数值为0的话,是一种折中的做法,它的IO效率理论上高于1的,低于2的。这种策略也有丢失数据的风险,也无法保证D。

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

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

相关文章

Mysql或MariaDB数据库的用户与授权操作——实操保姆级教程

一、问题描述 在日常的工作中,我们需要给不同角色的人员创建不同的账号,他们各自可访问的数据库或权限不一样,这时就需要创建用户和赋予不同的权限内容了。 二、问题分析 1、创建不同的角色账号; 2、给这些账号授予各自可访问数据库的权限。 三、实现方法 Centos8安装…

多层感知机(神经网络)

目录 一、感知机(逻辑回归、二分类)定义:二、感知机不能解决XOR问题:三、多层感知机定义:四、训练过程:1.参数维度:2.常用激活函数:2.1Sigmoid激活函数:2.2Tanh激活函数&…

排序XXXXXXXXX

信息学奥赛|常见排序算法总结(C+) - 腾讯云开发者社区-腾讯云 (tencent.com) https://cloud.tencent.com/developer/news/975232 常用序号层级排序 一、序号 序号Sequence Number,有顺序的号码,如数字序号…

数据结构: 链表回文结构/分割链表题解

目录 1.链表的回文结构 分析 代码 2.链表分割 ​编辑分析 代码 1.链表的回文结构 分析 这道题的难点是空间复杂度为O(1) 结合逆置链表找到链表的中间节点就可以解决了。 先找到链表的中间节点,再对中间节点的下一个节点进行逆置&…

代码随想录打卡第三十五天

代码随想录–动态规划部分 day 35 动态规划第三天 文章目录 代码随想录--动态规划部分一、卡码网46--携带研究材料二、力扣416--分割等和子集 一、卡码网46–携带研究材料 代码随想录题目链接:代码随想录 小明是一位科学家,他需要参加一场重要的国际科…

Leetcode—297. 二叉树的序列化与反序列化【困难】

2024每日刷题(148) Leetcode—297. 二叉树的序列化与反序列化 实现代码 /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode(int x) : val(x), left(NULL), right(…

学习记录——day18 数据结构 树

树的存储 1、顺序存储 对于普通的二叉树,不适合存储普通的二叉树顶序存储,一般用于存储完全二叉树而言,如果使用顺序存储,会浪费大量的存储空间,因为需要给没有节点的位置留出空间,以便于后期的插入。 所以…

Springboot循环依赖的解决方式

Springboot循环依赖的解决方式 起因原因解决方案配置文件解决使用工具类获取bean还有一种我设想的方案 起因 今天重构代码时,发现之前的代码结构完全混乱,没有按照MVC分层思想去编写,很多业务逻辑写在了controller中,导致引用的很…

WebStorm中在Terminal终端运行脚本时报错无法加载文件进行数字签名。无法在当前系统上运行该脚本。有关运行脚本和设置执行策略的详细信息,请参阅

错误再现 我们今天要 在webstorm用终端运行脚本 目的是下一个openAPI的 前端请求代码生成的模块 我们首先从github上查看官方文档 我们根据文档修改 放到webstorm终端里执行 报错 openapi : 无法加载文件 C:\Users\ZDY\Desktop\多多oj\dduoj\node_modules\.bin\openapi.p…

LabVIEW多种测试仪器集成控制系统

在现代工业生产与科研领域,对测试设备的需求日益增长。传统的手动操作测试不仅效率低下,而且易出错。本项目通过集成控制系统,实现了自动化控制,降低操作复杂度和错误率,提高生产和研究效率。 系统组成与硬件选择 系…

逆向软件更新 x64dbg 加入 windows api 函数设断点插件

百度网盘链接:https://pan.baidu.com/s/1VaGP0rN8uTf8j_SzBgaEPg?pwd6666

Docker容器限制内存与CPU使用

文章目录 Docker 容器限制内存与 CPU 使用内存限额内存限制命令举例使用 `nginx` 镜像学习内存分配只指定 `-m` 参数的情况CPU 限制命令举例验证资源使用Docker 容器限制内存与 CPU 使用 在生产环境中,为了保证服务器不因某一个软件导致服务器资源耗尽,我们会限制软件的资源…

用uniapp 及socket.io做一个简单聊天app 2

在这里只有群聊,二个好友聊天,可以认为是建了一个二人的群聊。 const express require(express); const http require(http); const socketIo require(socket.io); const cors require(cors); // 引入 cors 中间件const app express(); const serv…

学术研讨 | 区块链治理与应用创新研讨会顺利召开

学术研讨 近日,国家区块链技术创新中心组织,长安链开源社区支持的“区块链治理与应用创新研讨会”顺利召开,会议围绕区块链治理全球发展现状、研究基础、发展趋势以及区块链行业应用创新展开研讨。北京大学陈钟教授做了“区块链治理与应用创…

我们的人生,向阳而生,去更远的地方,见更亮的光

若该文为原创文章,转载请注明原文出处 本文章博客地址:https://hpzwl.blog.csdn.net/article/details/140683410 长沙红胖子Qt(长沙创微智科)博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV…

qt SQLite学习记录

1. 查看qt中数据库的驱动的类型的支持 QStringList drivers QSqlDatabase::drivers();//获取qt中所支持的数据库驱动类型foreach(QString driver,drivers){qDebug()<<driver;}2. Qt SQL 模块包含的主要类的功能介绍 Qt SQL 模块包含了一些主要的类&#xff0c;用于在 …

自动驾驶系统开发与调试:车路云一体化无人驾驶挑战赛参赛体验

点击蓝字 关注我们 在过去的几年里&#xff0c;自动驾驶技术在全球范围内吸引了大量关注。其潜力不仅在于提升行车安全&#xff0c;而且还可以改变我们的出行方式和城市规划&#xff0c;提高交通运输效率。国际汽车工程师学会&#xff08;SAE&#xff09;根据不同自动驾驶程度&…

Linux中,MySQL数据库管理

使用MySQL数据库 查看数据库结构 MySQL是一套数据库管理系统&#xff0c;在每台MySQL服务器中&#xff0c;均支持运行多个数据库&#xff0c;每个数据库相当于一个容器&#xff0c;其中存放着许多表&#xff0c;如图2.1所示。 下面分别介绍查看数据库、表结构的相关操作语句。…

单片机原理及技术(四)—— C51语言程序设计基础(C51编程)

目录 一、C51语言中的数据类型与存储类型 1.1 数据类型 1.2 C51语言的扩展数据类型 1.3 数据存储类型 1.4 数据存储模式 二、C51语言的特殊寄存器及变量定义 2.1 特殊功能寄存器的C51语言定义 2.1.1 使用关键字定义sfr 2.1.2 使用头文件访问SFR 2.1.3 特殊功能寄存器…

《梦醒蝶飞:释放Excel函数与公式的力量》18.1 图表类型与设计

第18章&#xff1a;创建图表和数据可视化 18.1 图表类型与设计 Excel提供了多种图表类型&#xff0c;帮助用户以直观的方式展示数据。选择合适的图表类型和设计可以显著提高数据的可读性和理解度。以下将介绍常见的图表类型及其应用&#xff0c;并通过具体案例进行说明。 18.…