前言
大家好,我是xicheng。现在继续更新MySQL,本篇讲InnoDB的表空间,该部分类容比较枯燥繁琐,但又是MySQL后续内容的基础。所以大家可以先学习理解整体框架,等后续篇章用到的时候,再回过头查阅,进一步加深理解。另外,InnoDB的知识脑图如下所示,大家坐稳了。
表空间
表空间(tablespace)由段(sagment)组成,段由区(extent)组成,区由页(page)组成,页由行组成。如下图所示。
所有数据都存放在表空间中。如果用户手动启用了参数innodb_file_per_table,则每张表的数据可以单独放在一个表空间中。
段
逻辑上的概念,⼀个索引会⽣成2个段,⼀个叶⼦节点段(存放叶⼦节点的区),⼀个⾮叶⼦节点段(存放⾮叶⼦节点的区)。
在刚开始向表中插⼊数据的时候,段是从某个碎⽚区(并不是所有页都是存储一个段的数据的区)以⻚为单位来分配存储空间的。
当某个段已经占⽤了32个碎⽚区⻚⾯之后,就会以完整的区为单位来分配存储空间(原先占用的碎片区的页不会被复制到新的区中来)。
常见的段由数据段,索引段,回滚段等。
区结构
对于16KB的页,物理位置连续的64个页就是一个区(extend),大小1MB。256个区被划分为1个组。
每个组中第一个区的固定页如下图所示。
第一组中第0区开始的3个⻚的类型是固定的:
- FSP_HDR(16KB):整个表空间的⼀些整体属性以及本组所有的区,整个表空间只有⼀个该类型的⻚⾯。
- IBUF_BITMAP(16KB):本组所有的区的所有⻚⾯关于INSERT BUFFER的信息。
- INODE(16KB):存储了许多 INODE 的数据结构。
其余各组最开始的 2 个⻚⾯的类型是固定的:
- XDES ( extent descriptor):本组 256 个区的属性。
- IBUF_BITMAP:存储本组所有的区的所有⻚⾯关于 INSERT BUFFER 的信息。
- 在表中数据量⼤的时候,为某个索引分配空间的时候就不再按照⻚为单位分配了,⽽是按照区为单位分配。
区分类
空闲的区:FREE,还没有⽤到这个区中的任何⻚⾯。
有剩余空间的碎⽚区:FREE_FRAG,表示碎⽚区中还有可⽤的⻚⾯。
没有剩余空间的碎⽚区:FULL_FRAG,表示碎⽚区中的所有⻚⾯都被使⽤,没有空闲⻚⾯。
附属于某个段的区:FSEG。
区的XDES Entry
结构
为了方便管理区而设计的。共40个字节,分为4个部分。
- SegmentID(8字节):段唯一编号,表示就是该区所在的段(前提是该区已被分配给某段了,否则该字段无意义)。
- ListNode(12字节):PreNodePageNumber(4字节,前一页的页号)和PreNodeOffset(2字节,前一页的页号在页内的偏移量)指向前⼀个XDESEntry。NextNodePageNumber(4字节,后一页的页号)和NextNodeOffset(2字节,后一页的页号在页内的偏移量)指向后⼀个XDESEntry。
- State:区的状态。参见“InnoDB表空间-区分类”