MySQL底层概述—4.InnoDB数据文件

news/2024/11/29 21:48:02/文章来源:https://www.cnblogs.com/mjunz/p/18577617

大纲

1.表空间文件结构

(1)表空间Tablesapce

(2)段Segment

(3)区Extend

(4)页Page

(5)行Row

2.Page结构

(1)页结构各部分说明

(2)页结构整体划分

3.行记录格式

(1)行格式分类

(2)COMPACT行记录格式

(3)Compact中的行溢出机制

(4)其他行格式记录

 

1.表空间文件结构

(1)表空间Tablesapce

(2)段Segment

(3)区Extend

(4)页Page

(5)行Row

 

InnoDB表空间文件结构从逻辑上可以分为:

Tablespace(表空间)->Segment(段)->

Extent(区)->Page(页)->Row(行)

 

一个表空间会包含多个段,一个段会包含多个区(256个区就是一个组);一个区又会包含64个页,一个页里面又会包含一行一行的记录Row。

(1)表空间Tablesapce

一.表空间是什么

表空间能够看作是InnoDB存储引擎逻辑结构的最高层。表空间用于存储多个ibd数据文件,用于存储表的记录和索引。一个表空间文件可以包含多个段:叶子节点段、非叶子节点段、回滚段。

 

二.表空间类型

系统表空间、独占表空间、通用表空间、 临时表空间、Undo表空间。

 

(2)段Segment

一.段是什么

段是用来管理空间的申请以及将同类的区和页用链表管理起来。段是个逻辑概念,本质上是由若干个零散页面和若干个完整的区组成。段是为了保持叶子节点在磁盘上的连续,可以实现更好的顺序IO操作。

 

一个B+树索引被划分为两个段:一个叶子节点段和一个非叶子节点段。这样叶子节点就可以尽可能地存放在一起,非叶子节点也可以尽可能地存放在一起。

 

二.段的类型

常见的段有数据段、索引段、回滚段等。其中索引段就是非叶子节点部分,而数据段就是叶子节点部分,回滚段用于数据的回滚和多版本控制。

 

三.为什么引入段

原因一:

使用B+树执行查询时只是扫描叶子节点记录,如果不区分叶子节点和非叶子节点,通通把节点代表的页面放到申请的区中,那么扫描效果就大打折扣,而段可以让叶子节点的数据页尽可能连续和差距不那么大。所以InnoDB对B+树的叶子节点和非叶子节点进行区别对待,叶子节点和非叶子节点各有自己独有的区。而存放叶子节点的区的集合就算是一个段,存放非叶子节点的区的集合也算是一个段。即一个索引会生成两个段:一个叶子节点段和一个非叶子节点段。

 

原因二:

以完整的区为单位分配给某个段时,对于数据量较小的表来说太浪费存储空间。因为当段以区为单位申请存储空间时,由于一个区默认占用1MB存储空间以及一个聚簇索引会生成两个段,所以默认情况下只存放了几条记录的小表也需要2MB的存储空间,这就有点浪费了。

 

原因三:

出现上述问题的根源是:区中的所有页面都是为了存储同一个段的数据而存在,即使区的页面用不完也不能作他用。于是InnoDB便有了碎片区。在一个碎片区中,并非所有页都是为了存储同一个段的数据而存在,碎片区的页可以用于不同的目的的。比如有些页属于段A、有些页属于段B、有些页甚至不属于任何段。碎片区直属于表空间,不属于任何段。

 

原因四:

为某个段分配存储空间的策略:刚开始向表中插入数据时,段是从某个碎片区中以单个页面为单位来分配存储空间的。当某个段已经占用了32个碎片区页面后,就会以完整的区为单位来分配存储空间,原先占用的碎片区页面并不会被复制到新申请的完整的区中。所以说,段是一些零散的页面以及一些完整的区的集合。

 

(3)区Extend

一.区是什么

区由连续页组成的空间,一个区的大小是1M,一个区有64个连续的页。为了保证区中页的连续性,扩展时InnoDB一次从磁盘申请4~5个区。无论是系统表空间还是独立表空间,都可看成是由若干个连续的区组成。当一个段使用了32个碎片页后才是以区来分配,每256个区被分成一组。

 

二.为什么引入区

原因一:

向表中插入一条记录,本质上就是向该表的聚簇索引以及所有二级索引代表的B+树的节点中插入数据。而B+树每一层中的页都会形成一个双向链表,如果以页为单位来分配存储空间,那么双向链表中相邻的两个页之间的物理位置可能离得非常远。

 

原因二:

使用B+树来减少记录的扫描行数的过程是:通过一些搜索条件,到B+树的叶子节点中定位到第一条符合该条件的记录,然后沿着由记录组成的单向链表以及由数据页组成的双向链表,一直向后进行扫描。全表扫描就是定位到第一个叶子节点的第一条记录。

 

