java应用连mysql报communicationsexception且含interactive_timeout字样,实为mysql服务端主动断开空闲连接;须同步配置wait_timeout与interactive_timeout,并匹配连接池空闲策略。

Java 应用连 MySQL 报 CommunicationsException 或 Lost connection to MySQL server,且错误里带 interactive_timeout 字样,基本不是网络问题,而是 MySQL 服务端主动断开了空闲连接 —— 你得同步调 wait_timeout 和连接池的空闲策略,光改一边没用。
为什么改了 interactive_timeout 还报错?
因为 JDBC 连接默认是非交互式(non-interactive)的,走的是 wait_timeout 而非 interactive_timeout。但这两个变量在会话初始化时会互相影响:wait_timeout 的初始值,取决于客户端类型和全局 interactive_timeout 的设置。所以只改其中一个,可能被覆盖或不生效。
- 用
show variables like '%timeout%'查到的两个值必须一致,否则说明配置未加载成功 - 临时命令
set global wait_timeout = 86400不会自动同步interactive_timeout,得显式设两次 - MySQL 重启后,如果配置文件没写全,
wait_timeout会回落到默认 28800(8 小时),而你的连接池可能设了 10 小时空闲,必然断连
my.cnf 里必须同时配 wait_timeout 和 interactive_timeout
Linux 下编辑 /etc/my.cnf,Windows 下是 %MYSQL_HOME%\my.ini,在 [mysqld] 段下写:
wait_timeout = 31536000 interactive_timeout = 31536000
注意:wait_timeout 最大值 Linux 是 31536000(365 天),Windows 是 2147483(约 24.8 天),别超限;设完必须重启 MySQL 服务,systemctl restart mysqld 或 Windows 服务管理器里重启,光 reload 不生效。
- 不要用
set global临时改 —— 应用重启、MySQL 重启后就丢 - 阿里云 RDS 等托管服务不开放配置文件修改,只能通过控制台参数模板调整,且需确认该参数可动态修改(
wait_timeout在多数 RDS 版本中支持在线修改) - 改完立刻执行
show global variables like '%timeout%'验证,不能只信配置文件内容
HikariCP 连接池必须开启连接有效性检测
即使 MySQL 端 timeout 设得很长,连接池若长期复用一个连接,中间经过防火墙、NAT、代理等设备,仍可能被静默断开。HikariCP 默认不验证连接有效性,得手动配:
-
connection-test-query=SELECT 1(MySQL 8.0.19+ 推荐用isValid(),所以更推荐下面这条) -
connection-test-query=/* ping */ SELECT 1是兼容性更好的写法 -
test-on-borrow=false(废弃,HikariCP 5+ 不再支持)→ 改用validation-timeout=3000+keepalive-time=30000 - 关键参数:
keepalive-time=30000(每 30 秒发一次保活 ping) +max-lifetime=35000000(略小于 MySQL 的wait_timeout,比如设 35000000 ≈ 405 天,留出缓冲)
Spring Boot 中示例配置:
spring:
datasource:
hikari:
keepalive-time: 30000
max-lifetime: 35000000
validation-timeout: 3000
connection-test-query: "/* ping */ SELECT 1"
jdbc url 里加 autoReconnect=true 已无效,别再用了
MySQL Connector/J 5.1.39+ 和 8.x 完全移除了 autoReconnect 行为,文档明确标注为“deprecated and ignored”。你在 URL 里写 jdbc:mysql://x?autoReconnect=true&failOverReadOnly=false,驱动根本不会处理,还可能掩盖真实问题。
- 真正有效的重连机制,由连接池自己实现(如 HikariCP 的
connection-timeout+ 异常后重建) -
useSSL=false或serverTimezone=UTC这类参数可以保留,但autoReconnect必须删掉 - 如果看到老项目里还留着这个参数,优先排查是否因它导致连接异常后没有抛出真实错误,而是静默失败
最易被忽略的一点:MySQL 的 wait_timeout 是按「最后一次收到包」算的,不是按「最后一次执行 SQL」。如果应用层有长事务、大结果集流式读取、或者用了 Statement.setFetchSize(Integer.MIN_VALUE),期间没有网络包来回,也可能提前触发超时 —— 这时候调大 timeout 不治本,得优化 SQL 或分页逻辑。











