Innodb 表空间
前面的文章中我们知道了,在Innodb
中,一张表就对应一个.idb
文件。Innodb 管理数据的最小单位是页
。而表空间是一种抽象的概念,对底层文件系统的抽象,我们今天要研究的是在表空间中,是如何管理这些页的。
表空间可以分为独立表空间
和系统表空间
,其实组织结构是差不多的,所以这里重点研究独立表空间
,系统表空间中知识增加了 MySQL 进程的一些运作信息而已(事实上也没有这么简单,不过不做深入研究)。
区的概念
Innodb 规定,区(extent)是磁盘上一块连续的存储空间,一个区由64
个页组成,也就是占1MB
的存储空间。
表空间其实就是由很多个区组成的。
为什么要进行分区呢?
我们都知道用户记录存放在叶子节点
上,无论是叶子节点还是非叶子节点,处于B+树
同一层的数据页,都会维护一个双向链表,方便跨页查询。这些数据页,是逻辑上连续的,物理上可连续或分散存储。
Innodb 是持久化的存储引擎,意味着数据是要刷到磁盘上的。既然是在磁盘上存储,那么顺序I/O
肯定比随机I/O
效率要高很多。顺序 I/O 主要依赖于数据在磁盘上的一种连续性的存储。
区,作为一块物理上连续的存储空间,可以很好的利用顺序 I/O
的高效性,加快数据的访问速度。一个区中的数据页都是连续存储的,即页号
是连续的。
XDES Entry
一个区对应一个 XDES Entry
结构,该结构用于描述对应区的一些属性:
(图片百度找的,上面有蓝色字体,注意看)
Segment ID
段
id,这个区是属于哪个段的(下文会说什么是段的)List Node
不同区之间,需要建立联系,具体的表现就是它们对应的
XDES Entry
会形成一个双向链表,指向上一个和下一个Entry
的位置State
区的“状态”,或者说区的“类型”:
- 空闲区:分配了空间,但是未被使用
- 有剩余空间的碎片区:碎片区中,还有未被填充或者胃未填充完的数据页
- 没有剩余空间的碎片区:碎片区空间使用完毕
- 属于某个段的区:与Segment ID呼应
(关于段和碎片区的概念,后续会说)
Page State Bitmap
“页状态位图”,用两个比特位表示页的状态,有 64 个页就有 128 个比特位。第一个比特位表示页是否空闲;第二个比特位是预留位,还没有被使用。
段的概念
段是一些零散的页面和完整的区的集合。
(我知道你很懵,且看下文)
段是逻辑上对区的一种划分。主要可以分为:叶子节点段、非叶子节点段、其他类型的段(后面的文章会说)。
为什么要将叶子节点和非叶子节点分开呢?
如果不区分叶子节点和非叶子节点,统一的放入同一个区中,扫描的效率就会降低很多,所以才对两者进行了区别对待。
但是分开之后,遇到了一个问题,段的基本分配单位是区,也就意味着如果一张小表,只存放了几条记录,分配了两个段之后,就占用了2MB
的空间,岂不是有很多的空间浪费?(不确保这些空间未来将被利用)
碎片区
区的一种,目的就是为了解决上文段空间分配的空间浪费问题。
怎么解决的呢?
在表数据量较小的时候,从碎片区分配数据页进行数据的存储,意味着碎片区中的数据页可能归属于不同的段。当某个段占满了碎片区中32
个页之后,段空间扩张时,就是以区为单位去分配存储空间了。
这里就涉及到另一个问题了,我怎么知道哪些是碎片区呢?遍历嘛?
XDES Entry 链表
遍历是不可能遍历的,这辈子都不可能遍历!
表空间内维护了三种不同类型的链表:
FREE 链表
所用已分配但是未使用的空闲区对应的
XDES Entry
组成一个链表FREE_FRAG 链表
有剩余空间的碎片区对应的
XDES Entry
组成一个链表FULL_FARG 链表
没有剩余空间的碎片区对应的
XDES Entry
组成一个链表
这样一来,找碎片区还不简单嘛,直接取出链表头节点即可。
现在问题又来了,段分配了新的区,以后的插入操作肯定是在这个区中进行的(区没有满的话),那么这么多的区,怎么知道哪个区是哪个段的呢?
设计 Innodb 的人也考虑到了这个问题,同样的,也会为每个段维护三个链表:
FREE 链表
同一个段中空闲区对应的
XDES Entry
组成的链表NOT_FULL 链表
同一个段中还有剩余空间的区对应的
XDES Entry
组成的链表FULL 链表
同一个段中已经使用完毕的区对应的
XDES Entry
组成的链表
现在知道怎么找到对应的区了吧。
还有问题,这么多的链表,怎么找到这些链表的头节点呢?
链表基节点
这也是个数据结构,存储着上述各种各样链表的:节点数量、头节点位置、尾节点位置。
OK,问题完美解决。
补充概念 —— 组
每256
个区归位一组,每组的前几个页面的类型很类似,当然这里不会多说。这里主要强调的是,组和段的区别。组可以理解是一种数据在物理上的组织形式,数据是这么划分的,组是连续的;段它是一种逻辑上的概念,是抽象的集合。
(好吧我的描述可能还是很抽象,大家自行体会)
总结
其实如果要详细的描述表空间的话,很多,描述不完,这里就挑了一些重点。
2025/02/01
writeBy kaiven