首页 > 数据库 >【MySQL系列】- 浅析undo log

【MySQL系列】- 浅析undo log

时间:2022-10-06 17:03:40浏览次数:55  
标签:回滚 log 事务 undo UPDATE innodb 日志 浅析

undo log 是什么

undo log可以称为撤销日志、undo 日志,它记录着事务回滚前的数据。

官方定义:

A storage area that holds copies of data modified by active transactions.

翻译过来就是undo log是保存活动事务修改的数据副本的存储区域。

undo 日志只记录事务中的增删改操作,查询并不会记录,因为查询不会修改数据。 undo 日志存在于undo日志段中,undo日志段包含在回滚段中。

undo日志段

undo日志段(undo log segment)是undo日志的集合。undo 日志段包含在回滚段中,一个undo日志段可能包含来自多个事务的undo日志,一个undo日志段一次只能被一个事务使用,但是在事务提交或回滚时,释放undo日志段以后可以重用它。undo日志段也可以被称为“undo segment(undo 段)”。

回滚段

回滚段(rollback segment)是包含undo日志的存储区域。回滚段通常位于系统表空间中。从MySQL 5.6开始,回滚段可以存储在undo表空间中,从MySQL 5.7开始,回滚段也被分配到全局临时表空间。

InnoDB最多支持128个回滚段,其中有1个回滚段用于系统表空间,32个回滚段位于临时表空间,剩余的95个用于undo表空间。

可以通过参数​​innodb_rollback_segments​​修改回滚段的个数,默认是最大值128。要分配多余的回滚段给undo表空间的话,回滚段在修改的时候值要大于33。

  • 如果innodb_rollback_segments配置的回滚段个数小于等于32,InnoDB仍然会分配一个回滚段给系统表空间,32个回滚段给临时表空间,也就是说配置无效。
  • 如果innodb_rollback_segments配置的回滚段个数大于32,InnoDB会分配一个回滚段给系统表空间,32个回滚段给临时表空间,其余的用于undo表空间。如果undo表空间不存在,则其余的用于系统表空间。

undo slot

回滚段实际上是一种Undo 文件组织方式,每个回滚段又由多个undo slot组成。回滚段支持的事务数取决于回滚段中的撤销槽(undo slot)位数和每个事务所需的undo日志数。根据InnoDB页面的大小,回滚段中undo槽的数量是不同的。

InnoDB页大小

Undo Slot在回滚的中的数量(InnoDB页大小 / 16)

4096 (4KB)

256

8192 (8KB)

512

16384 (16KB)

1024

32768 (32KB)

2048

65536 (64KB)

4096

InnoDB页大小默认为16k,所以Undo Slot数量默认为1024。

事务产生的undo日志

一个事务在以下4种情况会产生undo日志,分别为:

  1. 在用户自定义的常规表上的INSERT操作
  2. 在用户自定义的常规表上的UPDATE和DELETE操作
  3. 在用户自定义的临时表上的INSERT操作
  4. 在用户自定义的临时表上的UPDATE和DELETE操作

可以发现,大多数对数据的变更操作包括INSERT/DELETE/UPDATE,总的还是分为两类undo 日志,INSERT操作独自占一类,UPDATE和DELETE归为一类。 其中INSERT操作在事务提交前只对当前事务可见,因此产生的Undo日志可以在事务提交后直接删除,INSERT操作产生的undo日志称为insert undo ,而对于UPDATE/DELETE则需要维护多版本信息,在InnoDB里,UPDATE和DELETE操作产生的Undo日志被归成一类,称为update undo。

undo日志会按需分配,需要哪类日志就用哪类。比如,如果一个事务同时有INSERT、UPDATE和DELETE操作,那么这4种情况的undo日志就都需要。如果一个事务只有INSERT操作,那就只需要一种undo日志。

事务如果操作的是用户自定义的常规表,那undo日志就会从系统表空间或者undo表空间的回滚段分配。反之,如果事务操作的是用户定义的临时表,那么undo日志就会从临时表空间的回滚段分配。

InnoDB 支持的并发读写事务数量

根据回滚段可以预估出InnoDB 能支持多少个并发读写事务:

  • 当事务对临时表进行操作时,InnoDB能够支持的并发读写事务的数量受限于分配给临时表空间的回滚段的数量,即32个。
  • 如果一个事务在常规表上执行INSERT、UPDATE或DELETE操作中的一个,那么支持的并发读写事务数量计算公式为:
(innodb_page_size / 16) * (innodb_rollback_segments - 32)
复制代码
  • 如果一个事务在常规表上执行INSERT和UPDATE或DELETE操作中的一个,那么支持的并发读写事务数量计算公式为:
(innodb_page_size / 16 / 2) * (innodb_rollback_segments - 32)
复制代码
  • 如果一个事务在临时表上执行INSERT、UPDATE或DELETE操作中的一个,那么支持的并发读写事务数量计算公式为:
(innodb_page_size / 16) * 32
复制代码
  • 如果一个事务在临时表上执行INSERT和UPDATE或DELETE操作中的一个,那么支持的并发读写事务数量计算公式为:
(innodb_page_size / 16 / 2) * 32
复制代码

undo日志作用

undo 日志主要有两个作用,事务回滚和作为MVCC的一部分:

  1. 事务回滚

上面说的就是事务回滚,主要用于保证事务的原子性。通过undo日志在事务需要回滚的时候,让数据恢复到最初的样子。

  1. 作为MVCC的一部分

undo日志作为MVCC(Multi-Versioin Concurrency Control)版本链的一部分,Undo记录中存储的是老版本数据,当一个旧的事务需要读取数据时,为了能读取到老版本的数据,需要顺着undo链找到满足其可见性的记录。

undo日志机制

