Mysql日志系统-InnoDB引擎层

news2025/2/27 23:00:47

一、redo log日志

接下来的两个日志,是innodb为解决不同问题而引出的两类日志文件。

redo log(重做日志)的设计主要是为了防止因系统崩溃而导致的数据丢失,其实解决因系统崩溃导致数据丢失的思路如下:

1、每次提交事务之前,必须将所有和当前事务相关的【buffer pool中的脏页】刷入磁盘,但是,这个效率比较低,可能会影响主线程的效率,产生用户等待,降低响应速度,因为刷盘是I/O操作,同时一个事务的读写操作也不是顺序读写,是随机I/O。

2、把当前事务中修改的数据内容在日志中记录下来,日志记录是顺序写,性能很高。其实mysql就是这么做的,这个日志被称为redo log。执行事务中,每执行一条语句,就可能有若干redo日志,并按产生的顺序写入磁盘,redo日志占用的空间非常小,当redo log空间满了之后又会从头开始以循环的方式进行覆盖式的写入。

3、需要理解:为什么不直接更新数据,而是记录数据的变化 ?

4、总结:redo log记录的是数据变化的值,保存的数据再内存后修改的值,当系统崩溃后,我们就可以查看redo log有哪些值被修改了但是还没有被刷盘,这样在启动时进行恢复

redo log的格式比较简单,包含一下几个部分:

  • type:该日志的类型,在5.7版本中,大概有53种不同类型的redo log,占用一个字节

  • space id:表空间id

  • page number:页号

  • data:日志数据

1、MTR

在innodb执行任务时,有很多操作,必须具有原子性,我们把这一类操作称之为MIni Transaction。

我们以下边的例子为例:

在我们向B+树中插入一条记录的时候,需要定位这条数据将要插入的【数据页】,因为插入的位置不同,可能会有以下情况:

1、待插入的页拥有【充足的剩余空间】,足以容纳这条数据,那就直接插入就好了,这种情况需要记录一条【MLOG_COMP_REC_INSERT类型】的redo日志就好了,这种情况成为乐观插入。
在这里插入图片描述

2、待插入的页【剩余空间不足】以容纳该条记录,这样就比较麻烦了,必须进行【页分裂】了。必须新建一个页面,将原始页面的数据拷贝一部分到新页面,然后插入数据。这其中对应了好几个操作,必须记录多条rede log,包括申请新的数据页、修改段、区的信息、修改各种链表信息等操作,需要记录的redo log可能就有二三十条,但是本次操作必须是一个【原子性操作】,在记录的过程中,要全部记录,要么全部失败,这种情况就被称之为一个MIni Transaction(最小事务)。

在这里插入图片描述

(1)MTR的按组写入

对于一个【MTR】操作必须是原子的,为了保证原子性,innodb使用了组的形式来记录redo 日志,在恢复时,要么这一组的的日志全部恢复,要么一条也不恢复。innodb使用一条类型为MLO_MULTI_REC_END类型的redo log作为组的结尾标志,在系统崩溃恢复时只有解析到该项日志,才认为解析到了一组完整的redo log,否则直接放弃前边解析的日志。

在这里插入图片描述

(2)单条redolog的标识方法

有些操作只会产生一条redo log,innodb是通过【类型标识】的第一个字符来判断,这个日志是单一日志还是组日志,如下图:

在这里插入图片描述

(3)事务、sql、MTR、redolog的关系如下

  • 一个事务包含一条或多条sql
  • 一条sql包含一个或多个MTR
  • 一个MTR包含一个或多个redo log

2、log buffer

任何可能产生大量I/O的操作,一般情况下都会设计【缓冲层】,mysql启动时也会向操作系统申请一片空间作为redo log的【缓冲区】,innodb使用一个变量buf_free来标记下一条redo log的插入位置(标记偏移量),log buffer会在合适的时机进行刷盘:

  • log buffer空间不足。logbuffer的容量由innodb_log_buffer_size指定,当写入log buffer的日志大于容量的50%,就会进行刷盘。
  • 提交事务时,如果需要实现崩溃恢复,保证数据的持久性,提交事务时必须提交redo log,当然你也可以为了效率不去提交,可以通过修改配置文件设置该项目。
  • 后台有独立线程大约每隔一秒会刷新盘一次。
  • 正常关闭服务器。
  • 做checkpoint时,后边会讲。

