diff --git a/mysql/mysql文档/mysql_表.md b/mysql/mysql文档/mysql_表.md index 6630969..4424fcd 100644 --- a/mysql/mysql文档/mysql_表.md +++ b/mysql/mysql文档/mysql_表.md @@ -161,14 +161,47 @@ page directory(页目录)中存放了记录的相对位置,这些记录指 在slots中,记录按照索引键值顺序存放,可以通过二叉查询迅速找到记录的指针。 -由于在innodb存储引擎中,page directory是稀疏目录,二叉查找结果只是一个粗略的结果, +由于在innodb存储引擎中,page directory是稀疏目录,二叉查找结果只是一个粗略的结果,innodb存储引擎必须通过record header中的next_record来继续查找相关记录。 +#### B+树索引 + +如上图所示,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时,都会检查页面的完整性。