MySQL(七):undo日志——保证事务的原子性

news2024/11/17 16:31:17

目录

  • 一、前言
    • 1.1 如何回滚事务
    • 1.2 事务id
    • 1.3 roll pointer 隐藏列
    • 1.4 trx_id 隐藏列
  • 二、undo日志
    • 2.1 undo日志的格式
    • 2.2 insert 对应的undo日志
    • 2.3 delete 操作对应的undo日志
    • 2.4 update操作对应的undo日志
    • 2.5 Undo页面链表
    • 2.6 undo日志写入过程
      • 2.6.1 Undo Log Header
    • 2.7 回滚段
      • 2.7.1 回滚段的概念

一、前言

1.1 如何回滚事务

原子性是事务的其中一个特性,指的是要么全部执行完,要么全都不执行,说的容易,如何保证这一特性呢?

事务在执行的过程中难免会发生某些意外:

  • 服务器错误、操作系统错误、电脑直接掉电、、、
  • 有时程序员也想手动的回滚事务

上述这些情况,都会导致事务执行一般就结束,但是事务在执行过程中已经修改了很多数据,为了保证事务的原子性,我们必须改回原来的样子。


数据库的回滚操作和悔棋类似,如果向数据库中插入了一条数据,对应的回滚操作就是把这条记录删除掉,更新了一条记录,对应的回滚操作就是把该记录更新回旧值;
因此,每当对一条记录进行改动的时候,都需要将回滚所需的东西记录下来,

  • 插入一条记录时,要记录该记录的主键,便于回滚时根据主键删除记录
  • 删除一条记录时,要把该记录的内容记下来,

MySQL中规定,把用来记录事务回滚时所需信息的日志称为undo日志,由于select不会对记录进行改动,所以进行select操作时,不用记录undo日志.

1.2 事务id

如果某个事务在执行过程中对某个表执行了增删改操作,那么InnoDB存储引擎会为该事务分配一个独一无二的事务id,对于只读事务来说,只有在它对用户创建的临时表进行增删改查操作时,才会为该事务分配一个事务id,否则不会分配;

1.3 roll pointer 隐藏列

roll pointer作为用户记录的隐藏列,本质上是一个指向记录对应的undo日志的指针
在这里插入图片描述

1.4 trx_id 隐藏列

trx_id保存的是,对该条聚簇索引记录进行改动的语句所在的事务id

二、undo日志

2.1 undo日志的格式

在某些更新操作中,一条更新语句,可能对应多条undo日志,这些日志从0编号,被放在类型为FIL_PAGE_UNDO_LOG的页面中。

2.2 insert 对应的undo日志

在这里插入图片描述

  • undo no:在一个事务中,undo no 从0开始递增,每生成一条undo日志,undo no增加1
  • 主键个列信息:如果主键中包含多个列,会将这多个列占用的存储空间大小和对应的真实值记录下来

2.3 delete 操作对应的undo日志

向页面中插入的记录会根据记录头信息中的next_record属性组成一个单向链表,同样,被删除的记录也会根据记录的头信息中的next_record组成一个链表,只不过在该链表中的记录占用的空间可以被覆盖,所以也称为垃圾链表

通过delete语句删除一条记录分为以下两个阶段:

  1. 仅将记录的deleted_flag置为1,该阶段并不会将该记录加入到垃圾链表中,算是一条处于中间状态的记录
    在这里插入图片描述
  2. 当该删除语句所在的事务提交之后,会将该记录头插到垃圾链表中,因此也会更改PAGR_FREE属性
    在这里插入图片描述
    因此delete语句对应的undo日志,只需考虑对阶段1所做的影响进行回滚就可以了。
    在这里插入图片描述
    注意:
    在对一条记录进行delete mark操作前,需要把该记录的trx_id和roll_pointer隐藏列的旧值写到对应的undo日志中,这样有一个好处就是,可以通过undo日志的roll_pointer属性找到上一次对该记录进行改动时产生的undo日志
    在这里插入图片描述

2.4 update操作对应的undo日志

在执行update语句时,InnoDB在对更新主键和不更新主键采取两种不同的方案

不更新主键的情况中也可分为被更新列占用的存储空间是否发生变化两种情况

(1)当被更新列占用的存储空间不发生变化时,采用就地更新的方式

(2)当被更新列占用的存储空间发生变化时,会先删除旧纪录,再插入新纪录,这里所说的删除不是delete mark,而是真正的删除


更新主键的情况

在聚簇索引中,记录之间根据主键进行排序,如果我们将索引从1更新成10000,并且在1-10000之间还有很多记录,此时主键值为1的记录和主键值为10000的记录之间会离的很远,对于这中情况,InnlDB分两步处理:
在这里插入图片描述

第一步:对旧纪录进行delete mark操作,记录一条类型为 TRX_UNDO_DEL_MARK_REC的undo 日志
第二步:插入一条新的记录到聚簇索引中,记录一条类型为TRX_UNDO_INSERT_REC的undo日志
也就是说,对更新一条记录的主键值时,会生成两条undo日志

2.5 Undo页面链表

