Mysql 学习(三)InnDB 存储引擎-页结构

news2025/1/20 10:47:53

数据页结构的大概

  • 首先我们先来了解一下,InnoDB的存储单元是数据页的概念,页的大小一般是16KB,而InnoDB里面存放了很多不同目的 的数据页,比如存放Insert Buffer的信息页,Undo的日志页等等。
  • 但是这里我们主要讲解的是存放表中的数据页,官方称这种存放数据的页,叫索引页。
  • 接下来我们先大致来了解数据页的结构,总共分为 7个 部分,根据顺序分别为:
    • File Header:文件头部,占用空间大小为38字节,主要存放页的一些通用信息
    • Page Header:页面头部,占用空间大小为56字节,主要是数据页专有的一些信息
    • Infimum + Supermum:最小记录和最大记录,占用空间36个字节,主要是存放两个虚拟的行记录
    • User Records:用户记录数据,占用空间大小是未知,主要是用来存放记录数据的
    • Free Space:空闲空间,占用空间大小是未知的,主要是页中没有使用的空间
    • Page Directory:页面目录,占用空间大小是未知,主要是页中的某些记录的相对位置
    • File Tailer:文件尾部,占用空间大小为8字节,主要是校验页是否完整
  • 了解了数据页的大概结构,接下来我们就需要了解更加详细的信息,从头到尾接着说

File Header 文件头部

  • 想象一下,当你翻书的时候,特别是对应的百科全书,你想要找到某一页的内容,是否需要一些信息才能更好的找到,比如 页的号码,页的归类等等。
  • InnoDB 引擎的数据页也需要这些东西,这样才能更快更好的找到所需要的数据,但是 文件头部的信息存储还没有那么详细,他主要是存储一些页的状态信息,因为这样存储可以通用于不同类型的数据页。
  • 文件头部主要存储的状态信息有这些:
    • FIL_PAGE_SPACE_OR_CHKSUM:页的校验和
    • FIL_PAGE_OFFSET:页的号码,每个页都有单独的页号
    • FIL_PAGE_PREV:上一页,之所以存储上一页和下一页是因为数据页不一定是按照顺序来进行分配的,也有可能在存储的各个地方,所以就需要双向索引来进行关联。
    • FIL_PAGE_NEXT:下一页
    • FIL_PAGE_LSN:页面被最后修改时对应的日志序列位置
    • FIL_PAGE_TYPE:这个代表当前页的类型
      在这里插入图片描述
    • FIL_PAGE_FILE_FLUSH_LSN:仅在系统表空间的一个页中定义,代表文件至少被刷新到了对应的LSN值
    • FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID:页属于哪个表空间

Page Information 页的相关信息

  • 介绍完 文件头部 以后,我们可以来看看页的头部,上面讲了,页的头部更多存储了页的相关信息,主要是为了查询记录更加方便,所以接下来我们就来探索。
  • 由于页的头部信息主要是为了记录做铺垫,所以我们就从记录开始讲解,从里到外一步步来

User Records

  • 首先先创建一个表,为了简便理解,先建一个字符集是ascii,一个字符一个字节,且行格式是Compact的表
CREATE TABLE page_test ( p1 INT, p2 INT, p3 VARCHAR ( 10000 ), PRIMARY KEY ( p1 ) ) CHARSET = ascii ROW_FORMAT = Compact;
  • 创建完之后,我们来看看表的记录行结构
    在这里插入图片描述
  • 这个结构,有些上一节已经说过了,有一些没有说,但是这节最重要的是记录的头部信息,头部信息各个指标是:
    • 预留位1:没有使用
    • 预留位2:没有使用
    • delete_mask:这条记录是否给删除
    • min_rec_mask:B+树的每层非叶子节点中的最小记录都会添加该标记
    • n_owned:表示截止到当前记录为止,数据页拥有的记录数
    • heap_no:表示当前记录在记录堆中的位置信息
    • record_type:表示当前记录的类型
      • 0 普通记录
      • 1 B+树非叶节点记录
      • 2 最小记录
      • 3 最大记录
    • next_record:表示下一条记录的位置信息
  • 了解记录头部信息以后,我们再插入几条记录更加直观的看看
INSERT INTO page_test VALUES(1, 1, '1111'), (2, 22, '2222'), (3, 333, '3333'), (4, 4444, '4444');

