MySQL之InnoDB存储引擎中的页用法解读

 更新时间:2025年06月26日 09:45:56   作者:在成都搬砖的鸭鸭  
这篇文章主要介绍了MySQL之InnoDB存储引擎中的页用法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

1、背景

mysql中存储数据是存储引擎干的事,存储引擎存储数据的基本单位是页,我们往数据库插入表中的一条条记录就是存储在页上的,今天我们就来熟悉一下页上面有哪些内容。

2、页的组成

页由7部分组成,先大概字面意思理解一下,后面再各部分详细讲解,组成图如下:

在这里插入图片描述

表格解释如下:

名称字节大小描述
文件头部38页的通用信息
页头部56页的专有信息
最小记录和最大记录262个固定的行记录
行记录不固定存放用户数据
空闲空间不固定未使用存放用户数据的空间
页目录不固定存放槽
文件尾部8校验页面是否完整

3、各部分讲解

【1】文件头部

文件头部38个字节由8个部分组成,看表理解:

名称字节大小描述
FIL_PAGE_SPACE_OR_CHKSUM4表空间id或校验和
FIL_PAGE_OFFSET4页号,当前页的唯一标识
FIL_PAGE_PREV4上一个页号唯一标识
FIL_PAGE_NEXT4下一个页号唯一标识
FIL_PAGE_LSN8该页最后一次修改对应的redo日志序号
FIL_PAGE_TYPE2页类型
FIL_PAGE_FILE_FLUSH_LSH8该页被刷到磁盘的redo日志序号
FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID4归档日志编号或页属于哪个表空间

1、本文是在FIL_PAGE_TYPE为数据页的基础上进行讲解

2、FIL_PAGE_SPACE_OR_CHKSUM对于数据页的类型含义为校验和,用来和文件尾部的校验和进行对比

【2】页头部

页头部的56个字节由14个部分组成,看表理解:

名称字节大小描述
PAGE_N_DIR_SLOTS2页目录中存储槽的数量
PAGE_HEAP_TOP2页中空闲空间地址
PAGE_N_HEAP2未标记删除用户记录 + 已标记删除用户记录 + 最小记录 + 最大记录
PAGE_FREE2第1条标记为已删除的用户记录地址
PAGE_GARBAGE2所有标记为已删除记录占用的字节数
PAGE_LAST_INSERT2最后一条用户记录插入位置
PAGE_DIRECTION2最后一条用户记录插入方向,主键/unique健/隐藏列唯一键比上一条大就为右,反之为左
PAGE_N_RECS2未标记为删除的用户记录数
PAGE_MAX_TRX_ID8修改当前页的最新事务id
PAGE_LEVEL2当前页在B+树中的层级
PAGE_INDEX_ID8当前页属于的索引ID
PAGE_BTR_SEG_LEAF10B+树叶子段的头部信息
PAGE_BTR_SEG_TOP10B+树非叶子段的头部信息

【3】最小记录和最大记录

最小记录和最大记录2条记录是页中固定就存在的,最小记录和最大记录都是由5字节头部信息+8字节数据组成,所以它们总共占用空间26字节,最小记录数据部分固定为’infimum’,最大记录数据部分固定为’supremum’, 在讲它之前我们先了解一下Compact行格式中头部信息用5字节来存储的行记录信息,其组成部分如下:

名称位大小描述
预留位1未使用
预留位1未使用
delete_mask10-记录未删除,1-记录已删除
min_rec_mask1B+树非叶子节点中的最小记录
n_owned4当前记录在记录组里拥有记录数
heap_no13当前记录在记录堆中的位置
record_type3记录类型,0-普通记录,1-B+数非叶子节点记录,2-最小记录,3-最大记录
next_record16指向下一条未被删除的记录

当页中没有任何用户记录时,最小记录和最大记录可以如图表示:

在这里插入图片描述

最小记录中的n_owned为1表示以最小记录结尾的分组记录中只有一条记录,这条记录就是最小记录本身,最小记录的next_record为13代表最小记录数据部分与下一条数据部分的偏移量,所以上图箭头指向最大记录的固定数据部分,13字节大小是这样计算的: 最小记录固定数据部分(8) + 最大记录头部信息(5)

next_record之所以指向下一条记录的数据部分是因为:对于用户记录,指向位置往左的头部信息中还有逆序的长度列表、逆序的是否为NULL列表,往右就是数据部分。

最大记录中的n_owned为1表示以最大记录结尾的分组记录中只有一条记录,这条记录就是最大记录本身,最大记录的next_record为0代表没有下一条记录,它就是最后一条记录。

n_owned数有这样的定义:

  • 1、最小记录所在分组记录数最多只能有1条。
  • 2、最大记录所在分组记录数范围为1~8条。
  • 3、用户记录所在分组记录数范围为4~8条。

【4】行记录

行记录讲解需要根据数据来进行理解了,我们先创建一张表如下:

