MySQL连接频繁断开重连的典型表现是服务端日志出现“Lost connection”、客户端报“server has gone away”、Threads_connected波动剧烈、Aborted_connects上升、CPU和连接开销升高;根本原因包括应用未复用连接、wait_timeout/interactive_timeout过短、中间件主动踢连接及网络不稳定。

MySQL 连接频繁断开重连的典型表现
服务端日志里反复出现 Lost connection to MySQL server during query 或客户端报 MySQL server has gone away;监控看到 Threads_connected 波动剧烈,Aborted_connects 持续上升;QPS 没涨,但 CPU 和连接建立开销明显升高。
根本原因通常是:应用没复用连接、wait_timeout/interactive_timeout 设置过短、中间件或代理(如 ProxySQL、HAProxy)主动踢连接、网络不稳定但重试逻辑粗暴。
PHP PDO / Python PyMySQL / Java JDBC 怎么配长连接
不是加个 PDO::ATTR_PERSISTENT => true 就完事——持久化连接在 PHP-FPM 下实际效果有限,因为 worker 进程重启后连接就丢;PyMySQL 默认不支持真正的长连接,得靠外部连接池;JDBC 则必须关掉 autoReconnect=true(它会掩盖问题,且已废弃)。
- PHP:优先用
mysqlnd驱动 + 连接池中间件(如 mysql-proxy 或自研轻量池),避免依赖PERSISTENT - Python:用
SQLAlchemy配pool_pre_ping=True和pool_recycle=3600,别直接用裸PyMySQL.connect() - Java:HikariCP 是首选,设
connection-timeout=3000、idle-timeout=600000、max-lifetime=1800000,禁用autoReconnect
MySQL 服务端 timeout 参数怎么调才不翻车
wait_timeout 控制非交互式连接空闲超时,默认 28800 秒(8 小时),看着很安全,但若应用层连接池的 maxLifetime 比它长,连接就会在 MySQL 侧被无声 kill,导致下一次 query 直接失败。
正确做法是让服务端和客户端 timeout 形成梯度:
- MySQL 端:把
wait_timeout设为 3600(1 小时),interactive_timeout同步调整(部分客户端会读这个) - 连接池端:设
maxLifetime为 3000(50 分钟),idleTimeout为 600(10 分钟) - 务必在 MySQL 配置文件里改,不要只用
SET GLOBAL,否则重启失效
连接池健康检测该不该开?怎么开才不拖慢请求
不开检测,死连接积压到 query 时才暴露,用户体验断崖式下跌;全量开 ping,每次获取连接都多一次 round-trip,吞吐直接打七折。
折中方案看场景:
- 高并发低延迟服务(如 API 网关):关
pre_ping,开testOnBorrow+ 快速超时(connect_timeout=500) - 后台任务类服务:开
pool_pre_ping=True,但搭配pool_size=5~10控制并发检测数 - 所有情况都要配
validationQuery=SELECT 1,别用SELECT NOW()这种带函数的,MySQL 8.0+ 对其权限校验更严
真正难处理的是跨机房、经 NAT 的连接——TCP keepalive 时间要同步调,Linux 内核参数 net.ipv4.tcp_keepalive_time 建议设为 1200,否则连接可能卡在 ESTABLISHED 却收不到 FIN。











