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。

相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
打赏
0
0
0
0
4
分享
相关文章
MySQL底层概述—10.InnoDB锁机制
本文介绍了:锁概述、锁分类、全局锁实战、表级锁(偏读)实战、行级锁升级表级锁实战、间隙锁实战、临键锁实战、幻读演示和解决、行级锁(偏写)优化建议、乐观锁实战、行锁原理分析、死锁与解决方案
174 24
MySQL底层概述—10.InnoDB锁机制
InnoDB与MyISAM实现索引方式的区别?
首先两者都是用的是B+树索引,但二者的实现方式不同。 对于主键索引,InnoDB中叶子节点保存了完整的数据记录,而MyISAM中索引文件与数据文件是分离的,叶子节点上的索引文件仅保存了数据记录的地址. 对于辅助索引,InnoDB中辅助索引会对主键进行存储,查找时,先通过辅助索引的B+树在叶子节点获取对应的主键,然后使用主键在主索引B+树上检索操作,最终得到行数据;MyISAM中要求主索引是唯一的,而辅助索引可以是重复的,主索引与辅助索引没有任何区别,因此,MyISAM中索引检索的算法为首先按照B+Tree搜索算法搜索索引,如果指定的Key存在,则取出其data域的值,然后以data域的值为地址
MySQL底层概述—5.InnoDB参数优化
本文介绍了MySQL数据库中与内存、日志和IO线程相关的参数优化,旨在提升数据库性能。主要内容包括: 1. 内存相关参数优化:缓冲池内存大小配置、配置多个Buffer Pool实例、Chunk大小配置、InnoDB缓存性能评估、Page管理相关参数、Change Buffer相关参数优化。 2. 日志相关参数优化:日志缓冲区配置、日志文件参数优化。 3. IO线程相关参数优化: 查询缓存参数、脏页刷盘参数、LRU链表参数、脏页刷盘相关参数。
133 12
MySQL底层概述—5.InnoDB参数优化
MySQL底层概述—4.InnoDB数据文件
本文介绍了InnoDB表空间文件结构及其组成部分,包括表空间、段、区、页和行。表空间是最高逻辑层,包含多个段;段由若干个区组成,每个区包含64个连续的页,页用于存储多条行记录。文章还详细解析了Page结构,分为通用部分(文件头与文件尾)、数据记录部分和页目录部分。此外,文中探讨了行记录格式,包括四种行格式(Redundant、Compact、Dynamic和Compressed),重点介绍了Compact行记录格式及其溢出机制。最后,文章解释了不同行格式的特点及应用场景,帮助理解InnoDB存储引擎的工作原理。
MySQL底层概述—4.InnoDB数据文件
MySQL底层概述—3.InnoDB线程模型
InnoDB存储引擎采用多线程模型,包含多个后台线程以处理不同任务。主要线程包括:IO Thread负责读写数据页和日志;Purge Thread回收已提交事务的undo日志;Page Cleaner Thread刷新脏页并清理redo日志;Master Thread调度其他线程,定时刷新脏页、回收undo日志、写入redo日志和合并写缓冲。各线程协同工作,确保数据一致性和高效性能。
MySQL底层概述—3.InnoDB线程模型
数据管理服务DMS支持MySQL数据库的无锁结构变更
本文介绍了使用Sysbench准备2000万数据并进行全表字段更新的操作。通过DMS的无锁变更功能,可在不锁定表的情况下完成结构修改,避免了传统方法中可能产生的锁等待问题。具体步骤包括:准备数据、提交审批、执行变更及检查表结构,确保变更过程高效且不影响业务运行。
116 2
【YashanDB知识库】原生mysql驱动配置连接崖山数据库
【YashanDB知识库】原生mysql驱动配置连接崖山数据库
【YashanDB知识库】原生mysql驱动配置连接崖山数据库
docker拉取MySQL后数据库连接失败解决方案
通过以上方法,可以解决Docker中拉取MySQL镜像后数据库连接失败的常见问题。关键步骤包括确保容器正确启动、配置正确的环境变量、合理设置网络和权限,以及检查主机防火墙设置等。通过逐步排查,可以快速定位并解决连接问题,确保MySQL服务的正常使用。
283 82
大数据新视界--大数据大厂之MySQL数据库课程设计:MySQL 数据库 SQL 语句调优方法详解(2-1)
本文深入介绍 MySQL 数据库 SQL 语句调优方法。涵盖分析查询执行计划,如使用 EXPLAIN 命令及理解关键指标;优化查询语句结构,包括避免子查询、减少函数使用、合理用索引列及避免 “OR”。还介绍了索引类型知识,如 B 树索引、哈希索引等。结合与 MySQL 数据库课程设计相关文章,强调 SQL 语句调优重要性。为提升数据库性能提供实用方法,适合数据库管理员和开发人员。
大数据新视界--大数据大厂之MySQL 数据库课程设计:MySQL 数据库 SQL 语句调优的进阶策略与实际案例(2-2)
本文延续前篇,深入探讨 MySQL 数据库 SQL 语句调优进阶策略。包括优化索引使用,介绍多种索引类型及避免索引失效等;调整数据库参数,如缓冲池、连接数和日志参数;还有分区表、垂直拆分等其他优化方法。通过实际案例分析展示调优效果。回顾与数据库课程设计相关文章,强调全面认识 MySQL 数据库重要性。为读者提供综合调优指导,确保数据库高效运行。
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等