真正控制MySQL连接空闲超时的是wait_timeout(普通应用)和interactive_timeout(仅交互式客户端),绝大多数应用只需调整wait_timeout;默认28800秒过长,建议设为300秒,并同步配置客户端连接池的健康检查。

wait_timeout 和 interactive_timeout 到底该设哪个
MySQL 里真正控制连接空闲超时的,是 wait_timeout 和 interactive_timeout 两个参数,不是 connect_timeout(那是 TCP 握手阶段用的)。普通应用连接默认走 wait_timeout;只有客户端显式声明自己是交互式连接(比如 MySQL CLI 加了 --interactive),才用 interactive_timeout。绝大多数 ORM、连接池、Web 应用发的连接都属于非交互式,所以重点调 wait_timeout 就行。
常见错误现象:应用偶尔报 Lost connection to MySQL server during query 或 MySQL server has gone away,但不是每次必现——往往发生在夜间或低峰期之后第一次请求时,就是这个值太长 + 连接被服务端主动断开导致的。
-
wait_timeout默认值通常是 28800 秒(8 小时),对长连接池来说太长,容易积累僵死连接 -
interactive_timeout默认值一样,但除非你真在写交互式管理工具,否则不用动它 - 修改后只影响新建立的连接,已存在的连接仍按旧值计时
怎么改才不影响线上业务
直接改全局变量风险高:如果设得太小(比如 60 秒),而应用没做连接有效性检测,就会大量触发重连,甚至雪崩。稳妥做法是「服务端配合客户端」一起调。
实操建议:
- 先查当前值:
SHOW VARIABLES LIKE 'wait_timeout'; - 临时调整(重启失效):
SET GLOBAL wait_timeout = 300;(5 分钟,适合验证效果) - 永久生效要改配置文件
/etc/my.cnf或/etc/mysql/mysql.conf.d/mysqld.cnf,在[mysqld]下加一行:wait_timeout = 300 - 改完必须重启 MySQL 或执行
RELOAD(但部分版本不支持动态 reload 此参数,以实际为准)
为什么光调 wait_timeout 还不够
因为客户端连接池(比如 HikariCP、Druid、mysql-connector-python)自己也有连接存活检查逻辑。如果池子以为连接还活着,但 MySQL 已经在 5 分钟后把它关了,下一次取连接就会失败。
必须同步配客户端:
- HikariCP:设
connection-test-query=SELECT 1(MySQL 8.0.22+ 推荐用connection-init-sql)和validation-timeout=3000,再打开test-on-borrow=true或更推荐的test-on-return=true - Druid:开启
testWhileIdle=true,并设timeBetweenEvictionRunsMillis=30000(30 秒检测一次) - Python 的 PyMySQL/MySQLdb:确保使用
ping(True)检测连接,或设autocommit=True避免事务卡住连接
不配客户端的话,wait_timeout 调再准也没用——连接池会把已断开的连接继续塞给业务代码。
超时时间设多少算合理
没有标准答案,取决于你的流量模式和容忍度。300 秒(5 分钟)是目前较通用的平衡点:够长,避免频繁重连;又够短,能及时清理闲置连接。
需要权衡的点:
- 若应用有定时任务拉长连接(比如导出大表),得单独处理——别让这类连接进公共池,或用
SET SESSION wait_timeout = 86400临时延长 - 云数据库(如阿里云 RDS、AWS RDS)可能自带代理层,实际空闲超时可能比你设的
wait_timeout更短,要以SHOW PROCESSLIST中Time列为准观察真实连接存活时长 -
max_connections虽然不直接相关,但如果wait_timeout太大,又没及时回收连接,容易把连接数顶满,引发Too many connections
真正容易被忽略的是:MySQL 的 wait_timeout 是按“最后一条语句执行完毕后”开始倒计时的,不是连接建立时间。如果你的应用在事务里 hold 住连接不做任何操作,那它不会被 timeout 清掉——直到事务提交或回滚后才开始计时。


















