max_execution_time 是 mysql 5.7.8+ 的会话级 select 查询超时参数(毫秒),仅在执行器扫描行时计时,不拦截锁等待、解析、优化等阶段,不中断非 select 语句,超时仅中断当前语句且不回滚事务。

max_execution_time 是什么,它能拦住哪些查询
max_execution_time 是 MySQL 5.7.8+ 引入的会话级(也可设全局)超时控制参数,单位毫秒。它只对 SELECT 查询 生效,INSERT/UPDATE/DELETE/DDL 都不响应这个设置。
常见误解是以为它能“杀死所有慢 SQL”,实际它只在执行器扫描行时做计时检查——比如全表扫描、索引范围扫描中每读一行就判断一次是否超时;但像等待锁、网络传输、解析、优化阶段耗时都不计入。所以遇到 Waiting for table metadata lock 或长事务阻塞时,max_execution_time 完全无效。
它适合防住意外的全表 SELECT,比如开发误写 SELECT * FROM huge_table 却没加 WHERE;不适合替代慢查询日志或 pt-kill 做主动治理。
怎么设才真正生效:会话级优先于全局,且需客户端支持
max_execution_time 默认值为 0(不限制),设为非 0 才启用。但要注意:
- 全局设置(
SET GLOBAL max_execution_time = 3000)只影响之后新建立的连接,已有连接不受影响 - 会话设置(
SET SESSION max_execution_time = 2000)立即生效,但每次连接都要重设 - 某些客户端(如老版本 MySQL Workbench、部分 JDBC 驱动)可能忽略服务端返回的超时中断信号,表现为“SQL 看似卡住”,其实是客户端没处理
Query execution was interrupted错误 - PHP 的 mysqli 默认不自动重连,超时后需手动检查
mysqli_error()是否含Query execution was interrupted
推荐方式:在应用连接池初始化 SQL 中加上 SET SESSION max_execution_time = 5000,比依赖全局配置更可控。
超时后的行为:不是 kill,而是中断,且不回滚事务
当查询触发 max_execution_time 限制时,MySQL 返回错误:
ERROR 1317 (70100): Query execution was interrupted
关键点:
- 这只是中断当前语句,**不会 KILL 连接**,连接保持打开状态
- 如果该 SELECT 在事务中(比如前面有
BEGIN),**事务不会自动回滚**,后续语句仍处于同一事务上下文,可能造成隐性数据不一致 - 无法通过
SHOW PROCESSLIST看到 “Killed” 状态,只会显示 “Query” 或 “Sending data”,直到超时发生 - 慢查询日志(
slow_query_log)默认不记录被中断的查询,除非同时开启log_queries_not_using_indexes且满足其条件
这意味着:靠 max_execution_time 防拖库,必须配合应用层异常捕获和事务兜底逻辑,不能假设“超时=安全”。
和其它限流机制的关系:别指望它替代 long_query_time
max_execution_time 和 long_query_time 完全是两套逻辑:
-
long_query_time控制哪些查询被记入慢查询日志,不影响执行本身 -
max_execution_time主动中断 SELECT,但不保证进慢日志 - 两者可共存:一个查得慢但没超时(进慢日志),一个查得快但设了 10ms 超时(直接中断)
- 真正防拖库需要组合手段:连接数限制(
max_connections)、内存限制(sort_buffer_size等)、线程池(Enterprise)、以及外部工具如 pt-kill 监控Time列杀长事务
最常被忽略的是:超时值设太小会导致正常分页查询(如 LIMIT 10000,20)频繁中断,而设太大又失去意义——建议从 3000–10000 毫秒起步,在监控中观察 Aborted_clients 和错误日志中的中断频次再调优。











