首先澄清一个常见误区:很多人误以为 MySQL 查询超时是由操作系统(如 Linux)配置的,但实际并非如此。查询超时的控制权完全掌握在 MySQL 服务端手中,Linux 仅能影响网络栈的部分行为(如 net_read_timeout),真正能中断慢查询的配置项只有 MySQL 自身的 max_execution_time。

max_execution_time 是唯一能中断 SELECT 执行的 MySQL 参数
该参数自 MySQL 5.7.8 起引入,仅对 SELECT 语句生效——INSERT、UPDATE、DELETE 均不受其影响。它在 SQL 执行阶段开始计时,一旦超过设定的毫秒数,便会抛出错误:Query execution was interrupted, maximum statement execution time exceeded。需要注意以下几个关键细节:
- 这是一个会话级的只读变量,无法写入
my.cnf实现全局生效。每个连接建立后需手动设置,例如在应用初始化时执行SET SESSION max_execution_time = 5000。 - 值设为
0表示明确禁用,并非“不限制”。 - 存储过程内部的
SELECT不会继承会话设置,必须在过程内显式执行SET SESSION才能生效。 - 当前用户必须拥有
PROCESS权限,否则像/*+ MAX_EXECUTION_TIME(3000) */这样的 hint 会被静默忽略,无法起到任何作用。
wait_timeout 和 interactive_timeout 管理的是空闲连接,而非查询执行
这两个参数常被误认为“查询超时”,但实际仅在连接没有任何活动时才会开始倒计时。即便一个 SELECT 已执行 10 分钟且仍在计算中,只要连接未断开、未发送新请求,wait_timeout 就完全不会触发。
wait_timeout控制非交互式连接(例如 Java 应用的 JDBC 连接)。interactive_timeout控制交互式连接(例如mysql -u root -p命令行)。- 默认值均为 28800 秒(8 小时),线上环境建议调低至 300–600 秒,但这与“查询过慢需要提前终止”无关。
- 连接池的
idleTimeout必须小于wait_timeout,否则连接池可能获取到已经失效的连接。
net_read_timeout / net_write_timeout 仅作用于网络收发,不涉及 SQL 执行
这两个参数作用于 TCP/IP 连接的数据传输阶段:前者是 MySQL 等待客户端发送下一段请求的超时时间,后者是 MySQL 向客户端返回结果时卡住的超时。它们对查询逻辑本身没有任何影响。
- 仅对 TCP/IP 连接有效,Unix socket、命名管道等本地连接不遵循此逻辑。
- 如果查询已经计算完毕,正在向客户端推送数据(状态显示为
Writing to net),此时即使执行KILL QUERY或启用max_execution_time也无效——线程仍在填充 socket 缓冲区。 - 默认值分别为 30 秒和 60 秒。若应用侧存在大结果集导出场景,可适当调高,但请勿设置为 0。
- 它们无法替代
max_execution_time,因为计时范围不覆盖 SQL 解析、执行、锁等待等核心阶段。
KILL QUERY 有时不生效的真实原因分析
执行 KILL QUERY [id] 后查询仍在运行,大概率不是配置问题,而是卡在 MySQL 无法中断的环节:
- 正在执行 InnoDB 大事务回滚(回滚操作不可中断,这是引擎的硬性限制)。
- 卡在操作系统 I/O 层(例如磁盘已满、页缓存刷盘缓慢),MySQL 已发出中断信号但内核未响应。
- 使用了 UDF 或自定义存储引擎插件,且代码中未轮询
thd->killed标志位。 - 查询处于
Sending data或Writing to net状态,结果集已生成,但网络传输受阻无法发出。
这些场景下,max_execution_time 同样无效——它仅在 SQL 引擎执行阶段生效,不覆盖回滚、I/O 操作、网络传输等外围环节。
