mysql连接超时断开主因是服务端wait_timeout和interactive_timeout参数过小,需同步调整二者值并匹配应用层连接池配置,云数据库须通过控制台修改,且不宜盲目设过大以防连接数耗尽。

MySQL 连接超时后报错 Lost connection to MySQL server during query 怎么办
这不是网络问题,大概率是服务端主动断开了空闲连接。MySQL 用两个变量控制这个行为:wait_timeout(普通连接)和 interactive_timeout(交互式连接,比如你用 mysql 命令行连上的那种)。它们默认都是 28800 秒(8 小时),但很多中间件、ORM 或连接池会发 SET SESSION interactive_timeout = ...,导致实际生效的是更短的那个值。
实操建议:
- 先查当前值:
SHOW VARIABLES LIKE '%timeout%';,重点关注wait_timeout和interactive_timeout两行 - 如果应用用的是长连接池(如 Java 的 HikariCP、Python 的 SQLAlchemy + pool),真正起作用的通常是
wait_timeout;命令行或调试工具连的则看interactive_timeout - 别只改一个——这两个值最好设成一样,否则容易因会话类型判断偏差导致意外断连
- 临时修改(重启失效):
SET GLOBAL wait_timeout = 28800; SET GLOBAL interactive_timeout = 28800;(需 SUPER 权限)
永久修改 wait_timeout 必须改配置文件,不是只执行 SQL
SET GLOBAL 只影响当前运行实例,MySQL 重启就回退。要持久化,必须编辑 MySQL 配置文件(通常是 /etc/my.cnf 或 /etc/mysql/mysql.conf.d/mysqld.cnf),在 [mysqld] 段落下加:
wait_timeout = 28800 interactive_timeout = 28800
注意:
- 改完必须重启 MySQL(
systemctl restart mysql或service mysqld restart),光 reload 不生效 - 某些云数据库(如阿里云 RDS、腾讯云 CDB)不开放配置文件修改权限,只能通过控制台参数模板调整,且可能有取值范围限制(比如最小 10 秒,最大 31536000 秒)
- 如果配置里已存在这两项但被注释了,取消注释即可;不要重复写,否则启动失败
应用层也要配合:连接池的 maxLifetime 和 idleTimeout 别比 MySQL 超时还长
就算把 MySQL 的 wait_timeout 改到 24 小时,如果连接池自己设了 maxLifetime=1800(30 分钟),那连接早就在池子里被回收了,MySQL 根本没机会超时。典型冲突场景:
- HikariCP 的
maxLifetime默认是 1800000(30 分钟),若 MySQL 设了 7200(2 小时),它会先一步销毁连接 - Druid 的
minEvictableIdleTimeMillis如果设得比wait_timeout小,连接会被池提前踢出,再获取时可能遇到Connection reset - Node.js 的
mysql2池默认waitForConnections = true,但没设acquireTimeout的话,超时错误会卡在应用层,看不出是 MySQL 断的还是池子卡的
wait_timeout 设太大有风险,不是越大越好
超时时间拉太长,会导致大量“假空闲”连接长期占着 max_connections 名额,尤其在突发流量后连接没及时释放,下次请求可能直接被拒绝(Too many connections)。
稳妥做法:
- 先观察真实空闲连接时长:查
SHOW PROCESSLIST;,看Time列里长时间为非零值的连接多不多 - 业务能接受 5~10 分钟空闲就断,就设
wait_timeout = 600;别盲目设成 86400(24 小时) - 如果用的是 Serverless 数据库或连接数昂贵的托管服务,更建议保持默认或略调高,靠应用层心跳保活(比如每 30 秒发个
SELECT 1)
最常被忽略的一点:有些 ORM(如 Django 的 CONN_MAX_AGE)或框架(如 Laravel 的 mysql.persistent)会接管连接生命周期,此时 MySQL 层的 timeout 只是兜底,优先级其实低于应用配置。