在这里插入图片描述

  • delete_mask:
    • 首先先来看看delete_mask这个字段,为什么会出现这个字段?
    • 因为删除记录的时候,我们不会立即删除,会先给这条记录打上标记,并且将上一条记录的next_record的字段附上我们的next_record字段,并且将我们的next_record字段置为0。并且之后如果有新记录插入到表中的话,可能把这些被删除的记录占用的存储空间覆盖掉。之所以这么做主要是有两个原因:
      • 移除它们之后把其他的记录在磁盘上重新排列需要性能消耗
      • 如果删除之后这些空间不用,就会有很多碎片化的空间
  • min_rec_mask:为索引做准备的
  • heap_no:
    • 这个属性表示当前记录在本页的位置,但是可以从图中看出来,我们是从2开始的,0和1都不在,为什么呢?
      • 这就是InnoDB的一个精巧的设计,在每个页创建之时,就会自动添加进去两条记录,分别是 Infimum 和Supermum ,没错就是最小记录和最大记录,最小记录的heap_no为0 放在最前面,最大记录的heap_no为1放到最后面,而这两条记录的构造都是定死的,都是由 5个字节大小的记录头信息和8个字节大小的固定部分组成的
      • 并且由于 Infimum + Supermum 跟 用户记录是不一样,所以放在 User Records 之前 当作一部分
        在这里插入图片描述
  • next_record:它表示从当前记录的真实数据到下一条记录的真实数据的地址偏移量。从结构上来看,这记录的存储像一个链表,通过一个记录找到他的下一个链表。还需要注意的是,链表的顺序是按照主键的顺序进行排列的,也就是说一个记录的下一个记录的地址一定是跟他的主键顺序有关的,而且规定 Infimum记录(也就是最小记录) 的下一条记录就是本页中主键值最小的用户记录,而本页中主键值最大的用户记录的下一条记录就是 Supremum记录(也就是最大记录) 。至于删除之后的操作,在delete_mask已经说过了
  • n_owned:这个参数十分重要,但是讲解这个需要跟Page Directory 页目录有关,下面我们就跟着页目录一起看看

Page Directory

  • 以上我们了解了记录在页中是按照主键值由小到大顺序串联成一个单链表。但是如果我们想根据主键值查找页中的某条记录,怎么查询呢?是一条一条遍历吗?那效率也太低了,这个时候我们就需要页目录了
  • 就像之前讲的我们在书中找到对应的模块,一般是根据目录的页码去查找,所以这边也会制作一个类似功能的页目录,制作流程如下:
    • 将所有正常的记录(包括最大和最小记录,不包括标记为已删除的记录)划分为几个组
    • 每个组的最后一条记录(也就是组内最大的那条记录)的头信息中的n_owned属性表示该记录拥有多少条记录,也就是该组内共有几条记录。
    • 将每个组的最后一条记录的地址偏移量单独提取出来按顺序存储到靠近页的尾部的地方,这个地方就是所谓的Page Directory,也就是页目录(此时应该返回头看看页面各个部分的图)。页面目录中的这些地址偏移量被称为槽(英文名:Slot),所以这个页面目录就是由槽组成的。
  • 备注:对于最小记录所在的分组只能有 1 条记录,最大记录所在的分组拥有的记录条数只能在1 - 8条之间,剩下的分组中记录的条数范围只能在是 4-8 条之间。所以分组是按照下面的步骤进行的:
    • 初始情况下一个数据页里只有最小记录和最大记录两条记录,它们分属于两个分组。
    • 之后每插入一条记录,都会从页目录中找到主键值比本记录的主键值大并且差值最小的槽,然后把该槽对应的记录的n_owned值加1,表示本组内又添加了一条记录,直到该组中的记录数等于8个。
    • 在一个组中的记录数等于8个后再插入一条记录时,会将组中的记录拆分成两个组,一个组中4条记录,另一个5条记录。这个过程会在页目录中新增一个槽来记录这个新增分组中最大的那条记录的偏移量。
  • 下面通过一个例子来讲解 :
  • 假设我们一下子添加12条记录,就会产生下面如图的分组
    在这里插入图片描述
  • 有了这个槽以后,我们查找对应主键的记录,就方便了多了,主要步骤是:
    • 通过二分法确定该记录的槽,并找到槽中主键值最小的记录
    • 通过记录的next_records 挨个遍历,找到记录

