InnoDB数据页结构

什么是页?什么是数据页?

页是InnoDB管理存储空间的基本单元,一个页的大小一般是16k。

InnoDB有许多不同的页,有存放表空间头部信息的页,INODE信息的页,当然还有存放我们记录信息的页,这个页叫做索引页,也可以叫做数据页。

数据页的结构有哪些?不同的结构分别对应什么功能?

File Header : 页的通用信息

Page Header: 数据页专有的信息

Infimum + supermum : 两个虚拟的行记录
User Records  :存储用户的实际记录,最开始为空,每当我们插入一条记录,都会从Free Space中申请空间划分到此处,然后记录以compact行格式进行存放。
Free Space: 页中尚未使用的空间Page Dictionary :页中某些记录的相对位置
File Tailer : 用来检验页是否完整

为了更好的管理User Records中的记录,InnoDB是怎么操作的?难道不是直接把记录按照指定的格式一条一条简单的摆放在User Records中的吗? compact记录头信息中的那一部分到底做了什么事情?

记录头信息到底做了什么?记录头信息的结构是什么?不同的结构对应的功能是什么?

 预留位置一,二:没有使用

delete_mask :标记该记录是否被删除,占用一个二进制位。 被标记为1的记录被删除掉了,但是还在页面中,被标记为1的记录会组成一个垃圾链表,这个链表被占用的空间被称之为所谓的可重用空间,如果之后有新的记录插入到表中的话,被删除的记录占用的存储空间会被覆盖掉。

min_rec_mask :标记 B+树每层的非叶子节点中的最小记录 (具体什么作用还不清晰)

n_owned: 表示当前记录拥有的记录数量 (具体什么作用还不清晰)

heap_no :表示当前记录在记录堆中的位置信息 ,也可以说是在当前记录页中的位置。 记录之间通过主键可以比大小; 我们插入的数据都是从 2 开始的,0 和 1 分别代表最小记录和最大记录,这两条记录的构造十分简单,都是由5字节大小的记录头信息和8字节大小的一个固定的部分组成的。

record_type :表示当前记录的类型,0代表普通记录,1代表B+树非叶子节点,2代表最小记录,3代表最大记录。

next_record:表示下一条记录的相对位置。

总上所述,记录头信息的作用是:就是把一条一条的记录按照一定的规则联系了起来,而不是我们想的那样只是简单的将用户的记录堆放在User Records中。

next_record这个指针有点儿怪,为什么要指向记录头信息和真实数据之间的位置呢?为什么不干脆指向整条记录的开头位置,也就是记录的额外信息开头的位置呢?

因为这个位置刚刚好,向左读取就是记录头信息,向右读取就是真实数据。我们前面还说过变长字段长度列表、NULL值列表中的信息都是逆序存放,这样可以使记录中位置靠前的字段和它们对应的字段长度信息在内存中的距离更近,可能会提高高速缓存的命中率。

删除一条中间的用户记录会发生哪些变化?

1.该记录没有从存储空间中移除,而是把这条记录的delete_mask值设置为1

2. 该条记录的next_record值变成了0,意味着该条记录并没有下一条记录了

3.该条记录的前一个记录的next_record指向了该条记录的后一个记录

4. 最大记录只n_owned值从5变成了4

页目录(page Directory)是什么?是为了解决什么问题?

在页中,所有的记录是通过单链表的形式连接在一起,如果我们想要查询下面的记录,c1是主键

SELECT * FROM page_demo WHERE c1 = 3;

最笨的方法是从Infimum记录开始,然后沿着单链表一直查下去,直到查出来符合条件的结果,或者直接查不出来。 如果表中的数据特别多的话,再这样一条一条记录的查找就不行了。 

我们可以设置一个目录,然后我们如果想要查找某一条记录的时候,先看一下目录,然后查找内容。

InnoDB也做了一个类似的目录:

1. 将所有的记录(不包括被删除的记录)分为几个组。

2. 每个组的最后一条记录,也就是组内最大的那条记录 的头信息中的n_owned属性表示该条记录中拥有多少记录,也就是组内有多少条记录。

3. 把组内最后一条记录的地址偏移量单独提取出来按照顺序存储在靠近页的尾部的地方,这个地方就是 Page Directiory,也就是页目录。