有缓冲就可能存在数据不一致,咱们接着往下看。

3、checkpoint

redolog日志文件容量是有限的,需要循环使用,redo log的作用仅仅是为了在崩溃时恢复脏页数据使用的,如果脏页已经刷到磁盘上,其对应的redo log也就没用了,他也就可以被重复利用了。checkpoint的作用就是用来标记哪些旧的redo log可以被覆盖。

我们已经知道,判断redo log占用的磁盘空间是否可以被重新利用的标志就是,对应的脏页有没有被刷新到磁盘。为了实现这个目的,我们需要了解一下下边几个记录值的作用:

(1)lsn

lsn(log sequence number)是一个全局变量。mysql在运行期间,会不断的产生redo log,日志的量会不断增加,innodb使用lsn来记录当前总计写入的日志量,lsn的初始值不是0,而是8704,原因未知。系统在记录lsn时是按照【偏移量】不断累加的。lsn的值越小说明redo log产生的越早。

每一组redo log都有一个唯一的lsn值和他对应,你可以理解为lsn是redo log的年龄。

(2)flush_to_disk_lsn

flush_to_disk_lsn也是一个全局变量,表示已经刷入磁盘的redo log的量,他小于等于lsn,举个例子:

1、将redo log写入log buffer,lsn增加,假如:8704+1024 = 9728,此时flush_to_disk_lsn不变。

2、刷如512字节到磁盘,此时flush_to_disk_lsn=8704+512=9256。

如果两者数据相同,说明已经全部刷盘。

(3)flush链中的lsn

其实要保证数据不丢失,核心的工作是要将buffer pool中的脏页进行刷盘,但是刷盘工作比较损耗性能,需要独立的线程在后台静默操作。

回顾一下flush链,当第一次修改某个已经加载到buffer pool中的页面时,他会变成【脏页】,会把他放置在flush链表的头部,flush链表是按照第一次修改的时间排序的。再第一次修改缓冲页时,会在【缓冲页对应的控制块】中,记录以下两个属性:

  • oldest_modification:第一次修改缓冲页时,就将【修改该页面的第一组redo log的lsn值】记录在对应的控制块。
  • newest_modification:每一次修改缓冲页时,就将【修改该页面的最后组redo log的lsn值】记录在对应的控制块。

既然flush链表是按照修改日期排序的,那么也就意味着,oldest_modification的值也是有序的。

(4)checkpoint过程

执行一个check point可以分为两个步骤

第一步:计算当前redo log文件中可以被覆盖的redo日志对应的lsn的值是多少:

1、flush链是按照第一次修改的时间排序的,当然控制块内的【oldest_modification】记录的lsn值也是有序的。

2、我们找到flush链表的头节点上的【oldest_modification】所记录的lsn值,也就找到了一个可以刷盘的最大的lsn值,小于这个值的脏页,肯定已经刷入磁盘。

3、所有小于这个lsn值的redo log,都可以被覆盖重用。

4、将这个lsn值赋值给一个全局变量checkpoint_lsn,他代表可以被覆盖的量。

第二步:将checkpoint_lsn与对应的redo log日志文件组偏移量以及此次checkpoint的编号(checkpoint_no也是一个变量,记录了checkpoint的次数)全部记录在日志文件的管理信息内。

4、一个事务的执行流程

在这里插入图片描述

主线程

1、客户端访问mysql服务,在buffer pool中进行操作(如果目标页不在缓冲区,需要加载进入缓冲区),此时会形成脏页。

2、记录redo log,可能产生很多组日志,redo log优先记录在缓冲区,会在提交事务前刷盘。

3、刷盘时根据checkpoint的结果,选择可以使用的日志空间进行记录。

4、成功后即可返回,此时数据不会落盘,这个过程很多操作只在内存进行,只需要记录redo log(顺序写),所以速度很快。

线程1:

