InnoDB数据页结构
名称 | 中文名 | 占用空间大小 | 简单描述 |
---|---|---|---|
File Header | 文件头部 | 38字节 | 页的一些通用信息 |
Page Header | 页面头部 | 56字节 | 数据页专有的一些信息 |
Infimum+Supremum | 页面中最小记录和最大记录 | 26字节 | 两个虚拟的记录 |
User Records | 用户记录 | 不确定 | 用户存储的记录内容 |
Free Space | 空闲空间 | 不确定 | 页中尚未使用的空间 |
Page Directory | 页目录 | 不确定 | 页中某些记录的相对位置 |
File Trailer | 文件尾部 | 8字节 | 校验页是否完整 |
记录头信息
名称 | 大小(位) | 描述 |
---|---|---|
预留位1 | 1 | 没有使用 |
预留位2 | 1 | 没有使用 |
deleted_flag | 1 | 标记该记录是否被删除 |
min_rec_flag | 1 | B+树的每层非叶子节点中最小的目录项记录都会添加该标记 |
n_owned | 4 | 一个页面中的记录会被分成若干个组,每个组中有一个记录是“带头大哥”,其余的记录都是“小弟”。“带头大哥”记录的n_owned值代表该组中所有的记录条数,“小弟”记录的n_owned值都为0 |
heap_no | 13 | 表示当前记录在页面堆中的相对位置 |
record_type | 3 | 表示当前记录的类型,0表示普通记录,1表示B+树非叶子节点的目录项记录,2表示Infimum记录,3表示Supremum记录 |
next_record | 16 | 表示下一条记录的相对位置 |
deleted_flag:值为0没有被删除,值为1表示记录被删除了。
InnoDB会自动给每个页里面添加两条记录,称为伪记录。一条代表最小记录,heap_no值为0,一条代表页面最大记录,heap_no值为1。记录大小就是键值的大小。Infimum和Supremum这两条记录都是由5字节的记录头和8字节的固定单词组成。
记录在表中是一个单向链表,下一个记录是按照主键值从小到大的顺序排列的下一条记录。本页主键值最大的用户记录的下一条记录是Supremum记录。
被删除的记录不会从磁盘上移除,但是会形成一个垃圾链表,所以heap_no值也仍然保持不变。如果删除一个记录,那么仅仅将它的deleted_flag改成1,然后将指向它的指针指向它的下一个记录,该组中带头大哥的n_owned的值也减一。如果重新插入该值,则会复用这个被删除的记录。
页目录
- 将所有正常的记录划分成几个组
- 将每组的最后一个记录作为带头大哥,其余的记录是小弟,带头大哥的n_owned表示该组中有几条记录
- 将每组中最后一条记录在页面中的地址偏移量提取,存储到页尾部的地方,这个地方就是Page Directory。地址偏移量为槽。
规定:对于Infimum记录所在的分组只能有1条记录,Supremum记录所在的分组只能在1到8条之间,剩下的分组中记录条数范围在4到8之间。
查找记录:
- 先通过二分法查找对应的槽
- 然后找到记录所在槽后,从上一个槽的记录顺序向下找
页面头部
状态名称 | 占用空间大小 | 描述 |
---|---|---|
PAGE_N_DIR_SLOTS | 2字节 | 在页目录中的槽数量 |
PAGE_HEAP_TOP | 2字节 | 还未使用的空间最小地址,也就是说从该地址之后就是Free Space |
PAGE_N_HEAP | 2字节 | 第1位表示本记录是否为紧凑型的记录,剩余的15位表示本页的堆中记录的数量 |
PAGE_FREE | 2字节 | 各个已删除的记录通过next_record组成一个单向链表,这个单向链表中的记录所占用的存储空间可以被重新利用;PAGE_FREE表示该链表头结点对应记录在页面中的偏移量 |
PAGE_GARBAGE | 2字节 | 已删除记录占用的字节数 |
PAGE_LAST_INSERT | 2字节 | 最后插入记录的位置 |
PAGE_DIRECTION | 2字节 | 记录插入的方向 |
PAGE_N_DIRECTION | 2字节 | 一个方向连续插入的记录数量 |
PAGE_N_RECS | 2字节 | 该页中用户记录的数量 |
PAGE_MAX_TRX_ID | 8字节 | 修改当前页的最大事务id,该值仅在二级索引页面中定义 |
PAGE_LEVEL | 2字节 | 当前页在B+树中所处的层级 |
PAGE_INDEX_ID | 8字节 | 索引ID,表示当前页属于哪个索引 |
PAGE_BTR_SEG_LEAF | 10字节 | B+树叶子节点段的头部信息,仅在B+树的根页面中定义 |
PAGE_BTR_SEG_TOP | 10字节 | B+树非叶子节点段的头部信息,仅在B+树的根页面中定义 |
文件头部
固定38字节
名称 | 占用空间大小 | 描述 |
---|---|---|
FIL_PAGE_SPACE_OR_CHKSUM | 4字节 | 页的校验和(checksum值) |
FIL_PAGE_OFFSET | 4字节 | 页号 |
FIL_PAGE_PREV | 4字节 | 上一个页的页号 |
FIL_PAGE_NEXT | 4字节 | 下一个页的页号 |
FIL_PAGE_LSN | 8字节 | 页面被最后修改时对应的日志序列位置(英文名是:Log Sequence Number) |
FIL_PAGE_TYPE | 2字节 | 该页的类型 |
FIL_PAGE_FILE_FLUSH_LSN | 8字节 | 仅在系统表空间的一个页中定义,代表文件至少被刷新到了对应的LSN值 |
FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID | 4字节 | 页属于哪个表空间 |
其他类型的页
类型名称 | 十六进制 | 描述 |
---|---|---|
FIL_PAGE_TYPE_ALLOCATED | 0x0000 | 最新分配,还没使用 |
FIL_PAGE_UNDO_LOG | 0x0002 | Undo日志页 |
FIL_PAGE_INODE | 0x0003 | 段信息节点 |
FIL_PAGE_IBUF_FREE_LIST | 0x0004 | Insert Buffer空闲列表 |
FIL_PAGE_IBUF_BITMAP | 0x0005 | Insert Buffer位图 |
FIL_PAGE_TYPE_SYS | 0x0006 | 系统页 |
FIL_PAGE_TYPE_TRX_SYS | 0x0007 | 事务系统数据 |
FIL_PAGE_TYPE_FSP_HDR | 0x0008 | 表空间头部信息 |
FIL_PAGE_TYPE_XDES | 0x0009 | 扩展描述页 |
FIL_PAGE_TYPE_BLOB | 0x000A | BLOB页 |
FIL_PAGE_INDEX | 0x45BF | 索引页,也就是我们所说的数据页 |
页之间通过一个双向链表串起来的。
文件尾部
该部分由8字节组成,是为了检查页是否完整。
- 4字节的校验和,和文件头的校验和进行比较,若不同则刷新期间发生错误
- 4字节的LSN