wait_timeout 是 mysql 服务端断开空闲连接的超时参数,仅作用于非交互式连接;修改后新连接生效,已存在连接沿用旧值;需配合连接池的空闲检测(如 hikaricp 的 idle-timeout)协同配置,否则仍会因时间差导致“mysql server has gone away”。

wait_timeout 是什么,改它真能断开空闲连接?
是的,wait_timeout 控制的是 MySQL 服务端对**空闲连接**的等待上限。一旦客户端没发任何请求(包括心跳),超过这个秒数,MySQL 就主动 KILL 连接。但注意:它只影响非交互式连接(比如应用服务器用 JDBC/ORM 建的连接),交互式连接(如 mysql 命令行)走的是 interactive_timeout,俩参数默认值还可能不同。
- 常见错误现象:
MySQL server has gone away错误频繁出现,但日志里查不到明显 crash 或网络中断,大概率是连接空闲太久被服务端单方面断开了 - 修改后不会立即生效所有连接——已建立的连接仍按旧值计时;新连接才用新配置
- 别只调大不设限:设成 24 小时(86400)看似稳妥,但会堆积大量僵尸连接,拖慢
SHOW PROCESSLIST、增加线程开销
怎么改 wait_timeout:会话级、全局级、配置文件级的区别
三种改法作用范围和持久性完全不同,选错等于白改。
- 会话级(临时):
SET SESSION wait_timeout = 300;—— 只影响当前连接,退出重连就失效,适合调试验证 - 全局级(重启前有效):
SET GLOBAL wait_timeout = 300;—— 影响后续所有新连接,但 MySQL 重启后恢复默认值(通常 28800 秒) - 配置文件级(永久):在
my.cnf的[mysqld]段落下加一行wait_timeout = 300,然后重启 MySQL。这是生产环境唯一推荐的方式 - 注意:
SET GLOBAL需要SUPER权限;配置文件修改后必须重启,光 reload 不生效
Java 应用连不上?光调 wait_timeout 不够,还得看连接池
很多 Java 项目用 HikariCP、Druid 等连接池,它们自己也管连接生命周期。如果池子没配检测机制,即使 MySQL 断了,应用还在用“假连接”,照样报错。
- 典型症状:MySQL 日志显示连接被
wait_timeout干掉,但应用日志里还是持续报Connection closed或执行失败 - HikariCP 必须配:
connection-test-query=SELECT 1(MySQL 8.0.22+ 改用connection-init-sql) +validation-timeout=3000+idle-timeout=300000(建议略小于wait_timeout) - Druid 要开:
testWhileIdle=true+timeBetweenEvictionRunsMillis=60000+minEvictableIdleTimeMillis=300000 - 关键点:连接池的空闲检查间隔,必须比
wait_timeout小至少 30 秒,否则永远赶不上服务端断连节奏
改完怎么确认生效?别只信 SHOW VARIABLES
SHOW VARIABLES LIKE 'wait_timeout'; 看到的是当前全局值,不代表你手里的连接真按这值跑。得从连接本身查。
- 先查当前连接 ID:
SELECT CONNECTION_ID(); - 再查这个连接实际用的超时值:
SELECT @@wait_timeout;(会话级变量,反映该连接启动时继承的值) - 如果应用刚重启,
@@wait_timeout和全局值一致;但如果连接复用很久,它可能还是旧值 - 最准的验证方式:起一个新连接,等它空闲超过你设的新阈值(比如 5 分钟),再发个查询——应该收到
MySQL server has gone away,而不是成功返回
真正麻烦的不是改参数,而是上下游时间不一致:MySQL 设了 300 秒,连接池设了 600 秒空闲检查,中间件又缓存了连接句柄……断连问题最后总卡在时间差那几秒里。