CREATE TABLE test
(
    id INT AUTO_INCREMENT PRIMARY KEY,
    str VARCHAR(255) NOT NULL DEFAULT ''
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;

插入3条记录:

INSERT INTO test (str)
VALUES ('AAA'),
       ('BBB'),
       ('CCC');

查看记录:

mysql [xxx]> select * from test;
+----+-----+
| id | str |
+----+-----+
|  1 | AAA |
|  2 | BBB |
|  3 | CCC |
+----+-----+
3 rows in set (0.001 sec)

此时插入的3条记录和最小最大记录可以如图表示:

在这里插入图片描述

可以看到所有记录通过nex_record的偏移量组成了一个链表,删除其中某条记录,就会把该条记录的delete_mask设置为1,next_record设置为0,但是记录依然存在,只是标记为了删除,这是为了后面插入新数据时可以对这部分空间进行复用,如图:

在这里插入图片描述

因为是第1条标记删除的记录,也会在页头部记录这条记录的地址,如果有多条删除记录,它们之间也会组成一个链表。

【5】空闲空间

空闲空间就是给行记录使用的,行记录空间增加,空闲空间就减少。

【6】页目录

页目录就是用来存储槽的,槽就是一组用户记录中,相对页起始位置偏移量最大的一条记录, 这条记录数据部分相对页起始位置的偏移量就作为槽,槽对应的记录中的n_owned属性就代表这条记录对应的用户组内有多少条记录,槽与记录关系可以如图表示:

在这里插入图片描述

最大记录看起来虽然是在最后面,起始它是和最小记录挨着的,所以后面记录增加导致分组产生新增槽时相对页起始位置的偏移量要比槽1大。

在讲最小记录和最大记录时讲过分组记录的约束,根据这个约束行记录分组产生规则如下:

1、新增记录放到比插入记录主键值大且主键值相隔最近的行记录对应的槽里,并将当前槽对应行记录的n_owned属性+1,表示该槽对应的记录组的记录多了1个。

2、当记录组的记录数变为9个时,会将这9条记录分为2个组,一组4个一组5个,对于4条记录的分组会将里面相对页起始位置最大的值的行记录的数据部分偏移量(相对页起始位置)设置为新的槽。

查找记录的规则如下:

1、通过二分法找到对应的槽。

2、根据行记录的next_record属性找到对应的行。

【7】文件尾部

文件尾部大小为8个字节,前4个字节代表页的校验和,和文件头部的校验和相等就代表是一个完成的页,后4个字节代表最后一次修改当前页是对应的redo日志序号,这个以后再讲。

4、总结

本篇文章讲解了数据页的组成,页是存储数据的基本单位;每个页的文件头部都会有一个上下页号,组成了一个双向链表;页中每条行记录的next_record组成一个单项链表;InnoDB会把多条记录分为一个组,组里的最大记录的数据部分相对于页面开头的偏移量就设置为槽,查找记录时通过二分法查找所在的槽,再通过行记录的next_record属性找到对应的记录。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • MySQL中ALTER LOGFILE GROUP 语句的具体使用

    MySQL中ALTER LOGFILE GROUP 语句的具体使用

    ALTER LOGFILE GROUP语句用于修改重做日志组的配置,本文主要介绍了MySQL中ALTER LOGFILE GROUP 语句的具体使用,需要的朋友们下面随着小编来一起学习学习吧
    2024-07-07
  • MySQL 集群迁移到 Kubernetes操作步骤

    MySQL 集群迁移到 Kubernetes操作步骤

    这篇文章主要为大家介绍了MySQL 集群迁移到 Kubernetes使用示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-09-09
  • mysql查看,创建,授权,删除用户的实现方式

    mysql查看,创建,授权,删除用户的实现方式

    这篇文章主要介绍了mysql查看,创建,授权,删除用户的实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-06-06
  • MySQL用limit方式实现分页的实例方法

    MySQL用limit方式实现分页的实例方法

    在本篇文章中小编给大家整理了一篇关于MySQL用limit方式实现分页的实例方法,有需要的朋友们可以参考学习下。
    2020-01-01
  • MySQL数据库设计之利用Python操作Schema方法详解

    MySQL数据库设计之利用Python操作Schema方法详解

    这篇文章主要介绍了MySQL数据库设计之利用Python操作Schema方法详解,还是比较不错的,这里分享给大家,供需要的朋友参考。
    2017-11-11
  • mysql 8.0.17 安装图文教程

    mysql 8.0.17 安装图文教程

    这篇文章主要为大家详细介绍了mysql 8.0.17 安装配置方法图文教程,文中安装步骤介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-08-08
  • window下mysql 8.0.15 winx64安装配置方法图文教程

    window下mysql 8.0.15 winx64安装配置方法图文教程

    这篇文章主要为大家详细介绍了window下mysql 8.0.15 winx64安装配置方法图文教程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-03-03
  • MySQL关键字问题分析与解决方案

    MySQL关键字问题分析与解决方案

    在实际开发中,我们常常会遇到由于SQL语法错误导致的数据库操作应用不能正常运行的情况,其中,使用了MySQL关键字作为表名或字段名,而没有逻辑地处理,带来的问题最为常见,本文将从一个实际案例出发,深入分析关键字问题及其解决方案,并提供进一步优化与避免方案
    2024-12-12
  • mysql添加索引反而速度变慢的问题

    mysql添加索引反而速度变慢的问题

    这篇文章主要介绍了mysql添加索引反而速度变慢的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-01-01
  • Mysql事务索引知识汇总

    Mysql事务索引知识汇总

    这篇文章主要介绍了Mysql事务索引知识汇总,mysql事务是用于处理操作量大、复杂性高的数据,索引能加快数据库的查询速度并高效获取指定的数据,下文相关详细内容,需要的小伙伴可以参考一下
    2022-03-03

最新评论