持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第3天
上次说到了页
然而记录本身也不是简简单单地放进去的
这些记录也需要某种规则来进行管理
也就是说,**页本身也是有结构的:**文件头部、页面头部、最小记录和最大记录、用户记录、空闲空间、页目录、文件尾部
而在这个里面,我们从最小记录和最大记录、用户记录看起,他们与记录最息息相关
最小记录和最大记录、用户记录
用户记录
用户记录的存放也是有组织的
- 通过 记录头信息 中的 next_record(下一个记录记录头信息中next record的相对位置),将记录连接起来,形成单向链表
-
- 按主键顺序从小到大连接
- 删除的时候,只是修改标记位、next record为0以及记录链表
- 新插入数据时,会重新填充被标记删除的记录
最小记录和最大记录
实际上用户记录的heap_no(页位置)是从2开始的
- 0为最小记录
- 1为最大记录
- 同时最小记录为链表头,最大记录为链表尾
这两个记录都只有记录头信息和一个固定数据在数据区
页目录
查询的时候,如果沿着链表查,复杂度为O(n),着实有点慢
这个时候需要个方法来加速查找
页目录出现了
原理
实际上就是把记录进行分组
分组主键最大记录为分组leader
- 每个分组记录数在5-8之间
- 分组记录数会放在该分组leader的n_owned字段
- 最小记录自己为一个分组
将分组leader的地址偏移记录到页目录中
形成一个分组地址集合后,可以采用二分查找的方式加快查询速度
形成过程
- 找到最近那个主键比自己大的分组leader,进入其分组
-
- 分组leader的n_owned++
- 如果该分组记录数==8
-
- 分裂成 4 + 5 的两个分组(包含新纪录)
- 新分组的leader地址记录到页目录中
File Header
每一个页都需要一个部分来表示当前页的状态
比如有几条记录、页目录状态啥的\
通用页的这些描述被称为FileHeader(文件头部) ,固定38个字节
数据页有自己特殊的描述,被称为PageHeader(页头部)
重要的属性
- FIL_PAGE_SPACE_OR_CHKSUM:当前页所有东西的校验和,4个字节
- FIL_PAGE_OFFSET:页号,类似记录主键
- FIL_PAGE_TYPE:页类型,如上述的数据页
- FIL_PAGE_PREV和FIL_PAGE_NEXT:类似记录中的next_record,分别为上一页、下一页的页号
File Trailer
也是一个通用页属性
8字节,前4个字节也是校验和,后4个字节为最后修改时对应的日志序列位置(LSN)
- 当记录写入时被中断(数据同步出错),FileTrailer与FileHeader的校验和会不一致