MySQL的InnoDB数据页结构

1 不同类型的页介绍

页是InnoDB管理存储空间的基本单位,一个页的大小一般是16KB。InnoDB为了不同的目的设计了多种不同类型的页,例如存放表空间的头部信息的页,存放Change Buffer信息的页、存放INODE信息的页、存放undo日志信息的页等等。
今天不准备说以上的页,而是说索引页,但是目前还是将其称之为数据页。

2 数据页结构

在这里插入图片描述
从上图中可以看出,一个InnoDB数据页存储空间大致被划分为7个部分,以下表格会说明一下这七个部分都存储一些什么内容

名称中文名简单描述
File Header文件头部页的一些通用信息
Page Header页面头部数据页专有的一些信息
Infimum + Supremum页面中的最小记录和最大记录两个虚拟的记录
User Records用户记录用户存储的记录内容
Free Space空闲空间页中尚未使用的空间
Page Directory页目录页中某些记录的相对位置
File Trailer文件尾部校验页是否完整

3 记录在页中的存储

在页的七个组成部分中,我们自己存储的记录会按照指定的行格式存储 User Records部分。最开始生成页的时候,并没有User Records部分,每当插入一条记录,都会从Free Space部分申请一个记录大小的空间,并将这个空间划分到User Records部分,当Free Space空间用完后,如果还有新的纪录就需要申请新的页了。

下面是记录在User Records中的一条数据记录的示例
在这里插入图片描述
deleted_flag:表示当前记录是否被删除,占用1比特,0表示未被删除,1表示已被删除,删除的记录不会从此版中移除掉,是因为在移除他们之后,还需要在磁盘上重新排列其他的记录,这回带来性能消耗,所有的被删除的记录会形成一个垃圾链表,记录这个链表占用的空间被称之为可重用空间,当插入新纪录时,他们可能会覆盖掉被删除的这些记录所占用的存储空间。
min_rec_flag:B+树每层非叶子节点中的最小的记录项纪录都会添加该标记。
n_owned
heap_no:向表中插入的记录实际上是一条一条的无间排列,而一条一条的无间排列的结构称之为堆(heap)为了方便管理,每条记录在堆中的相对位置即为heap_no。而我们插入的数据的heap_no是从2开始的,0和1 则是两条伪记录,一条是页面中的最小记录(Infimum),一条是页面中的最大记录(Supremum),而记录也可以比较大小,是根据主键的大小作比较。
无论我们向表中插入了多少条记录,任何记录都比Infimum记录大,任何记录都比Supremum记录小。
recoed_type:他表示当前记录的类型,一共有4种类型,0表示普通记录,1表示B+树非页节点的目录项记录,2表示I你覅木马记录,3表示Supremum记录。
next_record:表示当前记录到吓一跳记录的距离。如果该属性值为负数,则说明当前记录的下一条记录在当前记录的前面。
无论怎样对页中的记录进行增删改操作,InnoDB始终会维护一个按照主键值从小到大的顺序形成的一个单向链表。

4 Page Directory(页目录)

为了查询时方便,InnoDB 为我们的记录制作了一个类似的目录:
----1.将所有正常的记录划分为几个组
----2.每个组的最后一条记录的头信息中的n_owned属性表示该组内共有几条记录
----3.将每组的最后一条记录在页面中的地址偏移量(也就是该记录的真实数据与页面中第0个字节之间的距离)单独提取出来,按顺序存储到靠近页尾的地方。这个地方就是Page Directory(页目录)。页目录中的这些地址偏移量成为槽,每个槽占用2字节,页目录由多个槽组成。

而给所有的记录分组是按照以下的步骤进行的:
----1.初始情况下,一个数据页只有Infimum以及Supremum记录,他们分属于两个组,所以页目录中只有两个槽。
----2.之后没插入一条记录,都会从页目录中找到相对应的记录的主键值比待插入记录的主键值大,并且差值最小的槽(从本质上说,槽是一个组内最大的那条记录在页面中的地址偏移量,通过槽可以快速找到对应的记录的主键值),然后把该槽对应的记录的n_owned值加1,表示本组内新增了一条记录,直到该组内记录数为8个。
----3.当一个组内的记录数为8后,在插入一条记录,会将组内的记录分为两个组,其中一个组4条记录,另一个组5条记录。拆分过程中会新增一个槽,记录这个新增分组中的最大记录的偏移量。

而查找数据的过程分为两步:
----1.通过二分法确定该记录所在分组对应的槽,然后找到该槽所在分组中主键值最小的那条记录。
----2.在通过记录的nexr_record属性遍历该槽所在组中的各个记录。

