5_InnoDB的数据页结构

页是InnoDB管理存储空间的基本单位,不同类型的页存放不同的数据。

  1. 表空间头部信息;
  2. Insert Buffer信息;
  3. INODE信息;
  4. undo日志信息;
  5. 表中记录,官方称呼这种数据页为索引(INDEX)页,出于习惯,先称呼为数据页;

数据页结构总览

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

记录在页中的存储

存储过程

  1. 用户记录会按照行格式存储到User Records;
  2. User Records使用空间逐渐增多,Free Space占用空间逐渐减少;
  3. 当Free Space空间用完,即页空间用完,存储新的记录则需要再申请新的页;
记录在页中的存储过程

记录头信息

用户记录

记录头信息中各个属性

名称 大小(单位:bit) 描述
预留位1 1 没有使用
预留位2 1 没有使用
delete_mask 1 标记该记录是否被删除
min_rec_mask 1 B+树的每层非叶子节点中的最小记录都会添加该标记
n_owned 4 表示当前记录拥有的记录数
heap_no 13 表示当前记录在记录堆的位置信息
record_type 3 表示当前记录的类型,0表示普通记录,1表示B+树非叶子节点记录,2表示最小记录,3表示最大记录
next_record 16 表示下一条记录的相对位置

  1. delete_mask
    1. 标记当前记录是否被删除,值为0时表示没有被删除,为1时表示被删除
    2. 被删除的记录不会立即从磁盘上移除,因为移除后需要重新排列磁盘上其他的记录,性能消耗较多,因此先打一个删除标记
    3. 所有被删除掉的记录都会组成一个垃圾链表,如果有新记录插入到表中,可以把这部分占用的存储空间覆盖掉;
    4. 将delete_mask位设置为1和将被删除的记录加入到垃圾链表中是两个阶段,详见事务中的删除操作;
  2. min_rec_mask
    1. 标记是否为B+树的每层非叶子节点中的最小记录;
  3. n_owned
    1. 表示当前记录(分组)拥有的记录数;
  4. heap_no
    1. 表示当前记录在本页中的位置;
    2. User Records仅记录用户记录,Infimum + Supremum记录虚拟记录
      1. Infimum代表最小记录,heap_no为0;
      2. Supremum代表最大记录,heap_no为1;
      3. 链表避免边界条件,方便加间隙锁;
  5. record_type
    1. 值为0表示普通记录;
    2. 值为1表示B+树非叶节点记录,详见索引
    3. 值为2表示最小记录Infimum;
    4. 值为3表示最大记录Supremum;
  6. next_record
    1. 到下一条记录的真实数据的地址偏移量,构成行记录单链表数据结构;
    2. 下一条记录是按照主键值由小到大的顺序,而不是指插入顺序;
    3. 最小记录Infimum的下一条记录是本页中主键值最小的用户记录;
    4. 本页中主键值最大的用户记录的下一条记录是最大记录Supremum;

页中记录单链表
  1. 省略了隐藏列;
  2. next_record指向记录头信息和真实数据之间的位置,向左读取记录头信息,向右读取真实数据;
  3. 变长字段长度列表、NULL值列表中的信息逆序存放,使对应字段在记录头信息和真实数据的距离更近,读取到内存时有利于提高高速缓存的命中率;

页目录

