InnoDB操作的基本单位是页,大小一般是16KB。也分诸多类型,我们最常接触的类型就是数据页(INDEX类型)。比如还有存放表空间信息的信息页,日志页。。。。。
一、页的结构
字段名 | 中文名 | 长度 | 简单描述 | 作用 |
File Header | 文件头部 | 38B | 页的通用信息 | 起码能表明本页是属于哪个表空间的 |
Page Header | 页头 | 56B | 页的专有信息 | 能表明页的类型,一些统计信息等等 |
Infimum + Supermum | 最小记录与最大记录 | 26B | 虚拟记录 | 一页的最小纪录与最大记录你知道了,你就能快速定位是否要操作此页面 |
User Records | 用户记录 | 可变 | 行记录 | 用户自定义的记录。每多一条数据,Free space就少一条记录的空间 |
Free space | 空闲空间 | 可变 | 剩余空间 | 一开始没有记录的时候,User Records不存在,全是Free space |
Page Directory | 页的目录 | 可变 | 页面中某些记录的相对位置 | 一页中通过Infimum + Supermum可以知道要不要操作该页面。可是页里数据量还是很多,于是mysql又将这些数据进行了分组(会生成slot),此处保存的就是slot。mysql规定分组时,最小记录为单独一组,只保存最小记录一条虚拟数据。含有最大纪录虚拟机路的组1~8条记录,其余组4~8条记录。每大于8条的组会进行页分裂,形成新的组 |
File Trailer | 文件尾 | 8B | 校验页是否完整 | 页在操作过程中可能会损坏,这个字段能表明页是否完整 |
1、File Header
字段名(前缀Fil_PAGE_) | 描述 | 作用 |
SPACE_OR_CHECKSUM | 页面的校验和 | |
OFFSET | 页号 | Innodb通过页号定位页,页号并不像行记录一样顺序存放的,而是随机的 |
PREV | 上一页页号 | 通过上一页下一页,页能形成双向链表。 |
NEXT | 下一页页号 | 数据页这用得上两个字段,就是保存真实记录的页。其他页不知道 |
TYPE | 页类型 | 有数据页、日志页、溢出页等等等。。 |
LSN | 页被最后修改时的日志序列位置 | |
FLU_SH_LSN | 在系统表空间的一个页面中定义。代表文件至少被刷新到了对应的LSN值 | |
ARCH_LOG_NO_OR_SPACE_ID | 表空间ID | 页属于哪个表空间 |
2、Page Header
字段名(前缀PAGE_) | 描述 | 作用 |
N_DIR_SLOTS | slot槽的数量 | |
HEAP_TOP | 还未使用的空间的最小地址 | 意思就是这个地址之后都是Free Space,这个地址就是User Records最后一条的地址 |
N_HEAP | 本页的记录数 | 包括最大记录与最小记录和已删除的记录 |
N_RECS | 本页的记录数 | 不包括最大记录与最小记录和已删除的记录 |
FREE | 第一条delete_mask标记为1的记录的地址 | 标记被删除的记录也会组成一条单向链表,他们的空间可以被重用 |
GARAGE | 已删除记录占用的总字节数 | |
LAST_INSERT | 最后插入记录的位置 | 这个跟HEAP_TOP有什么区别吗?暂定 |
DIRECTION | 记录插入的方向 | 暂定 |
N_DIRECTION | 同一个方向连续插入的次数 | 不同方向会重新计数。暂定 |
MAX_TRX_ID | 修改当前页的最大事务ID,该值仅在二级索引中定义 | 暂定 |
LEVEL | 页在B+树中所处的等级 | 索引都是一颗B+树,B+树的节点都是页,叶子节点存放数据页(存放数据),非叶子节点都是索引页(存放索引相关的列) |
INDEX_ID | 索引ID,表示当前页属于哪个索引 | |
BTR_SEG_LEAF | B+树叶子段的头部信息,仅在B+树的Root页定义 | 复杂。解释不清 |
BTR_SEG_TOP | B+树非叶子段的头部信息,仅在B+树的Root页定义 | 复杂。解释不清 |
3、Page Directory
MySQL保存数据时,默认会生成一颗以主键建立的B+树(没有主键就用唯一索引,都没有就用隐藏列DB_ROW_ID),所有的叶子节点保存数据页,非叶子节点保存主键索引页(其实数据页跟索引页是一种页类型,只是好区分概念才这么叫的)。这棵树成为聚簇索引,每层页都组成双向链表,页内的记录也按照主键组成了单项链表(行格式有next_record字段)。在此基础上再往下看:
Mysql规定最小记录组一条记录就是它自身,最大记录组可以存1~8条记录,其他组保存4~8条记录。
其实一开始,页中只有最小记录与最大记录两条虚拟记录,也分为最小记录组,最大记录组。都在最大记录组插入数据,当插入第九条时,就进行分组;最大记录组为5条,另一组为4条。依次类推,就会产生很多组;分组之后,我们将每组最后一条数据的地址偏移量(也称为slot槽)提取出来,就组成了Page Directory部分。
这样,当有新纪录插入的时候,通过二分法遍历slot槽来确定该主键最接近哪一组,然后遍历该组的记录,将数据进行插入。
4、File Trialer
与File Header里的CHECKSUM作用很像。Innodb在内存与磁盘交互过程中,需要知道页是否完整,此字段也是校验完整性相关的,检查会使用到参数LSN。