数据结构论坛

首页 » 分类 » 定义 » MySQL2InnoDB数据页结构
TUhjnbcbe - 2021/3/7 10:32:00

InnoDB数据页结构概述

行格式中的记录头信息

delete_mask

heap_no

min_rec_mask

n_owned

record_type

next_record

PageDirectory(页目录)

PageHeader(页面头部)

PAGE_DIRECTION——插入方向

PAGE_N_DIRECTION

FileHeader文件头部

FIL_PAGE_TYPE

InnoDB数据页结构概述

一个数据页的大小一般是16kb。这16kb的存储空间被划分为多个部分,不同部分有不同的功能,如下图所示

数据页结构

这几个存储空间的相关信息见下表

名称中文名占用空间大小简单描述FileHeader文件头部38字节页的一些通用信息PageHeader页面头部56字节数据页专有的一些信息Infimum+supremum最小记录和最大记录26字节两个虚拟的行记录UserRecords用户记录不确定实际存储的行记录内容FreeSpace空闲空间不确定页中尚未使用的空间PageDirectory页面目录不确定页中某些记录的相对位置FileTrailer文件尾部8字节校验位是否完整

其中真正对用户有用的是UserRecords这一属性。每当我们插入一条记录,就从FreeSpace中申请一个记录大小空间划分到UserRecords中。当FreeSpace所有空间都用完时就说明这个页使用完成了。

UserRecords实际存储的也就是行,也接下来我们就好好学习在行格式未明确说明的记录头信息

行格式中的记录头信息

行记录中的记录头信息有关于我们页面中记录的存储,因此放在“页”这一章讲解

名称大小(单位:bit)描述预留位11没有使用预留位21没有使用delete_mask1标记该记录是否被删除min_rec_mask1B+树的每层非叶子节点中的最小记录都会添加该标记n_owned4表示当前记录拥有的记录数heap_no13表示当前记录在记录堆的位置信息record_type3表示当前记录的类型,0表示普通记录、1表示B+树非叶子节点记录,3表示最大记录next_record16表示下一条记录的相对位置delete_mask

标记着当前记录是否被删除,占用1个二进制位,值为0的时候记录并没有被删除。

被删除的记录并不是立刻就从页中/磁盘中移除,因为移除了之后其他记录在磁盘上重新排列需要性能消耗,所以只是打一个删除标记而已,所有被删除掉的记录都会组成一个垃圾链表,这个链表中记录占用的空间称之为可重用空间,在新纪录插入到表中时,被删除的记录占用的存储空间会被覆盖掉

heap_no

这个属性代表本记录在本页的位置,其中0,1代表着最小记录和最大记录(Infimum+supremum),这是两条虚拟记录。对于完整的列来说,根据主键比大小。

min_rec_mask

与InnoDB引擎中的B+树索引有关

n_owned

当前记录组拥有的记录数

record_type

这个属性表示当前记录的类型,一共四种类型的记录,0表示普通记录,1表示B+树非叶节点记录,2表示最小记录,3表示最大记录。

next_record

表示从当前记录的真实数据到下一条记录的真实数据的地址偏移量,也就是我们可以根据这个属性找到下一个记录。下一条记录并不是按照插入顺序的下一条记录,而是按照主键值从小到大的顺序的下一条记录。Infimum(最小记录)的下一条记录就是本页中主键值最小的用户记录,而本页中主键值最大的用户记录就是Supremum记录的上一条。

地址偏移量的作用

如果next_record形成的列表中有一个记录被删除了,就从链表中移除了这个记录。

next_record指向的是下一条记录的真实数据的起始位置。这样向右读取就是真实数据,向左就是记录头信息。这也是变长字段长度列表、NULL值列表中的信息都是逆序存放的原因。这样使记录中位置靠前的字段和它们对应的字段长度信息在内存中的距离更近,可能会提高告诉缓存的命中率

”PageDirectory(页目录)