在一个事务中,可能包含多个语句 ,所以在一个事务中可能产生很多的undo日志,这些日志可能一个页面中放不下,需要放到多个页面中,多个页面形成一个链表
在这里插入图片描述
InnoDB中规定,同一个undo页面中,要么只存储TRX_UNDO_INSERT大类的undo日志,要么只存储TRX_UNDO_UPDATE大类的undo日志,不能混着存,所以一个事务在执行过程中,需要2个undo页面的链表

在这里插入图片描述

2.6 undo日志写入过程

InnoDB中规定,每个Undo页面链表都对应着一个段,称为Undo Log Segment,链表中的页面都是从这个段中申请的,
在这里插入图片描述
Undo页面链表的第一个页面比普通页面多了一个Undo Log Segment Header
在这里插入图片描述
TRX_UNDO_STATE:当前页面链表处于什么状态
TRX_UNDO_LOG:Undo页面链表中最后一个Undo Log Header 的位置
TRX_UNDO_FSEG_HEADER:本Undo 页面链表对应的段的Segment Header信息
TRX_UNDO_PAGE_LIST:Undo页面链表的基节点

2.6.1 Undo Log Header

一个事务在向Undo页面中写入undo日志时,采用的方式很简单,直接往里"堆",写完一个Undo页面后,再从段中申请一个新页面
InnoDB中规定,同一事务向一个Undo页面链表中写入的undo日志算是一组

Undo Log Header 的结构:
在这里插入图片描述
TRX_UNDO_TRX_ID:生成本组undo日志的事务id
TRX_UNDO_TRX_NO:事务提交后生成的第一个序号
TRX_UNDO_DEL_MARKS:标记本组undo日志中是否包含由delete mark操作产生的undo 日志
TRX_UNDO_LOG_START:标记本组日志中第一条undo日志在页面中的偏移量

TRX_UNDO_NEXT_LOG:下一组undo日志在页面中开始的偏移量
TRX_UNDO_PREV_LOG:上一组undo日志在页面中开始的偏移量

2.7 回滚段

2.7.1 回滚段的概念

一个事务在执行的过程中最多可以分配4个Undo页面链表,因此同一时刻可以存在多个Undo页面链表,为了更好的管理这些Undo页面链表,InnoDB设计了一个名为Rollback Segment Header的页面,在这个页面中存放了各个Undo页面链表的first undo page的页号,这些页号称为undo slot

在这里插入图片描述
每一个Rollback Segment Header属于一个Rollback Segmeng段,同时,这个回滚段中其实只有一个页面

TRX_RSEG_MAX_SIZE:这个回滚段中所有undo链表中的所有undo页面之和的最大值
TRX_RSEG_HISTORY_SIZE:History链表占用的页面数量

TRX_RSEG_HISTORY:History链表的基节点
TRX_RSEG_FSEG_HEADER:这个回滚段对应的10字节大小的Segment Header结构
TRX_RSEG_UNDO_SLOTS:各个undo页面链表的first undo page的页号集合

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

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

相关文章

springboot请求参数绑定原理篇

上篇文章写了SpringBoot 参数接收只看这一篇文章就够了,只是写了使用方法,没有写为什么,原理是什么,这篇文章也是之前的预先的计划,稍微花点时间整理下,知其然知其所以然,才算是能彻底掌握&…

如何用IDEA创建SpringBoot项目

一、创建一个 Spring Initializr 工程 next后选择2.7.8版本,勾选以下几个 Web里的spring bootTemplate Engines 里的 ThymeleafSQL里的MyBatis Framework 和 Mysql Driver 然后finish完成 二、配置resources文件 2.1、 application.properties: #??…

Docker容器命令无权限,WEB访问403

问题背景(描述) 部署dockerWeb后,重启访问403,详细如下 docker容器正常运行,且开机自启 #通过如下命令开机自启 docker update --restart always 容器id但是访问web服务出现403. 进入容器后,输入命令提示如下: 解决方案 关闭selinux SELinux(Security-Enhanced…

【网络安全】记一次红队渗透实战项目

前言 【一一帮助安全学习(网络安全面试题学习路线视频教程工具)一一】 一、信息收集 信息收集非常重要,有了信息才能知道下一步该如何进行,接下来将用nmap来演示信息收集 1、nmap扫描存活IP 由于本项目环境是nat模式需要项目…

【Java基础】——面向对象:封装

【Java基础】——面向对象:封装一、类和对象二、类的结构:属性、方法、构造器1、属性2、方法2.1、方法的定义2.2、方法的重载2.3、可变个数的形参2.4、方法参数的值传递机制3、构造器3.1、构造器的特征3.2、构造器的作用:3.3、构造器重载三、封装与隐藏1…

细菌,真菌,病毒——感染,免疫反应以及治疗用药差异

谷禾健康 与人类密切相关的微生物 我们的世界大到浩瀚宇宙,小到微观下的生物分子。我们总说漫天繁星,其实身边微生物数量可能更多。动物、植物、真菌、细菌、病毒等,共同构成了丰富多彩的生命世界。 细菌、真菌、病毒是其中的三个大类&#x…

spring integration使用:消息路由

