页的主要作用是存储记录,所以“最大最小记录Infimum + Supremum” 和 “用户记录User Records” 部分占了页结构的主要空间。
User Records(用户记录)
User Records是用来存储数据的地方,简单来说就是怎么把每行数据摆在这个空间里。
当我们新建一个表的时候表中用户记录(用户记录)部分是空的,在外面插入一条记录后会被记录到其中,直到插入满是会把记录信息刷入到下一个页中,往复循环。
User Records 中的这些记录按照指定的行格式一条一条摆放在 User Records 部分,相互之间形成单链表。
记录行格式的记录头信息在摆放数据的过程中发挥了重要的作用,下面是记录头的各个属性:
-
delete_mask 1bit 标记该记录是否被删除,
- 0 表示记录没有删除,
- 1 表示记录被删除了
-
min_rec_mask 1bit B+数的每非叶子节点中的最小纪录数都会添加该标记,
- 只有最小纪录数的min_rec_mask 值为1,
- 其他别的记录min_rec_mask 值为0
-
n_owned 4bit 如果当前记录是组内最大记录,则代表槽内的记录数
-
heap_no 13bit 当前记录在本页中的位置信息
-
record_type 3bit 表示当前记录的类型,
- 0表示普通记录,
- 1表示B+树非叶子节点记录,
- 2表示最小记录,
- 3表示最大记录
-
next_record 16bit 表示从当前记录的真实数据到下一条记录的真实数据的地址偏移量。
比如:第一条记录的next_record值为32,意味着从第一条记录的真实数据的地址处向后找32个字节便是下一条记录的真实数据。
被删除的记录为什么还在页中存储呢?
你以为它删除了,可它还在真实的磁盘上。这些被删除的记录之所以不立即从磁盘上移除,是因为移除它们之后其他的记录在磁盘上需要重新排列,导致性能消耗。所以只是打一个删除标记而已,所有被删除掉的记录都会组成一个所谓的==垃圾链表==,在这个链表中的记录占用的空间称之为==可重用空间==,之后如果有新记录插入到表中的话,可能把这些被删除的记录占用的存储空间覆盖掉。
关于heap_no值为0和1的记录
MySQL会自动给每个页里加了两个记录,由于这两个记录并不是我们自己插入的,所以有时候也称为伪记录或者虚拟记录。这两个伪记录一个代表最小记录,一个代表最大记录。最小记录和最大记录的heap_no值分别是0和1,也就是说它们的位置最靠前。
Infimum + Supremum(最小最大记录)
比较记录的大小就是比较主键的大小。
InnoDB规定的最小记录与最大记录这两条记录的构造十分简单,都是由5字节大小的记录投信息和8个字节大小的一个固定的部分组成的:
定Infimum记录(也就是最小记录)的下一条记录就是本页中主键值最小的用户记录,而本页中主键值最大的用户记录的下一条记录就是Supremum记录(也就是最大记录)。