原因三:

如果双向链表中相邻的两个页的物理位置不连续,对于传统的机械硬盘来说,需要重新定位磁头位置,也就是会产生随机IO,影响性能。所以应尽量让页面链表中相邻的页的物理位置也相邻,以便扫描叶子节点的大量记录时可以使用顺序IO。

 

原因四:

为了尽量消除随机IO才引入了区的概念,一个区就是物理位置上连续的64个页,区中页面的页号都是连续的。当表中的数据量很大时,为某个索引分配空间时就不再按页为单位来分配了,而是按照区为单位进行分配。甚至当表中的数据非常非常多的时候,可以一次性分配多个连续的区,以消除更多的随机IO,但会造成一点空间的浪费。

 

(4)页Page

一.页是什么

区是由连续的页(Page)组成的空间,一个页的存储大小为16K,页用于存储多个Row行记录。

 

二.页的类型

页有很多种类型,如数据页、Undo页、系统页、事务数据页、大的BLOB对象页。

 

(5)行Row

InnoDB的数据是按行的方式进行存放的,每个页存放的行记录最多允许存放16K / 2 - 200行的记录,即每个页最多存放7992行记录。每行记录根据不同的行格式、不同的数据类型,会有不同的存储方式。

 

行包含的内容:记录的字段值、事务ID、回滚指针、字段指针等信息。

 

2.Page结构

(1)页结构各部分说明

(2)页结构整体划分

 

Page是InnoDB存储的最基本构件,也是InnoDB磁盘管理的最小单位,与数据库相关的所有内容都存储在这种Page结构里。

 

Page分为几种类型,常见的页类型有:数据页(B+Tree Node)、Undo页(Undo Log Page)、系统页(System Page)、事务数据页(Transaction System Page)等。

 

(1)页结构各部分说明

一.File Header字段用于记录Page的头信息

其中比较重要的是FIL_PAGE_PREV和FIL_PAGE_NEXT字段。通过这两个字段,就可以找到该页的上一页和下一页。实际上所有页通过两个字段可以形成一条双向链表。

二.Page Header字段用于记录Page的状态信息

三.Infimum和Supremum是最小和最大行记录

Infimum(下确界)记录比该页中任何主键值都要小的值,Supremum(上确界)记录比该页中任何主键值都要大的值,这两个伪记录构成了页中记录的边界。

四.User Records存放的是实际的数据行记录

五.Free Space中存放的是空闲空间

被删除的行记录会成为空闲空间。

六.Page Directory记录与二叉查找相关的信息

七.File Trailer存储检测数据完整性的数据

 

(2)页结构整体划分

页结构整体上可以分为三大部分,分别为:通用部分(文件头、文件尾)、数据记录部分、页目录部分。

 

一.通用部分(File Header&File Trailer)

通用部分主要指文件头和文件尾,将页的内容进行封装。通过文件头和文件尾校验的CheckSum方式可以确保页的传输是完整的,这时候就可以确认是否发生页断裂也就是页是否写失效了。

 

其中比较重要的是在文件头中的FIL_PAGE_PREV和FIL_PAGE_NEXT字段,通过这两个字段,可以找到该页的上一页和下一页,因此所有页可以形成一条双向链表。

 

二.数据记录部分(User Records&Free Space)

由于页的主要作用是存储记录,所以"最小和最大记录"和"用户记录"部分占了页结构的主要空间。另外空闲空间是个灵活的部分,当有新的记录插入时,会从空闲空间中进行分配用于存储新记录。

三.页目录部分(Page Directory)

数据页中的行记录会按照主键值由小到大顺序串联成一个单链表,单链表的链表头为最小记录,链表尾为最大记录。数据页目录中会顺序存储每一条行记录的地址,通过对数据页目录使用二分法,就能快速定位到查找的行记录。

 

3.行记录格式

(1)行格式分类

(2)COMPACT行记录格式

(3)Compact中的行溢出机制

(4)其他行格式记录

 

(1)行格式分类

表的行格式决定了它的行是如何物理存储的,这反过来又会影响查询和DML操作的性能。

 

如果在单个Page页中容纳更多行,那么查询和索引查找就能更快地工作,并且缓冲池中所需的内存会更少,写入更新时所需的IO也会更少。

 

InnoDB存储引擎支持四种行格式:Redundant、Compact、Dynamic和Compressed。

 

下面查询MySQL使用的行格式,MySQL5.7后默认是dynamic。

mysql> show variables like 'innodb_default_row_format';
+---------------------------+---------+
| Variable_name             | Value   |
+---------------------------+---------+
| innodb_default_row_format | dynamic |
+---------------------------+---------+

下面是指定行格式的语法:

CREATE TABLE <table_name(column_name)> ROW_FORMAT=行格式名称
ALTER TABLE <table_name> ROW_FORMAT=行格式名称