Page Header(页面头部)

为了能够得到存储在数据页中的记录的状态信息,比如数据页中已经存储了多少条记录、Free Space在页面中的地址偏移量、页目录中存储了多少个槽等,特意在数据页中定义了个名为Page Header的部分,它是页结构的第二部分,占用56字节,专门存储各种状态信息,具体用途如下:

状态名称占用空间大小描述
PAGE_N_DIR_SLOTS2字节在目录中的槽数量
PAGE_HEAP_TOP2字节还未使用的空间的最小地址
PAGE_N_HEAP2字节第一位表示本记录是否是紧凑型的记录,剩余的十五位表示本页的堆中记录的数量(包括Infimum和Supremum及被删除的记录)
PAGE_FREE2字节各个已删除记录通过next_record组成单向链表,这个单向链表中的记录所占用的存储空间可以被重新利用:PAGE_FREE表示该链表头节点对应记录在页面中的偏移量
PAGE_GARBAGE2字节已删除记录占用的字节数
PAGE_LAST_INSERT2字节最后插入记录的位置
PAGE_DIRECTION2字节记录插入的方向
PAGE_N_DIRECTION2字节一个方向连续插入的记录数量
PAGE_N_RECS2字节该页中用户记录的数量(不包括Infimum和Supremum及被删除的记录)
PAGE_MAX_TRX_ID8字节最该当前页的最大事务id,该值仅在二级索引页面中定义
PAGE_LEVEL2字节当前页在B+树种所处的层级
PAGE_INDEX_ID8字节索引id,表示当前页属于哪个索引
PAGE_BTR_SEG_LEAF10字节B+树叶子节点段的头部信息,仅在B+树的根页面中定义
PAGE_BTR_SEG_TOP10字节B+树非叶子节点段的头部信息,仅在B+树的根页面中定义

5.6 File Header

该部分主要是介绍一些通用于各个页的信息,比如这个页的编号,它的上一个页和下一个页是谁等等,File Header 占用固定的38个字节

状态名称占用空间大小描述
FIL_PAGE_SPACE_OR_CHKSUM4字节页的校验和
FIL_PAGE_OFFSET4字节页号
FIL_PAGE_PREV4字节上一页的页号
FIL_PAGE_NEXT4字节下一页的页号
FIL_PAGE_LSN8字节页面被最后修改时的LSN值(Log Sequence Number日志序列号)
FIL_PAGE_TYPE2字节该页的类型
FIL_PAGE_FILE_FLUSH_LSN8字节仅在系统表空间的第一个页中定义,代表文件至少被刷新到了对应的LSN值
FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID4字节页属于哪个表空间

FIL_PAGE_SPACE_OR_CHKSUM:校验和是什么? 就是对于一个很长的字节串来说,我们会通过某种算法计算出一个比较短的值来代表这个很长的字节串,这个比较短的值就是校验和。
FIL_PAGE_OFFSET:每个页都有一个单独的页号,I你弄DB通过页号来唯一定位一个页。
FIL_PAGE_TYPE:表示当前页的类型具体类型如下所示:

类型名称描述
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_PREV及FIL_PAGE_NEXT:I你弄DB是以页为单位存放数据,有时,数据量很大,占用空间非常大。InnoDB可能无法一次性胃饿么多数据分配一个非常大的存储空间,如果分散到多个不连续的页中进行存储,则需要把这些页关联起来,而这两个则代表本数据页的上一个页号和下一个页号,这样就可以建立起来一个双向链表,从而把数据页串联起来。

7 File Trailer(文件尾部)

InnoDB存储引擎会把数据存储到磁盘上,但是磁盘速度太慢,需要以页为单位把数据加载到内存中处理,如果该页中的数据在内存中被修改了,在修改后的某个时间还需要吧修改后的数据刷新到磁盘,如果在刷新的时候断电了,通常情况下无法判断数据页是否刷新完成,而File Trailer就是为了校验该页是否完成的。FIle Trailer分为两部分,共8个字节:
----前4个字节代表页的校验和,这个部分与FIle Header的校验和相对应,如果刷新成功,那么前后的校验和应该是一样的,如果刷新一部分断电了,那么File Header中的校验和代表着已经修改过的页,File Trailer中的校验和代表原先的页,二者不同意味着刷新期间发生了错误。
----后4个字节代表页面被最后修改时对应的LSN的后4字节,正常情况下应该与File Header部分的Fil_PAGE_LSN的后4字节相同,这个部分也是用于校验页的完整性。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值