玩命加载中 . . .

9-InnoDB的表空间


页面类型

类型名称(FIL_PAGE_) 十六进制 描述
TYPE_ALLOCATED 0x0000 最新分配,还未使用
UNDO_LOG 0x0002 undo日志页
INODE 0x0003 存储段的信息
IBUF_FREE_LIST 0x0004 Change Buffer 空闲列表
IBUF_BITMAP 0x0005 Change Buffer 的一些属性
TYPE_SYS 0x0006 存储一些系统数据
TYPE_TRX_SYS 0x0007 事务系统数据
TYPE_FST_HDR 0x0008 表空间头部信息
TYPE_XDES 0x0009 存储区的一些属性
TYPE_BLOB 0x000A 溢出页
INDEX 0x45BF 索引页,或说数据页

9.2 独立表空间结构

连续64个页组成一个区,所以一个区占用1MB空间,每256个区被划分一组

  • 第一个组最开始的3个页面的类型是固定的
    • FSP_HDR:登记整个表空间的一些整体属性以及本组所有区(extent 0~255)的属性
    • IBUF_BITMAP:存储关于Change Buffer的一些信息
    • INODE:存储了INODE Entry的数据结构
  • 其余各组最开始的2个页面类型是固定的
    • XDES:用来登记本组256个区的属性
    • IBUF_BITMAP:同上

表空间被划分为许多连续的区(区里页面的页号是连续的),每个区默认由64个页组成,每256个区划分为一组,每个组的最开始的几个页面类型是固定的

9.2.2 段的概念

分为叶子节点段和非叶子节点段

在表中数据量很大时,为某个索引分配空间的时候就不再按照页为单位分配了,而是按照区为单位进行分配

如果数据量较小,就分配在碎片区中,碎片区直属于表空间

所以为某个段分配存储空间的策略分2步:

  • 在刚开始向表中插入数据时,段是从某个碎片区以单个页面为单位来分配存储空间的

  • 当某个段已经占用了32个碎片区页面之后,就会以完整的区为单位来分配存储空间,原先占用的碎片区页面并不会被复制到新申请的完整的区中