Page Header

  • 根据上面的信息,我们终于可以说页面头部存那些信息了,想必你们都知道了,如果想要更快找到对应的记录,就需要在头部存储一些信息,比如目录存储了多少个槽,第一条记录的地址等等
  • 下面就是对应信息:
    • PAGE_N_DIR_SLOTS:在页目录中的槽数量
    • PAGE_HEAP_TOP:还未使用的空间最小地址,也就是说从该地址之后就是Free Space
    • PAGE_N_HEAP:本页中的记录的数量
    • PAGE_FREE:第一个已经标记为删除的记录地址
    • PAGE_GARBAGE:已删除记录占用的字节数
    • PAGE_LAST_INSERT:最后插入记录的位置
    • PAGE_DIRECTION:记录插入的方向
    • PAGE_N_DIRECTION:一个方向连续插入的记录数量
    • PAGE_N_RECS:该页中记录的数量
    • PAGE_MAX_TRX_ID:修改当前页的最大事务ID,该值仅在二级索引中定义
    • PAGE_LEVEL:当前页在B+树中所处的层级
    • PAGE_INDEX_ID:索引ID,表示当前页属于哪个索引
    • PAGE_BTR_SEG_LEAF:B+树叶子段的头部信息,仅在B+树的Root页定义
    • PAGE_BTR_SEG_TOP:B+树非叶子段的头部信息,仅在B+树的Root页定义

File Trailer

  • 由于InnoDB 存储引擎会把数据存储到磁盘上,但是磁盘速度太慢了,需要以页为单位把数据加载到内存中处理,如果有修改,则在某个时间点同步到磁盘中,但是如果在同步中出现一些不可抗力因素失败了,则需要一些信息来判定数据是否完整
  • 前4个字节代表 页的校验和:
    • 这个部分是和File Header中的校验和相对应的。每当一个页面在内存中修改了,在同步之前就要把它的校验和算出来,因为File Header在页面的前面,所以校验和会被首先同步到磁盘,当完全写完时,校验和也会被写到页的尾部,如果完全同步成功,则页的首部和尾部的校验和应该是一致的。如果写了一半儿断电了,那么在File Header中的校验和就代表着已经修改过的页,而在File Trialer中的校验和代表着原先的页,二者不同则意味着同步中间出了错。
  • 后4个字节代表页面被最后修改时对应的日志序列位置(LSN):
    • 这个部分也是为了校验页的完整性的,只不过我们目前还没说LSN是个什么意思,所以大家可以先不用管这个属性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/427704.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

从C语言到C++(第一章_C++入门_上篇)C++学习介绍(命名空间和C++输入输出流)

目录 前言 1.认识C 2.C的重要性 3.如何学习C 4.编写hello world! 5.关键字 6.命名空间(namespace) 6.1命名空间的定义 6.2命名空间里的内容 6.3命名空间重名问题 6.4命名空间展开问题 6.5匿名命名空间 7.C的输入与输出 7.1 输入和…

生产模块-报工自动产生返工订单(触发点-Trigger Point)

目录 应用场景 配置点-完整模式(通过自定义状态触发) 其他说明 应用场景 一般来说适合自动化程度高,生产集成了MES和质检的功能,工序报工时发生返工业务时,根据返工的指令,系统直接下达返工订单。例如&…

3年经验,面试测试岗只会功能测试开口要求18K,令我陷入沉思。

由于朋友临时有事, 所以今天我代替朋友进行一次面试,公司需要招聘一位自动化测试工程师,我以很认真负责的态度完成这个过程, 大概近30分钟。 主要是技术面试, 在近30分钟内, 我与被面试者是以交流学习的方式…

【CSS】定位 ③ ( 绝对定位 | 父容器有定位相对于父容器定位 | 父容器没有定位相对于浏览器进行定位 )

文章目录一、绝对定位二、标准流下的父容器与子元素关系1、标准流下父容器与子容器代码2、移动父容器后的效果三、子元素设置绝对定位与父容器是否有定位的效果对比1、父容器没有定位的情况下为子容器添加定位2、父容器有定位的情况下为子容器添加定位3、父容器没有定位爷爷容器…

Doris(2):Doris编译部署

1 Doris编译 Apache Doris提供直接可以部署的版本压缩包:https://cloud.baidu.com/doc/PALO/s/Ikivhcwb5 也可以自行编译压缩包后使用(推荐) 1.1 使用 Docker 开发镜像编译(推荐) 这个是官方文档推荐的,…

4.15搞力扣哈哈

1. 1023. 驼峰式匹配 难度中等107收藏分享切换为英文接收动态反馈 如果我们可以将小写字母插入模式串 pattern 得到待查询项 query,那么待查询项与给定模式串匹配。(我们可以在任何位置插入每个字符,也可以插入 0 个字符。) 给…

map原理

