InnoDB为了不同的目的而设计了许多种不同类型的页,比如存放表空间头部信息的页,存放Insert Buffer信息的页,存放INODE信息的页,存放undo日志信息的页等等。存放我们表中记录的那种类型的页,官方称这种存放记录的页为索引(INDEX)页。
记录在页中的存储
存储的记录会按照我们指定的行格式存储到User Records部分,记录插入过程:
在上一篇文章中提到记录头信息中有一些字段,在这里重点说明一下:
delete_mask
标记着当前记录是否被删除,占用1个二进制位,值为0的时候代表记录并没有被删除,为1的时候代表记录被删除掉了。这些被删除的记录不会立即从磁盘上移除,,所有被删除掉的记录都会组成一个所谓的垃圾链表,在这个链表中的记录占用的空间称之为所谓的可重用空间,之后如果有新记录插入到表中的话,可能把这些被删除的记录占用的存储空间覆盖掉。
next_record
它表示从当前记录的真实数据到下一条记录的真实数据的地址偏移量,指向记录头信息和真实数据之间的位置。这个位置刚刚好,向左读取就是记录头信息,向右读取就是真实数据。InnoDB通过这个字段将页中的所有记录按主键从小到大连接成一个单向链表。
Page Directory(页目录)
为了在单个页中根据主键快速找到某条记录,InnoDB将页中的记录划分为若干个组,每个组的最后一个记录的地址偏移量作为一个槽,存放在Page Directory中。
每个组的最后一条记录(也就是组内最大的那条记录)的头信息中的n_owned属性表示该记录拥有多少条记录,也就是该组内共有几条记录。InnoDB对每个分组中的记录条数是有规定的:对于最小记录所在的分组只能有1条记录,最大记录所在的分组拥有的记录条数只能在1~8条之间,剩下的分组中记录的条数范围只能在是4~8条之间。
所以在一个数据页中查找指定主键值的记录的过程分为两步:
- 通过二分法确定该记录所在的槽,并找到该槽所在分组中主键值最小的那条记录。
- 通过记录的next_record属性遍历该槽所在的组中的各个记录。
File Header
每个数据页的File Header部分都有上一个和下一个页的编号,所以所有的数据页会组成一个双链表。