对于INSERT操作,insert undo在事务提交后,ndo segment就释放了。而对于UPDATE/DELETE操作产生的update undo则比较复杂,。

  • DELETE操作:在执行一条DELETE语句时,在事务提交后,并不会直接删除而是会将记录delete_mask标识位设置为1,并加入history list,由后台线程Purge进行清理。
  • UPDATE操作:执行UPDATE语句又分为两种情况:
  • 更新主键: 这种情况下会分为两步: 1、先将之前记录的delete标志位设置为1,也就是说先删除之前的记录 2、重新插入一条记录。 所以对于更新主键的情况下其实是产生了两条undo日志,一个是delete操作产生的,一个是insert操作产生的。
  • 不更新主键:这种操作下,会根据被更新的列占用的存储空间是否变化分为两种情况:
  • 存储空间发生变化:这种情况称为就地更新(in-place update)。更新记录时,对于被更新的每个列来说,如果更新前后的列所占用的存储空间都一样大,那么就可以进行就地更新,也就是直接在原记录的基础上修改对应列的值。
  • 存储空间不发生变化:这种情况分为两步: 1、先删除旧记录 2、再插入旧记录。 这里的删除并不是上面所说的将delete标志位设置为1,而是将记录放到history list中,由用户线程同步执行真正的删除操作,真正删除之后紧接着就要根据各个列更新后的值创建的新记录入。 如果新创建的记录占用的存储空间大小不超过旧记录占用的空间,那么可以直接重用被加入到history list中的旧记录所占用的存储空间,否则的话需要在页面中新申请一段空间以供新记录使用,如果本页面内已经没有可用的空间的话,那就需要进行页面分裂操作,然后再插入新记录。

对于UPDATE/DELETE操作产生的update undo日志,则会加入history list,由后台线程Purge进行清理。

undo日志参数

可通过命令​​show variables like "%undo%"​​查看undo日志相关参数: [图片上传失败...(image-8d7215-1665020845170)]

  1. innodb_undo_directory
    InnoDB创建undo表空间的路径,通常用于将undo日志放置在不同的存储设备上。如果没有指定,默认会创建在MySQL数据目录下。
  2. innodb_undo_tablespaces
    undo表空间数量,默认为0。在MySQL8.0版本中已经废弃,需要添加的话可以使用CREATE TABLESPACE语句创建undo表空间。
  3. innodb_undo_log_truncate
    undo表空间清理开关,默认OFF,关闭。
  4. innodb_max_undo_log_size
    undo表空间的阈值,默认值为1073741824 bytes(1024 MiB)。如果超过了这个阈值,undo表空间将会进行truncate,如果innodb_undo_log_truncate开启的话。
  5. innodb_undo_logs
    innodb回滚段的数量,同innodb_rollback_segments,默认值为128。innodb_undo_logs在MySQL 5.7.19版本开始被废弃。

总结

undo log是MySQL最重要的日志之一,这里简单介绍了一下undo日志的概念、作用、机制等,算是对undo日志有了大致的了解。

标签:回滚,log,事务,undo,UPDATE,innodb,日志,浅析
From: https://blog.51cto.com/u_15773567/5733913

相关文章

  • 6.4.3Log4j配置文件
    1.输出级别log4jrootLogger=debug,stdout,logfiledebug指的是日志记录器(Logger)的输出级别,主要输出级别及含义如下:.fatal:指出严重的错误事件将会导致应用程序的退......
  • CF700E Cool Slogans
    CF700ECoolSlogans首先可以得到以下性质。性质1当\(k\)最大时,一定存在一组\(s\)满足\(s_{i}\)为\(s_{i+1}\)的后缀(\(1\lei<k\))。证明:设存在一组解使得......
  • Topology Attack and Defense for Graph Neural Networks: An Optimization Perspecti
    目录概符号说明TopologyAttack对抗训练代码XuK.,ChenH.,LiuS.,ChenP.,WengT.,HongM.andLinX.Topologyattackanddefenseforgraphneuralnetworks:......
  • python记录日志神器- loguru库
    写了这么多年的Python,我一直都是使用Python自带的logging模块来记录日志,每次需要写一些配置将日志输出到不同的位置,设置不同日志输出格式,或者将日志进行分文件和压缩......
  • verilog中结构说明语句
    结构说明语句Verilog语言中的任何过程模块都从属于以下四种结构的说明语句。1)initial说明语句2)always说明语句3)task说明语句4)function说明语句initial和alwa......
  • Verilog 基本语句
    VerilogHDL语句包括过程语句、块语句、赋值语句、条件语句、循环语句、编译导向语句等。类别语句赋值语句持续赋值语句:assign过程赋值:=,<=块语句串行......
  • verilog行为级描述与结构级描述
    verilog行为级描述与结构级描述1、在使用verilog描述电路时,既可以进行行为级的描述,也可以进行结构级的描述。(1)行为级描述:侧重对模块行为功能的抽象描述。(......
  • verilog实现rgb2gray
    前言  项目算法需求,需要将RGB彩色图像转换为灰度图像,算法原理是很简单的,但是对于刚接触FPGA的宝宝来说,进行时序的设计和调试还是不那么容易的,为了省事儿,就按照上一篇中值......
  • graylog MessageProcessor 简单说明
    MessageProcessor是在ProcessBufferProcessor使用的,主要进行消息的加工,比如过滤,提取,扩展ProcessBufferProcessor参考处理privatevoidhandleMessage(@Nonnul......
  • graylog RawMessage&RawMessageEvent&MessageEvent&Message 说明
    RawMessage是从grayloginput组件获取到的还没解析处理的消息,是有SimpleChannelInboundHandler处理的原始消息RawMessageEvent是Disruptor处理的事件包装MessageE......