参考:高性能 MySQL(第 4 版) · MySQL 技术内幕:InnoDB 存储引擎(第 2 版) · MySQL 8.4 Reference Manual。每章含可暂停 Lab 动画 + 面试问答 + 书籍章节对照。
MySQL 面试 · Lab A+ · InnoDB 存储结构
InnoDB 存储结构
主问题
-- 一行 user 数据,在 InnoDB 里到底存在哪?为什么说「InnoDB 表就是按主键组织的索引」?
这题真正考什么
- · 不是考你背页 / 区 / 段的定义。
- · 而是考你知不知道行就存在聚簇索引叶子里,以及主键设计怎么牵动二级索引。
学完你要能做到
- · 说清聚簇索引叶子、二级索引叶子分别存什么
- · 解释为什么推荐短、稳定、递增的主键
- · 把行的隐藏事务字段和 MVCC 连起来
- · 说明 Buffer Pool 命中怎么影响查询
InnoDB 表本身就是一棵按主键组织的聚簇索引 B+Tree,叶子节点直接存整行。
二级索引是另外的 B+Tree,叶子只存索引列 + 主键。
所以主键查询不回表,二级索引查询可能回表。
学习路线
点节点跳转 · 滚动时自动高亮当前位置
这道题到底在问什么?
表面问「一行数据存在哪」,实际是在问:你知不知道行就存在聚簇索引叶子里, 以及主键设计怎么牵动所有二级索引。
面试官嘴上问
数据怎么存?页是什么?
其实在考
行 = 聚簇索引叶子;主键牵动所有二级索引。
页、区、段:存储的基本单位
InnoDB 不是按「行」读写磁盘,而是按「页」。
页 Page
读写的基本单位
InnoDB 以页(默认 16KB)为单位读写磁盘,B+Tree 的节点就是一个个页。
区 / 段 Extent / Segment
服务页的分配
区是连续页的集合,段服务索引增长,让顺序访问和空间分配更高效。
Buffer Pool
页的内存缓存
缓存数据页和索引页,命中率直接决定一次查询是否要落到磁盘 IO。
聚簇索引 vs 二级索引(Lab)
逐步看一行数据存在哪、二级索引又多存了什么。走到第 4 步可切换主键类型,看二级索引怎么膨胀。
聚簇索引 PRIMARY
按主键组织 · 叶子 = 完整行
整张表就是这一棵按主键组织的 B+Tree —— 没有单独的「堆表」。
二级索引 name_idx
键 = name,值 = 主键
(进入下一步,看二级索引另外存了什么)
当前发生了什么
InnoDB 的表本身就是一棵按主键组织的聚簇索引 B+Tree。
为什么会这样
InnoDB 没有单独的「堆表」,数据按主键有序组织在 B+Tree 里。
面试怎么回答
InnoDB 表就是聚簇索引,主键决定数据的物理组织顺序。
常见误区
误区:以为 InnoDB 是堆表、主键只是一个普通索引。
主键为什么要短、要递增?
主键被带进所有二级索引,它的选择牵一发动全身。
| 主键方案 | 二级索引体积 | 写入 / 页分裂 | 建议 |
|---|---|---|---|
| 自增 BIGINT | 小 | 顺序插入,页分裂少 | 常用默认 |
| 随机 UUID | 大 | 随机插入,页分裂多 | 谨慎 |
| 业务长字符串 | 很大 | 放大所有二级索引 | 不推荐做主键 |
聚簇 vs 二级 对比
把两类索引一次对齐,存储题就答得清楚。
| 对比项 | 聚簇索引 PRIMARY | 二级索引 |
|---|---|---|
| 叶子保存什么 | 完整行(+ 隐藏字段) | 索引列 + 主键 |
| 一张表有几个 | 1 个 | 可以多个 |
| 命中后能直接返回吗 | 能(叶子就是行) | 看是否覆盖,否则回表 |
| 主键变长的影响 | 自身变大 | 所有二级索引都变大 |
面试回答生成器
按时间预算选一档念出来。
InnoDB 表本身就是一棵按主键组织的聚簇索引 B+Tree,叶子节点直接存整行。
二级索引是另外的 B+Tree,叶子只存索引列 + 主键。所以主键查询不回表,二级索引查询可能回表。
追问链 + 复习清单
勾掉每一条,这道题就算通关。
通关检查
0/5 已掌握追问链
- Q没有主键时 InnoDB 如何选择聚簇索引?
- Q覆盖索引遇到更新中的记录为什么可能还要检查聚簇记录?
- Q长事务为什么会让 purge 和 undo 空间压力变大?