页面中的目录的地址偏移量被称为槽,页目录也就是槽组成的。

 上面的图中,为什么最小记录的n_owned的值为1,而最大记录的n_owned的记录是5呢? 

InnoDB对于每个组的记录条数是有规定的:对于最小记录所在的分组只能有一个记录,最大记录所在的分组可以有1-8条记录,剩下的分组中的记录条数只能是4-8 条之间。

具体分组是按照下面的步骤进行的:

初始情况只有两组,每组中只有一条记录,分别是最小记录和最大记录。

之后每次插入一条数据,都会页目录中找到主键值比本记录的主键值大,并且差值最小的槽,然后把该槽的对应的记录的n_owned记录值+1 ,表示本组内添加了一条记录,直到改组中的记录数量等于8 个。

在一个组中的记录数量等于8后,再插入一条数据,那个这个组将被拆分为两个组,一个组四条记录,一个组是五条记录,这个过程会在页目录中新增一个槽来记录这个新增分组的最大的那条记录的偏移量。

 

不要忘记,我们最初都是为了通过主键来定位一条数据。现在我们有了页目录,我们开始定位这条数据了。

假如说我们想要定位主键是6的数据,我们需要进行如下操作

设置low 为0 ,high 是4

先找到中间槽对应的主键:中间槽是(0+4)/ 2 = 2 ,槽2 对应的主键是8 ,8  > 6 ,设置high = 2 ,low不变

然后再计算中间槽 (0 + 2) = 1 ,槽1对应的主键是4 , 4 < 6 ,设置low = 1 

此时higt - low 的值是1 ,所以 该主键就是在第high个组内 ,也就是槽2中 。 然后我们只需要找到槽2中主键最小的那条记录,然后沿着单向链表遍历槽2即可找到数据。  

还有一个问题是我们现在知道该条记录是在槽2中的,同时我们也知道了槽2的最大主键记录,但是我们其实是从槽2的最小记录开始遍历,这个时候该怎么找到槽2的最小记录呢? 

正确做法是,我们可以先拿到刚才记录出来的槽1,然后拿到槽1的最大记录,槽1和槽2是互相紧邻的,然后往后一下,就是槽2的最小记录了。 

总结一下,在一个数据页中查找主键值的记录的过程分为两步:

1. 通过二分法确定该记录所在的槽的位置,并找到该槽中主键值最小的那条记录。 

2. 通过next_record 属性遍历该槽所在的组中的各个记录。 

综上所述,目录页的作用就是把User Record中分组的数据安装索引一一对应起来,方便通过主键进行数据的查找。

Page Header(页面头部)是干什么的?

记录数据页中存储的记录的状态信息,比如说本页中存储了多少条记录,第一条记录的地址是什么? 页目录中存储了多少个槽 ? Page Header也页的第二部分,占用固定的56个字节。

 

File Header (文件头部)是干什么的?

之前介绍的Page Header是专门针对数据页的,不是所有页特有的,现在的File Header文件头部是公有的,也就是说,不同类型的页都会有个File Header 部分,并且作为第一组成部分,File Header记录是一些针对各种页都通用的信息,比如说,此页的编号,他的上一个页,下一个页是谁等等,固定38个字节。

 FIL_PAGE_SPACE_OR_CHKSUM 是页面的校验和,用来把长的字符串通过一定的算法转化成比较短的值,到时候比较的时候,不再直接把字符串进行比较,而是使用校验和来进行比较,从而提升性能。

Fil_PAGE_OFFSET:页的号码,就像身份中一样,通过页号定位一个页。

FIL_PAGE_TYPE : 页的类型,除了我们上面一直说的索引页(也叫数据页),还有其他好多类型

FIL_PAGE_PREV 和 FIL_PAGE_NEXT ,数据非常多的时候,是被存储在不同的页中,页在物理空间上并不相邻,这个时候InnoDB是同过双向链表把页给连接起来的,这个两个字段就是连接的字段。

 File Trailer

用来检验页面是否完整。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

车载以太网 - SomeIP - 协议用例 - Messages_01

