InnoDB的逻辑存储结构学习

本文介绍了InnoDB存储引擎的表空间、逻辑存储结构及其组成部分,包括段、区、页和行的概念。阐述了InnoDB如何管理和存储数据,以及不同的行存储格式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

InnoDB存储引擎在存储设计方面之前一直是迷迷糊糊,这几天在读《MySQL技术内幕 InnoDB存储引擎》,有点了解,特意记下消化一下^^

我们知道InnoDB是使用表空间结构来进行管理的。默认情况下InnoDB有一个共享表空间ibdata1,即所有的数据都存放在这个表空间内,但是我们可以设定innodb_file_per_table为ON使每一张表的数据可以单独放在一个表空间里


虽然我们启动了innodb_file_per_table参数选项,但是注意的是每张表的表空间存放的只是数据,索引和插入缓冲,其他的数据如撤销信息,系统事务信息等还是存放在原来的共享表空间里。

而在InnoDB存储引擎表中,每一张表都有一个主键,假如我们没有在创建表的时候显式定义主键,则InnoDB会按照如下方式选择或者创建主键:

1、首先表中是否有非空唯一索引,如果有,那么该列即为主键;

2、否则它会自动创建一个6个字节大小的指针。


大致了解InnoDB的表空间概念之后我们看一下他的逻辑存储结构,如下图:


清晰明了,它是由段(segment),区(extent,有书也叫簇),页(page),行(row)组成。


段:

段是用来管理物理文件,构成索引,表,回滚段的基本元素。常见的段有数据段,索引段,回滚段等。创建一个索引(B+树)会创建两个段,分别是内节点段和叶子段,内节点段用来管理或存储B+树中非叶子结点的数据,叶子段用来管理或存储B+树中叶子结点的数据。在随着索引数据量的增大时,所有的新存储空间申请都是从段这个概念开始的。


区:

区是构成段的基本元素,一个段由若干个区组成,区是由64个连续的页组成,每个页大小为16kb,所以每一个区大小为1MB,我们在新建一个innodb的表时候,即使没有插入任何数据,他的大小也是96KB,而区是64个连续的页,按道理应该是1MB才对的,之所以会这样,是在每个段开始时,先会有32个页大小的碎片页来存放数据,只有这些页使用完之后才是64个连续的页申请,同时我们知道,因为段之间是没有位置关系,而每一个段都是一个或者多个区组成,所以区之间也是没有物理位置关系。


页:

页是区的组成单位,常见的页类型有如下:

数据页(B_tree Node)

Undo页(Undo Log Page)

系统页(System Page)

事务数据页(Transaction system Page)

插入缓冲位图页(Insert Buffer Bitmap)

插入缓冲空闲列表页(Insert Buffer Free List)

未压缩的二进制大对象页(Uncompressed Blob Page)

压缩的二进制大对象页(Compressed BLOB Page)

一个区默认是64个页面,这个数量通常称为区的大小,在逻辑上页面号从小到大连续的,并且在物理上也是连续的,再向表中插入数据时,如果一个页面被写完,系统就会从当前区分配一个新的空闲页使用,而当区中64个页面(默认)就会从所在的段中分配一个新的区供使用。

行:

InnoDB存储引擎是面向行的,也就是说数据的存放按行进行存放,每一个页存放的行记录也是有硬性规定的,而在MySQL中,为了帮助管理升级与降级以及运行不同版本的MySQL系统,使用了命名文件格式,目前支持的是Antelope和Barracuda两种。

Antelope支持compact和redundant两种行存储格式;Barracuda是最新的文件存储格式,它支持COMPRESSED和DYNAMIC行存储格式

在目前的版本(使用的是5.7)文件存储格式已经更改为Barracuda了,在这之前是Antelope。

而在新的行存储格式中对于过长的BLOB和VARCHAR等字段,则是将它们存储在单独分配的溢出页,在数据页中只存放20个字节的指针,同时将长度大于或者等于768字节的固定长度字段编码为可变长字段。

默认的行存储格式由innodb_default_row_format定义,默认值是DYNAMIC,我们可以在建表时候使用ROW_FORMAT指定行格式,如下图


Compact行记录格式:

变长字段长度列表 NULL标志位记录头信息列1数据列2数据……

如上可以知道Compact行格式,它的首部是一个非NULL变长字段长度列表,当列的长度小于255字节,用1字节表示,若大于255字节,用2个字节表示,变长字段长度最大不超过2个字节,这也解释了MySQL中varchar的最大长度为65535,因为2个字节为16位,2^16=65535;还需记住它是逆序存放值的。

