MySQL第四讲 MySql Undo日志 - 对聚簇索引进行CUD操作

2023-10-15 03:30

本文主要是介绍MySQL第四讲 MySql Undo日志 - 对聚簇索引进行CUD操作,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

事务需要保证原子性,如果在事务执行过程中出现以下情况,就需要用到undo log

 1:事务执行中遇到各种错误,比如服务器本身的错误,操作系统错误甚至是断电导致的错误2:事务在执行过程手动rollback结束当前事务

每当对一条记录进行改动的时候(值 Insert Update Delete)都需要留一手把需要回滚的东西记录下载,比如: 在插入一条记录的时候,至少要把这条记录的主键值记录下来,这样之后需要回滚的时候只需要将对应的主键值记录删除;在删除一条记录的时候,需要将这条记录的内容记录下载,需要回滚的时候就把这些内容在插入到表中;在修改一条记录的时候,至少需要将要被更细的旧值记录下载,回滚的时候只需要再把这些列更新为旧的记录值。

分配事务id的时机

通过start transaction read only 可以开启一个只读事务,在只读事务中不可以对普通的表(其他事务也能访问的表)进行增删改操作,但是可以对临时表进行增删改操作

通过start transaction read write 语句开启一个读写事务,(begin, start transaction 也算读写事务),读写事务可以对表进行增删改操作

对于只读事务来说,只有对某一个用户创建的临时表进行增删改操作的时候,才会分配一个事务id,否则不分配事务id,

对于读写事务来说,只有对某条记录进行增删改操作时,才会分配事务Id(包含用户定义的临时表)

事务Id是一个全局属性,默认开始时是0,随着事务分配每次递增1,每当这个变量值为256的倍数时,就会将这个变量值刷新到系统空间表页号为5的页面中一个名为MAX TRx ID的属性中,这个属性占据8个字节空间,当系统下一次重新启动的时候,会将这个MAX TRX ID 属性加载到内存中,将该值加256之后赋予前面提到的全局变量中(因为在上次关机的时候,该全局变量的值可能大于磁盘页面的MAX TRX ID属性值)

记录的额外信息row_idtrx_idroll_pointer用户列信息
其中隐藏的row_id并不是必须的

undo日志也是从下标0开始进行编号的,根据生成的顺序分别称为第0号undo日志,第1号undo日志…第n号undo日志等,这个编号也称为undo no. 这些undo日志被记录到类型为FIL_PAGE——UNDO_LOG(对应的十六机制为0X0002)的页面中。这些页面可以从系统表空间中分配,也可以从专门存放undo日志的表空间分配(undo tablespace).

前面有说到在插入一条记录的时候,不管是乐观插入还是悲观插入,最终的结果都是将这条记录放到一个数据页中。在写undo日志的时候,只要把这条记录的主键信息记上就行,所以设计indoDB的大哥设计了一个类型为TRX_UNDO_INSERT_REC的undo日志,他的整体结构如下:
在这里插入图片描述

undo no 在一个事务中是从10开始递增的
如果记录中主键只包含一列,那么类型为 TRX_UNDO_INSERT_REC的undo日志中,只需要把该列占用的存储空间大小和真实值记录下来,如果记录中的主键值包含多个列,那么每一列占用的存储空间大小和对应的真实值都需要记录下来。len代表列占用的存储空间大小, value表示列的真实值
INSERT操作对应的 undo日志

实际上我们向表中插入一条记录的时候,需要向聚簇索引和所有的二级索引都插入一条记录,不过在记录undo日志的时候,我们只需要针对聚簇索引记录来记录一条undo日志,聚簇索引记录和二级索引记录都是一一对应的,我们在回滚insert记录的时候,只需要知道这条记录对应的主键信息,就可以根据主键信息进行对应的删除操作,在删除的同时也会把聚簇索引和所有的二级索引中对应的记录都删除掉。DELETE UPDATE操作也是针对聚簇索引记录的改动来记录undo日志的。

现在说一下roll_pointer,这个占用七个字节的字段其实本质上就是执向记录对应的undo日志的指针。比如 在一条表执行了两条更新操作,就会通过roll_pointer将生成的两条undo 日志链接起来,聚簇索引是存放在FILE_PAGE_INDEX的页面中(也就是数据页),undo日志存放在FILE_PAGE_UNDO_LOG页面中。
在这里插入图片描述
roll_pointer本质上就是一个指针,指向记录对应的undo日志。

DELETE操作对应的undo日志

