执行器调用innodb时传的是table->record[0]内存地址;innodb按server层定义的字段偏移和格式将数据原地写入该固定地址,而非返回结构体或对象,二者无共享缓存或状态协商。

执行器不“取数据”,InnoDB也不“返回结果”——它们之间只做一次“填空”:把数据原地写进 table->record[0] 这块固定内存里。
执行器调用 InnoDB 时传的到底是什么?
执行器每次调用 ha_innobase::index_read() 或 ha_innobase::rnd_next(),核心参数不是 WHERE 条件,也不是 SQL 语句,而是一个指针:table->record[0]。这个地址由 Server 层预先分配,大小等于该表定义的「最大行长度」(哪怕实际只存了几个字节)。
常见错误现象:
- 字段类型错配(比如 Server 层定义
Field为TINYINT,InnoDB 却写了 4 字节整数),会导致 WHERE 判断失效,甚至崩溃 - 字段偏移(
Field::ptr)和实际写入位置不一致,Server 层读到的是垃圾值
关键点:InnoDB 不构造结构体、不 malloc 新内存、不序列化成 JSON 或二进制流——它只是按 Server 层给的字段布局,把字节原样覆写进去。
为什么 WHERE 条件没全走索引,InnoDB 还要吐大量无效行?
因为 InnoDB 只负责按 B+ 树定位起点和范围,不做 Server 层语义的条件过滤(除非启用 ICP)。例如:
WHERE create_time BETWEEN '2025-01-01' AND '2025-12-31' AND status = 1,若 status 没索引,InnoDB 就得把整个时间范围内所有行都填进 table->record[0],再交回给执行器二次过滤。
性能影响明显:
- 每多传一行,就多一次内存拷贝 + 执行器判断开销
- Buffer Pool 命中率低时,还会触发大量随机 I/O,但 Server 层完全感知不到磁盘细节
-
EXPLAIN显示type=range≠ 实际只扫一次磁盘
索引下推(ICP)是怎么减少无效传输的?
MySQL 5.6+ 启用 ICP 后,部分 WHERE 条件可下推到 InnoDB 层执行,前提是这些条件涉及的列都在联合索引里。
例如联合索引 (a, b) 上执行:
WHERE a LIKE '99%' AND b = 'd'
有 ICP 时,InnoDB 在索引页内就能跳过 b != 'd' 的项;没 ICP 时,它得把所有 a LIKE '99%' 对应的索引项全部返回,让 Server 层逐行判断 b。
注意限制:
- ICP 只对索引列生效;回表后查的非索引列(如
SELECT *中主键以外的字段),仍需 Server 层过滤 - ICP 不改变索引扫描范围,只减少“填进
table->record[0]”的行数
Server 层和 InnoDB 之间有没有共享缓存或状态协商?
没有。二者之间是纯粹的单向指令式交互:执行器发调用、传地址、等返回;InnoDB 收指令、填内存、返回状态码。
容易被忽略的关键事实:
- Buffer Pool 是 InnoDB 独占的,Server 层无法复用
- 没有共享锁管理、没有事务状态同步、没有跨层缓存一致性协议
- 所谓“执行器发个 SQL,引擎吐结果”的理解,在分析慢查询、锁等待、崩溃日志时会彻底失效
真正决定性能瓶颈的,往往不是 SQL 写得有多好,而是 table->record[0] 这块内存怎么被填、填了多少次、填了哪些不该填的行。











