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

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

3.4 行溢出

我们在介绍另外两种行格式DynamicCompressed之前,先介绍下行溢出

InnoDB存储引擎可以将一条记录中的数据存储在真正的数据页面之外。下面将举例说明这一点,先创建一个数据表。

65535字节是VarCahr类型存储的最大长度,而ASCII码一个字符占一个字节,因此我们指定的VARCHAR(65535)就表示其存储的字符数是65535,这些字符占65535字节,正好是VARCHAR数据类型存储字节的上限。

如果您还不理解就可以不指定字符集试试。

上面的语句将会报错。

这是因为不指定字符集时,默认使用的是utf-8,一个字符占3个字节,因此存储的字符上限就是65535/3=21845。

言归正传,我们再来执行下最开始的建表语句。

居然还是报错了,错误信息如下。

这是为什么呢?其实是因为VARCHAR的数据是变长的,需要2个字节额外的空间来记录数据的长度,1个字节标识NULL值信息,因此存储空间不能够达到65535字节,只能达到65532字节。

当然,我们可以加上非空约束,这样就不用记录NULL值列表了。

我们之前介绍过一个页的大小是16kb,也就是16384字节,而现在我们一个字段就比它大。这就会导致行溢出

CompactRuduntant两种行格式中,对于占用空间非常大的列,在存储真实数据时只会存储真实数据的一部分。将剩余的数据存储到其它页中进行分页存储

3.5 Dynamic和Compressed行格式

Dynamic和Compressed行格式与Compact大体是相同的,不过这两种行格式对于行溢出的处理策略与Compact不同。

它们采取了完全行溢出的策略。也就是数据页不存储任何溢出真实数据,只是存储指针,将真实数据完全存储到其它页中。

Compressed还采用了zlib算法对数据进行压缩,因此对于BLOB、TEXT、VARCHAR等大长度类型的数据能够进行有效的存储。


3.6 Redundant行格式

Redundant是Mysql5.0之前InnoDB的行格式。Mysql5.0支持Redundant是为了兼容以前版本的页格式,其格式如下。我们可以对比之前Compact行格式。

我们可以发现,Redundant采用字段长度偏移列表来定位数据,而Compact采用变长字段长度列表和Null值列表。如果是Compact行格式,不是变长数据就不会记录变长字段长度列表。而Redundant行格式必须所有列(包括隐藏列)的偏移长度都逆序进行记录,因此其名字是Redundant(冗余的)。


另外,其存储的是字段与记录开始位置的偏移长度,不如变长列表直接存储长度直观。

另外,Redundant因为所有的字段的偏移长度都记录了,也不用担心Null值导致记录的位置对不起的问题,所以没有Null值列表。

其记录头信息如下,黄色是较Compact多的属性信息。它也没有Record_type属性。了解即可。


4.区、段和碎片区

4.1 为什么要有区

页与页是通过双向链表进行连接的,如果以页为单位分配存储空间,逻辑上相邻的两个页在物理磁盘上实际距离比较远。在进行范围查询时,如果页与页之间的距离过远,在进行磁盘I/O操作时加载页就需要花许多时间(寻道、旋转等),就是随机I/O。磁盘和内存的速度相差了好几个数量级,磁盘随机I/O会花大量时间在数据页的查找加载上,是非常慢的。


出于性能考虑,我们希望能够在相邻的位置存取数据,以便能够顺序读取数据页。当然,我们也不能够让所有数据都存储到连续的空间,毕竟越大的连续空间在磁盘上越难找到。因此我们引入了区的概念。一个区就是64个在物理空间上连续的页。因此一个区的大小是16KB * 64 = 1MB。在表的数据量大的时候,我们就不再以页为单位进行存储空间的分配了,而是连续分配一个区,甚至是多个区。


4.2 为什么要有段

一个区中存放的页可能是数据页或者目录页,但当我们进行范围查询时,感兴趣的只有普通数据页。如果因为存放了目录页的原因,导致范围查找的效果大打折扣。我们希望一个区存储数据页就存储数据页,存储目录页就只存储目录页,因此出现了段的概念。常见的段有数据段、索引段、回滚段。段是逻辑上的概念。由若干零散的页(碎片区中的页,下一节介绍)和完整的区所组成。


4.3 为什么要有碎片区

InnoDB存储引擎一个聚簇索引会生成两个段,数据段和索引段,而每个段是以区作为单位申请存储空间的,如果表的数据量只有几条,也需要申请2M的空间么(一个区的大小为1M)?而且每增加一个索引,又需要增加2M,这空间浪费的也太严重了。


因此提出了碎片区,在一个碎片区中,可以让多个段共用一个公共空间,一些页给段A,一些页给段B,让空间得到充分的利用。就好比一个大广场可以给体育生大篮球,也可以给大妈跳广场舞,但它不是任何人所独有,而是一块公共空间。

现在我们可以知道InnoDB存储引擎分配存储空间的具体策略了。


在刚向表中插入数据时,先使用碎片区以页为单位进行存储空间的分配。

当某个段占用的存储空间达到了32个碎片区以后,我们再以完整的区为单位分配存储空间。

4.4 区的分类

区大体可以分成四个类型。


空闲区(Free):现在还没有用到这个区的任何页面。

有剩余空间的碎片区(Free-Frag):表示碎片区中还有可用的页面。

没有剩余空间的碎片区(Full-Frag)。

附属于某个段的区(FSEG):专属于给某一个段使用的完整的区。

前三种类型的区都是独立的,直属于表空间。FSEG是属于段的。


5.表空间

表空间是一个逻辑上的容器。可以划分为:独立表空间,系统表空间,撤销表空间,临时表空间等。


5.1 独立表空间

每个表对应一个表空间,也就是一个表的索引和数据会被单独保存在自己的表空间中,可以在不同的数据库之间进行数据的迁移。


其空间回收也比较方便,可以通过Drop Table操作自动回收表空间。对于统计分析或者日志表,还可以在删除大量数据之后,通过alter table tableName engine=innodb回收不用的空间。这个特性使碎片空间不会太影响性能。


独立表空间的结构由段、区、页等组成,不再赘述。


一个新建表的.idb文件大小是96kb,也就是6个页面大小(Mysql5.7),当然随着数据量的增加,有些idb也是自扩展的,表空间的文件大小会变大。在mysql5.6后,默认使用的都是独立表空间。可使用下面的语句查询。

5.2 系统表空间

与独立表空间的结构基本类似,整个MySQL进程只有一个表空间,会额外记录一些关于整个系统的数据,这是独立表空间中所没有的。比如在information_schema中提供了以INNODB_SYS开头的一些表,用于帮助我们查看与数据库系统相关的信息(相当于数据字典的副本)。

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
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
|
4月前
|
存储 SQL 关系型数据库
(十三)MySQL引擎篇:半道出家的InnoDB为何能替换官方的MyISAM?
MySQL是一款支持拔插式引擎的数据库,在开发过程中你可以根据业务特性,从支持的诸多引擎中选择一款适合的,例如MyISAM、InnoDB、Merge、Memory(HEAP)、BDB(BerkeleyDB)、Example、Federated、Archive、CSV、Blackhole.....
下一篇
无影云桌面