InnoDB 的逻辑存储结构从大到小分为 5 个层级:
text
markdown
表空间(Tablespace)
└── 段(Segment)
└── 区(Extent)
└── 页(Page)
└── 行(Row)
记忆口诀:表 → 段 → 区 → 页 → 行。
五个层级详解
1. 表空间(Tablespace)
最顶层 的逻辑存储结构,是 InnoDB 存储数据的逻辑容器。
| 类型 | 说明 | 文件 |
|---|---|---|
| 系统表空间 | 存储系统数据、回滚段等 | ibdata1 |
| 独立表空间 | 每张表一个,推荐 | 表名.ibd |
| 通用表空间 | 多表共享一个表空间 | .ibd |
| 临时表空间 | 临时表、排序等 | ibtmp1 |
| Undo 表空间 | 回滚日志 | undo_001 等 |
特点:
- 一个表空间可包含多个段
- 独立表空间便于单表备份、回收空间
2. 段(Segment)
表空间由多个段组成 ,段是一组区的集合,用于管理特定类型的数据。
| 段类型 | 说明 |
|---|---|
| 数据段(Leaf node segment) | B+Tree 的叶子节点 |
| 索引段(Non-leaf node segment) | B+Tree 的非叶子节点 |
| 回滚段(Rollback segment) | 存储 undo 日志 |
关键 :每个索引 对应两个段------数据段(叶子)+ 索引段(非叶子)。
特点:
- 一个段包含多个区
- 段是逻辑概念,不直接对应物理文件
- 段随数据增长而扩展
3. 区(Extent)
段由多个区组成 ,区是连续的页的集合。
| 属性 | 说明 |
|---|---|
| 大小 | 1MB(默认) |
| 页数 | 1MB ÷ 16KB = 64 个页 |
| 分配方式 | 按区分配,保证页的连续性 |
sql
-- 查看区大小
SHOW VARIABLES LIKE 'innodb_page_size'; -- 默认 16384(16KB)
-- 1MB / 16KB = 64 页
为什么按区分配?
- 顺序 IO:保证页在磁盘上连续,提高读取效率
- 减少碎片:批量分配,降低管理开销
新版本优化 :MySQL 8.0 引入区大小可变(默认 1MB,可到 4MB)。
4. 页(Page)
InnoDB 磁盘管理的最小单位 ,也是内存与磁盘交互的最小单位。
| 属性 | 说明 |
|---|---|
| 默认大小 | 16KB |
| 可配置 | 4KB / 8KB / 16KB / 32KB / 64KB |
| 作用 | 数据读写的最小单元 |
常见页类型
| 页类型 | 说明 |
|---|---|
| 数据页(B+Tree Node) | 存储行数据 |
| Undo 页 | 回滚日志 |
| 系统页 | 系统数据 |
| 事务数据页 | 事务信息 |
| 插入缓冲页 | Insert Buffer |
| 自适应哈希索引页 | AHI |
| 锁信息页 | 锁数据 |
| BLOB 页 | 大对象数据 |
页的内部结构(数据页)
text
┌─────────────────────────────┐
│ File Header(38 字节) │ 页类型、校验和、页号等
├─────────────────────────────┤
│ Page Header(56 字节) │ 记录数、槽数、层级等
├─────────────────────────────┤
│ Infimum + Supremum Records │ 虚拟最小/最大记录
├─────────────────────────────┤
│ User Records │ 实际行数据
├─────────────────────────────┤
│ Free Space │ 空闲空间
├─────────────────────────────┤
│ Page Directory │ 页目录(槽)
├─────────────────────────────┤
│ File Trailer(8 字节) │ 校验和
└─────────────────────────────┘
sql
-- 查看页大小
SHOW VARIABLES LIKE 'innodb_page_size';
为什么是 16KB? 兼顾 IO 效率和空间利用率,与操作系统页大小匹配。
5. 行(Row)
InnoDB 存储数据的最小单位,即表中的一行记录。
行格式(Row Format)
| 格式 | 说明 | 特点 |
|---|---|---|
| COMPACT | 紧凑格式 | 节省空间,常用 |
| REDUNDANT | 冗余格式 | 旧格式,兼容用 |
| DYNAMIC | 动态格式 | 默认,大字段溢出存储 |
| COMPRESSED | 压缩格式 | 节省空间,CPU 换空间 |
sql
-- 查看行格式
SHOW TABLE STATUS LIKE 'user'\G
-- 指定行格式
CREATE TABLE user (...) ROW_FORMAT=DYNAMIC;
COMPACT 行格式结构
text
┌──────────────────────────────────┐
│ 变长字段长度列表 │ VARCHAR 等长度
├──────────────────────────────────┤
│ NULL 值列表 │ 哪些列为 NULL
├──────────────────────────────────┤
│ 记录头信息(5 字节) │ 删除标记、记录类型等
├──────────────────────────────────┤
│ 列1 数据 │
├──────────────────────────────────┤
│ 列2 数据 │
├──────────────────────────────────┤
│ ... │
└──────────────────────────────────┘
隐藏列
InnoDB 每行有3 个隐藏列:
| 隐藏列 | 长度 | 说明 |
|---|---|---|
DB_ROW_ID |
6 字节 | 无主键时生成的行 ID |
DB_TRX_ID |
6 字节 | 最近修改该行的事务 ID |
DB_ROLL_PTR |
7 字节 | 回滚指针,指向 undo log |
DB_TRX_ID和DB_ROLL_PTR是 MVCC 的基础。
三、层次结构对照表
| 层级 | 大小 | 数量关系 | 说明 |
|---|---|---|---|
| 表空间 | 不定 | 1 个表空间 → N 个段 | 逻辑容器 |
| 段 | 不定 | 1 个段 → N 个区 | 索引的叶子/非叶子 |
| 区 | 1MB | 1 个区 → 64 个页 | 连续页集合 |
| 页 | 16KB | 1 个页 → N 行 | 磁盘 IO 最小单位 |
| 行 | 不定 | 最小单位 | 实际数据 |
换算关系:
text
1 表空间 = N 段
1 段 = N 区
1 区 = 1MB = 64 页
1 页 = 16KB
1 页 = N 行
四、完整层次图
text
┌─────────────────────────────────────────┐
│ 表空间(Tablespace) │
│ ┌───────────────────────────────────┐ │
│ │ 段(Segment) │ │
│ │ ┌─────────────────────────────┐ │ │
│ │ │ 区(Extent, 1MB) │ │ │
│ │ │ ┌──────┐ ┌──────┐ ┌──────┐ │ │ │
│ │ │ │页 16K│ │页 16K│ │页 16K│ │ │ │
│ │ │ │ 行 │ │ 行 │ │ 行 │ │ │ │
│ │ │ └──────┘ └──────┘ └──────┘ │ │ │
│ │ │ ... 共 64 个页 │ │ │
│ │ └─────────────────────────────┘ │ │
│ └───────────────────────────────────┘ │
└─────────────────────────────────────────┘
五、关键要点
- 表空间 → 段 → 区 → 页 → 行,五级结构
- 区 = 1MB = 64 页 ,页 = 16KB(默认)
- 每个索引 对应两个段:数据段(叶子)+ 索引段(非叶子)
- 页是磁盘 IO 的最小单位,读写以页为单位
- 行格式 默认
DYNAMIC,每行有 3 个隐藏列 DB_TRX_ID+DB_ROLL_PTR是 MVCC 基础