第21章_InnoDB数据页结构

news2024/12/27 15:12:27

文章目录

  • 概述
  • UserRecords和FreeSpace
  • Infimum + Supremum(最小记录和最大记录)
  • File Header(文件头部)
  • Page Directory(页目录)
  • File Trailer

概述

它是InnoDB管理存储空间的基本单位,一个页的大小一般是16KB。我们表中记录都是存放在页中的,官方称这种存放记录的页为索引(INDEX)页。因为这种类型的页是用来存放表数据的,也可以称为数据页。

一个InnoDB数据页的存储空间大致被划分成了7个部分,有的部分占用的字节数是确定的,有的部分占用的字节数是不确定的。如下图
在这里插入图片描述
从图中可以看出,一个InnoDB数据页的存储空间大致被划分成了7个部分,有的部分占用的字节数是确定的,有的部分占用的字节数是不确定的。下边我们用表格的方式来大致描述一下这7个部分都存储一些啥内容
在这里插入图片描述

UserRecords和FreeSpace

当插入一条新的记录时,会按照我们指定的行格式存储到User Records部分。但是,在页刚生成的时候,是没有User Records这个部分的,每当插入一条记录,都会从Free Space开辟相应的空间划分到User Records,当Free Space部分的空间全部被User Records部分替代掉之后,也就意味着这个页使用完了,如果还有新的记录插入的话,就需要去申请新的页了,这个过程的图示如下:
在这里插入图片描述

Infimum + Supremum(最小记录和最大记录)

但是不管我们向页中插入了多少自己的记录,设计InnoDB的大叔们都规定他们定义的两条伪记录分别为最小记录与最大记录。这两条记录的构造十分简单,都是由5字节大小的记录头信息和8字节大小的一个固定的部分组成的,如图所示
在这里插入图片描述
由于这两条记录不是我们自己定义的记录,所以它们并不存放在页的User Records部分,他们被单独放在一个称为Infimum + Supremum的部分,如图所示:
在这里插入图片描述
从图中我们可以看出来,最小记录和最大记录的heap_no值分别是0和1,也就是说它们的位置最靠前。

File Header(文件头部)

我们现在描述的File Header针对各种类型的页都通用,也就是说不同类型的页都会以File Header作为第一个组成部分,它描述了一些针对各种页都通用的一些信息,比方说这个页的编号是多少,它的上一个页、下一个页是谁等等。这个部分占用固定的38个字节,是由下边这些内容组成的:
在这里插入图片描述
对照着这个表格,我们看几个目前比较重要的部分:

  • FIL_PAGE_SPACE_OR_CHKSUM

    这个代表当前页面的校验和(checksum)。啥是个校验和?就是对于一个很长很长的字节串来说,我们会通过某种算法来计算一个比较短的值来代表这个很长的字节串,这个比较短的值就称为校验和。这样在比较两个很长的字节串之前先比较这两个长字节串的校验和,如果校验和都不一样两个长字节串肯定是不同的,所以省去了直接比较两个比较长的字节串的时间损耗。

  • FIL_PAGE_OFFSET

    每一个页都有一个单独的页号,就跟你的身份证号码一样,InnoDB通过页号来可以唯一定位一个页。

  • FIL_PAGE_TYPE

    这个代表当前页的类型,我们前边说过,InnoDB为了不同的目的而把页分为不同的类型,我们上边介绍的其实都是存储记录的数据页,其实还有很多别的类型的页,具体如下表:
    在这里插入图片描述
    我们存放记录的数据页的类型其实是FIL_PAGE_INDEX,也就是所谓的索引页。

  • FIL_PAGE_PREV和FIL_PAGE_NEXT
    我们前边强调过,InnoDB都是以页为单位存放数据的,有时候我们存放某种类型的数据占用的空间非常大(比方说一张表中可以有成千上万条记录),InnoDB可能不可以一次性为这么多数据分配一个非常大的存储空间,如果分散到多个不连续的页中存储的话需要把这些页关联起来,FIL_PAGE_PREV和FIL_PAGE_NEXT就分别代表本页的上一个和下一个页的页号。这样通过建立一个双向链表把许许多多的页就都串联起来了,而无需这些页在物理上真正连着。需要注意的是,并不是所有类型的页都有上一个和下一个页的属性,不过我们本集中唠叨的数据页(也就是类型为FIL_PAGE_INDEX的页)是有这两个属性的,所以所有的数据页其实是一个双链表,就像这样:

在这里插入图片描述

Page Directory(页目录)

记录在页中是按照主键大小依次串联成一个单链表。如果我们想查找某一条记录该怎么办,最笨的办法可能就是从Infimum记录(最小记录)开始,沿着链表一直往后找,相当于全都遍历一遍。如果数据量小的话,这种方法的效率还勉强能用,如果数据量很大的情况下呢,这种方法就相当耗时了。如果能像课本查找某个内容那样快速就好了,这时候InnoDB设计师想出了一个办法:

  • 将所有正常的记录(包括最大和最小记录,不包括标记为已删除的记录)划分为几个组。
  • 每个组的最后一条记录(也就是组内最大的那条记录)的头信息中的n_owned属性表示该记录拥有多少条记录,也就是该组内共有几条记录。
  • 将每个组的最后一条记录的地址偏移量单独提取出来按顺序存储到靠近页的尾部的地方,这个地方就是所谓的Page Directory,也就是页目录(此时应该返回头看看页面各个部分的图)。页面目录中的这些地址偏移量被称为槽(英文名:Slot),所以这个页面目录就是由槽组成的。

比方说现在的page_demo表中正常的记录共有6条,InnoDB会把它们分成两组,第一组中只有一个最小记录,第二组中是剩余的5条记录,看下边的示意图:
在这里插入图片描述
从这个图中我们需要注意这么几点:

  • 现在页目录部分中有两个槽,也就意味着我们的记录被分成了两个组,槽1中的值是112,代表最大记录的地址偏移量(就是从页面的0字节开始数,数112个字节);槽0中的值是99,代表最小记录的地址偏移量。
  • 注意最小和最大记录的头信息中的n_owned属性

最小记录的n_owned值为1,这就代表着以最小记录结尾的这个分组中只有1条记录,也就是最小记录本身。
最大记录的n_owned值为5,这就代表着以最大记录结尾的这个分组中只有5条记录,包括最大记录本身还有我们自己插入的4条记录。

99和112这样的地址偏移量很不直观,我们用箭头指向的方式替代数字,这样更易于我们理解,所以修改后的示意图就是这样:
在这里插入图片描述
单纯从逻辑上看一下这些记录和页目录的关系:
在这里插入图片描述
InnoDB的设计师对每个分组中的记录条数是有规定的:对于最小记录所在的分组只能有 1 条记录,最大记录所在的分组拥有的记录条数只能在1~8条之间,剩下的分组中记录的条数范围只能在是4~8条之间。所以分组是按照下边的步骤进行的:

  • 初始情况下一个数据页里只有最小记录和最大记录两条记录,它们分属于两个分组。
  • 之后每插入一条记录,都会从页目录中找到主键值比本记录的主键值大并且差值最小的槽,然后把该槽对应的记录的n_owned值加1,表示本组内又添加了一条记录,直到该组中的记录数等于8个。
  • 在一个组中的记录数等于8个后再插入一条记录时,会将组中的记录拆分成两个组,一个组中4条记录,另一个5条记录。这个过程会在页目录中新增一个槽来记录这个新增分组中最大的那条记录的偏移量。

由于现在page_demo表中的记录太少,无法演示添加了页目录之后加快查找速度的过程,所以再往page_demo表中添加一些记录:

mysql> INSERT INTO page_demo VALUES(5, 500, 'eeee'), (6, 600, 'ffff')
, (7, 700, 'gggg'), (8, 800, 'hhhh'), (9, 900, 'iiii'), 
(10, 1000, 'jjjj'), (11, 1100, 'kkkk'), (12, 1200, 'llll'), 
(13, 1300, 'mmmm'), (14, 1400, 'nnnn'), (15, 1500, 'oooo'), 
(16, 1600, 'pppp');
Query OK, 12 rows affected (0.00 sec)
Records: 12  Duplicates: 0  Warnings: 0

现在页里边就一共有18条记录了(包括最小和最大记录),这些记录被分成了5个组,如图所示:
在这里插入图片描述
现在看怎么从这个页目录中查找记录。因为各个槽代表的记录的主键值都是从小到大排序的,所以我们可以使用所谓的二分法来进行快速查找。4个槽的编号分别是:0、1、2、3、4,所以初始情况下最低的槽就是low=0,最高的槽就是high=4。比方说我们想找主键值为6的记录,过程是这样的:

  1. 计算中间槽的位置:(0+4)/2=2,所以查看槽2对应记录的主键值为8,又因为8 > 6,所以设置high=2,low保持不变。
  2. 重新计算中间槽的位置:(0+2)/2=1,所以查看槽1对应的主键值为4,又因为4 < 6,所以设置low=1,high保持不变。
  3. 因为high - low的值为1,所以确定主键值为6的记录在槽2对应的组中。此刻我们需要找到槽2中主键值最小的那条记录,然后沿着单向链表遍历槽2中的记录。但是我们前边又说过,每个槽对应的记录都是该组中主键值最大的记录,这里槽2对应的记录是主键值为8的记录,怎么定位一个组中最小的记录呢?别忘了各个槽都是挨着的,我们可以很轻易的拿到槽1对应的记录(主键值为4),该条记录的下一条记录就是槽2中主键值最小的记录,该记录的主键值为5。所以我们可以从这条主键值为5的记录出发,遍历槽2中的各条记录,直到找到主键值为6的那条记录即可。由于一个组中包含的记录条数只能是1~8条,所以遍历一个组中的记录的代价是很小的。

所以在一个数据页中查找指定主键值的记录的过程分为两步:

  • 通过二分法确定该记录所在的槽,并找到该槽中主键值最小的那条记录。
  • 通过记录的next_record属性遍历该槽所在的组中的各个记录。

File Trailer

我们知道InnoDB存储引擎会把数据存储到磁盘上,但是磁盘速度太慢,需要以页为单位把数据加载到内存中处理,如果该页中的数据在内存中被修改了,那么在修改后的某个时间需要把数据同步到磁盘中。但是在同步了一半的时候中断电了咋办,这不是莫名尴尬么?为了检测一个页是否完整(也就是在同步的时候有没有发生只同步一半的尴尬情况),InnoDB的设计师在每个页的尾部都加了一个File Trailer部分,这个部分由8个字节组成,可以分成2个小部分:

  • 前4个字节代表页的校验和

    这个部分是和File Header中的校验和相对应的。每当一个页面在内存中修改了,在同步之前就要把它的校验和算出来,因为File Header在页面的前边,所以校验和会被首先同步到磁盘,当完全写完时,校验和也会被写到页的尾部,如果完全同步成功,则页的首部和尾部的校验和应该是一致的。如果写了一半儿断电了,那么在File Header中的校验和就代表着已经修改过的页,而在File Trialer中的校验和代表着原先的页,二者不同则意味着同步中间出了错。

  • 后4个字节代表页面被最后修改时对应的日志序列位置(LSN)

    这个部分也是为了校验页的完整性的

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

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

相关文章

【3D图像分割】基于Pytorch的 VNet 3D 图像分割4(改写数据流篇)

