mysql的InnoDB的独立表空间介绍

表空间是一个抽象的概念,对于系统表空间来说,对应着文件系统中一个或者多个实际文件,对于每个独立表空间来说,对应着文件系统中一个名为表名**.ibd**的实际文件。

1、回忆一些旧知识

1.1 页面类型

InnoDB是以页为单位管理存储空间的,我们的聚簇索引(也就是完整的页数据)和其他的二级索引都是以B+树的形式保存到表空中的,而B+树的节点也就是数据页,这个数据页的类型名为FIL_PAGE_INDEX。

下面表格中则是展示的各种常用的页面类型

类型名称描述
FIL_PAGE_TYPE_ALLOCATED最新分配还未使用
FIL_PAGE_UNDO_LOGundo日志页
FIL_PAGE_INODE存储段的信息
FIL_PAGE_IBUF_FREE_LISTchange Buffer 空闲列表
FIL_PAGE_IBUF_BITMAPchange Buffer的一些属性
FIL_PAGE_TYPE_SYS存储一些系统数据
FIL_PAGE_TYPE_TRX_SYS事务系统数据
FIL_PAGE_TYPE_FSP_HDR表空间头部信息
FIL_PAGE_TYPE_XDES存储区的一些属性
FIL_PAGE_TYPE_BLOB溢出页
FIL_PAGE_INDEX索引页,也就是我们说的数据页

由于页面类型的名称前面都有一个FIL_PAGE或者FIL_PAGE_TYPE的前缀,后文会将前缀省略。

页面通用部分

数据页(index类型的页)由7部分组成,其中有两部分是所有类型的页面通用的:
File Header:记录页面的一些通用信息。
File Trailer:校验页是否完整,保证页面从内存刷到磁盘中后内容是相同的。

独立表空间结构

区的概念

表空间中的页实在是太多了,为了更好的管理这些页面,所以提出了区(extent)的概念。对于16KB的页来说,连续的64个页就是一个区,也就是说一个区默认占用1MB的空间。无论是系统表空间还是独立表空间,都可以看作由若干个连续的区组成,每256个区被划分为一组。
其中extent0-extent255为一组,extent256-extent511为一组,依此类推,可以划分更多的组。

区的结构

第一组最开始的三个页面的类型是固定的,也就是说extent0这个区最开始的3个页面的类型是固定的,分别如下:
FSP_HDR:用来登记整个表空间的一些整体属性以及本组所有的区的属性,需要注意的是整个表空间只有一个FSP_HDR类型的页面。
IBUF_BITMAP:用来存储关于Change Buffer的一些信息。
INODE:存储了许多称为INODE Entry的数据结构。

其余各组最开始的2个页面的类型是固定的,分别如下:
XDES:全称为extent descriptor,用来登记本组256个区的属性。
IBUF_BITMAP:用来存储关于Change Buffer的一些信息。

段的概念

段是一些零散页的页面以及一些完整的区的集合。

我们每向表中插入一条记录,本质上就是向该表的聚簇索引以及所有二级索引代表的B+树的节点中插入数据。而B+树每一层中的页都会形成一个双向链表,如果以页尾单位来分配存储空间,双向链表相邻的两个页之间的物理位置可能离的非常远。前面提到使用B+树来减少存储记录的扫描行数的过程是通过一些搜索条件到B+树的叶子节点中定位到第一条符合该条件的记录,然后沿着由该记录组成的单向链表以及数据页组成的双向链表一直向后扫描就可以了。
如果双向链表中相邻的两个页的物理位置不连续,对于传统的机械硬盘来说,需要重新定位磁头位置,也就是会产生随机I/O,这样会影响磁盘的性能,所以我们应该尽量让页面链表中相邻的页的物理位置页尽量相邻,这样在扫描叶子节点中大量的记录时才可以使用顺序I/O。

所以才引入了区的概念,一个区就是在物理位置上连续的64个页。在表中的数据量很大时,为某个索引分配空间的时候就不再按照页尾单位分配了。而是按照区为单位进行分配。甚至在表中的数据非常非常多的时候,可以一次性分配多个连续的区。虽然可能造成一点点空间的浪费,但是可以消除很多随机I/O。
我们在使用B+树执行查询时,只是在扫描叶子节点的记录,如果不区分叶子节点和非叶子节点,而是统统把节点代表的页面放到申请到的区里,扫描效果就大打折扣了,所以这里对叶子节点和非叶子节点进行了区分,也就是说,叶子节点和非叶子节点都有自己独立的区。存放叶子节点的区的集合就是一个段(segment),存放非叶子节点的区的集合也是一个段。也就是说一个索引会生成两个段,一个叶子节点段,一个非叶子节点段。

碎片区的概念

在一个碎片区(fragment)内,并不是所有的页都是为了存储同一个段的数据,碎片区内的页可以用于不同的目的,比如有些页面属于段A,有些页面属于段B,有些页面甚至不属于任何段。碎片区直属于表空间,并不属于任何一个短。所以此后为某个段分配存储空间的策略是这样的:
1、在刚开始向表中插入数据的时候,段是某个碎片区以单个页面为单位来分配存储空间的;
2、当某个段已经占用了32个碎片区页面后,就会以完整的区为单位,来分配存储空间。

区的分类

区的分类也被称为区的四种状态
1、空闲的区(FREE):还没有用到这个区内的任何页面,直属于表空间;
2、有剩余空闲页面的碎片区(FREE_FRAG):表示碎片区内还有可被分配的空闲页面,直属于表空间;
3、没有任何剩余空闲页面的碎片区(FULL_FRAG):表示碎片区内的所有页面都被分配使用,直属于表空间。
4、附属于某个段的区(FSEG):InnoDB会定义一些特殊用途的段,当这些段中的数据量很大时,将使用区作为基本的分配单位,这些区中的页面完全用于存储该段中的数据,附属于某个段。

为了方便管理这些区,所以设计了一个称为XDES Entry(Extent descriptor Entry)。每个区都对应着一个XDES Entry结构。
XDES Entry结构大概分为4个部分:
1、Segment ID(8字节):每个段都有一个唯一的编号,用ID表示。Segment ID字段表示的就是该区所在的段。
2、List Node(12字节):这个部分可以将若干个XDES Entry结构串联成一个链表,如果我们想定位表空间中的某个位置,只需指定页号以及该位置在指定页号中的页内偏移量即可。
----Pre Node Page Number 和 Pre Node Offset的组合就是指向前一个XDES Entry的指针。
----Next Node Page Number 和 Next Node Offset的组合是指向后一个XDES Entry的指针。
3、State(4字节):这个字段表明区的状态。可选的值分别是FREE、FREE_FRAG/FULL_FRAG和FSEG。
4、Page State Bitmap(16个字节):这个段占用16字节,也就是128位,一个区默认64个页,这128位被划分为64个部分,每个部分两位,对应区中的一个页,这2个位中的第一位表示对应的页是否是空闲的,第二位还没用到。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值