1、不断的对flush链表的脏页进行刷盘,对响应时间没有过高要求。

线程2:

1、不断的进行checkpoin操作,保证redo log可以及时写入。

5、系统崩溃的影响

(1)log buffer中的日志丢失,log buffer中的日志会在每次事务前进行刷盘,如果在事务进行中崩溃,事务本来就需要回滚。

(2)buffer pool中的脏页丢失,崩溃后可以通过redo log恢复,通过checkpoint操作,我们可以确保,内存中脏页对应的记录都会在redo log日志中存在。

redo log保证了崩溃后,数据不丢失,但是一个事务进行中,如果一部分redo log已经刷盘,那么系统会将本应回滚的数据同样恢复,为了解决回滚的问题,innodb提出了undo log。

二、undo log日志

1、概述

undo log(也叫撤销日志或者回滚日志),他的主要作用是为了实现回滚操作。同时,他是MVCC多版本控制的核心模块。undo log保存在共享表空间【ibdata1文件】中。

在这里插入图片描述

注意:8.0以后undolog有了独立的表空间:

在这里插入图片描述

在讲undo log之前需要先了解行数据中的两个隐藏列:

2、事务id(trx_id)

我们已经讲过,在innodb的行数据中,会自动添加两个隐藏列,一个是【trx_id】,一个是【roll_pointer】,本章节会详细介绍这两列的具体作用,如果该表中没有定义主键,也没有定义【非空唯一】列,则还会生成一个隐藏列【row_id】,这个我们之间也讲过,是为了生成聚簇索引使用的。

事务id是一个自增的全局变量,如果一个【事务】对任意表做了【增删改】的操作,那么innodb就会给他分配一个独一无二的事务id。

tip:

  • 事务id保存在一个全局变量【MAX_TRX_ID】上,每次事务需要分配事务id,就会从这个全局变量中获取,然后自增1。
  • 该变量每次自增到256的倍数会进行一个落盘(保存在表空间页号为5的页面中),发生服务停止或者系统崩溃后,再起启动服务,会读取这个数字,然后再加256。这样做既保证不会有太多I/O操作,还能保证id的有序增长。比如:读到256进行落盘,后来有涨到302,突然崩溃了,下次启动后,第一个事务的id就是256+256=512,保证新的事务id一定大。

3、roll_pointer

undo log在记录日志时是这样记录的,每次修改数据,都会将修改的数据标记一个【新的版本】,同时,这个版本的数据的地址会保存在修改之前的数据的roll_pointer列中,如下:

在这里插入图片描述

4、分类

当我们对数据库的数据进行一个操作时必须记录之前的信息,将来才能【悔棋】,如下:

  • 插入一条数据时,至少要把这条数据的主键记录下来,以后不想要了直接根据主键删除。
  • 删除一条数据时,至少要把这个数据所有的内容全部记录下来,以后才能全量恢复。但事实上不需要,每行数据都有一个delete_flag,事务中将其置1,记录id,如需要回滚根据id复原即可,提交事务后又purge线程处理垃圾。
  • 修改一条数据时,至少要将修改前后的数据都保存下来。

innodb将undo log分为两类:

  1. 一类日志只记录插入类型的操作(insert)
  2. 一类日志只记录修改类型的操作(delete,update)

什么分为这两类呢?

  • 插入型的记录不需要记录版本,事务提交以后这一片空间就可以重复利用了。
  • 修改型的必须将每次修改作为一个版本记录下来,即使当前事务已经提交,也不一定能回收空间,应为其他事务可能在用。

5、物理存储结构

undo同样是以页的形式进行存储的,多个页是使用链表的形式进行管理,针对【普通表和零时表】,【插入型和修改型】的数据,一个事务可能会产生以下四种链表:

在这里插入图片描述

这是物理存储模型,分成四种类型,是为了更好的管理。

6、记录流程

  1. 开启事务,执行【增删改】时获得【事务id】。

  2. 在系统表空间中第5号页中,分配一个回滚段,回滚段是轮动分配的,比如,当前事务使用第5个回滚段,下个事务就使用第6个。

    【回滚段】是一个【数据页】,里边划分了1024个undo slot,用来存储日志链表的头节点地址。

  3. 在当前回滚段的cached链表(回收可复用的)和空闲solt中,找到一个可用的slot,找不到就报错。

  4. 创建或复用一个undo log页,作为first undo page,并把他的地址写入undo solt中。