map源码结构体: type hmap struct {count int // 元素的个数B uint8 // buckets 数组的长度就是 2^B 个overflow uint16 // 溢出桶的数量​buckets unsafe.Pointer // 2^B个桶对应的数组指针oldbuckets unsafe.Pointer // 发生扩容时&#xff0…

系统学习Git

Git目录工作区、暂存区和版本库分别是什么?Git常用命令有哪些?Git是如何进行分支管理的?Git如何查看提交历史?实践出真知!报错fatal: pathspec text1.txt did not match any filesGit 是一个开源的分布式版本控制系统工…

【k8s完整实战教程4】使用kubesphere部署项目到k8s

系列文章:这个系列已完结,如对您有帮助,求点赞收藏评论。 读者寄语:再小的帆,也能远航! 【k8s完整实战教程0】前言【k8s完整实战教程1】源码管理-Coding【k8s完整实战教程2】腾讯云搭建k8s托管集群【k8s完…

SSM学习记录4:SSM整合(注释方式 + SprigMVC项目 + 2022发布版本IDEA)

SSM整合 整合中Tomcat等配置与前面学习相同 注:SpringMvcConfig里扫描的用Configuration注解的组件可以装载SpringConfig里扫描的组件,而SpringMvc不可以装载SpringMvcConfig里扫描的组件,相同配置类中扫描的组件可以相互装载 1.添加依赖↓ …

PLATO: Pre-trained Dialogue Generation Model with Discrete Latent Variable论文学习

一、大纲内容 二、详细内容 Abstract ○ 对话生成模型可以用于闲聊、知识对话、对话问题生成 ○ 本文 ■ 构建了一个灵活的attention机制,充分的促进了单向和双向的语言生成模型 ■ 介绍了一个离散的潜变量,较好的解决了一问多答的问题 ■ 上述两个结构…

DAY 36 文本处理命令awk

awk的概述 awk: 在 Linux/UNIX 系统中,awk 是一个功能强大的编辑工具,逐行读取输入文本, 默认以空格或tab键作为分隔符作为分隔,并按模式或者条件执行编辑命令 awk信息的读入也是逐行指定的匹配模式进行查找&#x…

Unity ——使用贝塞尔曲线对三维管状物体进行弯曲

参考链接:【Unity】弹性鱼竿简单实现-通过贝塞尔曲线修改Mesh - 简书 参考论文:吴晓亮, 黄襄念. Unity 中使用贝塞尔曲线对三维物体进行弯曲[J]. 现代计算机, 2016 (5): 57-59. unity项目下载:https://download.csdn.net/download/weixin_4…

时间序列 | MATLAB实现CNN-GRU-Attention时间序列预测

时间序列 | MATLAB实现CNN-GRU-Attention时间序列预测 目录时间序列 | MATLAB实现CNN-GRU-Attention时间序列预测预测效果基本介绍模型描述程序设计参考资料预测效果 基本介绍 MATLAB实现CNN-GRU-Attention时间序列预测,CNN-GRU结合注意力机制时间序列预测。 模型描…

涨点技巧:卷积变体DCNV2引入Yolov8,助力小目标涨点

1.DCN V2介绍 DCN V2: Improved Deep & Cross Network and Practical Lessons for Web-scale Learning to Rank Systems 论文:https://arxiv.org/abs/2008.13535 作者通过在DCN的基础上,增加了2个创新点,分别是调制模块和使用多个调制后的DCN模块,从形成了DCN的升级版…

解码营养行业新趋势 2023晶球益生菌与肠内营养健康高峰论坛圆满落幕

后疫情时代,国人自身健康管理意识日益提高,越来越多的人认识到到微生物组、营养吸收与免疫健康的密切联系,并逐渐认可微生态和肠内营养在临床应用过程中的积极作用,使得营养治疗研究成果进一步落地转化。消费升级新时代&#xff0…

一文带你读懂,这三个交换机层级的区别和联系。

01 第二层交换机 OSI参考模型的第二层叫做数据链路层,第二层交换机通过链路层中的MAC地址实现不同端口间的数据交换。 第二层交换机主要功能,就包括物理编址、错误校验、帧序列以及数据流控制。 因为这是最基本的交换技术产品,目前桌面型交…

CDN到期不想续费?!MINIO救个场!

一、安装MINIO 下载 wget https://dl.min.io/server/minio/release/linux-amd64/archive/minio-20230413030807.0.0.x86_64.rpm -O minio.rpm 安装 yum install minio.rpm 二、启动 MinIO 服务器 创建启动实例目录 mkdir ~/minio 启动 MInIO实例 minio server ~/minio -…

解析hash(散列)数据结构

前言 在学习完map、set这两个由红黑树构成的容器后,我们来到了这里hash,首先我们要有一个基础的认知——哈希和map与set的仅在使用时的差别区别:前者内部的元素没有序,而后者有序,其它的都相同,这里我们可…

【C++进阶之路】第一篇:C++中的继承

🌟hello,各位读者大大们你们好呀🌟 🍭🍭系列专栏:【C学习与应用】 ✒️✒️本篇内容:继承的基础概念,定义方法,基类和派生类的转换,继承中类的作用域&#xf…