MySQL undo日志精讲3-从回滚段中申请 Undo 页面链表

回滚段-Rollback Segment Header 页面

回滚段的概念

我们现在知道一个事务在执行过程中最多可以分配4个 Undo 页面链表,在同一时刻不同事务拥有的 Undo 页面链表是不一样的,所以在同一时刻系统里其实可以有许许多多个 Undo 页面链表存在。为了更好的管理这些链表,设计InnoDB的大佬又设计了一个称之为 Rollback Segment Header 的页面,在这个页面中存放了各个 Undo 页面链表的 first undo page 的页号,他们把这些页号称之为 undo slot
在这里插入图片描述
设计InnoDB的大佬规定,每一个 Rollback Segment Header 页面都对应着一个段,这个段就称为Rollback Segment,翻译过来就是回滚段。与我们之前介绍的各种段不同的是,这个Rollback Segment里其实只有一个页面(这可能是设计InnoDB的大佬们的一种洁癖,他们可能觉得为了某个目的去分配页面的话都得先申请一个段,或者他们觉得虽然目前版本的MySQL里Rollback Segment里其实只有一个页面,但可能之后的版本里会增加页面也说不定)。

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

初始情况下,由于未向任何事务分配任何Undo页面链表,所以对于一个Rollback Segment Header页面来说,它的各个undo slot都被设置成了一个特殊的值:FIL_NULL(对应的十六进制就是0xFFFFFFFF),表示该undo slot不指向任何页面。

随着时间的流逝,开始有事务需要分配Undo页面链表了,就从回滚段的第一个undo slot开始,看看该undo slot的值是不是FIL_NULL:

  • 如果是FIL_NULL,那么在表空间中新创建一个段(也就是Undo Log Segment),然后从段里申请一个页面作为 Undo 页面链表的 first undo page,然后把该 undo slot 的值设置为刚刚申请的这个页面的地址,这样也就意味着这个undo slot被分配给了这个事务。
  • 如果不是 FIL_NULL,说明该 undo slo t已经指向了一个undo链表,也就是说这个 undo slot 已经被别的事务占用了,那就跳到下一个undo slot,判断该undo slot的值是不是FIL_NULL,重复上面的步骤。

一个Rollback Segment Header页面中包含1024个undo slot,如果这1024个undo slot的值都不为FIL_NULL,这就意味着这1024个undo slot都已经名花有主(被分配给了某个事务),此时由于新事务无法再获得新的Undo页面链表,就会回滚这个事务并且给用户报错:

Too many active concurrent transactions

用户看到这个错误,可以选择重新执行这个事务(可能重新执行时有别的事务提交了,该事务就可以被分配Undo页面链表了)。

多个回滚段

我们说一个事务执行过程中最多分配 4 个 Undo 页面链表,而一个回滚段里只有1024个 undo slot,很显然 undo slot的数量有点少啊。我们即使假设一个读写事务执行过程中只分配1个Undo页面链表,那 1024 个 undo slot 也只能支持1024个读写事务同时执行,再多了就崩溃了。这就相当于会议室只能容下1024个班长同时开会,如果有几千人同时到会议室开会的话,那后来的那些班长就没地方坐了,只能等待前面的人开完会自己再进去开。

话说在InnoDB的早期发展阶段的确只有一个回滚段,但是设计InnoDB的大佬后来意识到了这个问题,咋解决这问题呢?会议室不够,多盖几个会议室不就得了。所以设计InnoDB的大佬一口气定义了128个回滚段,也就相当于有了128 × 1024 = 131072 个 undo slot。假设一个读写事务执行过程中只分配1个Undo页面链表,那么就可以同时支持131072个读写事务并发执行(这么多事务在一台机器上并发执行,还真没见过呢~)。
  每个回滚段都对应着一个Rollback Segment Header页面,有128个回滚段,自然就要有128个Rollback Segment Header页面,这些页面的地址总得找个地方存一下吧!于是设计InnoDB的大佬在系统表空间的第5号页面的某个区域包含了128个8字节大小的格子:
  在这里插入图片描述每个8字节的格子的构造就像这样:
  
在这里插入图片描述如果所示,每个8字节的格子其实由两部分组成:

4字节大小的Space ID,代表一个表空间的ID。
4字节大小的Page number,代表一个页号。  
也就是说每个8字节大小的格子相当于一个指针,指向某个表空间中的某个页面,这些页面就是Rollback Segment Header。
这里需要注意的一点事,要定位一个Rollback Segment Header还需要知道对应的表空间ID,这也就意味着不同的回滚段可能分布在不同的表空间中。

所以通过上面的叙述我们可以大致清楚, 在系统表空间的第5号页面中存储了 128 个 Rollback Segment Header 页面地址,每个 Rollback Segment Header 就相当于一个回滚段。在Rollback Segment Header页面中,又包含1024个undo slot,每个undo slot都对应一个Undo页面链表。我们画个示意图:
  在这里插入图片描述


undo 日志在崩溃时的作用???
redo 日志最终是需要写在磁盘里的,
undo 日志是存在内存里的,但是写 undo 页对应 的 redo 是在磁盘里的

相关推荐

  1. logback日志原理

    2023-12-24 12:44:02       19 阅读
  2. Hudi Spark Sql Procedures Hudi 数据

    2023-12-24 12:44:02       7 阅读
  3. Vue 3 单处理:打造响应式注册表单的艺术

    2023-12-24 12:44:02       34 阅读
  4. 【达梦数据库】查看pesg信息的视图和SQL

    2023-12-24 12:44:02       28 阅读

最近更新

  1. TCP协议是安全的吗?

    2023-12-24 12:44:02       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2023-12-24 12:44:02       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2023-12-24 12:44:02       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2023-12-24 12:44:02       20 阅读

热门阅读

  1. 基于LDPC和QAM的通信链路误码率MATLAB仿真

    2023-12-24 12:44:02       39 阅读
  2. 【Bash】重点总结

    2023-12-24 12:44:02       38 阅读
  3. 乐才无代码开发:连接CRM提升电商与营销系统

    2023-12-24 12:44:02       43 阅读
  4. 【C#与Redis】--Redis 命令

    2023-12-24 12:44:02       26 阅读
  5. ArchLinux搭建riscv测试环境(失败)

    2023-12-24 12:44:02       42 阅读
  6. Mysql四种事务隔离级别(简易理解)

    2023-12-24 12:44:02       38 阅读
  7. Python机器学习实战:用Python构建10个有趣的应用

    2023-12-24 12:44:02       35 阅读