目录 Service Discovery Messages 1、验证Instance ID为0xFFFF时DUT需要返回该Serveice ID包含的所有Instance ID

「实验记录」MIT 6.824 Raft Lab2B Log Replication

#Lab2B - Log Replication I. SourceII. My CodeIII. MotivationIV. SolutionS1 - leader上任即初始化S2 - leader发送AppendEntriesS3 - follower接收AppendEntriesS4 - leader收到AppendEntries 回信S5 - candidate选举限制S6 - defs.go约定俗成和实现Start() V. Result I. S…

LeetCode 栈和队列OJ题目分享

目录 有效的括号&#xff08;括号匹配&#xff09;用栈实现队列用队列实现栈设计循环队列 有效的括号&#xff08;括号匹配&#xff09; 链接: link 题目描述&#xff1a; 题目思路&#xff1a; 1、如果是左括号“&#xff08; { [ ”就入栈 2、如果是右括号“&#xff09; }…

程序员:面试造火箭,入职拧螺丝?太难了···

刚开始工作的时候&#xff0c;我也想不通这个问题&#xff0c;甚至很鄙视这种现象。后面当了面试官&#xff0c;做到了公司中层管理&#xff0c;也会站在公司以及行业角度去重新思考这个问题。 为什么这种现象会越来越普遍呢&#xff1f;尤其在 IT 行业愈加明显。 面试看的是…

Packet Tracer – VLAN 实施故障排除场景 2

Packet Tracer – VLAN 实施故障排除场景 2 拓扑图 地址分配表 设备 接口 IPv4 地址 子网掩码 默认网关 S1 VLAN 56 192.168.56.11 255.255.255.0 不适用 S2 VLAN 56 192.168.56.12 255.255.255.0 不适用 S3 VLAN 56 192.168.56.13 255.255.255.0 不适用 P…

头歌计算机组成原理实验—运算器设计(11)第11关:MIPS运算器设计

第11关&#xff1a;MIPS运算器设计 实验目的 学生理解算术逻辑运算单元&#xff08;ALU&#xff09;的基本构成&#xff0c;掌握 Logisim 中各种运算组件的使用方法&#xff0c;熟悉多路选择器的使用&#xff0c;能利用前述实验完成的32位加法器、 Logisim 中的运算组件构造指…

图神经网络:(处理点云)PointNet++的实现

文章说明&#xff1a; 1)参考资料&#xff1a;PYG官方文档。超链。 2)博主水平不高&#xff0c;如有错误还望批评指正。 3)我在百度网盘上传了这篇文章的jupyter notebook和有关文献。超链。提取码8848。 文章目录 简单前置工作学习文献阅读PointNet的实现模型问题 简单前置工作…

智慧井盖监测终端,智能井盖-以科技解决智慧城市“顽疾”,守护城市生命线

平升电子智慧井盖监测终端,智能井盖-以科技解决智慧城市“顽疾”,守护城市生命线-智慧井盖&#xff0c;实现对井下设备和井盖状态的监测及预警&#xff0c;是各类智慧管网管理系统中不可或缺的重要设备&#xff0c;解决了井下监测环境潮湿易水淹、电力供应困难、通讯不畅等难题…

XDP入门--BPF程序如何转发报文到其它网卡

本文目录 1、测试环境&#xff1a;2、实现的功能&#xff0c;使用bpf_redirect直接转发收到的报文到另外一张网卡3、测试步骤与测试结果 1、测试环境&#xff1a; 参照把树莓派改造成无线网卡(3)-----共享无线网络&#xff0c;无线网络转换成有线网络&#xff0c;让有线网络设…

插入排序、选择排序、冒泡排序小结(45)

小朋友们好&#xff0c;大朋友们好&#xff01; 我是猫妹&#xff0c;一名爱上Python编程的小学生。 和猫妹学Python&#xff0c;一起趣味学编程。 今日主题 插入排序、选择排序、冒泡排序有什么区别&#xff1f; 原理不同 插入排序是将未排序的元素逐个插入到已排序序列中…

Unity之ASE从入门到精通 目录

