mysql undo日志 - undo页面链表和undo日志写入过程

Undo页面链表

单个事务中的undo页面链表

因为一个事务可能包含很多的语句,而且一个语句可能会对若干条记录进行改动,而每一条记录进行改动前(z这里指的是聚簇索引记录)都需要一条或者两条undo日志,所以在一个事务执行过程中可能产生很多undo日志,他们可能在一个页面,也可能在多个页面,这些页面就是通过TRX_UNDO_PAGE_NODE进行链接。如图:
mysql undo日志 - undo页面链表和undo日志写入过程_第1张图片

一个事务执行过程中会混着执行insert delete update语句,这也就是意味着产生不同类型的undo日志。而同一个undo页面要么只存储TRX_UNDO_INSERT大类的undo日志,要么存放TRX_UNDO_UPDATE大类下的undo日志,不能混着存储。所以在一个事务执行中就可能需要两个undo页面的链表,一个称为insert undo链表,另外一个称为update undo链表。

而对普通表和临时表的记录改动产生的undo日志又需要分别记录,所以在一个事务中最多产生4个以undo页面为节点组成的。当然并不是在事务一开始就为他们分配这4个链表,而是根据具体事务执行过程中更新的表的类型以及执行的操作,在开启事务时,一个undo页面链表也不分配。

多个事务中undo页面链表

为了尽可能提高undo日志的写入效率,不同事务执行过程中产生的undo日志需要写入不同的undo页面链表中。

undo日志具体写入过程

这里稍微说一个段的概念,简单来说段就是一个逻辑上的概念,本质上是由若干个零散页面和若干个完整的区组成的。比如,一个B+树索引被划分为两个段,一个叶子节点段和一个非叶子节点段,这样叶子节点就可以被尽可能地存放在一起,非叶子节点被尽可能存储在一起,每一个段对应一个INDO ENTRY 结构,这个INDO ENTRY结构描述了这个段的各种信息,比如段的ID,段内的各种链表基节点,零散页面的页号有哪些等。

每页UNDO页面链表都对应着一个段,称为UNDO LOG SEGMENT , 也就是说,链表中的页面都是从这个段中申请的,所以他们在undo页面链表的第一个页面(也就是 first undo page)设计一个undo log segment header 的部分,这个部分包含该链表对应的段的segment header信息,以及其他的一些关于这个段的信息。
mysql undo日志 - undo页面链表和undo日志写入过程_第2张图片
可以看到,这个undo页面链表的第一个页面比普通的页面多了一个 UNDO LOG Segment HEADER,我们看一下它的结构,如图:

mysql undo日志 - undo页面链表和undo日志写入过程_第3张图片

其中各个属性的意思如下:
TRX_UNDO_STATE: 本undo页面链表处于什么状态,可能的状态有下面几种:

TRX_UNDO_ACTIVE: 活跃状态,也就是一个活跃的事务正在向undo页面链表中写入undo日志
TRX_UNDO_CACHED: 被缓存状态,处于该状态的Undo页面链表等待之后被其他事务重用
TRX_UNDO_TO_FREE: 等待被释放的状态,对于insert undo链表来说,如果在它对应的事务提交之后,该链表不能被重用,那么就会处于这种状态
TRX_UNDO_TO_PURGE: 等待被purge的状态,对于处于update undo链表来说,如果在它对应的事务提交之后,该链表不能被重用,那么就会处于这种状态
TRX_UNDO_PREPARED: 处于此状态的Undo页面链表用于存储处于PREPARE阶段的事务产生的日志,该阶段是在分布式事务中才会出现

对于没有被重用的Undo页面链表来说,链表的第一个页面在真正写入undo日志前,会填充undo page header, undo log segment header , undo log header 这三个部分,之后才开始正式写入undo日志。对于其他页面(也就是normal undo page)来说,在真正写入undo 日志前,只会填充undo page header ,链表基节点存放到first undo page的undo log segment header部分, 链表节点信息存放到每一个undo页面的undo page header部分。

mysql undo日志 - undo页面链表和undo日志写入过程_第4张图片

你可能感兴趣的:(mysql数据库,链表,mysql,java)