生产环境必须将wait_timeout和interactive_timeout设为300秒,因默认28800秒易导致事务锁残留、连接泄漏及资源耗尽;需同步配置应用层连接池maxlifetime、validationquery等参数才能真正规避风险。

生产环境必须把 wait_timeout 和 interactive_timeout 设为 300 秒(5 分钟),否则连接堆积、锁残留、MySQL server has gone away 错误会反复出现。
为什么默认 28800 秒在生产中等于埋雷
MySQL 默认的 wait_timeout=28800 是为本地调试设计的。真实业务里,一个空闲 8 小时的连接大概率已处于异常状态:
- 事务已开启但未提交,持续持有行锁或间隙锁,阻塞其他写操作
- 应用端因网络抖动、GC 停顿或未捕获异常而没关闭连接,连接池复用后直接报
The last packet successfully received from the server was X milliseconds ago - 攻击者可故意维持大量空闲连接,耗尽
max_connections,触发拒绝服务
执行 SHOW PROCESSLIST,如果看到大量 Sleep 状态且 Time > 300 的连接,就是明确的风险信号。
只改 MySQL 服务端参数远远不够
服务端断开连接后,客户端连接池并不知情——它仍会把失效连接当作“健康”分配出去。必须同步调整应用层配置:
-
wait_timeout=300→ 对应 JDBC 连接池(如 HikariCP)设maxLifetime=270000(4.5 分钟),确保连接在被 MySQL 主动 kill 前被池主动回收 -
interactive_timeout=600→ 仅影响mysql命令行等交互式登录,设高一点避免 DBA 忘退出导致连接长期占用 -
connect_timeout=10→ TCP 握手+认证阶段超时,设太大(如 30)会让网络抖动时线程卡死更久 -
innodb_lock_wait_timeout=15→ OLTP 场景推荐值;它不解决死锁,只控制“等锁多久就报错”,设太高会导致Lock wait timeout exceeded日志延迟暴露真实锁热点
JDBC 连接字符串里两个 timeout 绝不能漏
MySQL 服务端超时和 JDBC 驱动层超时是两套独立机制,缺一不可:
-
connectTimeout=5000:单位毫秒,控制建立 TCP 连接最大等待时间;跨云环境建议设到10000,但绝不能超过服务端connect_timeout(单位秒) -
socketTimeout=30000:单位毫秒,控制单次 SQL 执行读写阻塞上限;必须小于应用 HTTP 接口超时(如 Spring Boot 的server.tomcat.connection-timeout),否则会出现“数据库已断开但 HTTP 请求还在等”的级联超时 - 禁用
autoReconnect=true:官方文档明确警告其可能导致事务状态丢失、主从 GTID 不一致;有效性靠validationQuery=SELECT 1+testOnBorrow=true更可靠
最容易被忽略的隐式长事务陷阱
有些事务看似短,实则因代码逻辑或框架行为被意外延长:比如 MyBatis 开启了 transactionManager type="JDBC" 但没显式提交,或 Spring @Transactional 方法内调用了异步任务却未处理异常回滚。这类事务不会触发 wait_timeout,但会持续持有锁——此时 innodb_lock_wait_timeout 才是第一道防线,而它只管“等锁”,不管“持锁”。监控 INFORMATION_SCHEMA.INNODB_TRX 表里的 TRX_STARTED 时间戳,比依赖超时参数更能提前发现隐患。