第二个部分是NULL标志位,该位指示该行数据中是否有NULL值,用1表示;

第三部分记录头信息,固定占用5个字节:

名称大小(bit)描述
()1未知
()1未知
deleted_flag1该行是否已被删除
min_rec_flag1为1,如果该记录是预先被定义为最小的记录
n_owned4该记录拥有的记录数
heap_no13索引堆中该条记录的排序记录
record_type3

该记录类型000=普通,001=B+树节点指针,010=Infimum

011=Supremum,1xx=保留

next_recorder16页中下一条记录相对位置
Redundant行记录格式:

它是MySQL5.0版本之前的InnoDB行记录存储方式,只是为了向前兼容,它的存储方式如下:

字段长度偏移列表记录头信息列1数据列2数据列3数据……

首部是长度偏移列表,同样是逆序放置值,当列的长度小于255字节,用1字节表示;若大于255字节,用于2个字节表示。

第二个部分为记录头信息,但是不同于Compact行格式,它占用6个字节

Compressed与Dynamic行记录格式:

如前面所说,再对存放BLOB的数据时候完全采用行溢出方式,在数据页只存放20个字节的指针,实际数据都存放在BLOB page中,而在这之前的两个格式中会存放768前缀字节。

Compressed行记录格式的另一个功能就是,存储在其中的行数据会以zlib的算法进行压缩,因此对于BLOB、TEXT、VARCHAR这类大长度类型的数据能进行非常有效的存储。


