执行器是SQL执行阶段的核心组件,负责按执行计划调用存储引擎接口完成数据操作,并在校验字段级权限、处理锁冲突、协调多引擎JOIN、响应事务隔离级别等方面起关键作用。

执行器是SQL真正干活的“操作员”
执行器不解析语法、不选索引、不验权限(权限已在连接器阶段缓存,但执行器会再做一次校验),它只干一件事:按优化器生成的执行计划,调用存储引擎接口,把数据读出来、写进去、删掉或改掉,并把结果组装好返回给客户端。
执行器为什么还要再查一次权限?
因为权限缓存在连接器阶段只读取一次,而执行器面对的是具体表和字段——比如你有 SELECT 权限,但没被授予对 users.phone 字段的访问权,执行器在真正访问该字段时就会报错:
ERROR 1142 (42000): SELECT command denied to user 'app'@'%' for column 'phone' in table 'users'
- 权限检查发生在打开表之后、读取数据之前
- 即使
SELECT *语句能通过分析器,执行器仍可能因字段级权限不足而中断 - 视图、触发器、存储过程内部的 SQL,其字段权限也由执行器动态校验
执行器如何与存储引擎协作?
执行器本身不存数据,它只调用统一接口,具体行为由表使用的存储引擎决定:
- 对
InnoDB表:执行器调用ha_innobase::rnd_next()或index_read()等接口,走聚簇索引或二级索引扫描 - 对
Memory表:执行器调用内存哈希/树结构接口,无磁盘 I/O - 如果 SQL 中涉及多个引擎(如 JOIN
InnoDB和MyISAM表),执行器需分别调用各自引擎 API,协调数据流转 - 遇到锁冲突(如行锁等待)、事务隔离级别限制(如不可重复读下看到旧版本),也是执行器层感知并响应
容易被忽略的执行器行为细节
很多慢查询或报错看似在“查不到数据”,其实卡在执行器阶段:
-
SELECT ... FOR UPDATE在执行器尝试加锁时阻塞,不是优化器问题,也不是网络问题 - 执行器发现表不存在(
ERROR 1146 (42S02))是在打开表时才报,而非分析器阶段——因为表名可能来自变量或视图展开 - 使用
FORCE INDEX后仍走错索引?那大概率是执行器已拿到计划,但存储引擎实际执行时因统计信息过期或锁状态绕开了预期路径 - 执行器返回结果前会做字符集转换、时间戳时区调整、NULL 处理等——这些开销在
SHOW PROFILE的Sending data阶段体现,不是纯 I/O
EXPLAIN,要配合 SHOW PROFILE FOR QUERY N 和 INFORMATION_SCHEMA.INNODB_TRX 看它到底卡在哪一步。