9.2.3 区的分类

  • 空闲的区(FREE
  • 有剩余空闲页面的碎片区(FREE_FRAG
  • 没有剩余空闲页面的碎片区(FULL_FRAG
  • 附属于某个段的区(FSEG

XDES Entry(Extent Descriptor Entry)数据结构可以用来管理这些区,描述每个区的属性

总共40字节,包括4部分

  • Segment ID(8字节):每个段的编号
  • List Node(12字节):将多个XDES Entry结构串成一个链表
  • State(4字节):表明区的状态,即FREE/FREE_FRAG/FULL_FRAG/FSEG
  • Page State Bitmap(16字节):128位,每2位对应一个页面,所以总共是64个页面,第1位表示页是否空闲,第2位还没用到

1、XDES Entry链表

向表中插入数据本质上就是向表中各个索引的叶子节点段、非叶子节点段插入数据

当段中数据较少时,首先会查看表空间中是否有状态为FREE_FRAG的区(也就是查找还有空闲页面的碎片区)。如果找到了,那么从该区中取一个零散页把数据插进去;否则到表空间中申请一个状态为FREE的区(也就是空闲的区),把该区的状态变FREE_FRAG,后从该新申请的区中取一个零散页把数据插进去。之后,在不同的段使用零散页的时候都从该区中取,直到该区中没有空闲页面;然后该区的状态就变成了FULL_FRAG

每个区的XDES Entry中都记录了该区的状态,这样就可以把相同状态的区串联成一个链表,形成三种链表

  • FREE链表
  • FREE_FRAG链表
  • FULL_FRAG链表

当段中的数据已经占满32个零散的页后,就直接申请完整的区来插入数据了

XDES Entry中的Segment ID用来描述这个区属于哪个段,相同状态的区连接成链表,这样我们就可以快速找到某个段的不同状态的区了

  • FREE链表:同一个段中的所有页面都是空闲页面的区
  • NOT_FULL链表:同一个段中的仍有空闲页面的区
  • FULL链表:同一个段中的没有空闲页面的区

一个索引对应两个段,每个段都会维护上述3个链表

2、链表基节点

每条链表都有一个List Base Node结构与之对应,包括3部分

  • List Length表明该链表公有多少个节点
  • First Node Page NumberFirst Node Offset表明该链表的头结点在表空间中的位置
  • Last Node Page NumberLast Node Offset表明该链表的尾节点在表空间中的位置

9.2.4 段的结构

段由若干个零散的页面以及一些完整的区组成

每个段都有一个INODE Entry结构与之对应,分为5部分,共192字节

  • Segment ID(8字节):段的ID
  • NOT_FULL_N_USED(4字节):在NOT_FULL链表中已经使用了多少个页面
  • 3个List Base Node(3X16字节):分别为段的FREE链表、NOT_FULL链表、FULL链表定义的List Base Node,这样就可以快速找到段对应的不同状态的区
  • Magic Number(4字节):标记这个INODE Entry是否已经被初始化
  • Fragment Array Entry(4X32字节):对应段的32个零散的页面

段是一些零散的页面和一些完整的区的集合

9.2.5 各类型页面的详细情况

1、FSP_HDR类型

第一个组的第一个区的第一个页面

名称 中文名 大小(字节) 描述
File Header 文件头部 38 页的通用信息
File Space Header 表空间头部 112 表空间的一些整体属性信息
XDES Entry 区描述信息 10240 存储本组256个区对应的属性信息
Empty Space 尚未使用的空间 5986 用于页结构的填充
File Trailer 文件尾部 8 校验页是否完整

2、XDES类型

之后每个分组的第一个页面只需要记录本组内所有的区对应的XDES Entry结构即可,不需要再记录表空间的信息,所以XDES类型和FSP_HDR类型是一样的,只是没有File Space Header部分

3、IBUF_BITMAP类型

每个分组中第二页页面类型都是IBUF_BITMAP,这种类型的页中记录了一些有关Change Buffer的东西

为了减少插入删除数据带来的随机IO,在修改非唯一二级索引页面时,如果该页面尚未被加载到内存中,那么该修改将先被暂存到Change Buffer中,之后服务器空闲或者其他原因导致对应的页面被加载从内存中时,再将修改合并到对应页面

4、INODE类型

第一个分组的第三个页面是INODE类型,INODE类型的页面是为了存储段的INODE Entry结构而存在的

名称 中文名 大小(字节) 描述
File Header 文件头部 38 页的通用信息
List Node for INODE Page List 通用链表节点 12 存储上一个INODE页面和下一个INODE页面的指针
INODE Entry 段描述信息 16320 存储INODE Entry结构
Empty Space 尚未使用的空间 5986 用于页结构的填充
File Trailer 文件尾部 8 校验页是否完整

一个页面可以存85个INODE Entry结构

如果超过了85个,就需要另外的INODE页面来存储,就需要把这些INODE页面串联起来,形成两个链表

  • SEG_INODES_FULL链表:在该链表中,INODE类型的页面中已经没有空闲空间来存储额外的INODE Entry结构
  • SEG_INODE_FREE链表:在该链表中,INODE类型的页面中还有空闲空间来存储额外的INODE Entry结构

存储INODE Entry的过程大致为:

  • 先看看SEG_INODES_FREE链表是否为空。如果不为空,直接从该链表中获取一个节点,也就相当于获取到一个仍有空闲空间的INODE类型的页面,然后把该INODE Entry结构放到该页面中。当该页面中无剩余空间时,就把该页放到SEG_INODES_FULL链表中
  • 如果SEG_INODES_FREE链表为空,则需要从表空间的FREE_FRAG链表中申请一个页面,并将该页面的类型修改为INODE,把该页面放到SEG_INODES_FRFE链表中;与此同时把该INODE Entry结构放入该页面

9.2.6 Segment Header结构的运用

每个索引的两个段的INODE Entry结构保存在根节点中,在根节点的页面中定义了两个字段

名称(PAGE_) 大小(字节) 描述
BTR_SEG_LEAF 10 B+树叶子节点段的头部信息,仅在B+树根页面中定义
BTR_SEG_TOP 10 B+树非叶子节点段的头部信息,仅在B+树根页面中定义

这两个字段都对应着Segment Header结构

名称 大小 描述
Space ID of the INODE Entry 4 INODE Entry结构所在的表空间ID
Page Number of the INODE Entry 4 INODE Entry结构所在的页面页号
Byte Offset of the INODE Entry 2 INODE Entry结构在该页面中的偏移量

这样索引和对应的段的关系就建立起来了


文章作者: kunpeng
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 kunpeng !
  目录