mysql连接超时需协同数据库与应用层解决:数据库端应统一设置wait_timeout和interactive_timeout并写入my.cnf持久生效,应用端须配置连接池maxlifetime、连接验证及jdbc超时参数,否则单改数据库参数无效。

MySQL连接超时不是单个参数能解决的问题,wait_timeout 和 interactive_timeout 只控制“空闲断连”,不等于连接建立失败或查询卡住的超时——它们只在连接已建立、但长时间没发任何语句时才生效。
为什么改了 wait_timeout 还有“MySQL server has gone away”?
因为这个错误通常不是空闲断连导致的,而是连接被服务端主动关闭后,应用层还试图复用该连接。常见原因包括:
-
wait_timeout已生效,但应用连接池(如 HikariCP)没设maxLifetime,导致连接在服务端被杀后仍被取出使用 - 客户端发起大查询,超过
net_read_timeout,服务端中断读取,但应用未捕获异常 - 网络中间件(如 ProxySQL、LVS)有自己的空闲超时,比 MySQL 更早断连
验证是否是 wait_timeout 触发:执行 SHOW PROCESSLIST;,看状态为 Sleep 的连接持续时间是否接近你设的值。
wait_timeout 和 interactive_timeout 必须设成一样吗?
不一定,但强烈建议设成相同值。区别在于:
-
wait_timeout作用于非交互式连接(绝大多数应用连接、脚本、连接池获取的连接) -
interactive_timeout仅影响带CLIENT_INTERACTIVE标志的连接(比如 mysql 命令行加--interactive启动,或 JDBC 中显式设置useSSL=false&requireSSL=false&interactiveClient=true)
问题在于:很多 JDBC 驱动默认不设该标志,但某些 ORM(如旧版 Hibernate)或 Python 的 PyMySQL 在特定条件下会误设,导致同一应用里部分连接走 interactive_timeout,部分走 wait_timeout,行为不一致。所以生产环境统一设为相同值最稳妥。
怎么改才真正生效?重启不是唯一方式
动态修改可用,但要注意权限和范围:
- 需要
SUPER权限才能执行SET GLOBAL wait_timeout = 600; - 动态修改只对新建立的连接生效,已有连接保持原超时值不变
- 重启 MySQL 后,动态修改的值会丢失,必须写入配置文件才持久
配置文件路径常见位置:/etc/my.cnf、/etc/mysql/my.cnf 或 /usr/etc/my.cnf;Windows 下是 my.ini。在 [mysqld] 段下添加:
[mysqld] wait_timeout = 600 interactive_timeout = 600
改完别忘了确认:执行 SHOW VARIABLES LIKE 'wait_timeout';,输出值应与你设的一致。如果仍是 28800,说明配置文件没加载成功(比如路径错、段名错、语法错),或被其他配置覆盖。
应用层不配合,数据库端调再细也没用
数据库只管“我等你多久”,不管“你有没有在用”。真正防超时的关键在应用侧:
- 连接池必须启用连接验证,例如 HikariCP 的
connection-test-query=SELECT 1或validation-timeout=3000 -
maxLifetime应比wait_timeout小至少 60 秒(如wait_timeout=600,则设maxLifetime=540000ms) - JDBC URL 中建议加上
socketTimeout=30000&connectTimeout=5000,分别控制读写和建连超时(单位毫秒)
最容易被忽略的是:wait_timeout 改小后,如果应用没做连接有效性检查,就会在凌晨低峰期批量报错——因为大量连接在空闲中被 MySQL 关闭,而连接池不知道,下次直接扔给业务代码用,一执行就报 “Lost connection to MySQL server during query”。











