max_execution_time是会话级SELECT超时限制,设0禁用,非零值可SET SESSION覆盖;需SET GLOBAL生效且要求SUPER权限;错误码1969表示被主动中断,非网络断开;须协同调整wait_timeout防误判。
MySQL 5.7+ 中 max_execution_time 是会话级限制,不是全局“开关”
这个配置只对 select 查询生效,且仅在服务器端强制中断执行超过阈值的语句;insert/update/delete 不受它控制。设成 0 表示禁用超时(但不推荐),设成非零值后,每个新连接默认继承全局值,但客户端可随时用 set session max_execution_time = n 覆盖。
常见错误是以为改了 my.cnf 里的 max_execution_time = 30000 就一劳永逸——其实需要重启 MySQL 或执行 SET GLOBAL max_execution_time = 30000 才生效,而后者对已存在的连接无效。
- 全局设置需
SET GLOBAL max_execution_time = 30000(要求 SUPER 权限) - 会话级覆盖更安全:
SET SESSION max_execution_time = 60000 - 某些 ORM(如 Django 的
raw())或连接池(如 HikariCP)可能复用连接,导致旧会话仍沿用旧值
超时触发时返回的错误是 Query execution was interrupted, maximum statement execution time exceeded
这不是网络超时或连接断开,而是 MySQL 主动 kill 掉正在执行的 SELECT 线程。错误码为 1969,和 ERROR 2013 (HY000): Lost connection to MySQL server during query 容易混淆——后者通常是网络或服务器崩溃,前者才是 max_execution_time 在起作用。
如果你在监控里看到大量 1969 错误,先确认是不是慢查询本身没优化,而不是急着调高阈值。盲目加大 max_execution_time 可能让一个低效 JOIN 占满线程资源数分钟。
- 查当前会话值:
SELECT @@session.max_execution_time - 查线程是否被超时中断:
SHOW PROCESSLIST中看State列是否为Killed - 配合
slow_query_log和long_query_time对比分析,区分是“真慢”还是“被砍”
PHP PDO 和 Python PyMySQL 默认不自动设置会话级 max_execution_time
连接建立后,它们不会帮你发 SET SESSION 命令。如果你的应用有固定几类长耗时报表查询,得在执行前显式设置,而不是依赖全局值。
比如 PHP 中用 PDO 执行报表前要加一句:$pdo->exec("SET SESSION max_execution_time = 120000");Python PyMySQL 同理,在 cursor.execute() 前调用 conn.cursor().execute("SET SESSION max_execution_time = 120000")。
- 别在连接字符串里加
?max_execution_time=120000—— MySQL 协议不支持这种参数传递方式 - 使用连接池时,确保每次从池中取出连接后都重置该变量,避免被上一个请求污染
- Node.js 的
mysql2同样需要手动connection.query('SET SESSION max_execution_time = ...')
调整后仍超时?检查是不是被 wait_timeout 或 interactive_timeout 先干掉了
max_execution_time 控制单条语句执行时长,而 wait_timeout 控制空闲连接存活时间。如果一条 SQL 执行到 59 秒时卡在磁盘 I/O,连接却已在 60 秒整被 wait_timeout 断开,错误日志里显示的就不是 1969,而是 MySQL server has gone away(错误码 2006)。
这类问题容易误判:你调大了 max_execution_time,但忘了同步调高 wait_timeout,结果还是失败。两者必须协同调整,尤其在批量导出、ETL 场景下。
- 查当前值:
SELECT @@wait_timeout, @@interactive_timeout, @@max_execution_time - 临时提高空闲超时:
SET SESSION wait_timeout = 300(注意单位是秒) - Docker 或云数据库(如 RDS)可能锁定部分系统变量,
SET GLOBAL会报错,此时只能靠会话级设置 + 应用层重试










