首页
/
行业洞察
/
正文
INDUSTRY INSIGHT · 深度
InnoDB存储结构:记录在页里,为什么不从第一行一直找?
📅 2026/10/6 2:19:33
✍️ 爱科研究院
👁 阅读 3,247
我最开始整理 InnoDB列了很多问题没建索引怎么存页里有什么记录为什么有 next_record长字符串放哪里问题不少却没有把它们连接起来。这次先抓一个问题索引已经找到某个叶子页以后还要在里面找一条记录。难道从第一条一直遍历到最后一条本文以 MySQL 8.4 文档为概念基线页目录另引用官方源码说明。图是结构示意不是 .ibd 文件的实测字节布局本轮没有运行 MySQL 实例不虚构 EXPLAIN、页转储或 I/O 数字。1. 先分清在哪个页与页内哪条记录按主键找记录可以先这样理解两个层次聚簇索引 B 树 | v 定位叶子页 第一层在哪个页 | v 页目录缩小范围 - 记录链查找 第二层页内哪条记录这不是完整 SQL 执行流程省略了缓存、锁、可见性判断等工作。上一篇存储引擎笔记讨论页与缓存等层次本篇接着看页内组织。InnoDB 普通索引是 B 树结构。聚簇索引的叶子记录包含行数据二级索引记录则包含相应索引列和用于定位行的主键值不能说“所有索引里的记录都是完整业务行”。索引的物理结构、聚簇与二级索引。没有显式主键也不等于表没有聚簇索引InnoDB 会优先采用第一个所有键列都 NOT NULL 的 UNIQUE 索引没有合适索引时生成隐藏的 GEN_CLUST_INDEX使用 6 字节行 ID。同一官方说明。因此原笔记“必须有主键”应改成引擎需要组织聚簇索引但建表语句不一定声明 PRIMARY KEY。日常设计仍建议显式选择合适主键。2. 有序的是记录之间的逻辑关系不是连续数组学数组查找时我习惯把“有序”理解成连续存放a[0]、a[1]、a[2]。页内记录不能照搬这个想象。页内有记录之间的链接按索引键形成逻辑顺序。记录在页里的物理位置不必按键值紧挨着排列变长字段也让每条记录不一定等长。逻辑键顺序 10 - 20 - 30 - 40 页内位置 不保证是四个等长、连续的数组元素所以“第 100 条”的地址不能简单用起点加 100 倍记录长度得到。顺着 next_record 可以访问下一条逻辑记录但如果只有这条链查找可能走很多步。这里的 next_record 是记录头中的定位信息不是业务字段更不是 C 程序可以直接解引用的内存指针。解析真实文件时必须按对应版本和格式解释。3. 页目录先翻目录再看附近几条页目录保存槽槽指向记录组边界。它不像给每条记录都做一个完整目录而是把记录分组用较少槽缩小查找范围。下面故意用较小的组画出思想不是实际 InnoDB 分组大小记录链 10 - 20 - 30 | 40 - 50 - 60 | 70 - 80 - 90 示意槽 30 60 90 查 50 1. 先在槽里缩小到 (30, 60] 这一段 2. 从前一边界继续沿链查找40 - 50为什么不是“一路二分每条记录”因为完整记录不是可用下标随机访问的连续数组。但槽可以用于二分缩小范围剩下的一小段再沿链检查。为什么不是“所有记录只走链”因为随着页内记录增多长链查找重复比较太多。目录多花一点空间换来更短的查找路径。官方源码对槽所拥有记录数给出 4 与 8 的通常界限并明确首尾槽有例外。因此不能把图里的每组都画成固定 8 条更不能说“整页最多只比较 8 次”还有目录定位等比较。官方 page0page.h 源码说明。这里引用的是 8.0.46 源码文档不把它假称为 8.4 的现场转储。4. 找到记录以后行格式在解决什么问题定位到一条记录不代表它是一串无需解释的字段值。引擎还要知道哪些列是 NULL变长字段多长下一条记录在哪内容解决的问题记录头信息记录状态、逻辑链接等管理信息NULL 标记区分字段没有值与有实际内容变长字段长度信息确定变长字段边界字段数据保存实际值部分长值也可能使用页外存储这是职责概括不是四块必然按这个表格顺序排列的字节图。具体布局要看行格式。MySQL 8.4 支持 REDUNDANT、COMPACT、DYNAMIC、COMPRESSED。REDUNDANT 是较早格式但不能写成已经不支持。COMPACT 系列使用 NULL 位图没有可空列时不需要给 NULL 位图硬塞一个字节。官方行格式说明。5. 长字段不是“类型大就全放外面”页的空间有限一行中的长字段可能有页外部分但不能仅看到 VARCHAR 或 TEXT 就断定固定存法。COMPACT 与 DYNAMIC 的页外策略不同COMPACT 的长字段页外存储会保留页内前缀DYNAMIC 在需要页外存储时可以把长变长字段整体放到页外页内保留定位信息。不是每个字段都会发生溢出也不是每个字符串固定占 20 字节。行格式中的页外存储说明。这也说明为什么“VARCHAR 最多多少字符”不能只拿一个固定数字当答案字符集每字符最大字节数、其他列、行大小限制都有关。本文不通过一段 SQL 反推所有物理布局。6. 可以在自己的 MySQL 中观察什么以下只读语句可检查环境与已有表不要求修改全局参数。把表名替换成自己的测试表。SELECT VERSION(); SHOW VARIABLES LIKE innodb_page_size; SHOW CREATE TABLE your_test_table; SHOW TABLE STATUS LIKE your_test_table; SHOW INDEX FROM your_test_table;这些命令能看到版本、页大小配置、建表语句、行格式和索引定义不能直接显示页目录的每个槽也不能由 SHOW INDEX 没有显式主键就证明没有内部聚簇索引。真要研究槽和记录头下一步应针对确定版本做离线页解析而不是修改生产数据文件。7. 用一个小模型检查“目录 短链”的想法上面的三组示意可以做成一个独立程序先在组尾键里找边界再在所选组里找目标用完整顺序扫描作对照。验证时包含命中、落在键间、比最小值小和比最大值大。本次验证程序检查这幅示意中的全部整数查询范围并对不同长度的递增数组重复测试两种查法应得到同一位置或同为不存在。这个实验只能证明所画简化模型的查询结果一致。它没有实现 InnoDB 的槽维护、记录头、重复键规则或并发行为也不是对 MySQL 存储引擎做完整正确性验证。回头看有序与连续存储不是一回事记录链与二分查找也不互斥。InnoDB 用不同层次解决不同问题树先找页目录缩小页内范围记录信息再帮助定位和解释字段。这样学才不必把几十个名词孤立地背下来。
📌 标签:
工业官网
设计趋势
AI 建站
SEO
获取完整报告 →
RELATED ARTICLES
推荐阅读
2026/10/6 2:19:33
Moodle 主题图标尺寸控制指南:从 `{{pix}}` 模板助手到 `icon-size` 工具类
2026/10/6 2:19:33
Rufus 3.22 还能做 Windows 7 启动盘吗?版本边界一查便知
2026/10/6 2:19:33
cppcheck 的 uselessCallsConstructor 检查:识别容器自我切片赋值的低效构造调用
2026/10/6 6:44:49
AR眼镜硬件设计实战:H616+Micro OLED+嘉立创EDA全链路拆解
2026/10/6 6:44:49
轻型AI中台实战:搞定财务对账与重复录入
2026/10/6 6:44:49
LA1787电调收音头+NE5532+TDA2030复古收音机DIY全攻略
2026/10/6 6:44:49
全桥LLC谐振变换器从原理到调试:欠谐振、准谐振与过谐振全解析
2026/10/6 6:44:49
RV1126B视觉SoC实战指南:ISP-NPU直连与工业级DDR3选型
2026/10/6 6:39:48
基于Jev的浏览器Agent插件:自然语言驱动网页自动化实战解析
2026/10/6 1:04:29
搭建无线EEG采集前端:BW16+ESP32-CYD实时波形显示实战
2026/10/6 1:04:29
CH10D功放芯片DIY音箱实战:从选型到调试的完整指南
2026/10/6 1:04:29
视频序列目标跟踪实战:解决ID跳变与遮挡丢失
2026/10/5 4:43:56
Jev+Agent接管浏览器:browser-use实战与jev-ultrafast性能优化
2026/10/6 4:47:52
多智能体集群实战:DeepAgents编排、MCP与A2A协议及Skills体系
2026/10/5 13:05:37
hindsight:面向LLM应用的事后可观测性工程实践
2026/10/5 20:28:25
我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频
2026/10/5 20:28:23
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证
2026/10/5 20:28:21
2026 大模型集体涨价:用 Python 做企业 Token 成本测算与选型避坑(附配置)