MySQL空闲连接超时由wait_timeout参数控制,它决定非交互式连接空闲多久后被服务端断开;交互式连接受interactive_timeout控制,但业务连接通常遵循wait_timeout。

MySQL空闲连接超时由哪个参数控制
核心是 wait_timeout,它决定非交互式连接(比如应用通过 JDBC、PyMySQL、mysqlclient 建立的连接)空闲多久后被服务端主动断开。交互式连接(如你手动敲 mysql -u root -p 进去的)受 interactive_timeout 控制,但绝大多数业务连接都走 wait_timeout。
注意:这个值只影响「已建立但不再发请求」的连接,不干预正在执行的查询或事务。设太小会导致连接频繁中断;设太大则堆积大量僵尸连接,拖慢 SHOW PROCESSLIST、占用线程资源、甚至触发 max_connections 限制。
-
wait_timeout默认值通常是 28800 秒(8 小时),生产环境一般要调低到 300–1800 秒(5–30 分钟) - 修改后仅对新建立的连接生效,已有连接仍沿用旧值
- 必须在 MySQL 服务端配置(
my.cnf或启动时指定),不能靠客户端 SET 修改持久化
如何安全设置 wait_timeout 并避免应用报错
直接改全局 wait_timeout 很危险——如果应用连接池没配好心跳或回收策略,连接会在池里“悄无声息”断掉,下次取出就抛 Lost connection to MySQL server during query 或 MySQL server has gone away。
真正可行的做法是「服务端 + 客户端协同」:
- 服务端设合理值,例如在
/etc/my.cnf的[mysqld]段加:wait_timeout = 600
- 客户端连接池必须开启连接验证(如 HikariCP 的
connection-test-query=SELECT 1或validation-timeout) - 连接池最大空闲时间(如
max-idle-time)应略小于wait_timeout,留出网络延迟余量 - 避免应用层手动
SET SESSION wait_timeout = ...,这容易绕过统一管控且难以审计
如何确认哪些用户/应用受空闲超时影响
不是所有账号都需要一样严格的超时策略。DBA 往往想给监控账号、备份脚本、ETL 工具单独放宽,而普通业务账号收紧。这时得靠账号级权限配合:
- MySQL 5.7+ 支持
CREATE USER 'app'@'%' WITH MAX_CONNECTIONS_PER_HOUR 0 MAX_QUERIES_PER_HOUR 0 MAX_UPDATES_PER_HOUR 0 MAX_USER_CONNECTIONS 0;,但注意:它不控制空闲超时 - 真正能按账号设超时的是
ALTER USER ... ATTRIBUTE(8.0.19+)或更早的「账号级变量」方案(需配合init_connect) - 最稳的方式:用不同账号连接,再在
init_connect里根据USER()动态 SET SESSION wait_timeout —— 但要求该账号有SYSTEM_VARIABLES_ADMIN权限,且init_connect本身不能出错,否则用户连不进 - 查当前活跃连接的空闲时长:用
SELECT ID, USER, HOST, COMMAND, TIME, STATE FROM INFORMATION_SCHEMA.PROCESSLIST WHERE COMMAND != 'Sleep' OR TIME > 300;
清理后为什么 SHOW PROCESSLIST 还看到 Sleep 连接
常见误解:改了 wait_timeout 就立刻杀掉所有空闲连接。实际不会——MySQL 只在「下一次检查该连接是否超时」时才断开,检查频率由内部定时器控制(通常几秒一次),不是实时的。
所以你会看到:配置已生效,但 SHOW PROCESSLIST 里仍有 Sleep 状态且 TIME 值大于新 wait_timeout。这是正常现象,只要后续没新请求,它会在下次检查周期内消失。
- 强制立即清理可用
KILL [CONNECTION] id,但别批量 KILL,尤其别 KILLCommand=Query的连接 - 想观察效果,用
SELECT SLEEP(61)开个连接,等 61 秒后再查PROCESSLIST,看它是否自动消失 - 某些云厂商 RDS(如阿里云 PolarDB)会额外加一层代理超时,优先级可能高于 MySQL 自身
wait_timeout,得查对应控制台文档