Page Directory

  1. 快速根据主键值查找页中的某条记录,算法原理:数组二分查找 + 链表遍历,类似InnoDB存储引擎有缓存页的哈希表,快速查找缓存页;
  2. 制作大致的过程
    1. 将所有正常的记录(包括最大和最小记录,不包括标记为已删除的记录)划分为几个组;

    2. 每个组的最后一条记录(组内最大的那条记录)的头信息中的n_owned属性表示该记录拥有多少条记录(组内拥有的记录数);

    3. 每个组的最后一条记录的地址偏移量(槽,Slot)单独提取出来按顺序存储到靠近页的尾部的地方,构成页目录Page Directory;

  3. 分组细节
    1. 分组记录数
      1. 最小记录的分组记录条数:1条;
      2. 中间记录的分组记录条数:4~8条;
      3. 最大记录的分组记录条数:1~8条;
    2. 分组过程
      1. 初始化一个数据页里只有最小记录和最大记录两条记录,分别属于两个分组;
      2. 之后每插入一条记录,都会从页目录中找到主键值比本记录的主键值大并且差值最小的槽,然后把该槽对应的记录的n_owned值加1,表示本组内又添加了一条记录,直到该组中的记录数等于8个;
      3. 在一个组中的记录数等于8个后再插入一条记录时,会将组中的记录拆分成两个组,一个组中4条记录,另一个5条记录。这个过程新增分组并新增一个槽;
    3. 最小记录和最大记录实际在一块Infimum + Supremum,逻辑上为清晰,图示分开了;
    4. 页的逻辑分组
    5. 页的逻辑分组2
    6. 查找页中记录的过程
      1. 通过二分法确定该记录所在的槽,并找到该槽中主键值最小的那条记录。(上一个槽的next_record)

      2. 通过记录的next_record属性遍历该槽所在的组中的各个记录。


页面头部

Page Header

存储数据页的各种状态信息。

名称 占用空间大小 描述
PAGE_N_DIR_SLOTS 2字节 在页目录中的槽数量
PAGE_HEAP_TOP 2字节 还未使用的空间最小地址,也就是说从该地址之后就是Free Space
PAGE_N_HEAP 2字节 本页中的记录的数量(包括最小和最大记录以及标记为删除的记录)
PAGE_FREE 2字节 第一个已经标记为删除的记录地址(各个已删除的记录通过next_record也会组成一个单链表,这个单链表中的记录可以被重新利用)
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+树的Root页定义
PAGE_BTR_SEG_TOP 10字节 B+树非叶子段的头部信息,仅在B+树的Root页定义
  • PAGE_DIRECTION
    1. 最后一条记录插入方向;
    2. 右边:新插入的一条记录的主键值 > 上一条记录的主键值大;
  • PAGE_N_DIRECTION
    1. 连续沿着同一个方向插入记录的条数,插入方向改变会清零重新统计;

文件头部

File Header

存储各种页的通用信息。

名称 占用空间大小 描述
FIL_PAGE_SPACE_OR_CHKSUM 4字节 页的校验和
FIL_PAGE_OFFSET 4字节 页号
FIL_PAGE_PREV 4字节 上一个页的页号
FIL_PAGE_NEXT 4字节 下一个页的页号
FIL_PAGE_LSN 8字节 页面被最后修改时对应的日志序列位置(Log Sequence Number,LSN)
FIL_PAGE_TYPE 2字节 该页的类型
FIL_PAGE_FILE_FLUSH_LSN 8字节 仅在系统表空间的一个页中定义,代表文件至少被刷新到了对应的LSN值
FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID 4字节 页属于哪个表空间
  • FIL_PAGE_SPACE_OR_CHKSUM

    1. 当前页面的校验和,快速比较出页的内容不同;
  • FIL_PAGE_OFFSET

    1. 页号,唯一标识一个页;
  • FIL_PAGE_TYPE

    1. 当前页的类型;

    2. 类型名称 十六进制 描述
      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 索引页,俗称数据页
  • FIL_PAGE_PREVFIL_PAGE_NEXT

    1. 数据页构成双向链表;
    2. 索引页双向链表

文件尾部

File Trailer,校验页的完整性,防止内存仅成功同步磁盘一半数据的异常情况发生。

  • 前4个字节
    1. 页的校验和,与文件头部的FIL_PAGE_SPACE_OR_CHKSUM对应;
  • 后4个字节;
    1. 页面被最后修改时对应的日志序列位置,与文件头部的FIL_PAGE_LSN对应;

posted @ 2024-10-08 11:21  夜是故乡明  阅读(11)  评论(0编辑  收藏  举报