D
RuntimeScope/MySQL 面试专题/innodb-storage/InnoDB 存储结构

参考:高性能 MySQL(第 4 版) · MySQL 技术内幕:InnoDB 存储引擎(第 2 版) · MySQL 8.4 Reference Manual。每章含可暂停 Lab 动画 + 面试问答 + 书籍章节对照。

MySQL 面试 · Lab A+ · InnoDB 存储结构

InnoDB 存储结构

主问题

-- 一行 user 数据,在 InnoDB 里到底存在哪?

为什么说「InnoDB 表就是按主键组织的索引」?

这题真正考什么

  • · 不是考你背页 / 区 / 段的定义。
  • · 而是考你知不知道行就存在聚簇索引叶子里,以及主键设计怎么牵动二级索引。

学完你要能做到

  • · 说清聚簇索引叶子、二级索引叶子分别存什么
  • · 解释为什么推荐短、稳定、递增的主键
  • · 把行的隐藏事务字段和 MVCC 连起来
  • · 说明 Buffer Pool 命中怎么影响查询
30 秒答案先记结论,再看推导

InnoDB 表本身就是一棵按主键组织的聚簇索引 B+Tree,叶子节点直接存整行。

二级索引是另外的 B+Tree,叶子只存索引列 + 主键

所以主键查询不回表,二级索引查询可能回表。

学习路线

点节点跳转 · 滚动时自动高亮当前位置

01

这道题到底在问什么?

表面问「一行数据存在哪」,实际是在问:你知不知道行就存在聚簇索引叶子里, 以及主键设计怎么牵动所有二级索引。

面试官嘴上问

数据怎么存?页是什么?

其实在考

行 = 聚簇索引叶子;主键牵动所有二级索引。

02

页、区、段:存储的基本单位

InnoDB 不是按「行」读写磁盘,而是按「页」。

页 Page

读写的基本单位

InnoDB 以页(默认 16KB)为单位读写磁盘,B+Tree 的节点就是一个个页。

区 / 段 Extent / Segment

服务页的分配

区是连续页的集合,段服务索引增长,让顺序访问和空间分配更高效。

Buffer Pool

页的内存缓存

缓存数据页和索引页,命中率直接决定一次查询是否要落到磁盘 IO。

03

聚簇索引 vs 二级索引(Lab)

逐步看一行数据存在哪、二级索引又多存了什么。走到第 4 步可切换主键类型,看二级索引怎么膨胀。

主键类型
页 Page · 16KB读写的基本单位 ·Buffer Pool缓存数据页 / 索引页

聚簇索引 PRIMARY

按主键组织 · 叶子 = 完整行

PRIMARY root(页)
叶子页

整张表就是这一棵按主键组织的 B+Tree —— 没有单独的「堆表」。

二级索引 name_idx

键 = name,值 = 主键

(进入下一步,看二级索引另外存了什么)

当前发生了什么

InnoDB 的表本身就是一棵按主键组织的聚簇索引 B+Tree。

为什么会这样

InnoDB 没有单独的「堆表」,数据按主键有序组织在 B+Tree 里。

面试怎么回答

InnoDB 表就是聚簇索引,主键决定数据的物理组织顺序。

常见误区

误区:以为 InnoDB 是堆表、主键只是一个普通索引。

结论聚簇索引叶子 = 完整行(含隐藏字段);二级索引叶子 = 索引列 + 主键。主键被复制进每一个二级索引,所以它越长,所有二级索引越大。
04

行记录里的隐藏字段

聚簇索引叶子里的「整行」,除了业务列,还有两个隐藏字段。

id=10
name='Tom'
age=18
DB_TRX_ID
最近修改的事务 ID
DB_ROLL_PTR
指向 undo 旧版本
结论DB_TRX_ID 和 DB_ROLL_PTR 是 MVCC 的地基:可见性判断看 trx_id,版本回溯靠 roll_pointer。
05

主键为什么要短、要递增?

主键被带进所有二级索引,它的选择牵一发动全身。

主键方案二级索引体积写入 / 页分裂建议
自增 BIGINT顺序插入,页分裂少常用默认
随机 UUID随机插入,页分裂多谨慎
业务长字符串很大放大所有二级索引不推荐做主键
结论主键要短、稳定、趋势递增;业务唯一性用唯一索引保证,别硬塞进主键。
06

聚簇 vs 二级 对比

把两类索引一次对齐,存储题就答得清楚。

对比项聚簇索引 PRIMARY二级索引
叶子保存什么完整行(+ 隐藏字段)索引列 + 主键
一张表有几个1 个可以多个
命中后能直接返回吗能(叶子就是行)看是否覆盖,否则回表
主键变长的影响自身变大所有二级索引都变大
07

面试回答生成器

按时间预算选一档念出来。

InnoDB 表本身就是一棵按主键组织的聚簇索引 B+Tree,叶子节点直接存整行。

二级索引是另外的 B+Tree,叶子只存索引列 + 主键。所以主键查询不回表,二级索引查询可能回表。

08

追问链 + 复习清单

勾掉每一条,这道题就算通关。

通关检查

0/5 已掌握

追问链

  • Q没有主键时 InnoDB 如何选择聚簇索引?
  • Q覆盖索引遇到更新中的记录为什么可能还要检查聚簇记录?
  • Q长事务为什么会让 purge 和 undo 空间压力变大?