插入到页面中的记录会根据记录头信息的next_record属性组成一个单向链表,称这个链表为正常记录链表。其中被删除的记录也会根据记头的信息中的next record属性组成一个链表,只不过这个链表中的记录占用的存储空间可以被重新利用,所以也称这个链表为垃圾链表。PAGE HEader中存在一个名为PAGE_FREE的属性,指向由被删除记录组成的垃圾链表中的头节点。
在这里插入图片描述

在垃圾链表中,这些记录占用的·存储空间可以被重新利用,在页面的page header部分中,page free属性的值代表指向垃圾链表头节点的指针。在delete语句把正常记录链的最后一条记录删除,这个删除操作过程历经两个阶段。

阶段1: 仅仅将记录的deleted_flag标识位设置为1,其他的不做修改(trx_id,roll_pointer也会修改,但是是隐藏列的值)这个阶段被称为delete mark,这个时候并不会把删除的正常记录添加到删除链表(加入到链表的头结点),在删除语句所在的事务提交前,被删除的记录一直处于这个中间状态。这个就是实现MVCC机制的一个功能。

阶段2: 删除语句的事务提交后,会有专门的线程来真正执行删除操作,把记录从正常记录链表删除,添加到垃圾链表,修改页面中的用户记录数量 PAGE_N_RECS,上次插入记录的位置PAGE_LAST_INSERT,垃圾链表头结点的指针 PAGE——FREE,页面中可重用的字节数 PAGE_GARBAGE,这个阶段被称为 purge。被删除后的记录占用的空间就可以被重新利用。

这里有一个问题,随着新插入记录的增多,如果新插入的记录小于垃圾链表头节点对应删除记录占用的空间,那意味着头结点占用的存储空间就要有一部分存储空间用不到,这部分空间就是碎片空间,随着记录越插越多,由此产生的碎片也越来越多,如何管理利用这部分碎片空间就变得十分重要。MYSQL设计值将这些碎片空间统计到 PAGE_GARBAGE属性中,这些碎片空间在整个页面快使用完之前并不会被重新利用,在页面快满时,如果再插入一条心记录,此时页面中并不能分配一条完整记录的空间,这个时候就需要看PAGE_GARBAGE的空间和剩余的可用空间相加之后是否可以容纳这条记录。这个时候INNODB会尝试重新组织页内的记录。重新组织的过程会先开辟一个临时页,把页面的记录依次插入一遍。因为依次插入记录时不会产生碎片,之后再把临时页面的内容复制到本页面,这样就可以把那些碎片空间都解放了,当然重新组织页面内的记录会比较耗费性能。

Update操作对应的undo日志

update不更新主键的时候,可以细分为被更新的列占用的列存储空间不发生变化和发生变化
1:不更新主键-就地更新

对于更新的列,更新前后占用的存储空间大小一样,那么就可以就地更新

2:不更新主键-先删除旧记录,再插入新记录
这里的删除并不是delete mark操作而是真正的删除,也就是会把这条正常记录从正常记录链表中移除,并加入到垃圾链表头部,并且修改页面对应的统计信息。这里执行真正删除的操作线程不是在DElete语句中进行的purge操作时使用的线程,而是由用户线程同步执行真正的删除操作。、

3: 更新主键

需要先对旧记录进行delete mark操作,在update事务提交后才会由专门的线程执行purge操作。之索引只是对记录执行delete mark操作,是因为其他事务可能会访问这条记录,如果把它删除并加入到垃圾链表后,别的事务就无法访问了,这个功能就是MVCC。

之后会根据更新后各列的值创建一条记录,并将其插入到聚簇索引中。

增删改操作对二级索引的影响,对于二级索引来说执行INSERT DELETE操作与聚簇索引中执行是产出的影响是差不多的,但是在执行UPDATE的时候会有差别,当我们在二级索引执行UPDATE操作时,会执行两个操作;
1: 对旧的二级索引执行delete mark操作
2:根据更新后的值创建一条新的二级索引记录,然后再二级索引对应的B+树中重新定位到它的位置并插进去。

注意 :这里同样是delete mark操作,也就是说在update语句所在的事务提交前,对旧的记录只是执行了delete mark操作,并不是直接删除旧记录,在事务提交后会有专门的线程执行purge操作,从而把它们加入到垃圾链表中。(如果直接进行正在的删除并加入到垃圾链表中,别的事务就访问不到了,这个功能就是MVCC)

增删改操作对二级索引的影响

一个表可以拥有一个聚簇索引以及多个二级索引,对于二级索引来说,insert操作和delete对二级索引的影响和在聚簇索引中执行的操作产生的影响差不多,但是对于update操作,有稍微不同的地方,如果我们的update操作的列字段没有涉及到二级索引,那么就不需要对二级索引执行任何的操作,相反,如果在update的时候修改了二级索引列,就需要进行下面的操作:

