阅读inndob page directory相关文档
This commit is contained in:
@@ -161,14 +161,47 @@ page directory(页目录)中存放了记录的相对位置,这些记录指
|
|||||||
|
|
||||||
在slots中,记录按照索引键值顺序存放,可以通过二叉查询迅速找到记录的指针。
|
在slots中,记录按照索引键值顺序存放,可以通过二叉查询迅速找到记录的指针。
|
||||||
|
|
||||||
由于在innodb存储引擎中,page directory是稀疏目录,二叉查找结果只是一个粗略的结果,
|
由于在innodb存储引擎中,page directory是稀疏目录,二叉查找结果只是一个粗略的结果,innodb存储引擎必须通过record header中的next_record来继续查找相关记录。
|
||||||
|
|
||||||
|
#### B+树索引
|
||||||
|
<img src="//cloud.mo4tech.com/images/ldWYtlmLrJXYtJXZ0F2dtA3YmBnYmFTdzsWL2xGc05XYhR2MwIjZycTMyczN4gDOmBTY0Y2Y5QmYygjY1YTNk9CcjZGciZWM1NzatkWLuNWLz9Gdv02bj5yZtlWZ0lnYu4WaqVWdq1iNw9yL6MHc0RHa/cefbe79c0791cd0781f7c6aa3a923e21.image" data-cdn="">
|
||||||
|
如上图所示,innodb中的数据是按照索引来进行组织的。但是,通过B+树索引,其无法直接查询到指定的记录,其只能查询到记录所位于的页。
|
||||||
|
|
||||||
|
例如,在上图示例中,其在查询`ID=32`的时,只能查询到该记录位于page 17中。
|
||||||
|
|
||||||
|
> 在B+树的叶子节点,每个页的File Header中都存有指向前一个页和后一个页的指针,`故而每个页之间是通过双向列表结构来维护的`;但是对于页中的记录,`记录与记录之间维维护的时单向列表的关系`。
|
||||||
|
>
|
||||||
|
> 对于Compact或Dynamic行格式的页,其每条记录的record header中都包含一个next_record字段指向下一条记录。故而,位于同一个页中的记录可以单向访问。
|
||||||
|
|
||||||
|
但是,在一个页内查找某条记录时,沿着单向链表进行查找其效率很低。故而,page中的数据时机被分为了多个组,被分为的组构成了一个subdirectory,故而,通过子目录能够缩小查询范围,提高查询性能。
|
||||||
|
|
||||||
|
page directory是一个能够存储多个slots的部分,每个slot中存储了group中最后一条记录的相对位置。假设slot中最大一条记录为`r`,那么group中记录的条数被存储在`r`记录record header的`n_owned`字段中。
|
||||||
|
|
||||||
|
group中record的数量约束如下:
|
||||||
|
- infimum group中records数量限制为`[1,8]`
|
||||||
|
- supremum group中records数量限制为`[1,8]`
|
||||||
|
- 其他group中records限制为`[4,8]`
|
||||||
|
|
||||||
|
page directory生成过程如下所示:
|
||||||
|
- 最开始时,页中只有infimum和supremum两条记录,它们分别属于两个group。page directory中有两个slots指向这两条记录,两个slot的n_owned都为1
|
||||||
|
- 后续,当新的记录被插入页时,系统会查找page directory中主键值大于待插入记录的第一个slot。slot对应最大记录的`n_owned`字段会增加1,代表group中新插入了记录,直到group中的记录数量到达8
|
||||||
|
- 当新纪录被插入到的group中记录数大于8时,group中的记录被分为2个group,一个group包含4条记录,另一个group包含5条记录。该过程将会向page directory中新增一个新的slot
|
||||||
|
- 当记录被删除时,slot最最大一条记录的`n_owned`将会减少1,当n_owned字段小于4时,会触发再平衡操作,平衡后的page directory满足上述要求
|
||||||
|
|
||||||
|
page directory中的slots数量如page header中的`PAGE_N_DIR_SLOTS`所示。
|
||||||
|
|
||||||
|
一旦innodb中页包含page directory后,其会通过二分查找快速的定位slot,并且从group中最小记录开始,通过`next_record`指针来遍历页中的记录列表。这样能够快速的定位记录位置。
|
||||||
|
|
||||||
|
### File Trailer
|
||||||
|
|
||||||
|
#### 完整性校验
|
||||||
|
在innodb中,页的大小为16KB,可能和磁盘的扇区大小不同。通常磁盘的扇区大小为512字节,故而在写入一个页到磁盘中时,需要分32个扇区进行写入。
|
||||||
|
|
||||||
|
在写入一个页时,可能会发生宕机场景,这时,一个页只写入了一部分,可能会发生脏写。此时,可以通过double write buffer机制对脏写的页进行恢复。
|
||||||
|
|
||||||
|
在一个页被写入到磁盘中时,首先会被写入的是File Header的`FIL_PAGE_SPACE_OR_CHKSUM`,该部分是page的checksum。
|
||||||
|
|
||||||
|
innodb设置了File Trailer部分来校验page是否被完全写入到磁盘中,File Trailer中只包含一个`FIL_PAGE_END_LSN`部分,占用8字节,前4字节代表该页的checksum值,后4字节和File Header中的`FIL_PAGE_LSN`相同,`代表最后一次修改该页关联的LSN位置`。将上述两个字段和File Header中的`FIL_PAGE_SPACE_OR_CHKSUM`和`FIL_PAGE_LSN`值进行比较,查看是否一致,从而保证页的完整性。
|
||||||
|
|
||||||
|
默认情况下,在innodb每次从磁盘读取page时,都会检查页面的完整性。
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user