Mysql进阶索引篇02——InnoDB存储引擎的数据存储结构(二)

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: 前面我们已经剖析了mysql中InnoDB与MyISAM索引的数据结构,了解了B+树的设计思想、原理,并且介绍了B+树与Hash结构、平衡二叉树、AVL树、B树等的区别和实际应用场景。页和页之间并不一定在物理上相连,只是在逻辑上使用双向链表关联。指针、记录究竟是如何存储的呢?其实这就需要联系我们之前提到的行格式了。数据查找在页目录中二分法快速定位到槽,上面的过程都与页的内部结构相关,本文将详细的阐述。

3.2 Compact行格式

compact是一种经典的行格式,它也是mysql5.1的默认行格式,我们把它作为讲解的重点介绍。其示意图如下。

现在我们对这个结构进行里的各个部分进行依次讲解。

3.2.1 变长字段长度列表

执行如下语句,创建一张新的数据表。

插入几条数据。

我们知道,在mysql数据库中,VARCHAR(M),VARBINARY(M),TEXT,BLOB类型都是变长的。我们在上面指定col1时设置的长度是8,单我们实际使用时字段长度可能并没有到8(如’tong’这个数据字段)。变长字段的长度列表其实就是需要记录字段实际存储的长度。


注意,变长字段列表记录存储长度的顺序与我们变量声明的顺序是反过来的。比如我们声明两个Varchar字段的顺序是a(15),b(10),那么变长字段列表的存储的长度顺序就是10,15.


上面插入的第一条数据长度对应转为16进制如下。

因此变长长度列表存储的内容为060408.如下图。

3.2.2 Null值列表

Compact行格式会把Null值列统一管理起来。当然,如果表中不允许存放Null值,那么Null值列表就不存在了。


为什么要定义Null值列表呢?这是因为mysql数据库中定义的数据是对齐的。比如我们现在存储了四个数据(‘a,’Null,Null,‘b’),我们在存储完a以后再存储b,那么在查找数据的时候不是会造成混乱么?当然,我们也可以把Null值数据存储的空间提前预留出来,但是这无疑会浪费空间。因此,我们在记录信息之前开辟了一块空间来存储Null值的位置。而且这个实现也很简单,我们只需要一个bit位来存储是否字段是空。如果是空则置为1,否则为0。


上面第1条记录的Null值列表如下所示。同样,Null值列表的记录顺序与字段声明的顺序是相反的,并且col2声明是指定了Not Null非空约束,不会在Null值列表中进行记录。另外,如果声明时指定了主键,由于主键一定非空,因此也不会在声明列表中出现。

3.2.3 记录头信息

我们先创建一张数据表。

然后插入一些数据。重点关注下这些数据的记录头信息.

我们将上面的字段介绍如下。


delete_mask:该记录是否被删除。如果这个值是0,说明记录没有被删除,否则说明记录被删除。

由此可知记录删除是采用的逻辑删除,这是因为我们记录之间是紧密相连的,如果真正删除一个记录,将会需要导致后面的记录依次进行位移。所有被删除的记录会通过next_record构成一个垃圾链表,它们所占用的空间称为可重用空间。


min_rec_mask:存储目录项记录中主键值最小的目录项记录置为1,其它情况都置0.


Record_type:记录类型,0表示普通记录,1表示B+树的非叶子节点(目录页节点)、2表示最小记录,3表示最大记录。


heap_no:表示当前记录在本页中的位置。我们注意到前面图片的第一条记录的heap_no是2,那么0和1呢?实际上,mysql会自动创建两条虚拟记录,即最小记录和最大记录。位于记录链表的最前面位置。由于这两个记录不是我们创建的,因此并没有存储在用户空间中,而是放在Infimum和Supermun部分。他们其实是相当于头尾节点。



n_owned:页目录中每个组的最后一条记录会存储该组的记录数,作为n_owned字段。值的关注的是,在mysql中最小记录是一组,普通记录与其它记录是一组,因此最小记录中n_owned属性是1,最大记录的n_owned值是5.


next_record:它表示当前记录的真实数据到下一个记录的真实数据之间的偏移量。


介绍完以上知识点,我们来举一个例子,比如我们需要删除第2条记录,那么记录行格式会发生什么变化呢?删除第2条记录后的示意图如下。可以看到,首先第2条记录的delete_mask将标记为1,next_record标记为0。它前一个节点第一条记录的next_record会指向第3条记录。同时最大记录中的n_owned属性值变为4.

3.2.4 真实数据

真实数据里除了真实列还存储了三个隐藏列。

实际上,这几个列的真实名字是DB_ROW_ID,DB_TRX_ID,DB_ROW_PTR。


我们在上一篇文章介绍InnoDB索引的时候提到过,如果表中无主键,也没有适合做主键的(声明了唯一标识)其它列,会隐式的指定一个聚簇索引。实际上,在这种情况下就是会添加一个row_id的隐藏列。另外两个隐藏列与事务相关,我们会在之后介绍事务的博客中再进行介绍。

3.3 Compact行格式存储实例剖析

上面我们已经介绍了行格式,现在根据具体的实例进行下剖析。创建数据表并插入数据。

找到对应的mytest.idb文件(注:推荐使用notepad++并安装使用Hex-Editor插件)

读出来的有效数据内容如下。我们采用不同颜色对于行格式的不同部分做了区分。

