MySQL执行器与InnoDB交互本质是单向指令式“填空”:执行器传入table->record[0]内存地址,InnoDB按字段偏移和格式将数据原地写入,而非返回结构体;类型错配会导致WHERE误判,ICP可减少无效行传输,二者无共享缓存或状态协商。

执行器不“拿数据”,而是让InnoDB把数据“填进指定内存地址”——table->record[0]才是真正的交互契约。
执行器调用InnoDB时只传一个内存地址
执行器每次调用ha_innobase::index_read()或ha_innobase::rnd_next(),核心参数不是SQL条件,而是table->record[0]这个指针。InnoDB读到某行后,必须按Server层定义的字段偏移(Field::ptr)和格式,把值原地写进去。
- 不是返回结构体或对象,是“填空式”覆写:VARCHAR先写1–2字节长度,再写内容
-
record[0]大小等于该表“最大行长度”,哪怕实际只存了5个字节,也得预留完整空间 - 字段类型错配(比如Server层认为是
TINYINT,InnoDB写了4字节整数)会导致WHERE误判甚至崩溃
WHERE条件不全在索引里时,InnoDB仍要吐出大量无效行
EXPLAIN显示type=range,不代表InnoDB只扫一次磁盘。它只负责按B+树定位起点和范围,但Server层仍要对每条返回记录做二次过滤。
- 例如
WHERE create_time BETWEEN ? AND ? AND status = 1,若status无索引,InnoDB无法跳过不满足的行,只能全量返回范围内所有create_time匹配的记录 - 每调用一次
ha_rnd_next()或index_read()都有开销,Buffer Pool命中率低时,会触发大量随机I/O - Server层完全感知不到磁盘读取细节,也无法复用InnoDB的Buffer Pool缓存
索引下推(ICP)是唯一能减少无效行传输的优化
MySQL 5.6+启用ICP后,部分WHERE条件可下推到InnoDB层执行,避免把不满足条件的行传给Server层。
- 联合索引
(a,b)上执行WHERE a LIKE '99%' AND b = 'd',ICP允许InnoDB在索引页内就过滤掉b != 'd'的项 - 没ICP时,InnoDB会把所有
a LIKE '99%'的索引项都返回,Server层再逐行判断b - ICP只对索引列生效;涉及回表后的非索引列(如
SELECT *中主键以外的字段),仍需Server层过滤
真正容易被忽略的是:Server层和InnoDB之间没有共享内存、没有联合缓存、没有状态协商——只有单向指令与填空式交付。任何想当然地认为“执行器发个SQL,引擎就直接吐结果”的理解,都会在慢查询分析或崩溃排查时踩坑。


















