数据库连接本质是客户端与数据库之间的会话通道,建立连接是重操作(TCP 三次握手、身份认证、权限加载、初始化会话上下文),不能频繁创建销毁,大部分连接性能问题都围绕:连接创建开销、连接泄漏、连接池配置不合理、长连接 / 短连接误用、网络、事务持有连接这几大块。
1. 频繁创建销毁连接(短连接滥用)
现象
每次执行 SQL 都新建连接,用完直接关闭,不使用连接池。
高并发下大量时间消耗在
TCP握手、认证、权限初始化,CPU 大量消耗在数据库侧处理连接握手。数据库服务器
processlist瞬间大量连接进来又消失,端口大量 TIME_WAIT。
根源
没有连接池,每次业务请求:新建连接→执行 SQL→close。
危害
QPS 稍微上来,数据库就被建连接压垮,SQL 本身很快,但整体响应很慢。
解决
必须使用连接池复用连接,不要裸用短连接。

2. 连接泄漏(最常见线上故障)
拿到连接,没有归还回连接池。
现象
连接池活跃连接数持续上涨,不回落,最终打满最大连接数;
新请求拿不到连接,报:
cannot get connection from pool;数据库侧看到大量 sleep 空闲连接。
泄漏常见场景
代码异常,没有
finally关闭 / 归还连接;老 JDBC 手动写 Connection,异常分支没 close;事务卡住:开启事务之后,异常没有回滚 / 提交,连接一直被事务占有;
框架错误:部分框架异常场景不自动归还连接;
调用外部接口、RPC 的时候,事务内做耗时 IO,连接被长时间占用。
重点误区:不是 SQL 慢叫泄漏,是连接拿出去之后永不归还。
排查
监控连接池指标:活跃连接、空闲连接、等待队列长度。活跃只涨不降基本就是泄漏。
3. 连接池参数配置错误(线上重灾区)
以 HikariCP、Druid 为例,几个核心参数:
核心认知:连接池最大连接不是越大越好。数据库 CPU、锁、buffer 有限,MySQL 单实例通常 maxPoolSize 几十就足够,不是几百上千。 公式参考:
最大连接数 ≈ CPU核心数 * 2 + 磁盘数,业务有慢 SQL 可适当调大,严禁无脑上千。
4. 长连接 vs 短连接误用
长连接(连接池):连接建立后一直复用。优点:省去建连开销;风险:连接会被数据库端 kill(wait_timeout),出现 “死连接”,应用拿到已经断开的连接执行 SQL 报错。 👉 连接池必须配置
maxLifetime小于数据库wait_timeout,定期淘汰旧连接。短连接:用完立刻关闭。适合低频小并发;高并发绝对禁止,会打满 TIME_WAIT,数据库扛不住建连压力。
常见坑:MySQL 设置wait_timeout=8小时,连接池 maxLifetime 没配置,8 小时后池子里全是僵尸连接。
5. 连接被慢事务 / 慢 SQL 长时间占用
连接池连接总数有限,如果一个连接被占住不释放,其他业务就要排队等连接。
现象
连接池活跃连接打满,但没有泄漏;看数据库:大量事务长时间运行,Sleep或者正在执行慢 SQL。 场景:
事务里面写大量业务逻辑、HTTP 调用、RPC、循环大计算;事务没提交,连接死死占用。
慢 SQL 执行几十秒,连接被占用。 后果:业务线程全部阻塞在获取数据库连接,整个服务雪崩,不是数据库挂,是应用拿不到连接。
重要:连接池耗尽 ≠ 数据库 CPU 高。很多时候数据库负载很低,但应用全部超时,根源就是连接被长事务占死。
6. 网络层面带来的连接问题
防火墙、NAT 超时:中间网络设备空闲超时,静默断开 TCP 连接,应用不知情,池子里存在僵尸连接。
网络抖动:丢包,连接半开状态。 解决:连接池的连接检测(testOnBorrow /testWhileIdle),定期校验连接可用性。
testOnBorrow 每次拿连接都校验性能差,生产推荐
testWhileIdle。

7. 数据库侧最大连接数限制
MySQL max_connections参数,数据库全局允许最大会话。
应用连接池总和超过数据库 max_connections → 数据库拒绝新连接,报
Too many connections。很多人只调应用连接池,忘记数据库侧上限。
max_connections 不是越大越好,连接过多内存、锁上下文开销暴涨。
8. 经典故障区分,快速定位
报错:获取连接超时
看连接池活跃连接:打满。
活跃连接不下降:连接泄漏 OR 长事务 / 慢 SQL 占住连接。
活跃连接没打满:并发太高,maxPoolSize 设置太小。
偶发 SQL 报错,通信链路失败:大概率僵尸连接,maxLifetime 配置不对,NAT 防火墙断开空闲连接。
数据库大量新建连接,TIME_WAIT 高:没有连接池,短连接模式。
简单总结记忆
创建连接很重,所以要用连接池复用连接;
连接池两个杀手:连接泄漏、长事务占用连接;
连接池不是越大越好,maxPoolSize 要和数据库能力匹配;
长连接会变成僵尸连接,池子里要设置连接过期时间,小于数据库 wait_timeout;
事务里不要做远程调用、耗时逻辑,连接会被霸占;
监控指标:活跃连接数、空闲连接、获取连接等待队列、数据库当前连接数。
本文原创作者:易君召,详见:https://www.yijunzhao.cn/authors/yijunzhao,转载请注明出处。
原文链接
欢迎访问 小易撩挨踢