前言 Amplify Shader Editor (ASE) 是受行业领先软件启发的基于节点着色器创建工具。它是一个开放且紧密集成的解决方案,提供了熟悉和连贯的开发环境,使 Unity 的 UI 约定和着色器的使用无缝地融合一起 目录 这里是ASE从入门到精通专栏的目录,不停更新中,有问题随时留…

入门JavaScript编程:上手实践四个常见操作和一个轮播图案例

部分数据来源&#xff1a;ChatGPT 简介 JavaScript是一门广泛应用于Web开发的脚本语言&#xff0c;它主要用于实现动态效果和客户端交互。下面我们将介绍几个例子&#xff0c;涵盖了JavaScript中一些常见的操作&#xff0c;包括&#xff1a;字符串、数组、对象、事件等。 例子…

rk3568 适配rk809音频

rk3568 适配rk809音频 RK809是一款集成了多种功能的电源管理芯片&#xff0c;主要用于笔记本电脑、平板电脑、工控机等设备的电源管理。以下是RK809的详细功能介绍&#xff1a; 电源管理&#xff1a;控制电源的开关、电压、电流等参数&#xff0c;保证设备的稳定运行。音频管…

Unity之使用Photon PUN开发多人游戏教程

前言 Photon是一个网络引擎和多人游戏平台,可以处理其服务器上的所有请求,我们可以在 Unity(或其他游戏引擎)中使用它,并快速把游戏接入Photon的网络中,而我们就可以专注于在项目中添加逻辑,专注于游戏玩法和功能了。 PUN(Photon Unity Networking)是一种开箱即用的解…

什么是DevOps?如何理解DevOps思想?

博文参考总结自&#xff1a;https://www.kuangstudy.com/course/play/1573900157572333569 仅供学习使用&#xff0c;若侵权&#xff0c;请联系我删除&#xff01; 1、什么是DevOps? DevOps是一种思想或方法论&#xff0c;它涵盖开发、测试、运维的整个过程。DevOps强调软件开…

Maven方式构建Spring Boot项目

文章目录 一&#xff0c;创建Maven项目二&#xff0c;添加依赖三&#xff0c;创建入口类四&#xff0c;创建控制器五&#xff0c;运行入口类六&#xff0c;访问Web页面七&#xff0c;修改访问映射路径八&#xff0c;定制启动标语1、创建标语文件2、生成标语字符串3、编辑标语文…

DNDC模型在土地利用变化、未来气候变化下的建模方法及温室气体时空动态模拟实践技术

DNDC模型讲解 1.1 碳循环模型简介 1.2 DNDC模型原理 1.3 DNDC下载与安装 1.4 DNDC注意事项 ​ DNDC初步操作 2.1 DNDC界面介绍 2.2 DNDC数据及格式 2.3 DNDC点尺度模拟 2.4 DNDC区域尺度模拟 2.5 DNDC结果分析 ​ DNDC气象数据制备 3.1 数据制备中的遥感和GIS技术 3…

Vue3 + TypeScript + Uniapp 开发小程序【医疗小程序完整案例·一篇文章精通系列】

当今的移动应用市场已经成为了一个日趋竞争激烈的领域&#xff0c;而开发一个既能在多个平台上运行&#xff0c;又能够高效、可维护的应用则成为了一个急需解决的问题。 在这个领域中&#xff0c;Vue3 TypeScript Uniapp 的组合已经成为了一种受欢迎的选择&#xff0c;特别…

ODB 2.4.0 使用延迟指针 lazy_shared_ptr 时遇到的问题

最近在学习使用C下的ORM库——ODB&#xff0c;来抽象对数据库的CURD&#xff0c;由于C的ORM实在是太冷门了&#xff0c;ODB除了官方英语文档&#xff0c;几乎找不到其他好用的资料&#xff0c;所以在使用过程中也是遇到很多疑惑&#xff0c;也解决很多问题。近期遇到的一个源码…

推荐系统系列之推荐系统概览(下)

在推荐系统概览的第一讲中&#xff0c;我们介绍了推荐系统的常见概念&#xff0c;常用的评价指标以及首页推荐场景的通用召回策略。本文我们将继续介绍推荐系统概览的其余内容&#xff0c;包括详情页推荐场景中的通用召回策略&#xff0c;排序阶段常用的排序模型&#xff0c;推…