mysql客户端连接空闲超时由服务端wait_timeout和interactive_timeout共同决定,必须两者同步设为相同值并写入my.cnf的[mysqld]段后重启生效;jdbc等客户端配置connecttimeout或sockettimeout仅影响连接建立或查询阶段,无法控制空闲断开。

MySQL 客户端连接超时不是由客户端自己“设”出来的,而是由服务端的 wait_timeout 和 interactive_timeout 决定的——你改错地方,客户端再怎么配都白搭。
为什么改 JDBC 的 connectTimeout 没用?
很多开发者在 URL 里加 connectTimeout=5000 或设 socketTimeout,结果还是报 MySQL server has gone away。这是因为这些参数只管「建立连接那几秒」,不管连接建好后空闲多久被 MySQL 主动 kill。
-
connectTimeout:TCP 握手 + 认证阶段超时,防慢连,和空闲断开无关 -
socketTimeout(或readTimeout):查询执行中读响应超时,比如大结果集卡住 - 真正决定「连接活多久」的是服务端的
wait_timeout,且它对绝大多数应用生效
必须同步设置 wait_timeout 和 interactive_timeout
这两个值不一致,会导致诡异行为:JDBC 连接可能继承了 interactive_timeout 的旧值(比如默认 28800),而你只改了 wait_timeout,结果连接池里的连接照常活 8 小时,但你预期是 10 分钟——然后某天凌晨第一批请求就崩。
- 所有新连接初始化时,会按客户端类型选其一作为会话级
wait_timeout值 - 非交互式连接(JDBC、ORM、Web 应用)默认用
interactive_timeout初始化,不是wait_timeout - 所以必须两个都设,且设成相同值:比如
wait_timeout = 600和interactive_timeout = 600 - 永久生效只能写进配置文件:
/etc/my.cnf或C:\ProgramData\MySQL\MySQL Server 8.0\my.ini的[mysqld]段
改完不重启,等于没改
SET GLOBAL wait_timeout = 600 看似立刻生效,但只影响后续新建连接;已存在的连接仍按老值计时,且 MySQL 8.0 多数版本不支持 reload 生效,必须重启服务。
- Linux:
systemctl restart mysqld - Windows:
net stop mysql && net start mysql -
connect_timeout更绝——它根本不能SET GLOBAL,只读,必须改配置+重启 - 验证是否真生效:
SHOW GLOBAL VARIABLES LIKE '%timeout%',重点看三行:wait_timeout、interactive_timeout、connect_timeout
应用层连接池不配合,照样出错
MySQL 设成 600 秒,但 HikariCP 的 maxLifetime 是 1800 秒,或者 Druid 的 timeBetweenEvictionRunsMillis 是 60000(1 分钟检测一次),池子里的连接早被 MySQL kill 了,取出来直接报错。
- HikariCP:
idleTimeout建议 ≤wait_timeout - 30,比如 MySQL 设 600,这里设 570 - Druid:
testWhileIdle=true+timeBetweenEvictionRunsMillis=30000(30 秒检查一次) - PyMySQL:
ping(True)开启自动探活,别依赖autocommit=True来“假装”连接还活着 - 验证连接有效性比调超时数字更重要——光设时间,不验连接,等于埋雷
最常被忽略的点:改完参数后不去查 PROCESSLIST,不知道有没有连接真按新值断开;也不看连接池日志,不确定它是不是在 MySQL 断开前就主动回收了。空闲连接是否归零,得靠数据说话,不是靠配置文件里写了就完事。











