【Mysql】InnoDB 引擎中的数据页结构
InnoDB 是 mysql 的默认引擎,也是我们最常用的,所以基于 InnoDB,学习页结构。而学习页结构,是为了更好的学习索引。
一、页的简介
页是 InnoDB 管理存储空间的基本单位,一个页的大小一般是 16kb。
为了达成不同的目的,作者设计了多种类型的页,比如:
- 存放表空间头部信息的页
- 存放 change buffer 信息的页
- 存放 inode 信息的页
- 存放 undo 日志信息的页
- ... ...
然而我们最关心的,还是那些存放进表中那些数据记录是在哪种页上,官方称这种存放记录的页为索引(INDEX)页,但是为了便于理解,本篇暂把它称为数据页。
二、数据页的结构
这数据页也有 16kb 的存储空间,可以大致划分为 7 个部分。
从结构图中可以看到,有些部分的占用字节数是确定的,有的是不确定的。我们最关心的用户存储的记录,在 User Records
部分。
不过,在一开始生成页的时候,并没有 User Records 部分。当有新的记录插入时,就会从 Free Space
部分申请一个记录大小的空间,然后划分到 User Records 部分,直到 Free Space 全部被 User Records 替代,表示这个页已经用完。如果还有新的记录插入,需要申请新的页。
我觉得这里可以把这个数据页当作是书本的页,书页上的内容通常是一行行的呈现,当整个页都用完了,就得翻到下一页(新页)去继续写了。
三、记录在页中的存储结构
那么,User Records 部分里的这些记录,是如何管理的呢?
先来建一张表:
CREATE TABLE pingguo_demo(
c1 INT,
c2 INT,
c3 VARCHAR(10000),
PRIMARY KEY (c1)
) CHARSET = ASCII ROW_FORMAT = COMPACT;
这里的指定使用行格式为 COMPACT(引擎中还存在其他的行格式),暂且知道 COMPACT 即可。
当我们在数据库的插入了一条记录后,其实背后的行格式是这样的:
注意这里橙色标识的记录头信息,它又包含了很多重要信息:
- 预留位1:占用 1 比特,没有使用。
- 预留位2:占用 1 比特,没有使用。
- deleted_flag:占用 1 比特,标记该记录是否被删除。
- min_rec_flag:占用 1 比特,在 B+ 树(后面索引会讲到)中每层非 叶子节点中的最小的目录项,都会添加此标记。
- n_owned:一个页面中的记录被分为若干个组,每个组里有一个记录是“大哥”,其他记录都是“小弟”。而这位“大哥”记录的 n_owned 就是所在组的所有记录条数,而小弟们的 n_owned 都是 0
- heap_no:占用 13 比特,表示当前记录在页面堆中的相对位置。
- record_type:占用 3 比特,表示当前记录的类型,0是普通记录,1是 B+树非叶节点的目录项记录,2是 Infimum 记录,3是 Suprememum 记录。
- next_record:占用 16 比特,表示下一条记录的相对位置。
四、记录头信息
现在,向上面新建的表中插入 4 条记录:
INSERT INTO pingguo_demo VALUES
(1, 100, 'aaaa'),
(2, 200, 'bbbb'),
(3, 300, 'cccc'),
(4, 400, 'dddd');
那么,对应这4条记录的行格式应该为:
注意,这里为了便于记忆,作了简化。另外,记录中的信息实际是二进制位数据,这里为了理解写的是十进制。而且,各条记录在 User Records 中存储是没有空隙的,这里抽象表示。
1. deleted_flag
这个属性用来标记当前记录是否被删除,1 表示被删除,0 表示没有被删除。
嗯?我表里删除了数据居然还在页里。
是的,你以为被删除了,其实还在磁盘上。为什么呢?
因为如果在磁盘上移除这些记录,还要再重新排列其他记录,会带来性能消耗,所以只打了一个删除的标记。
然后,所有的删除的记录会组成一个垃圾链表。而记录在这个链表中所占用的空间称为可重用空间,当后面有新记录插入到表中,它们就可能覆盖掉这些空间。
2. min_rec_flag
在 B+ 树中每层非叶子节点中的最小的目录项,都会添加此标记。这里说的目录项,要后续讲解。
这里4条记录的 min_rec_flag 都是 0,表示都不是 B+ 树非叶子节点中的最小的目录项记录。
3. n_owned
要下一章讲解。
4. heap_no
表示当前记录在页面堆中的相对位置。
上面的4条记录是抽象的描述,实际上这些记录都是一条一条紧密无缝排列在一起的,这就是堆(heap)。
为了方便管理,把一条记录在堆中的相对位置称为 heap_no。
- 在页面前面的记录 heap_no 相对较小
- 在页面后面的记录 heap_no 相对较大
- 每申请一条记录的存储空间时,该记录比物理位置在它之前的那条记录的 heap_no 值大 1
上述 4 条记录的 heap_no 分别为 2、3、4、5,嗯?怎么没有 0 和 1?
虚拟记录-Infimum 和 Supremum
这个在本文第二部分有提到过。其实这2条记录是页里自动添加的:
- Infimum:代表页面中的最小记录
- Supremum:代表页面中的最大记录
作者规定,无论向页中插入了多少条记录,任何用户记录都比 Infimum 记录大,都比 Supremum 记录小。
这 2 条虚拟记录的结构也很简单。
所以,对于上面插入的 4 条用户记录,还应该加上这2个默认记录,而且位置最靠前。
另外,还需要注意,当堆中记录的 heap_no 值分配后,就不会发生改动。即使删除了堆中的某条记录,这条被删记录的 heap_no 值也仍然不变。
5. record_type
这个属性表示当前记录的类型,共 4 种:
- 0:表示普通记录
- 1:表示 B+ 树非叶节点的目录项记录
- 2:表示 Infimum 记录
- 3:表示 Supremum 记录
6. next_record
这个属性很重要,表示从当前记录的真实数据到下一条记录的真实数据之间的距离。
- 属性值为正数:说明当前记录的下一条记录在当前记录的后面。
- 属性值为负数:说明当前记录的下一条记录在当前记录的前面。
比如,第 1 条记录的 next_record 值为 32,那么从此记录的真实数据地址向后找 32 字节就是下一条记录的真实数据。再比如,当值为 -111,那么就代表从此记录向前找 111 字节。
很熟悉?没错,就是链表。
- 下一条记录,是指按照主键从小到大排列的下一条。
- Infrimum 记录的下一条记录,就是本页中主键值最小的用户记录。
- 本页主键值最大的用户记录的下一条记录,就是 Supremum 记录。
所以,现在再来重新看下记录之间的示意图,可以用单向链表来描述了:
如果这时候,删掉其中的某条记录,改变的是指针。
本文参考书籍:
小孩子4919 《mysql是怎样运行的》
【Mysql】InnoDB 引擎中的数据页结构的更多相关文章
- Mysql之InnoDB行格式、数据页结构
Mysql架构图 存储引擎负责对表中的数据的进行读取和写入,常用的存储引擎有InnoDB.MyISAM.Memory等,不同的存储引擎有自己的特性,数据在不同存储引擎中存放的格式也是不同的,比如Mem ...
- [SqlServer] 理解数据库中的数据页结构
这边文章,我将会带你深入分析数据库中 数据页 的结构.通过这篇文章的学习,你将掌握如下知识点: 1. 查看一个 表/索引 占用了多少了页. 2. 查看某一页中存储了什么的数据. 3. 验证在数据库中用 ...
- InnoDB存储引擎介绍-(7) Innodb数据页结构
数据页结构 File Header 总共38 Bytes,记录页的头信息 名称 大小(Bytes) 描述 FIL_PAGE_SPACE 4 该页的checksum值 FIL_PAGE_OFFSET 4 ...
- InnoDB的数据页结构
页是InnoDB存储引擎管理数据库的最小磁盘单位.页类型为B-tree node的页,存放的即是表中行的实际数据了. InnoDB数据页由以下七个部分组成,如图所示: File Header(文件头) ...
- InnoDB数据页结构
前言 关于数据库我们知道是通过内存对磁盘进行操作的,也知道数据会落实到磁盘上,但是数据在磁盘上的存储结构可能大家还不是很清楚. MySQL服务器上负责对表中的数据的读取和写入的工作的部分是存储 ...
- 数据页结构 .InnoDb行格式、以及索引底层原理分析
局部性原理 局部性原理是指CPU访问存储器时,无论是存取指令还是存取数据,所访问的存储单元都趋于聚集在一个较小的连续区域中. 首先要明白局部性原理能解决的是什么问题,也就是主存容量远远比缓存大, CP ...
- mysql innodb 引擎
innodb 引擎 一.概述 InnoDB 是一个用的比较广泛的存储引擎,因为它支持事物和外键,还有不错的效率;我们先看看官方教程怎么说; 我们先读一下, 对于上面的文档, 对一个InnoDB的表首先 ...
- 聊一聊 InnoDB 引擎中的索引类型
索引对数据库有多重要,我想大家都已经知道了吧,关于索引可能大家会对它多少有一些误解,首先索引是一种数据结构,并且索引不是越多越好.合理的索引可以提高存储引擎对数据的查询效率. 形象一点来说呢,索引跟书 ...
- InnoDB 引擎中的索引类型
首先索引是一种数据结构,并且索引不是越多越好.合理的索引可以提高存储引擎对数据的查询效率. 形象一点来说呢,索引跟书本的目录一样,能否快速的查找到你需要的信息,取决于你设计的目录是否合理. MySQL ...
随机推荐
- YOLOv4 资源环境配置和测试样例效果
YOLOv4 资源环境配置和测试样例效果 基本环境:cuda=10.0,cudnn>=7.0, opencv>=2.4 一.下载yolov4 git clone https://githu ...
- TensorFlow XLA加速编译器
TensorFlow XLA加速编译器 加速线性代数器(Accelerated linear algebra,XLA)是线性代数领域的专用编译器.根据 https://www.tensorflow.o ...
- NSight Compute 用户手册(下)
主菜单 文件 新建项目使用"新建项目"对话框创建新的分析项目 4. Main Menu and Toolbar Information on the main menu and t ...
- Springboot-Redis分布式锁 -----StringRedisTemplate
这里引用别人, 用来自己回忆 https://blog.csdn.net/jack_shuai/article/details/91986690 https://www.cnblogs.com/mox ...
- Jmeter-逻辑控制器If Controller的实例运用
一.If Controller概述 Expression (must evaluate to true or false) :表达式(值必须是true或false),也就是说,在右边文本框中输入的条件 ...
- UE4.22编辑器界面操控设置(4)
视频课程地址:https://i.youku.com/i/UMzE2NDk2OTIw/custom?spm=a2hzp.8244740.0.0&id=32318 -在场景中按住鼠标左键上下移动 ...
- centos7 配置国内yum源
配置清华大学镜像仓库 URL:https://mirrors.cnnic.cn/ CentOS 镜像使用帮助 https://mirrors.cnnic.cn/help/centos/ 建议先备份 C ...
- 学习Qt Charts-创建一个简单的折线图
一.Qt Charts Qt Charts是基于Qt Graphics View实现的一个图表的组件,可以用来在QT GUI程序中添加现在风格的.可交互的.以数据为中心的图表,可以用作QWidget或 ...
- python使用venv
venv模块支持使用自己的站点目录创建轻量级"虚拟环境",可选择与系统站点目录隔离.每个虚拟环境都有自己的Python二进制文件(与用于创建此环境的二进制文件的版本相匹配),并且可 ...
- 关于Word中复杂表格转完美的Markdown格式的技巧
背景 我们都知道有很多工具能做到Word转Markdown格式,但是在某些复杂的需求下,比如带合并单元格的表格,就会出现错乱,效果非常不理想. 那我们今天来学习和探讨下怎么实现完美转换. 转换 如果想 ...