系列文章目录 …TODO spring integration开篇:说明 …TODO spring integration使用:消息路由 spring integration使用:消息路由系列文章目录前言消息路由的概念二、路由的分类基于内容的路由器spring integration中的实现RecipientListRoute…

Python property()函数:定义属性

我们一直在用“类对象.属性”的方式访问类中定义的属性,其实这种做法是欠妥的,因为它破坏了类的封装原则。正常情况下,类包含的属性应该是隐藏的,只允许通过类提供的方法来间接实现对类属性的访问和操作。因此,在不破坏…

AOP的四种增强方式

1. 前置增强,在核心功能之前执行的额外功能 public class MyBeforeAdvice implements MethodBeforeAdvice{Overridepublic void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {System.out.print("this is my before advice!");Str…

渲染函数render

文章目录节点、树以及虚拟 DOM树节点虚拟 DOMvue中render函数的作用render函数去创建子组件内容createElement官方文档参考节点、树以及虚拟 DOM 在深入渲染函数之前&#xff0c;了解一些浏览器的工作原理是很重要的。以下面这段 HTML 为例&#xff1a; <div><h1>…

user-select:none真的能禁止文本的复制粘贴吗?

1. 前言 面向搜索引擎开发时&#xff0c;我们经常看到这样的情况&#xff1a;登录后复制。 由于设置了css属性 user-select:none&#xff0c;此时鼠标无法实现选中文本&#xff0c;也就无法复制文本&#xff0c;通常会采用这种方式来禁止复制文本。打开开发者工具-审查元素&am…

k-means聚类

一、概述 当前人工智能技术实现的一种主要手段是机器学习&#xff0c;而机器学习能够解决的问题主要有三种&#xff1a;分类、聚类、回归&#xff0c;有监督的是分类&#xff0c;无监督的是聚类。所谓聚类&#xff0c;就是以一定的方法将一堆样本依它们本身的数据特性划分成不同…

docker安装mongdb

MongoDB是一个介于关系数据库和非关系数据库之间的产品&#xff0c;是非关系数据库当中功能最丰富&#xff0c;最像关系数据库的。它支持的数据结构非常松散&#xff0c;是类似json的bson格式&#xff0c;因此可以存储比较复杂的数据类型。Mongo最大的特点是它支持的查询语言非…

【操作系统】备忘录

进程上下文切换 用户态、内核态 内核态&#xff1a;也叫内核空间&#xff0c;是内核进程/线程所在的区域。主要负责运行系统、硬件交互。 用户态&#xff1a;也叫用户空间&#xff0c;是用户进程/线程所在的区域。主要用于执行用户程序。 内核态与用户态的区别 内核态与用户…

spring mvc文档阅读笔记——02

目录标题一、Asynchronous Requests&#xff08;异步请求&#xff09;&#xff08;一&#xff09;阻塞和非阻塞,同步和异步&#xff08;二&#xff09;DeferredResult&#xff08;三&#xff09;Callable二、跨域请求CORS&#xff08;一&#xff09;实现跨域请求的方式&#xf…

数据持久化-RDB-AOF

定义 将数据从掉电易失的内存放到永久储存的设备上 因为所有的数据都在内存是&#xff0c;所有必须得持久化 redis提供两种持久化方案 RDB默认开启、AOF RDB 1,保存真是的数据 2&#xff0c;将服务器包含的所有数据库数据以二进制文件形式保存到磁盘里面 3&#xff0c;默认…

JDBC管理事务

基本介绍 就是处理在mysql的事务 复习一下:事务是一组sql语句需要开启和提交&#xff0c;事务中的sql语句要么全部生效&#xff0c;要么全部不生效&#xff0c;提交之后就是全部生效&#xff0c;中间可以设置保存点&#xff0c;回退到保存点&#xff0c;或直接回退到最开始事务…

1.2.1存储结构:层次化存储结构、外存(辅存)、内存(主存)、CPU内部的寄存器、Cache(相联存储器)

1.2.1存储结构&#xff1a;层次化存储结构、外存&#xff08;辅存&#xff09;、内存&#xff08;主存&#xff09;、CPU内部的寄存器、Cache&#xff08;相联存储器&#xff09;存储系统--层次化存储结构外存&#xff08;辅存&#xff09;内存&#xff08;主存&#xff09;CPU…

并发编程学习(八):ReentrantLock

ReentrantLock 是java.util.concurrent.locks包下的类。相对于synchronized,它具备如下特性&#xff1a;可中断。可以设置超时时间。可以设置公平锁。支持多个条件变量。即可以有个多个waitset等待队列。与synchronized都支持可重入。ReentrantLock的基本语法&#xff1a;// 获…

数学建模相关竞赛零基础上手与入门介绍

文章目录1、赛事介绍与报名2、学习与训练2.1 比赛题目选择范围2.2 赛前组队与分工2.3 比赛时间分配1、赛事介绍与报名 什么是数学建模&#xff1f; 定义&#xff1a; 生活中的各种问题(如股票预测、火灾报警统计等)&#xff0c;运用数学的方式去阐述并解决它。 数学建模赛事 …