当记录多的时候依靠next_record将整个页遍历一遍,对性能是有很大的损耗的。InnoDB采用了一种类似树的目录的结构:

将所有正常的记录划分为几个组每个组的最后一条记录的头信息的n_owned属性表示该记录拥有多少条记录将每个组的最后一条记录的地址偏移量当都提取出来按顺序存储到靠近页的尾部的地方,就是页目录。页面目录中的地址偏移量被称为槽(Slot),所以页面目录就是由槽组成的

对应的规则:

初始情况下,一个数据页里只有最小记录和最大记录两条记录,它们分属于两个分组每插入一条记录,都会从页目录找到主键值必本记录大并且差值最小的槽,然后把该槽对应的记录的n_owned值加1,直至该组中的记录数等于8个。在一个组中的记录数等于8个后再插入一条记录时,会将组中的记录拆分成两个组,一个组中4条记录,另一个5条记录,页目录中会新增一个槽指向新增分组中最大的记录的偏移量

因此在一个数据页中查找指定主键值的记录的过程分为两步

通过二分法确定该记录所在的槽,并找到该槽中主键值最小的记录通过记录的next_record属性遍历该槽所在的各个记录PageHeader(页面头部)

页面头部用于存储页的状态信息,比如存了多少记录,第一条记录的地址等等,详细的见下表:

名称占用空间大小描述PAGE_N_DIR_SLOTS2字节在页目录中的槽数量PAGE_HEAP_TOP2字节还未使用的空间最小地址,也就是该地址之后就是FreeSpacePAGE_N_HEAP2字节本页中的记录的数量(包括最大最小和被删除的记录)PAGE_FREE2字节第一个被标记为删除的记录地址(被删除的记录会形成案例及链表)PAGE_GARBAGE2字节已删除记录占用的字节数PAGE_LAST_INSERT2字节最后插入记录的位置PAGE_DIREACTION2字节记录插入的方向PAGE_N_DIREACTION2字节一个方向连续插入的记录数量PAGE_N_RECS2字节该页中记录的数量PAGE_MAX_TRX_ID8字节修改当前页的最大事务IDPAGE_LEVEL2字节当前页在B+树所处的层级PAGE_INDEX_ID8字节索引ID,表示当前页属于哪个索引PAGE_BTR_SEG_LEAT10字节B+树叶子段的头部信息,仅在B+树的Root页定义PAGE_BTR_SEG_TOP10字节B+树非叶子段的头部信息,仅在B+树的ROot页定义PAGE_DIRECTION——插入方向

加入新插入的一条记录的主键值比上一条记录的主键值大,我们说这条记录的插入方向是右边,反之则是左边。用来表示最后一条记录插入方向的状态。

PAGE_N_DIRECTION

如果连续几次插入新纪录的方向都是一致的,InnoDB就会将同一个方向插入记录的条数记录下来。如果后面记录方向改变就会清零重新开始

FileHeader文件头部

描述了各种页都通用的一些信息,比如上一页和下一页等,具体见下表:

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

代表页的类型,InnoDB中有以下几种页:

类型名称十六进制描述FIL_PAGE_TYPE_ALLOCATED0x最新分配还没使用FIL_PAGE_UNDO_LOG0xUndo日志页FIL_PAGE_INODE0x段信息节点FIL_PAGE_IBUF_FREE_LIST0xInsertBuffer空闲列表FIL_PAGE_IBUF_BITMAP0xInsertBuffer位图FIL_PAGE_TYPE_SYS0x系统页FIL_PAGE_TYPE_TRX_SYS0x事务系统数据FIL_PAGE_TYPE_FSP_HDR0x表空间头部信息FIL_PAGE_TYPE_XDES0x扩展描述页FIL_PAGE_TYPE_BLOB0xABLOB页FIL_PAGE_INDEX0x45BF索引页,也就是存储数据的页预览时标签不可点收录于话题#个上一篇下一篇
1
查看完整版本: MySQL2InnoDB数据页结构