在这篇文章&#xff1a;【3D 图像分割】基于 Pytorch 的 VNet 3D 图像分割2&#xff08;基础数据流篇&#xff09; 的最后&#xff0c;我们提到了&#xff1a; 在采用vent模型进行3d数据的分割训练任务中&#xff0c;输入大小是16*96*96&#xff0c;这个的裁剪是放到Dataset类…

C++中如何获取虚表和虚函数的地址

获取虚函数的地址 虚函数是C中用于实现多态的一种机制&#xff0c;该机制的原理在此不做赘述。本文主要讨论如何获取虚表以及虚函数的地址&#xff1f; class ClassA { private:int _a;double _b; public:ClassA(int a, double b) : _a(a), _b(b) { }virtual int funcA(int a…

设计模式之组合模式-创建层次化的对象结构

目录 概述概念主要角色应用场景 组合模式的实现类图NS图基本代码组合模式的精髓意外收获&#xff08;❀❀&#xff09; 应用示例-公司组织架构管理需求结构图代码 组合模式的优缺点优点缺点 总结 概述 概念 组合模式是一种结构型设计模式&#xff0c;它允许将对象组合成树形结…

xshell和linux什么关系,其实很简单

如果你是从事网络安全相关的工作人员&#xff0c;那你一定对很多人xshell和linux这两词很熟悉&#xff0c;那么xshell和linux究竟是什么关系呢&#xff1f;今天就让小编给你详细讲讲。 xshell和linux什么关系 一、xshell和linux什么关系 Xsehll是一款在Windows平台上运行的远…

在WSL2中安装多个Ubuntu实例

参考&#xff1a;How to install multiple instances of Ubuntu in WSL2 本文主要内容 第一步&#xff1a;在 WSL2 中安装最新的 Ubuntu第二步&#xff1a;下载适用于 WSL2 的 Ubuntu 压缩包第三步&#xff1a;在 WSL2 中安装第二个 Ubuntu 实例第四步&#xff1a;登录到第二个…

pyspark将数据多次插入表的时候报错

代码 报错信息 py4j.protocol.Py4JJavaError: An error occurred while calling o129.sql. : org.apache.spark.sql.catalyst.parser.ParseException: mismatched input INSERT expecting <EOF>(line 12, pos 0) 原因 插入语句结束后没有加&#xff1b;结尾 把两个&am…

自定义注解+拦截器/AOP切面 实现权限管理

一、通过拦截器实现 1 权限表 为了方便&#xff0c;我直接用的现成的权限表&#xff0c;这是表结构 2 自定义注解 首先&#xff0c;创建一个自定义注解&#xff0c;用于controller层的方法或类上 // Target表示该注解可以用在方法和类上 Target({ElementType.METHOD, Ele…

5.注释和文档

本文讲解 Java 中的注释以及文档 ~ 文章目录 1. 注释1.1 引言1.1.1 何为注释&#xff1f;1.1.2 注释有何用&#xff1f; 1.2 类注释1.2 方法注释 2. 文档 1. 注释 1.1 引言 1.1.1 何为注释&#xff1f; 在我看来&#xff0c;注释无非是对一行或多行代码作的解释罢了。它能让…

Java学习_day08_finalnativeabstract接口

文章目录 final关键字注意 native关键字abstract关键字抽象类定义继承 接口定义实现 final关键字 final关键字表示常量&#xff0c;其值在程序运行期间不会改变。 final用来修饰变量&#xff0c;可以是静态变量&#xff0c;也可以是成员变量&#xff0c;也可以是局部变量&…

连接图书馆wifi无法验证如何解决

我们去图书馆连接wifi&#xff0c;无法验证自己身份&#xff0c;怎么办&#xff1f; 一般是电脑怀疑是不安全&#xff0c;进行了拦截。 我们点击不安全 再点击 与此站点的连接不安全 &#xff0c; 了解详情就可以显示登陆界面了&#xff0c;

点击清空按钮表单数据不能清空

