《从根上理解MySQL是怎样运行的》第二十三章笔记

第23章 后悔了怎么办-undo日志(下)

知道了undo日志是做什么的,不同类型的undo日志格式是什么

那么undo日志具体是写在哪些地方的呢,写入过程中需要注意什么问题?


通用链表的结构

Undo日志会使用多个链表,链表都有相同的节点结构。这些结构和之前学习表空间的中的链表实际上是差不多的

(1)在表空间中通过页号和页内的偏移量确定唯一一个节点的位置,这两个信息组合在一起相当于指针:

Pre Node Page Number + Pre Node Offset = 前一个节点的指针

Next···· + Next····· = 后一个节点的指针

(2)基节点,通过这个基节点的结构可以更好地管理整个链表,其中存储了头节点,尾节点,以及链表长度信息


FIL-PAGE-UNDO-LOG页面

该类型的页面存储的是UNDO日志。Undo页面中有特有的Undo Page Header存储了一些特有的信息:

TRX-UNDO-PAGE-TYPE:存储undo日志的类型,一种类型的undo日志只能放到相应的一种页面中去才行

TRX-UNDO-PAGE-START:标志存储第一条undo日志在本页中的位置

TRX-UNDO-PAGE-FREE:最后一条undo日志存放的位置,通过它可以知道下一条undo日志从哪里开始存储

TRX-UNDO-PAGE- NODE:代表一个List Node结构,也就是刚刚提到的链表的通用节点


Undo页面链表

一个事务可以产生很多undo日志,于是可以产生很多相应的undo页面,这些页面可以通过NODE属性构成一条链表

不同类型的Undo页面形成的链表的类型也是不一样的,所以一个事务可以有多个类型的undo页面链表组成,具体过程如下:

(1)一开始创建事务,什么类型页面的undo链表也不分配

(2)执行插入记录或者更新记录主键的操作以后,自动分配一个普通的insert undo链表

(3)执行了删除或者更新:分配普通update 链表

(4)执行临时表插入或者更新记录主键值:分配一个临时表的insert链表

(5)执行临时表的删除/更新:分配一个临时表的update undo页面链表

总结:按需分配,只会分配需要类型的对应的undo页面链表


多个事务中的Undo页面链表

不同的事务对应的Undo页面链表也是分别成组独立的,不会共用


Undo日志具体的写入过程

每一个Undo页面链表都对应一个段,称之为Undo Log Segment

链表中的页面都是从段中进行申请的,Undo段的第一个页中记录的是整个链表中的信息


Undo Log Header

申请完空间以后直接插入undo日志即可,同一个事务的多个不同的undo页面链表称之为一个组

一个组的首页会记录相关的该组的一些信息


小结:先申请空间-》划分成组的方式进行undo日志的记录


重用Undo页面

一个事务就要分配不同的独立的undo页面链表,如果存储的记录很少的话,还是挺浪费的。所以设计师设计出了undo页面链表的重用机制

重用的条件:

(1)该链表中只包含一个Undo页面

(2)Undo页面使用的空间小于整个页面空间的3/4:

对于insert类型的undo页面来说:直接将之前旧的undo日志页面覆盖掉,从头开始写新的事务的undo日志,并且调整相关的统计数据

对于update 类型:update设计MVCC,所以不可以直接删除,先留着,直接在后面跟着写新的事务的undo日志即可


回滚段

回滚段就是undo页面链表的集合


从回滚段中申请Undo页面链表

(1)Undo页面链表的形成过程

回滚段一开始就是创建在表空间中的,分配Undo页面链表的时候先看看undo slot,也就是回滚槽位是否为空:是否为FIL-NULL,是否已经指向了一个新的Undo页面了

如果是,那么创建一个新的回滚段,然后从该段中申请一个页面作为Undo页面的first undo page,如果不是就跳到下一个槽位中重复判断过程

如果槽位都被占满了,那么就会报错

(2)undo槽位占用后的结局是什么?

如果符合被重用的条件,那么直接放到缓存链表中进行存储,预备给新来的事务

如果不符合重用的规则,那么针对不同的undo页面类型做处理,insert类型则直接可以释放掉,update类型那么可以设置为FIL-NULL然后将本次事务写在一个新的Histroty链表中


多个回滚段

一个事务的执行可以最多索取4个Undo页面,但是一个回滚段只有1024个槽位

因此设计师一开始就定义了128个回滚段,也就是128个Rollback Segment Header页面,这些页面存放在第二号页面的某个区域中


回滚段的分类

临时回滚段和正常的回滚段

临时回滚段只需要在系统运行的时候有效就行了,所以不需要相应的redo日志。(因为写undo日志页面也是一种记录)但是针对普通的表是需要的


回滚段的使用实例:

事务执行 -》 索取回滚段 -〉 -》 看看有没有可以用的缓存槽位 -〉 没有就重新去Header页面中找一个槽位 -》 没有报错就说明有空位,于是分配一个Log Segment -〉 然后在这个链表中写入undo日志即可!!

如果缓存中有的话直接走缓存中的Log Segment即可

Log Segment对应的就是undo页面的意思


回滚段的配置

可以通过设置系统参数来调整回滚段的数量


配置undo表空间

指定参数定义表空间所在的目录和数量


总结

所以Undo日志是写在哪里的呢?

是写在Undo页面中的,对于单个事务来说不同的Undo页面形成不同的链表,这些链表统一放到回滚段中的槽位中管理的

写入的过程中要注意页面是否为可以重用的缓存页,如果不是害得开始寻找槽位,并且还要注意不同类型的undo是写在不同的链表中的


这一章主要是介绍了undo日志实现的背后的底层细节部分,了解一下即可

相关推荐
Mr.徐大人ゞ44 分钟前
13.MHA 常用问题
mysql
LSL666_44 分钟前
云服务器安装MySQL
运维·服务器·mysql
卿雪1 小时前
MySQL【数据类型】:CHAR 和 VARCHAR 的对比、VATCHAR(n) 和 INT(n) 里的 n 一样吗?
android·java·数据库·python·mysql·adb·golang
麦聪聊数据1 小时前
Web架构如何打通从SQL 脚本到API 服务的全链路追踪?
数据库·sql·架构
范小多1 小时前
mysql实战 C# 访问mysql(连载三)
数据库·mysql·oracle·c#
Austindatabases1 小时前
SQLite 开发中的数据库开发规范 --如何提升业务系统性能避免基础BUG
数据库·oracle·sqlite·bug·数据库开发
枫叶丹41 小时前
【Qt开发】Qt窗口(六) -> QMessageBox 消息对话框
c语言·开发语言·数据库·c++·qt·microsoft
星环处相逢1 小时前
MySQL 备份与还原:理论与实战全解析
数据库·mysql
一起养小猫1 小时前
MySQL数据库基础:从三层结构到常用操作
数据库·mysql