wait_timeout仅控制连接空闲超时,不中断SQL执行;真正终止慢查询需用max_execution_time,且仅对SELECT生效。

wait_timeout 不控制 SQL 执行,只管连接空闲
很多人看到名字就以为 wait_timeout 能让慢查询自动中断,其实完全不是。它只在连接**没有任何网络收发动作**时倒计时——只要客户端发了一条 SQL(哪怕只是 SELECT 1),计时器就重置;SQL 执行再久(比如扫描千万行、做复杂 JOIN),只要中间没断开,wait_timeout 就一直不触发。
- 它生效的前提是:连接建立后,客户端长时间(超过该值)没发任何请求
- 超时后 MySQL 主动断开 TCP 连接,客户端下次复用该连接时会报
MySQL server has gone away或Lost connection to MySQL server during query - 对交互式连接(如
mysql -u root -p命令行)实际走的是interactive_timeout,不是wait_timeout - 云数据库(如阿里云 RDS)可能强制改写该值且禁用
SET GLOBAL,必须查SELECT @@wait_timeout确认真实值
为什么改了 wait_timeout 还是报 “gone away”?
最常见原因是连接池“抢在 MySQL 断连前就把连接干掉了”。比如 HikariCP 的 idleTimeout 设为 30 秒,而 MySQL 的 wait_timeout 是 300 秒——连接池根本等不到 MySQL 动手,自己先驱逐了连接,但没验证有效性,业务取到的仍是已断开的 socket。
- 连接池必须启用验证机制:
connection-test-query=SELECT 1+validation-timeout=3000 -
idleTimeout(HikariCP)或minEvictableIdleTimeMillis(Druid)应比wait_timeout小至少 30 秒,留出检测与网络延迟余量 - 不要依赖
autoReconnect=true:MySQL 5.5+ 已废弃,它不真正重连,只抛异常,还可能破坏事务一致性 - Spring Boot 默认不开启连接验证,需显式配置
spring.datasource.hikari.connection-test-query
真正能中断慢 SQL 的参数是 max_execution_time
如果你要阻止一条 SELECT 跑太久,wait_timeout 完全无效,得用 max_execution_time。它从语句开始执行起计时(含锁等待),超时后服务端直接中止并返回错误:Query execution was interrupted, maximum statement execution time exceeded。
安装、修复、更新或打包一个基于 Python 和 PyMySQL 实现的 Windows `mysql` 命令。适用于用户希望在 PowerShell/CMD 中输入 `mysql` 时重定向到 Python 实现、需要交互式输入 MySQL 连接信息、需要同步到当前用户本地 bin 目录,或需要将该能力封装成可公开复用的 Codex skill。
- 只对
SELECT生效,UPDATE/INSERT/DELETE不识别该限制 - 可用 hint 写在单条语句里:
SELECT /*+ MAX_EXECUTION_TIME(2000) */ * FROM t(单位毫秒) - 会话级设置:
SET SESSION max_execution_time = 2000,但该变量不能写进my.cnf,必须每个连接初始化时手动设 - 注意权限:需要
PROCESS权限,否则 hint 被静默忽略
锁等待超时和执行超时是两回事
别把 innodb_lock_wait_timeout 和 wait_timeout 搞混。前者控制“等行锁多久”,后者控制“连上后多久不说话就踢人”。一个 UPDATE 卡在锁上 3 秒超时,报的是 Lock wait timeout exceeded;同一个 UPDATE 如果锁很快拿到,但自己要处理 10 秒,wait_timeout 依然不会干预,除非这 10 秒里客户端彻底没发任何新请求。
-
innodb_lock_wait_timeout是会话级变量,可临时设小:SET innodb_lock_wait_timeout = 3 - 它只影响锁等待阶段,不影响语句执行逻辑耗时
- 死锁检测由 MySQL 自动触发,和超时无关,错误类型是
Deadlock found when trying to get lock - 真正的“语句总耗时上限”只能靠客户端实现:如 Python 的
conn.set_statement_timeout(3000),或 JDBC 的setQueryTimeout(3)
真正容易被忽略的是:wait_timeout 的值在连接建立那一刻就固定了,后续无论你 SET SESSION wait_timeout = 10 多少次,都不会改变这个连接的空闲倒计时逻辑——它只决定新连接的初始值。

