第一行中有03 02 01字段,这其实就是表中插入的第一条数据(‘a’,‘bb’,‘bb’,‘ccc’)的变长字段列表;

之后紧跟的00 是Null值列表,4个字段都非空的,因此这里使用的是00。倒数第二行中红色的06表示第三条插入数据中非空的数据的表示。因为'd',Null,Null,'fff'中四个数据分别用1,0表示是否为空的情况是0 1 1 0,倒过来仍然是0 1 1 0,转为16进制信息就是06.

之后的五个字节00 00 10 00 2c是记录头信息。其中2c就是next_record;

接下来的00 00 00 2b 68 00是隐藏主键DB_ROW_ID;

00 00 00 06 05是DB_TRX_ID;

接下来的7个字节80 00 00 00 32 01 10对应的回滚指针DB_ROW_PTR;

接下来的61对应真实数据a,62 62对应bb,62 62 20 20 20 20 20 20 20 20表示的是定长的bb,其中20表示没有真实数据,之后的63 63 63则表示ccc。

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
8天前
|
缓存 关系型数据库 MySQL
MySQL索引策略与查询性能调优实战
在实际应用中,需要根据具体的业务需求和查询模式,综合运用索引策略和查询性能调优方法,不断地测试和优化,以提高MySQL数据库的查询性能。
|
13天前
|
存储 Oracle 关系型数据库
【赵渝强老师】MySQL InnoDB的数据文件与重做日志文件
本文介绍了MySQL InnoDB存储引擎中的数据文件和重做日志文件。数据文件包括`.ibd`和`ibdata`文件,用于存放InnoDB数据和索引。重做日志文件(redo log)确保数据的可靠性和事务的持久性,其大小和路径可由相关参数配置。文章还提供了视频讲解和示例代码。
120 11
【赵渝强老师】MySQL InnoDB的数据文件与重做日志文件
|
13天前
|
存储 Oracle 关系型数据库
【赵渝强老师】MySQL InnoDB的表空间
InnoDB是MySQL默认的存储引擎,主要由存储结构、内存结构和线程结构组成。其存储结构分为逻辑和物理两部分,逻辑存储结构包括表空间、段、区和页。表空间是InnoDB逻辑结构的最高层,所有数据都存放在其中。默认情况下,InnoDB有一个共享表空间ibdata1,用于存放撤销信息、系统事务信息等。启用参数`innodb_file_per_table`后,每张表的数据可以单独存放在一个表空间内,但撤销信息等仍存放在共享表空间中。
|
13天前
|
存储 Oracle 关系型数据库
【赵渝强老师】MySQL InnoDB的段、区和页
MySQL的InnoDB存储引擎逻辑存储结构与Oracle相似,包括表空间、段、区和页。表空间由段和页组成,段包括数据段、索引段等。区是1MB的连续空间,页是16KB的最小物理存储单位。InnoDB是面向行的存储引擎,每个页最多可存放7992行记录。
|
13天前
|
存储 Oracle 关系型数据库
【赵渝强老师】MySQL的InnoDB存储引擎
InnoDB是MySQL的默认存储引擎,广泛应用于互联网公司。它支持事务、行级锁、外键和高效处理大量数据。InnoDB的主要特性包括解决不可重复读和幻读问题、高并发度、B+树索引等。其存储结构分为逻辑和物理两部分,内存结构类似Oracle的SGA和PGA,线程结构包括主线程、I/O线程和其他辅助线程。
【赵渝强老师】MySQL的InnoDB存储引擎
|
5月前
|
存储 关系型数据库 MySQL
MySQL数据库进阶第六篇(InnoDB引擎架构,事务原理,MVCC)
MySQL数据库进阶第六篇(InnoDB引擎架构,事务原理,MVCC)
|
1月前
|
存储 缓存 关系型数据库
详细解析MySQL中的innodb和myisam
总之,InnoDB和MyISAM各有千秋,选择合适的存储引擎应基于对应用程序特性的深入理解,以及对性能、数据完整性和可扩展性的综合考量。随着技术发展,InnoDB因其全面的功能和日益优化的性能,逐渐成为更广泛场景下的首选。然而,在特定条件下,MyISAM依然保留其独特的价值。
125 0
|
3月前
|
监控 关系型数据库 MySQL
在Linux中,mysql的innodb如何定位锁问题?
在Linux中,mysql的innodb如何定位锁问题?
|
3月前
|
SQL 存储 关系型数据库
"MySQL增列必锁表?揭秘InnoDB在线DDL,让你的数据库操作飞一般,性能无忧!"
【8月更文挑战第11天】在数据库领域,MySQL凭借其稳定高效的表现深受开发者喜爱。对于是否会在给数据表添加列时锁表的问题,MySQL的行为受版本、存储引擎等因素影响。从5.6版起,InnoDB支持在线DDL,可在改动表结构时保持表的可访问性,避免长时间锁表。而MyISAM等则需锁表完成操作。例如,在使用InnoDB的表上运行`ALTER TABLE users ADD COLUMN email VARCHAR(255);`时,通常不会完全锁表。虽然在线DDL提高了灵活性,但复杂操作或大表变更仍可能暂时影响性能。因此,进行结构变更前应评估其影响并择机执行。
73 6
|
5月前
|
存储 SQL 关系型数据库
【MySQL技术内幕】6.3-InnoDB中的锁
【MySQL技术内幕】6.3-InnoDB中的锁
199 57
下一篇
无影云桌面