(2)COMPACT行记录格式

Compact设计目标是高效地存储数据,一个页中存放的行数据越多,其性能就越高。Compact行记录由两部分组成:记录的额外信息和记录的真实数据。

一.记录额外信息部分

服务器为了描述一条记录而添加了一些额外信息(元数据信息),这些额外信息分为3类,分别是:变长字段长度列表、NULL值列表和记录头信息。

 

第一类:变长字段长度列表

MySQL支持一些变长的数据类型,比如VARCHAR(M)、VARBINARY(M)、各种TEXT类型,各种BLOB类型。这些变长的数据类型占用的存储空间分两部分:真正的数据内容和占用的字节数。

 

变长字段的长度是不固定的,所以在存储数据时要把这些数据占用的字节数也存起来。读取数据时才能根据这个长度列表去读取对应长度的数据。

 

在Compact行格式中:会把所有变长类型的列的长度都存放在记录的开头部位形成一个列表,按照列的顺序逆序存放,这个列表就是变长字段长度列表。

 

第二类:NULL值列表

表中的某些列可能会存储NULL值,如果把这些NULL值都放到记录的真实数据中会比较浪费空间,所以Compact行格式把这些值为NULL的列存储到NULL值列表中。如果表中所有列都不允许为 NULL,就不存在NULL值列表。

 

第三类:记录头信息

记录头信息是由固定的5个字节组成,5个字节也就是40个二进制位,不同的位代表不同的意思。

delete_mask:这个属性标记着当前记录是否被删除,占用1个二进制位。值为0时代表记录并没有被删除,值为1时代表记录被删除掉。

 

min_rec_mask:标记该记录是否是B+树的每层非叶子节点中的最小记录。

 

n_owned:代表每个分组里,所拥有的记录的数量,一般是分组里主键最大值才有的。

 

heap_no:在数据页的User Records中插入的记录是一条条紧凑排列的,这种紧凑排列的结构又被称为堆。为了便于管理这个堆,把记录在堆中的相对位置给定一个编号heap_no,所以heap_no这个属性表示当前记录在本页中的位置。

 

record_type:这个属性表示当前记录的类型,一共有4种类型的记录。0表示普通用户记录、1表示B+树非叶节点记录、2表示最小记录、3表示最大记录。

 

next_record :表示从当前记录的真实数据到下一条记录的真实数据的地址偏移量,可以理解为指向下一条记录地址的指针。值为正数说明下一条记录在当前记录的后面,值为负数说明下一条记录在当前记录的前面。

 

二.记录真实数据部分

除了记录真实数据以外,MySQL还会为每条行记录添加一些列。这些列被称为隐藏列,具体的列如下:

列说明如下:

生成隐藏主键列的步骤:

 

步骤一:

服务器会在内存中维护一个全局变量,每当向某个包含隐藏的row_id列的表中插入一条记录时,就会把该变量的值当作新记录的row_id列的值,并且把该变量自增1。

 

步骤二:

每当这个变量的值为256的倍数时,就会将该变量的值,刷新到系统表空间的页号为7的页面中一个Max Row ID的属性中。

 

步骤三:

系统启动时会将页中的Max Row ID属性加载到内存中,并将该值加上256后赋值给全局变量,因为在上次关机时该全局变量的值可能大于页中Max Row ID属性值。

 

(3)Compact中的行溢出机制

一.什么是行溢出

MySQL中是以页为基本单位进行磁盘与内存之间的数据交互的。一个页的大小是16K = 16384字节。一个varchar(m)类型列最多可以存储65532个字节,一些大的数据类型如TEXT可以存储更多。如果一个表存在这样的大字段,那么一个页就无法存储一条完整的记录。这时就会发生行溢出,多出的数据就会存储在另外的溢出页中。

 

总结:如果某些字段信息过长,无法存储在B树节点中。这时候会被单独分配空间,此时被称为溢出页,该字段被称为页外列。

 

二.Compact中的行溢出机制

InnoDB规定一页至少存储两条记录(B+树特点),如果页中只能存放下一条记录,InnoDB会自动将行数据存放到溢出页中。当发生行溢出时,数据页只保存前768字节的前缀数据,接着是20个字节的偏移量,指向行溢出页。

(4)其他行格式记录

一.DYNAMIC和COMPRESSED行记录格式

DYNAMIC和COMPRESSED新格式引入的功能有:数据压缩、增强型长列数据的页外存储和大索引前缀。

 

Compressed和Dynamic行记录格式与Compact行记录格式是类似的。区别是在处理行溢出时:数据页不会存储真实数据的前768字节(完全溢出),而只存储20个字节的指针来指向溢出页。