1:对旧的二级索引进行delete mark操作
2:根据更新后的值创建一条新的二级索引记录,然后在二级索引对应的B+树中重新定位到它的位置并插入进去。

对二级索引进行修改的时候,会影响到二级索引所在页面的Page Header的部分中一个名为PAGE_MAX_TRX_ID的属性,这个属性表示修改当前页面的最大事务id.

这篇关于MySQL第四讲 MySql Undo日志 - 对聚簇索引进行CUD操作的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/215053

相关文章

MySQL中删除重复数据SQL的三种写法

《MySQL中删除重复数据SQL的三种写法》:本文主要介绍MySQL中删除重复数据SQL的三种写法,文中通过代码示例讲解的非常详细,对大家的学习或工作有一定的帮助,需要的朋友可以参考下... 目录方法一:使用 left join + 子查询删除重复数据(推荐)方法二:创建临时表(需分多步执行,逻辑清晰,但会

如何使用celery进行异步处理和定时任务(django)

《如何使用celery进行异步处理和定时任务(django)》文章介绍了Celery的基本概念、安装方法、如何使用Celery进行异步任务处理以及如何设置定时任务,通过Celery,可以在Web应用中... 目录一、celery的作用二、安装celery三、使用celery 异步执行任务四、使用celery

Springboot的ThreadPoolTaskScheduler线程池轻松搞定15分钟不操作自动取消订单

《Springboot的ThreadPoolTaskScheduler线程池轻松搞定15分钟不操作自动取消订单》:本文主要介绍Springboot的ThreadPoolTaskScheduler线... 目录ThreadPoolTaskScheduler线程池实现15分钟不操作自动取消订单概要1,创建订单后

oracle数据库索引失效的问题及解决

《oracle数据库索引失效的问题及解决》本文总结了在Oracle数据库中索引失效的一些常见场景,包括使用isnull、isnotnull、!=、、、函数处理、like前置%查询以及范围索引和等值索引... 目录oracle数据库索引失效问题场景环境索引失效情况及验证结论一结论二结论三结论四结论五总结ora

SpringBoot操作spark处理hdfs文件的操作方法

《SpringBoot操作spark处理hdfs文件的操作方法》本文介绍了如何使用SpringBoot操作Spark处理HDFS文件,包括导入依赖、配置Spark信息、编写Controller和Ser... 目录SpringBoot操作spark处理hdfs文件1、导入依赖2、配置spark信息3、cont

Mysql 中的多表连接和连接类型详解

《Mysql中的多表连接和连接类型详解》这篇文章详细介绍了MySQL中的多表连接及其各种类型,包括内连接、左连接、右连接、全外连接、自连接和交叉连接,通过这些连接方式,可以将分散在不同表中的相关数据... 目录什么是多表连接?1. 内连接(INNER JOIN)2. 左连接(LEFT JOIN 或 LEFT

使用JavaScript操作本地存储

《使用JavaScript操作本地存储》这篇文章主要为大家详细介绍了JavaScript中操作本地存储的相关知识,文中的示例代码讲解详细,具有一定的借鉴价值,有需要的小伙伴可以参考一下... 目录本地存储:localStorage 和 sessionStorage基本使用方法1. localStorage

使用JavaScript将PDF页面中的标注扁平化的操作指南

《使用JavaScript将PDF页面中的标注扁平化的操作指南》扁平化(flatten)操作可以将标注作为矢量图形包含在PDF页面的内容中,使其不可编辑,DynamsoftDocumentViewer... 目录使用Dynamsoft Document Viewer打开一个PDF文件并启用标注添加功能扁平化

JavaScript DOM操作与事件处理方法

《JavaScriptDOM操作与事件处理方法》本文通过一系列代码片段,详细介绍了如何使用JavaScript进行DOM操作、事件处理、属性操作、内容操作、尺寸和位置获取,以及实现简单的动画效果,涵... 目录前言1. 类名操作代码片段代码解析2. 属性操作代码片段代码解析3. 内容操作代码片段代码解析4.

SpringBoot使用minio进行文件管理的流程步骤

《SpringBoot使用minio进行文件管理的流程步骤》MinIO是一个高性能的对象存储系统,兼容AmazonS3API,该软件设计用于处理非结构化数据,如图片、视频、日志文件以及备份数据等,本文... 目录一、拉取minio镜像二、创建配置文件和上传文件的目录三、启动容器四、浏览器登录 minio五、