MySQL连接被服务端主动断开的主因是TCP Keepalive未生效或配置不当,导致中间设备先于MySQL清空连接;需同步调优Linux内核参数、MySQL超时设置及客户端连接池生命周期。

MySQL连接被服务端主动断开的典型现象
执行查询时突然报错 Lost connection to MySQL server during query,或者应用日志里频繁出现 MySQL server has gone away —— 这往往不是网络闪断,而是服务端主动关闭了空闲连接。
根本原因在于 MySQL 的 wait_timeout 和 interactive_timeout 默认值(通常 28800 秒,即 8 小时),但更隐蔽的问题常出在 TCP 层:Linux 内核的 tcp_keepalive_time 默认是 7200 秒(2 小时),远小于 MySQL 的超时,导致中间设备(如 NAT、防火墙)先清掉了连接,而 MySQL 还不知道。
无序列表呈现关键判断点:
- 如果异常集中在空闲 1–2 小时后,大概率是 TCP Keepalive 未生效或配置过长
- 如果连接刚建好就断,优先查客户端连接池配置(比如
maxLifetime设得太短) -
SHOW VARIABLES LIKE 'wait_timeout';查到的值 ≠ 实际生效值,它受客户端连接时的interactive标志影响
检查并设置 Linux 系统级 TCP Keepalive 参数
MySQL 本身不控制 TCP Keepalive,完全依赖操作系统。必须在运行 mysqld 的服务器上调整内核参数,否则改 MySQL 配置没用。
检查当前值:
cat /proc/sys/net/ipv4/tcp_keepalive_time cat /proc/sys/net/ipv4/tcp_keepalive_intvl cat /proc/sys/net/ipv4/tcp_keepalive_probes
推荐设置(写入 /etc/sysctl.conf 并执行 sysctl -p):
-
net.ipv4.tcp_keepalive_time = 600(连接空闲 10 分钟后开始发探测包) -
net.ipv4.tcp_keepalive_intvl = 60(每次探测间隔 60 秒) -
net.ipv4.tcp_keepalive_probes = 3(连续 3 次无响应才断连)
注意:tcp_keepalive_time 必须显著小于 MySQL 的 wait_timeout,否则探测还没开始,连接就被 MySQL 自己关了。
验证 MySQL 是否真的启用了 TCP Keepalive
MySQL 5.7+ 默认启用 tcp_keepalive,但旧版本或某些编译选项下可能被禁用。不能只信文档,得实测。
方法一:用 ss -i 查看活跃连接的 keepalive 状态
ss -tni | grep :3306
输出中若含 ka 字样(如 skmem:(r0,rb471840,t0,tb471840,f0,w0,o0,bl0,d0) 里的 ka),说明已启用;若没有,需确认 MySQL 编译时是否带 -DENABLED_LOCAL_INFILE=ON 等影响 socket 选项的参数。
方法二:临时修改 MySQL 配置强制开启(仅限 8.0.22+):
- 在
my.cnf的[mysqld]下加tcp_keepalive=ON - 重启后执行
SELECT @@tcp_keepalive;应返回ON
低版本无法通过 SQL 查,只能靠 ss 或抓包确认。
客户端连接池必须配合调整
光调服务端没用。Java 的 HikariCP、Go 的 sql.DB、Python 的 PyMySQL 都有独立的连接生命周期控制,它们可能比 TCP 或 MySQL 更早把连接干掉。
常见坑:
- HikariCP 的
connection-timeout是获取连接的超时,不是连接存活时间;真正管“活多久”的是max-lifetime,建议设为1800000(30 分钟),略小于服务端wait_timeout - PyMySQL 默认不启用
ping,需显式设ping=True且ping_interval=300,否则空闲连接在服务端断开后,客户端还傻等 - Node.js 的 mysql2 支持
enableKeepAlive: true,但必须搭配keepAliveInitialDelay: 300000,否则默认延迟 60 秒太晚
最稳妥的做法:客户端定期 ping + 服务端 TCP Keepalive + MySQL timeout 三者形成梯度,比如 5 分钟 ping、10 分钟 TCP 探测、30 分钟 MySQL 超时。
别指望单点配置解决所有中断。TCP 层看不见应用层心跳,MySQL 不知道中间设备清连接,客户端池又不管网络状态——每个环节都得动,而且得对齐时间尺度。


