Compressed与Dynamic相比:Compressed存储的行数据会以zlib的算法进行压缩以节省空间,因此对于BLOB、TEXT、VARCHAR这类大长度类型的数据能有效存储。MySQL5.7默认的行记录格式是Dynamic。

 

二.Redundant

Redundant是MySQL 5.0版本前InnoDB的行记录存储方式。Redundant行记录的格式是:首部是一个字段长度偏移列表,同样是按照列的顺序逆序放置的,该条记录中所有列的长度信息都按照逆序存储到字段长度偏移列表,这些列当然包括隐藏列、NULL值列等。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/843697.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

gin

Gin Gin入门 gin的学习要点如何定义路由:包括参数路由、通配符路由 如何处理输入输出 如何使用middleware解决AOP问题在 Gin 里面,用 Engine 来监听一个端口,是一个逻辑上的服务器。 一个 Go 进程可以创建多个 Engine。 hello, world 使用步骤:在应用中引入 Gin 依赖:go g…

MySQL底层概述—3.InnoDB线程模型

大纲 1.InnoDB的线程模型 2.IO Thread 3.Purge Thread 4.Page Cleaner Thread 5.Master Thread1.InnoDB的线程模型 InnoDB存储引擎是多线程的模型,因此其后台有多个不同的后台线程,负责处理不同的任务。后台线程的作用一:负责刷新内存池中的数据,保证缓冲池中的内存缓存是最…

20222427 2024-2025-1 《网络与系统攻防技术》实验七实验报告

1.实验内容 1.1 本周学习内容本周学习了有关Web安全的相关知识,复习了一些有关于Web的基础知识,比如:前、后端的定义,以及在前后端各自使用的语言,如:html、css、JS(前端);C/C++、Python、Java、Go、Php(后端)等。学习了有关于数据库攻击的一些基本操作,如:SQL注入…

基于Java+SpringBoot+Mysql实现的点卡各种卡寄售平台功能设计与实现四

部分功能:实名认证信息数据层Dao、银行卡类型信息数据层Dao、卡种类信息数据层Dao、卡类型信息数据层Dao、卡面值信息数据层Dao一、前言介绍: 免费学习:猿来入此 1.1 项目摘要 随着电子商务和在线支付技术的快速发展,数字商品和虚拟货币的交易需求日益增长。点卡及各种卡类…

kafka的搭建与使用

官网下载地址https://kafka.apache.org/downloads1、上传解压tar -zxvf kafka_2.11-1.0.0.tgz -C ../ mv kafka_2.11-1.0.0 kafka-1.0.02、修改环境变量 配置环境变量vim /etc/profileexport KAFKA_HOME=/usr/local/soft/kafka-1.0.0 export PATH=$PATH:$KAFKA_HOME/binsource …

河北公需课代 (可以补)

学时30个,需要联系15689397956

技术框架对MyBatis的入门学习

MyBatis快速入门 在回顾JDBC时,我们已经创建有Maven工程,而且在pom.xml中也已经导入 mysql 依赖包,这里就直接在原有工程上搭建MyBatis环境,以及使用MyBatis来实现JDBC查询user的操作流程。 MyBatis环境搭建 首先,在 Maven 项目的 pom.xml 中添加 MyBatis 的依赖 jar 包 &…

基于WOA-SVM的乳腺癌数据分类识别算法matlab仿真,对比BP神经网络和SVM

1.算法运行效果图预览 (完整程序运行后无水印) 2.算法运行软件版本 matlab2022a3.部分核心程序 (完整版代码包含详细中文注释和操作步骤视频)for t=1:Iterstfor i=1:Numif xwoa(i,1)<0xwoa(i,1)=0.1; endif xwoa(i,2)<0xwoa(i,2)=0.001; end%目标函数更新[pa(i)] = f…

安装苹果系统台式电脑如何正确选购装机硬件

结合自己的一些装机经验和网上查阅的相关资料,给大家安利一波 “ 如何正确选配黑苹果硬件 ” 方面的相关知识。文中配置推介表中的配置都是目前在安装黑苹果上比较常见且稳定的机型,并且EFI引导文件都有现成的,在各大资源网站中也比较好找,能帮助你 快速简单的吃上黑苹果。…

JavaWeb知识点总结

JavaWeb知识点总结和学习笔记目录JavaWebjunit黑盒测试白盒测试注解所需jar包反射作用获取Class对象的方式class对象功能应用注解作用预定义的注解自定义注解解析注解动态代理ProxyMaven作用概述仓库maven依赖仓库:IDEA集成Maven高级功能JDBC概念本质快速入门各个对象抽取JDBC工…

电话号码的字母序列

题目描述 输入一个仅包含数字 2-9 的字符串,输出所有它能表示的字母序列。 给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。输入 输入一个包含数字 2-9 的字符串,长度不超过6。 输出 按字典序输出所有能表示的字母序列,每行输出一个。 输入样例 23输出…