<think>我们正在讨论InnoDB存储引擎的逻辑结构。根据引用内容,InnoDB逻辑存储结构主要涉及表空间(Tablespace)、段(Segment)、区(Extent)、页(Page)以及行(Row)这几个层次。下面我将逐一详细介绍。 1. **表空间(Tablespace)**: - 表空间是InnoDB存储引擎逻辑结构的最高层,所有的数据都存储在表空间中。 - 表空间可以分为: - **系统表空间(System Tablespace)**:存储InnoDB的数据字典(在MySQL 8.0之前)、双写缓冲区(Doublewrite Buffer)、更改缓冲区(Change Buffer)、undo日志(在MySQL 8.0之前)以及一些表和索引数据(如果表创建在系统表空间中)。系统表空间由一个或多个数据文件组成,由参数`innodb_data_file_path`指定。 - **独立表空间(File-Per-Table Tablespace)**:每个表都有一个独立的表空间文件(.ibd文件),存储该表的索引和数据。这是MySQL 5.6之后的默认行为(由参数`innodb_file_per_table`控制)。 - **通用表空间(General Tablespace)**:多个表可以共享一个通用表空间,通过`CREATE TABLESPACE`创建。 - **Undo表空间(Undo Tablespace)**:在MySQL 8.0中,undo日志从系统表空间中分离出来,存储在单独的undo表空间中,用于存储undo日志。 - **临时表空间(Temporary Tablespace)**:存储临时表的数据。 2. **段(Segment)**: - 表空间由多个段组成,段是分配空间的基本单位。常见的段有数据段、索引段、回滚段等。 - 数据段存储表中的数据(即聚集索引的叶子节点),索引段存储非叶子节点(索引节点),回滚段存储undo日志。 3. **区(Extent)**: - 每个段由多个区组成,区是连续分配的页。在InnoDB中,一个区固定为1MB(在页大小为16KB时,一个区包含64个连续页)。 - 区可以避免频繁的磁盘分配操作,提高性能。 4. **页(Page)**: - 页是InnoDB磁盘管理的最小单位,默认大小为16KB(可以通过参数`innodb_page_size`设置,但一旦创建数据库就不能更改)。 - 页的类型有很多,例如:数据页(B-tree节点)、undo页、系统页、事务数据页、插入缓冲位图页、插入缓冲空闲列表页等。 - 数据页(B-tree节点)存储行记录和索引信息。InnoDB采用B+树索引结构,数据页就是B+树的叶子节点,索引页是非叶子节点。 5. **行(Row)**: - 页中存储的是行记录。InnoDB存储引擎是面向行的(row-oriented),即数据按行存储。 - 每行记录都包含事务ID(Transaction ID)、回滚指针(Roll Pointer)以及行数据(包括主键和其他列)。 - InnoDB采用索引组织表(Index Organized Table, IOT)的方式存储数据,即表中的数据按照主键顺序存储。如果没有显式定义主键InnoDB会选择一个唯一非空索引作为主键,如果也没有,则会自动生成一个6字节的rowID作为主键。 总结一下InnoDB逻辑存储结构:表空间由段组成,段由区组成,区由页组成,页中存储行记录。这种层次结构有助于高效地管理磁盘空间和进行数据读写。 另外,根据引用[1]和[3],InnoDB的表是索引组织表,即数据按照主键顺序存储。这种结构使得基于主键的查询非常高效。 [^1]:【MySQL】Innodb存储引擎逻辑存储结构与底层实现解析 [^2]:【MySQL数据库】InnoDB存储引擎:逻辑存储结构、内存架构、磁盘架构 [^3]:MySQL中InnoDB存储引擎详细介绍 §§相关问题§§ 1. InnoDB存储引擎中,表空间有哪些类型?各自的作用是什么? 2. 为什么InnoDB采用索引组织表(IOT)的方式存储数据?有什么优势? 3. InnoDB的页(Page)默认大小是多少?可以修改吗?修改时需要注意什么? 4. 在InnoDB中,如果没有显式定义主键,会发生什么? 5. InnoDB逻辑存储结构与物理存储结构有什么联系和区别?</think>### InnoDB存储引擎逻辑架构详解 InnoDB存储引擎采用分层的逻辑存储结构,从大到小依次为:**表空间 → 段 → 区 → 页 → 行**。以下是各层级的详细说明: --- #### **1. 表空间(Tablespace)** 表空间是InnoDB逻辑结构的最高层,分为两类: - **系统表空间(System Tablespace)** - 存储内容: - 数据字典(MySQL 8.0前) - 双写缓冲区(Doublewrite Buffer) - 更改缓冲区(Change Buffer) - Undo日志(MySQL 8.0前) - 未指定独立表空间的表数据与索引 - 配置文件:`innodb_data_file_path` 定义数据文件路径和大小[^2][^3]。 - **独立表空间(File-Per-Table Tablespace)** - 每个表单独存储为 `.ibd` 文件(默认启用)。 - 包含表数据、索引及关联的Undo日志(MySQL 8.0+)。 - **通用表空间(General Tablespace)** - 多个表共享一个表空间文件,通过 `CREATE TABLESPACE` 创建。 - **Undo表空间(Undo Tablespace)** - MySQL 8.0+ 将Undo日志从系统表空间分离,独立存储。 --- #### **2. 段(Segment)** 段是表空间的子结构,管理特定类型的数据分配: - **数据段**:存储B+树叶子节点(实际行数据)。 - **索引段**:存储B+树非叶子节点(索引指针)。 - **回滚段**:存储Undo日志,用于事务回滚。 > 每个索引对应两个段(叶子段+非叶子段),由InnoDB自动管理[^1]。 --- #### **3. 区(Extent)** 区是连续页的集合,用于优化空间分配: - 固定大小:**1MB**(默认页大小16KB时,1区=64页)。 - 作用:减少频繁分配小单元的开销,提升I/O效率。 --- #### **4. 页(Page)** 页是InnoDB磁盘管理的最小单元: - **默认大小**:16KB(可通过 `innodb_page_size` 配置,但需在初始化时设置)。 - 核心类型: - **数据页(B-tree Node)**:存储行记录与索引。 - **Undo页**:存储事务回滚日志。 - **系统页**:管理区、段等元数据。 - 页内结构: - 文件头(File Header):页编号、前后页指针(形成双向链表)。 - 行记录(Row Records):按主键顺序存储(索引组织表)。 - 页目录(Page Directory):槽位加速行记录查找。 --- #### **5. 行(Row)** 行是数据存储的基本单位: - **格式**:支持Compact、Redundant、Dynamic等行格式(默认Dynamic)。 - **组成**: - 事务ID(Transaction ID) - 回滚指针(Roll Pointer) - 列数据(含隐藏主键 `row_id`) - **主键规则**: - 显式定义主键 → 按主键顺序存储(索引组织表)。 - 未定义主键 → 自动生成6字节 `row_id` 作为主键[^1]。 --- ### 逻辑架构总结图 ```plaintext 表空间 (Tablespace) │ ├─ 段 (Segment) → 数据段 / 索引段 / 回滚段 │ │ │ └─ 区 (Extent) → 1MB (64个连续页) │ │ │ └─ 页 (Page) → 16KB (B+树节点) │ │ │ └─ 行 (Row) → 事务ID + 列值 ``` > 核心特性:**索引组织表(IOT)** > 所有数据按主键顺序存储在B+树中,非主键索引的叶子节点直接指向主键值[^1][^3]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值