第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日志实现的背后的底层细节部分,了解一下即可