在这里插入图片描述

7、回滚过程

  1. 服务再次启动时,通过表空间5号页面定位到128个回滚段的位置,
  2. 遍历所有的slot,找到所有状态不为空闲的slot,并且通过undolog的标记为找到现在活跃(未提交)的所有的事务id
  3. 根据undo log的记录,将数据全部回滚

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

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

相关文章

SpringBoot解决用户重复提交订单(方式二:通过Redis实现)

文章目录 前言1、方案实践1.1、引入Redis依赖1.2、添加Redis环境配置1.3、编写获取请求唯一ID的接口,同时将唯一ID存入redis 1.4、编写服务验证逻辑,通过 aop 代理方式实现1.5、在相关的业务接口上,增加SubmitToken注解即可 2、小结 前言 在…

华润数科、京东科技、京彩未来携手共进,求解“科技×产业”最大值

4月18日,华润数科、京东科技、京彩未来三方代表在中国深圳签署三方合作协议。面向产业数字化的市场机遇,华润数科物联网事业部总经理刘楚明先生表示,华润数科作为华润集团重点培育的数字科技业务单元,基于技术优势及资源整合能力&…

在SAP中使用QUERY

在SAP中使用QUERY 一、SAP query介绍 ​ QUERY是SAP提供的方便无编程基础用户的报表工具,使用图形化的界面,让用户托托拽拽就能轻松完成报表编写。我们可以将Query理解成QuickView的高级版本,它在QuickView的基础上增加的功能有&#xff1a…

一、摄影基础课

目录 第一章 控制曝光1. 曝光及曝光三要素1.1 曝光1.2 光圈1.3 快门1.4 感光度(ISO)1.5 曝光三要素之间的关系 2. 曝光模式3. 测光模式4. 曝光补偿 第二章 控制对焦1. 对焦区域2. 对焦模式 第三章 控制色彩 第一章 控制曝光 1. 曝光及曝光三要素 1.1 曝…

尚硅谷大数据技术Zookeeper教程-笔记01【Zookeeper(入门、本地安装、集群操作)】

视频地址:【尚硅谷】大数据技术之Zookeeper 3.5.7版本教程_哔哩哔哩_bilibili 尚硅谷大数据技术Zookeeper教程-笔记01【Zookeeper(入门、本地安装、集群操作)】尚硅谷大数据技术Zookeeper教程-笔记02【服务器动态上下线监听案例、ZooKeeper分布式锁案例、企业面试真…

外包干了4年,直接废了···

有一说一,外包没有给很高的薪资,是真不能干呀! 先说一下自己的情况,大专生,19年通过校招进入湖南某软件公司,干了接近4年的功能测试,今年年初,感觉自己不能够在这样下去了&#xff0…

[java/初学者]java常用API(1)——包装类

前言 在学习本课题之前,我们首先需要知道什么是API。 API,即Application Programming Interface,中文名称是“应用程序接口", 这些接口就是"jdk所提供"给我们使用的类,我们不需要去深究它是如何实现…

STM32+EC20实现4G无线通信

EC20是一款集成度非常高的4G无线通信模块,支持多种常见通信频段,能满足几乎所有的M2M(MachinetoMachine)应用需求。模块支持TCP/UDP/FTP等一众网络协议,内置多星座高精度定位GNSS接收机,快速提供准确的经纬度信息,UART…

vscode java环境扩展

下载安装jdk: Java Downloads | Oracle 下载安装maven: Maven – Download Apache Maven windows系统选择 Binary zip archive maven目录中的conf文件中有一个settins.xml文件 镜像&#xff08;mirrors&#xff09;二选一 <mirror><id>nexus-aliyun</…

影视动画设计有些SCI期刊推荐? - 易智编译EaseEditing

