区的分类&XDES Entry(3)---独立表空间结构(二十九)

上篇文章介绍了,表空间分为若干区,叶子节点和非叶子节点又分为不同的段,还有回滚段等,段里会存储碎片区不同数据页的集合和完全区的集合,碎片区是为了在数据刚存入表时候,存储不同段内的数据,当段内数据有32个碎片区时,会升级成为完整的区属于特有的段。

独立表空间结构(2)之段---InnoDB表空间(二十八)

区的区别

通过以上知识,知道了段分为若干个区,这些区大体可以分为四种类型:

  1. 空闲的区(FREE):现在还没有用到这个区中的任何页面。
  2. 有剩余空间的碎片区(FREE_FRAG):表示碎片区中还有可用的页面。
  3. 没有剩余空间的碎片区(FULL_FRAG):表示碎片区中所有的页面都被使用,无空闲页面。
  4. 附属某个段的区(FSEG):每个索引都有叶子节点段和非叶子节点段,除此之外innoDB还会定义一些特殊的作用段,这些段数据量很大时,将使用区来作为基本分配单位。

这四种类型称为区的状态state。

再次强调一下FREE、FREE_FRAG、FULL_FRAG因为是碎片区,这是直属于表空间管理的,而最后FSEG是直接属于某个段的。

为了方便管理这些区,于是mysql创建了extent descriptor Entry,简称xdes enrty,每个区都对应一个XDES Enrty结构,这些结构记录了区的对应属性,结构分为四大部分:

  1. Segment id(8个字节):每个段都有唯一的id,该字段就代表区属于哪个段,当然必须当前区已经分配给某个段了,不然没啥意思。
  2. List Node(12个字节):这个部分将若干个extent descriptor entry,xdes 组成双向链表,这里面的结构就是Prev Node Page Number(4个字节),Prev Node Offset(2个字节),Next Node Page Number(4个字节),Next Node Offset(2个字节)。若果我们在这里移动到某个位子,只要指向页号,和页内的偏移量即可。(温故知新:这里是不是和file header里的fil_page_prev和fil_page_next两个参数很像,也是吧数据页组成双向链表)
  3. State(4个字节):这就是前面我们说的,free空闲区,free_frag有空闲页的碎片区,full_frag没有空闲的碎片区,FSEG就是属于某个segment的区。
  4. Page State Bitmap(16个字节):16个字节,也就是128个比特位。我们说一个区是64个页,所以这里就分为一个区代表2个比特位,这里两个比特位的意思代表什么呢?第一个比特位代表对应的页是否是空闲,第二个比特位暂时还没使用到。
     

XDES Enrty链表

到现在为止,我们可以捋一捋数据整个的插入段的过程了,及其这个过程中xdes entry发挥的作用是什么。

首先新建表的数据很少,页属于某个区,区又属于某个段,但若在数据很少的情况下就让这个区属于特定的段,显然是浪费时间和空间的。

插入数据,先看free_frag是否有空闲的碎片区,有的话直接存进去,没有则去申请free碎片区,然后把free碎片区升级为free_frag碎片区,当free_frag碎片区存储满的时候,则会吧free_frag升级为full_frag碎片区。现在的问题是你如何知道哪些是空闲碎片区,哪些是碎片区,哪些是full_frag无空闲碎片区呢,难道遍历吗?

答案肯定是no,这时候xdes entry的作用就来了,他吧这三个类型链接成三个不同的链表,所以就有了

  1. free对应的xdes enrty组成的链表,链接起来的区叫做free 链表。
  2. free_frag对应的叫做free_frag链表。
  3. full_frag对应的xdes entry组成的叫做full_frag链表。

这样我们查找的时候,只需要看free frag链表是否为空,不为空则插入到当前碎片区,为空则去free链表新增free碎片区,并且修改state字段,当free_frag充满之后,也会修改state字段,进入full_frag碎片区。

那什么时候进入fseg区呢?当数据占满32个零散页后,就会升级到属于某个特定段的区。

那还是回到之前的问题,如何区分属于哪个段呢,直接把整个链表属于哪个段?肯定不行,整个链表里面的零散区是只属于表空间管理,存着不同段的数据,这样直接放又如何区分哪个是叶子节点段,非叶子节点段数据呢?按sengment Id也不行,因为段里面有很多区,有的区可能还是空闲的,并不是当前段的所有区进入了full_frag五空闲碎片区才开始属于某个特定段,所以还要继续细分。。。fseg区细分为三个链表:

  1. free链表:表示当前段还是空的碎片区。(与表空间直接管理的free不同,这里属于某个段)
  2. null_free链表:表示不为页空的碎片区。(与表空间直接管理的free_frag类似)
  3. full链表:表示存满的碎片区。(与表空间直节管理的full_frag类似)

所以分析一下,当一个表里有一个聚簇索引,一个二级索引的时候,有两个索引,而一个索引会生成子叶节点段和非子叶节点段,所以有四个段,而一个段需要管理三个链表,所以有12个链表,再加上表空间结构直接管理的3个链表,所以为了管理这些段里的区,一共有15个链表,当数据进入当前端的时候,会先看not_free链表,直接吧数据插入当前的段,当not_free为空的时候,则会进去段的full链表。

上一篇:ASP.NET Core 中文文档 第二章 指南(8) 使用 dotnet watch 开发 ASP.NET Core 应用程序


下一篇:MAC COCOA call command 调用终端控制台程序