MYSQL InnoDB 行格式揭秘:探讨数据行头信息的关键组成
目次一、数据行格式---行头信息回顾
(一)整体回顾
(二)行头信息再次重申说明
二、数据行记录头信息数据准备
三、delete_mask 属性
四、min_rec_flag 标志位
五、n_owned 属性
六、heap_no 属性
七、record_type 属性
八、next_record属性
(一)单向链表形成说明
(二)变更中的单向链表
记录插入
记录删除
记录更新
案例简单展示
九、总结了解
主要参考和学习来源
干货分享,感谢您的阅读!
在现代数据库管理体系中,数据的存储和组织方式直接影响着应用步调的性能与响应速度。对于 MySQL 的 InnoDB 存储引擎而言,了解其数据行格式的内部结构至关重要,尤其是在进行性能优化和数据完整性管理时。你是否曾经好奇,在你查询数据的背后,数据是如何被奥妙地存储和管理的?本文将深入探讨 InnoDB 数据行格式,重点分析行头信息中各个属性如 delete_mask、min_rec_flag、n_owned、heap_no、record_type 和 next_record 等的寄义与作用。
通过这篇文章,我们不仅可以或许更清楚地理解这些看似复杂的属性如何影响数据的存储和利用,还能为数据库的优化和性能提升提供理论支持。让我们一起揭开这些数据行格式背后的秘密,为我们的数据库管理之旅铺平门路!
一、数据行格式---行头信息回顾
聚焦 InnoDB 行格式,到现在为止一共计划了4种不同类型的行格式 ,分别是 Compact 、 Redundant 、Dynamic 和 Compressed 行格式,随着时间的推移,他们可能会计划出更多的行格式,但是不管怎么变,在原理上大体都是雷同的,本次还是针对Compact为背景展开。
(一)整体回顾
Compact 行格式适用于大多数通用场景,尤其是需要高效存储和读取的小型至中型表。它提供了良好的性能和平衡的存储效率,是 InnoDB 存储引擎中的默认选择。
https://i-blog.csdnimg.cn/blog_migrate/b4c989e92d5642e2486ecf0a0b2a5ad9.jpeg
Compact 行格式在物理存储上采用以下结构:
[*]行头信息:用于存储事务信息和回滚指针,占用 5 个字节。
[*]NULL 值位图:用于标识哪些列是 NULL 值,每个列对应 1 个 bit。
[*]变长字段长度列表:紧跟在 NULL 值位图之后,记录变长字段的长度信息。
[*]隐藏列:每行有 6 个字节用于两个隐藏的体系列,包罗事务 ID 和回滚指针。
[*]实际数据:存储实际的数据值,紧凑排列。
(二)行头信息再次重申说明
在 InnoDB 存储引擎中,每个记录都有一个记录头信息,它由固定的 5 个字节(40 个二进制位)组成。这 5 个字节中的每一位都有特定的寄义,形貌了记录的一些重要信息。
https://i-blog.csdnimg.cn/blog_migrate/4888d30a64928487f39287d547c3ba11.png
每个记录的开头有一个记录头信息,这些信息包含了对记录的形貌和控制。以下是每个二进制位代表的详细信息:
[*] 预留位1(1 bit):该位暂时未被利用。
[*] 预留位2(1 bit):该位暂时未被利用。
[*] delete_mask(1 bit):标记该记录是否被删除。如果被删除,则该位为 1;否则为 0。
[*] min_rec_mask(1 bit):B+树的每层非叶子节点中的最小记录都会添加该标记。如果是最小记录,则该位为 1;否则为 0。
[*] n_owned(4 bits):表示当前记录拥有的记录数。利用 4 个 bits 来表示,可以表示的最大值为 15。
[*] heap_no(13 bits):表示当前记录在记录堆中的位置信息。利用 13 个 bits 来表示,可以表示的最大值为 8191。
[*] record_type(3 bits):表示当前记录的类型。0:普通记录。1:B+树非叶子节点记录。2:最小记录。3:最大记录。
[*] next_record(16 bits):表示下一条记录相对于当前记录的位置。利用 16 个 bits 来表示,可以表示的最大值为 65535。
这些记录头信息的二进制位提供了有关记录的详细形貌,包罗了是否被删除、记录的拥有数量、位置信息等。理解这些信息有助于更好地理解 InnoDB 存储引擎中记录的存储和组织方式,以及对数据库的性能和功能的影响。
二、数据行记录头信息数据准备
为了深入理解 InnoDB 表的创建过程和记录头信息的寄义,我们创建demo 表分析
CREATE TABLE demo (
c1 INT,
c2 INT,
c3 VARCHAR(10000),
PRIMARY KEY (c1)
) CHARSET=ascii ROW_FORMAT=Compact;
c1 和 c2 列是用来存储整数的(把 c1 列指定为主键), c3 列是用来存储字符串的,并指定ascii 字符集以及 Compact 的行格式,具体格式如下:
https://i-blog.csdnimg.cn/blog_migrate/a89eb3eaa18de3f83260a663780d27ff.png
由于将 c1 列指定为主键,InnoDB 不需要为每行数据再额外创建 row_id 列。主键自己就作为数据的唯一标识符。
为了准备数据,我们现在向demo 表中插入了四条记录:
INSERT INTO demo VALUES
(1, 100, 'aaaa'),
(2, 200, 'bbbb'),
(3, 300, 'cccc'),
(4, 400, 'dddd');
为了简化理解,可以用十进制数来表示记录头信息和实际的列数据。实际上,这些信息是以二进制形式存储的,但用十进制数可以帮助我们直观地理解其结构。此时记录在 页 的 User Records 部门的存储结构如下:
https://i-blog.csdnimg.cn/blog_migrate/a4f4b7d65ee931da5e6082ccac140038.png
我们开始重点理解头信息中的内容。
三、delete_mask 属性
在 InnoDB 存储引擎中,每条记录都有一个 delete_mask 属性,这是一个单独的二进制位,用于标记记录的删除状态。
[*]当 delete_mask 的值为 0 时,表示记录未被删除;
[*]当值为 1 时,表示记录已被删除。
当用户执行 DELETE 利用时,InnoDB 并不会立刻从磁盘上物理移除该记录,而是将 delete_mask 设置为 1。这意味着记录仍然保留在数据页中,只是在逻辑上被标记为已删除。这种计划克制了频仍的磁盘写利用,从而提高了删除利用的性能。
被逻辑删除的记录会组成一个垃圾链表,这些记录的空间被称为可重用空间。当新记录插入时,InnoDB 可以优先利用这些可重用空间,而不是分配新的空间。这样既提高了空间利用率,又淘汰了磁盘 I/O 利用。
留意:将 delete_mask 设置为 1 和将记录加入垃圾链表是两个独立的阶段。固然记录被逻辑删除后仍然占据物理空间,但 InnoDB 可以在之后的事务提交或定期清理使命中进行真正的物理删除利用。这种延迟删除策略确保了数据库体系在处置惩罚大量数据删除和插入利用时的高效性和稳固性。
四、min_rec_flag 标志位
min_rec_flag 标志位用于标记 B+ 树中每层非叶子节点的最小记录,帮助优化查找和遍历利用。只有 B+ 树中每层非叶子节点的最小记录会被设置 min_rec_flag 标志位为 1,其他记录以及叶子节点中的记录,这个标志位都是 0。好比我们之前插入到 demo 表中的记录,它们都是叶子节点记录,min_rec_flag 都是 0。
为了更好的说明,假设我们有一张表,它的主键索引利用 B+ 树来组织数据。当我们插入记录时,这些记录会作为 B+ 树的叶子节点存储。
https://i-blog.csdnimg.cn/blog_migrate/3fcd403fa36b801a8cba3dc64fa93b01.png
在这个简化的 B+ 树中, 是一个叶子节点, 和 是非叶子节点。 假设 是叶子节点,其中的 1 是最小记录,但因为它是叶子节点,所以 `min_rec_mask` 为 0。 而 作为非叶子节点,其中的最小记录是 5,因此它的 `min_rec_mask` 为 1。
五、n_owned 属性
n_owned 是一个元数据字段,表示当前槽记录所拥有的记录数量,即从当前记录开始直到下一个槽记录(或页末尾)的记录数。
在 InnoDB 中,每个数据页的记录按主键次序排列,并分成若干组。每组记录的第一个记录称为槽记录(slot record),每个槽记录的 n_owned 属性表示它所拥有的记录数量。比方:
Record 1 (Slot) -> Record 2 -> Record 3 (Slot) -> Record 4 -> Record 5 在这个例子中:
[*]Record 1 是一个槽记录,其 n_owned 属性值为 2,因为它拥有 Record 1 和 Record 2。
[*]Record 3 是另一个槽记录,其 n_owned 属性值为 3,因为它拥有 Record 3、Record 4 和 Record 5。
这样以来,这个在页内查找数据时用处就很大了。
六、heap_no 属性
在 InnoDB 存储引擎中,heap_no 是一个重要的元数据字段,用于标识数据页中记录的位置温次序。heap_no 是一个整数,表示记录在数据页中的位置。它唯一标识一个记录在当前页中的次序,范围从 0 开始递增。heap_no 主要用于记录的物理定位和排序,在页内的记录管理、遍历和利用中起到关键作用。
每个数据页中有两个特别的记录,称为伪记录或虚拟记录:
https://i-blog.csdnimg.cn/blog_migrate/10fa40ce41427b09b7c92da652655f8a.png
[*]Infimum 记录:最小记录,heap_no 为 0,用于表示页的起始。
[*]Supremum 记录:最大记录,heap_no 为 1,用于表示页的竣事。
这两个伪记录帮助维护页内记录的有序性,并在记录插入、删除和查找时起到辅助作用。
上面向demo 表中插入了四条记录,其基本结构如下:
https://i-blog.csdnimg.cn/blog_migrate/6c07a5683c6c2c5739090a4ab5e50c0c.png
正如上面说的每个数据页中包含两个特别的伪记录,它们的 heap_no 值为 0 和 1,用于标识页的起始和竣事。而用户记录的 heap_no 从 2 开始递增,表示它们在页中的位置温次序。
七、record_type 属性
record_type 用于区分不同类型的记录,如用户记录、最小记录、最大记录以及临时记录等。根据 record_type 的值,InnoDB 可以执行特定的利用或处置惩罚逻辑。
[*]0 (普通记录):代表通例的用户记录。这是我们插入到表中的实际数据。
[*]1 (最小记录 - Infimum):这是一个特别的伪记录,用于表示页中的最小记录。它的作用是标记记录链表的起始位置。
[*]2 (最大记录 - Supremum):这是另一个特别的伪记录,用于表示页中的最大记录。它的作用是标记记录链表的竣事位置。
[*]3 (临时记录):这类记录通常用于一些临时利用或中心状态,具体实现中可能会用到。
按照之前的四条插入数据而言:
Record Type: 1 -> Infimum Record (heap_no: 0)
Record Type: 0 -> User Record 1 (heap_no: 2)
Record Type: 0 -> User Record 2 (heap_no: 3)
Record Type: 0 -> User Record 3 (heap_no: 4)
Record Type: 0 -> User Record 4 (heap_no: 5)
Record Type: 2 -> Supremum Record (heap_no: 1)
在这个例子中:
[*]Infimum 记录和 Supremum 记录的 record_type 值分别为 1 和 2,用于标识页的边界。
[*]实际用户记录的 record_type 值为 0,表示它们是通例用户数据。
八、next_record属性
next_record 是一个指针,表示当前记录的下一条记录的相对位置。它是记录头信息的一部门,占用 2 个字节。通过 next_record 字段,InnoDB 可以在数据页内形成记录的单向链表,从而有用地管理和遍历记录。
(一)单向链表形成说明
在 InnoDB 数据页中,记录按照主键值从小到大的次序排列,并通过 next_record 字段链接在一起,形成一个有序的单向链表。每条记录通过 next_record 指向下一条记录的相对位置(即相对于当前记录的偏移量),使得在页内查找和遍历记录更加高效。
这里有两个特别记录的 next_record
[*]Infimum 记录:这是页内的最小记录。它的 next_record 指向本页中主键值最小的用户记录。
[*]Supremum 记录:这是页内的最大记录。它的 next_record 指向无效位置,但它是本页中主键值最大的用户记录的下一条记录。
以demo 表中插入的四条记录来看,基本结构如下(留意内里的record_type是错误的,正确应该是我们上面讲的):
https://i-blog.csdnimg.cn/blog_migrate/eb91cfc39f506864d21c97a5451c79b4.png
接着岂论对页中的记录进行何种利用,InnoDB 始终会维护一条按照主键值由小到大次序排列的单链表。这一机制会通过在记录头信息中利用 next_record 指针来实现,确保记录之间的有序链接。
(二)变更中的单向链表
无论是插入、删除还是更新利用,InnoDB 都会动态调解链表中的指针,以维持记录的次序。具体表现为:
记录插入
当我们向 InnoDB 表中插入记录时,InnoDB 会根据记录的主键值找到得当的位置,将新记录插入到链表中,并更新相邻记录的 next_record 指针。比方:
[*]找到插入位置:如果插入的记录主键值为 5,且页中已有记录主键值为 1, 3, 7,InnoDB 会找到主键值为 3 和 7 之间的位置。
[*]更新指针:将新记录插入后,更新原记录链表中的 next_record 指针。具体来说,主键值为 3 的记录的 next_record 会指向新记录,新的记录的 next_record 会指向主键值为 7 的记录。
记录删除
删除记录时,InnoDB 并不会立刻移除记录,而是标记为删除(通过 delete_mask 位)。之后,InnoDB 会更新链表中的指针以跳过被删除的记录:
[*]标记删除:将记录的 delete_mask 设置为 1。
[*]更新指针:修改被删除记录前一条记录的 next_record,使其直接指向被删除记录的下一条记录,从而跳过被删除的记录。比方,如果删除主键值为 5 的记录,主键值为 3 的记录的 next_record 会指向主键值为 7 的记录。
记录更新
更新记录时,如果主键值不变,记录的位置也不变,只需要更新记录的内容。而如果主键值改变,InnoDB 需要删除旧记录并插入新记录:
[*]删除旧记录:将原记录标记为删除,并更新链表指针以跳过被删除的记录。
[*]插入新记录:根据新主键值找到合适的位置插入新记录,并更新链表中的指针。
案例简单展示
执行删除利用:
DELETE FROM demo WHERE c1 = 2;
InnoDB 并不会立刻移除该记录,而是会将记录 2 被标记为删除,将主键值为 1 的记录的 next_record 指针更新为指向主键值为 3 的记录,以跳过被删除的记录。具体如下:
https://i-blog.csdnimg.cn/blog_migrate/e31d13efe4c07fc39ab690631d7bffab.png
通过删除记录后的表示图,可以看到链表中的指针如何更新以维持链表的次序和连续性。尽管记录 2 被标记为删除,它的空间可能会被重用,但链表的有序性不会受到影响。
执行插入利用:
INSERT INTO demo VALUES(2, 200, 'bbbb');
InnoDB 会尝试重用之前删除记录 2 的存储空间:InnoDB 发现先前删除的记录 2 的存储空间仍然存在,并且标记为可重用,于是新的记录 2 将写入该可重用空间,链表中的指针将恢复,使新插入的记录 2 重新出现在正确的位置。具体如下:
https://i-blog.csdnimg.cn/blog_migrate/c59001945e60c452aed9090a549fc35a.png
重新插入主键值为 2 的记录时,InnoDB 重用了之前删除记录 2 的存储空间,并将链表结构恢复到删除前的状态。这样不仅节省了存储空间,还保证了链表的有序性和高效性。
九、总结了解
记录头信息(Record Header Information)包含了形貌和控制记录的一系列二进制位。从这次学习来看,我们可以清晰的看出这些基本重要信息起码计划上满足以下三方面的要求:
高效的空间管理:
[*]Delete Mask:记录是否被删除的标记。删除利用仅是逻辑删除,标记为删除而不立刻移除,允许空间被重用,提高了存储空间的利用效率。
[*]Next Record:记录链表指针,通过维护一个单向链表结构,使得插入、删除和查找利用更为高效。这一机制确保了记录在存储页面中的有序性,并有助于快速查找。
记录之间的关系维护:
[*]Heap Number (heap_no):记录在页面中的位置,用于记录的排序和检索。Infimum 和 Supremum 虚拟记录确保了页中记录的有序排列,便于遍历和维护。
[*]Min Rec Flag (min_rec_flag):用于标识 B+树非叶子节点中的最小记录,有助于树结构的维护和节点分裂、合并等利用。
优化查询性能:
[*]N Owned (n_owned):表示当前记录拥有的后继记录数量,优化了页面中的记录遍历利用,使得查找特定记录时更加高效。
[*]Record Type (record_type):区分不同类型的记录(普通记录、B+树非叶子节点记录、最小记录、最大记录),有助于优化树结构的利用和维护。
InnoDB 的记录头信息计划不仅是技术实现的细节,更是对数据库存储管理、性能优化、利用高效性等方面的深刻思考的表现。理解这些计划思想,有助于我们更好地把握 MySQL InnoDB 存储引擎的内部工作原理,并可以或许在实际应用中更有用地进行数据库优化和问题排查,希望大家可以多了解其重点寄义。
主要参考和学习来源
《MySQL 是怎样运行的:从根儿上理解 MySQL》
https://dev.mysql.com/doc/refman/5.7/en/
https://dev.mysql.com/doc/internals/en/
http://www.orczhou.com/
https://blog.jcole.us/innodb/
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页:
[1]