InnoDB的表类型,逻辑存储结构,物理存储结构

本文详细介绍了MySQL InnoDB存储引擎的表类型、逻辑存储结构及物理存储结构等内容,包括索引组织表特性、页和段的管理方式以及共享表空间等关键概念。

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

表类型

对比Oracle支持的各种表类型,InnoDB存储引擎表更像是Oracle中的索引组织表(index organized table)。在InnoDB存储引擎表中,每张表都有个主键,如果在创建表时没有显式地定义主键(Primary Key),则InnoDB存储引擎会按如下方式选择或创建主键。

  1. 首先表中是否有非空的唯一索引(Unique NOT NULL),如果有,则该列即为主键。
  2. 不符合上述条件,InnoDB存储引擎自动创建一个6个字节大小的指针。

回到顶部

逻辑存储结构

InnoDB存储引擎的逻辑存储结构和Oracle大致相同,所有数据都被逻辑地存放在一个空间中,我们称之为表空间(tablespace)。表空间又由段(segment)、区(extent)、页(page)组成。页在一些文档中有时也称为块(block),1 extent = 64 pages,InnoDB存储引擎的逻辑存储结构大致如图所示。

表空间

表空间可以看做是InnoDB存储引擎逻辑结构的最高层,所有的数据都是存放在表空间中。默认情况下InnoDB存储引擎有一个共享表空间ibdata1,即所有数据都放在这个表空间内。如果我们启用了参数innodb_file_per_table,则每张表内的数据可以单独放到一个表空间内。

对于启用了innodb_file_per_table的参数选项,需要注意的是,每张表的表空间内存放的只是数据、索引和插入缓冲,其他类的数据,如撤销(Undo)信息、系统事务信息、二次写缓冲(double write buffer)等还是存放在原来的共享表空间内。这也就说明了另一个问题:即使在启用了参数innodb_file_per_table之后,共享表空间还是会不断地增加其大小。

现在我们来做个实验,实验之前我已经将innodb_file_per_table设为ON了,看看初始共享表空间文件有多大:

show variables like 'innodb_file_per_table' \G

system ls -lh /usr/local/var/mysql/ibdata1

共享表空间ibdata1的大小为76M。

set autocommit=0;

update mytest set salary=0;

system ls -lh /usr/local/var/mysql/ibdata1

首先将自动提交设为0,即我们需要显式提交事务(注意,上面结束时我们并没有commit或者rollback该事务)。接着我们执行会产生大量Undo操作的语句update mytest set salary=0,完成后我们再观察共享表空间,会发现ibdata1已经增长到了114MB,这就说明了共享表空间中还包含有Undo信息。如果我rollback这个事务,ibdata1这个表空间会不会缩减至原来的58MB大小?我们接下去就来验证: 

rollback;

system ls -lh /usr/local/var/mysql/ibdata1

很“可惜”,还是114MB,即InnoDB存储引擎不会在rollback时去收缩这个表空间。虽然InnoDB不会帮你回收这些空间,但是MySQL会自动判断这些Undo信息是否需要,如果不需要,则会将这些空间标记为可用空间,供下次Undo使用。master thread每10秒会执行一次full purge操作。因此很有可能的一种情况是,你再次执行上述的UPDATE语句后,会发现ibdata1不会再增大了,那就是这个原因了。

上图中显示了表空间是由各个段组成的,常见的段有数据段、索引段、回滚段等。InnoDB存储引擎表是索引组织的(index organized),因此数据即索引,索引即数据。那么数据段即为B+树的页节点(上图的leaf node segment),索引段即为B+树的非索引节点(上图的non-leaf node segment)。

与Oracle不同的是,InnoDB存储引擎对于段的管理是由引擎本身完成,这和Oracle的自动段空间管理(ASSM)类似,没有手动段空间管理(MSSM)的方式,这从一定程度上简化了DBA的管理。

需要注意的是,并不是每个对象都有段。因此更准确地说,表空间是由分散的页和段组成。

区是由64个连续的页组成的,每个页大小为16KB,即每个区的大小为1MB。对于大的数据段,InnoDB存储引擎最多每次可以申请4个区,以此来保证数据的顺序性能。

在我们启用了参数innodb_file_per_talbe后,创建的表默认大小是96KB。区是64个连续的页,那创建的表的大小至少是1MB才对啊?其实这是因为在每个段开始时,先有32个页大小的碎片页(fragment page)来存放数据,当这些页使用完之后才是64个连续页的申请。

通过一个实验来显示InnoDB存储引擎对于区的申请:

create table t1 (

  col1 int not null auto_increment,

  col2 varchar (7000),

  primary key(col1)

)engine=InnoDB;

system ls -lh /usr/local/var/mysql/test/t1.ibd

创建了t1表,col2字段设为varchar(7000),这样能保证一个页中可以存放2条记录。可以看到,初始创建完t1后表空间默认大小为96KB.

同大多数数据库一样,InnoDB有页(page)的概念(也可以称为块),页是InnoDB磁盘管理的最小单位。与Oracle类似的是,Microsoft SQL Server数据库默认每页大小为8KB,不同于InnoDB页的大小(16KB),且不可以更改(也许通过更改源码可以)。

常见的页类型有:

  1. 数据页(B-tree Node)。
  2. Undo页(Undo Log Page)。
  3. 系统页(System Page)。
  4. 事务数据页(Transaction system Page)。
  5. 插入缓冲位图页(Insert Buffer Bitmap)。
  6. 插入缓冲空闲列表页(Insert Buffer Free List)。
  7. 未压缩的二进制大对象页(Uncompressed BLOB Page)。
  8. 压缩的二进制大对象页(Compressed BLOB Page)。

InnoDB存储引擎是面向行的(row-oriented),也就是说数据的存放按行进行存放。每个页存放的行记录也是有硬性定义的,最多允许存放16KB/2~200行的记录,即7992行记录。这里提到面向行(row-oriented)的数据库,那么也就是说,还存在有面向列(column-orientied)的数据库。MySQL infobright储存引擎就是按列来存放数据的,这对于数据仓库下的分析类SQL语句的执行以及数据压缩很有好处。类似的数据库还有Sybase IQ、Google Big Table。面向列的数据库是当前数据库发展的一个方向。

回到顶部

物理存储结构

从物理意义上来看,InnoDB表由共享表空间、日志文件组(更准确地说,应该是Redo文件组)、表结构定义文件组成。若将innodb_file_per_table设置为on,则每个表将独立地产生一个表空间文件,以ibd结尾,数据、索引、表的内部数据字典信息都将保存在这个单独的表空间文件中。表结构定义文件以frm结尾,这个是与存储引擎无关的,任何存储引擎的表结构定义文件都一样,为.frm文件。

<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]。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值