“too many connections”本质是连接资源被占满,需优先定位java应用侧的连接泄漏、长事务、慢sql及连接池配置失衡,并协同调优mysql wait_timeout与hikaricp参数。

Java 应用连接 MySQL 时出现“Too many connections”,本质不是数据库挂了,而是连接资源被占满、新请求进不来。解决重点不在调大 max_connections,而在于快速定位“谁占着不放”以及“为什么不放”。以下是实战中高效、可落地的排查与解决路径。
一、先看连接现状:30秒内摸清底数
别急着改配置或 kill 连接,先执行三步诊断:
- 查当前连接总数:
SHOW STATUS LIKE 'Threads_connected';,对比SHOW VARIABLES LIKE 'max_connections';—— 若两者接近(比如 148/151),基本确认打满; - 查活跃会话详情:
SELECT * FROM information_schema.processlist WHERE TIME > 60 ORDER BY TIME DESC LIMIT 20;,重点关注 State(如Locked、Sending data、Updating)、Time(持续秒数)、Info(SQL 片段); - 查来源分布:用系统命令看连接 IP 分布:
ss -ant | grep :3306 | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -rn,若某台应用服务器 IP 出现次数远超其他,大概率是它的问题。
二、重点排查四类 Java 层根因
连接打满,90%以上源于 Java 应用侧未合理释放资源。按优先级逐项检查:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
-
连接泄漏:检查是否有手动获取
Connection后未在finally或 try-with-resources 中关闭;尤其注意异常分支、循环内建连、RPC 调用前后的连接状态; -
长事务未结束:事务开启后调用外部 HTTP 接口、处理大批量数据、或 catch 异常但没 rollback,导致连接卡在
Transaction状态; -
慢 SQL 拖住连接:无索引查询、大表 JOIN、
ORDER BY + LIMIT走文件排序等,让单个连接长时间处于Query状态; -
连接池配置失衡:多个微服务共用同一库,各自设
maxPoolSize=50,叠加超限;或minIdle过高 + MySQLwait_timeout过长(如默认 8 小时),导致大量空闲 Sleep 连接长期滞留。
三、关键配置联动优化
单点调参易失效,需 Java 连接池与 MySQL 参数协同调整:
- MySQL 端:将
wait_timeout和interactive_timeout从默认 28800(8 小时)降至 60–300 秒,让空闲连接自动断开; - HikariCP 示例配置(推荐):
maximumPoolSize=20(避免单实例过度索取)idleTimeout=600000(10 分钟)maxLifetime=1800000(30 分钟,略短于 wait_timeout)connectionTestQuery=SELECT 1(启用连接有效性检测); - 禁止设置
autoReconnect=true,它会掩盖真实连接异常,增加排查难度。
四、加一层监控防复发
光救火不够,要建立可观测性:
- 在应用层埋点:统计连接池
active、idle、pending数,接入 Prometheus + Grafana; - 数据库侧监控:采集
Threads_connected、Max_used_connections、慢查询数量,设置阈值告警(如 > 90% max_connections); - 日志增强:开启 HikariCP 的
debug日志,记录连接获取/归还耗时,定位卡点; - 定期执行:
SELECT * FROM information_schema.processlist WHERE TIME > 300;,作为巡检脚本纳入运维 SOP。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