清空选项只能清空角色和状态的数据,无法清空用户名的数据, 经过排查后发现 username这个单词写错了,导致点击清空searchFormRef?.resetFields()不能清空用户名数据

算法之路(一)

&#x1f58a;作者 : D. Star. &#x1f4d8;专栏 :算法小能手 &#x1f606;今日分享 : 如何学习&#xff1f; 在学习的过程中&#xff0c;不仅要知道如何学习&#xff0c;还要知道避免学习的陷阱。1. 睡眠不足&#xff1b;2. 被动学习和重读&#xff1b;3. 强调标记或画线&am…

接口--抽象方法

回答问题&#xff1a; 1.接口是什么&#xff1f; 2.接口中可以包含什么内容&#xff1f; 3.如何定义接口格式&#xff1f; 4.接口定义抽象方法格式&#xff1f; Code //接口是公共规范标准&#xff0c;类似于“模具” //如何定义接口格式&#xff1f;/** public interface 接…

【Qt之QVariant】使用

介绍 QVariant类类似于最常见的Qt数据类型的联合。由于C禁止联合类型包括具有非默认构造函数或析构函数的类型&#xff0c;大多数有趣的Qt类不能在联合中使用。如果没有QVariant&#xff0c;则QObject::property()和数据库操作等将会受到影响。 QVariant对象同时持有一个单一…

View 自定义 - 路径 Path

参考文章 一、概念 用于描述顺序 & 区域&#xff0c;单使用无法产生效果。 图形绘制的本质是先画点再将点连接起来&#xff0c;所以点与点之间是存在一个先后顺序的。图形的方向影响的是&#xff1a;添加图形时确定闭合顺序(各个点的记录顺序)、图形的渲染结果(是判断图形…

ArcGIS进阶:水源涵养功能分级评价操作

首先抛出水源涵养重要性评价的公式&#xff1a;水源涵养量降雨量-蒸散发量-地表径流量&#xff0c;其中地表径流量降雨量*平均地表径流系数 声明&#xff1a;以下数据来源于来自于牛强老师书籍&#xff08;城乡规划GIS技术&#xff09;。 以下给出重要性评价阈值表&#xff1…

『MySQL快速上手』-⑥-表的约束

文章目录 1.空属性2.默认值3.列描述4.zerofill5.主键6.自增长7.唯一键8.外键9.综合案例 真正约束字段的是数据类型&#xff0c;但是数据类型约束很单一&#xff0c;需要有一些额外的约束&#xff0c;更好的保证数据的合法性&#xff0c;从业务逻辑角度保证数据的正确性。 1.空…

高校为什么需要企业数据库?

随着信息化数字化的发展&#xff0c;企业数据库已经成为高校不可或缺的一部分。企业数据库一般整合了多维度企业数据信息。比如&#xff0c;艾思依托丰富的数据沉淀和领先的模型算法&#xff0c;打造“1N”产业大数据平台&#xff0c;包含“1个企业数据中心”一一涵盖全国2.4亿…

计算机提示找不到concrt140.dll怎么办,分享4个有效的修复方法

在计算机使用过程中&#xff0c;我们经常会遇到一些错误提示或者系统崩溃的情况。其中&#xff0c;concrt140.dll是一个常见的错误提示&#xff0c;这个错误通常会导致某些应用程序无法正常运行。为了解决这个问题&#xff0c;我们需要采取一些修复措施。本文将介绍4个修复conc…

基于显著性的无人机多光谱图像语义杂草检测与分类

Saliency-Based Semantic Weeds Detection and Classification Using UAV Multispectral Imaging(2023&#xff09; 摘要1、介绍2、相关工作2.1 监督学习2.2 半监督学习2.3 无监督学习 3、方法3.1 贡献3.2 PC/BC-DIM NEURAL NETWORK&#xff08;预测编码/有偏竞争-分裂输入调制…