以下是几本影视动画设计方向的SCI期刊&#xff1a; ACM Transactions on Graphics: 该期刊是ACM&#xff08;Association for Computing Machinery&#xff0c;美国计算机协会&#xff09;下的一个子刊&#xff0c;涵盖了计算机图形学和交互技术等领域&#xff0c;也包括了动…

虚拟化技术 — 硬件辅助的虚拟化技术

目录 文章目录 目录硬件辅助的虚拟化技术概览CPU 虚拟化技术基于二进制翻译的全虚拟化技术&#xff08;Full-Virtualization&#xff09;需要改造 GuestOS 的半虚拟化技术&#xff08;Para-Virtualization&#xff09;Intel VT-x 硬件辅助的虚拟化技术&#xff08;Hardware-ass…

智芯Z20K11x串口printf重定向

智芯Z20K11x串口printf重定向 目录 智芯Z20K11x串口printf重定向前言1 串口代码编写2 Keil勾选MicroLIB库结束语 前言 智芯Z20K11x系列是基于ARM CORTEX M0的中低端微控制器&#xff0c;高达256K P FLASH 128K D FLASH&#xff0c;2路CANFD接口&#xff0c;4路UART/LIN接口&a…

综合能源系统中基于电转气和碳捕集系统的热电联产建模与优化研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

HashMap理解

简单介绍 HashMap是双列集合Map接口下的实现类&#xff0c;jdk1.8之前其数据结构是数组链表、jdk1.8之后是数组链表红黑树&#xff0c;是线程不安全的&#xff0c; 原理图&#xff1a; HashMap放值的过程&#xff1a; HashMap先是根据Hash算法算出key的hashcode码值&#xff0…

Vivado之VIO原理及应用

虚拟输入输出&#xff08;Virtual Input Output,VIO)核是一个可定制的IP核&#xff0c;它可用于实时监视和驱动内部FPGA的信号&#xff0c;如图所示。 可以定制VIO的输入和输出端口的数量与宽度&#xff0c;用于和FPGA设计进行连接。由于VIO核与被监视和驱动的设计同步&#xf…

Linux操作系统原理—内核网络协议栈

前言 本文主要记录 Linux 内核网络协议栈的运行原理 数据报文的封装与分用 封装&#xff1a;当应用程序用 TCP 协议传送数据时&#xff0c;数据首先进入内核网络协议栈中&#xff0c;然后逐一通过 TCP/IP 协议族的每层直到被当作一串比特流送入网络。对于每一层而言&#xff…

SwiftUI 使用 UIPageViewController 翻页后出现空白的原因及解决

问题现象 我们 SwiftUI 开发的 App 需要 UIPageViewController 的翻页功能,这可以非常方便的通过桥接 UIKit 到 SwiftUI 来搞定: 不过,观察上图可以发现 App 翻页显示的并不太对:当用户通过右下角的 UIPageControl 触发翻页时没有问题,但当用户直接手动在 UIPageViewCont…

【毕业设计】基于程序化生成和音频检测的生态仿真与3D内容生成系统----音频检测算法设计

(2条消息) 【开发日志】2022.09.02 ZENO----Audio----Beat detection algorithm----Combine Wav&Mp3_minimp3 和 ffmpeg_EndlessDaydream的博客-CSDN博客https://blog.csdn.net/Angelloveyatou/article/details/126670613 4 音频检测算法设计 4.1 节拍检测算法 4.1.1 节…

JavaSE——数组

这篇文章的面向读者为Java初级程序员&#xff0c;也就是刚刚接触到Java这门语言&#xff0c;里面描述的内容主要是数组相关的内容&#xff0c;讲解了最基础的一些数组扩容思路&#xff0c;数组赋值机制&#xff0c;什么是引用地址&#xff0c;什么是基础数据赋值。 Java该章节数…

JAVA入坑之线程

目录 一、&#xff1a;相关概念 1.1中央处理器(CPU&#xff0c;Central Processing Unit) 1.2程序、进程、线程 1.3线程与任务 二、线程的创建&#xff1a; 2.1继承Thread创建线程&#xff1a; 使用Thread子类创建线程的优缺点 2.2实现Runnable接口创建线程&#xff1a;…