You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Spring+Tomcat+PostgreSQL连接槽耗尽问题求助(已配Tomcat连接池)

解决PostgreSQL连接槽耗尽问题(FATAL: remaining connection slots are reserved...)

看起来你遇到了PostgreSQL连接数耗尽的典型问题——数据库的总连接数已经被占满,剩下的连接槽预留给超级用户使用,导致普通应用用户无法建立新连接。结合你的技术栈(Spring 4.1 + Tomcat 8.5.30 + PostgreSQL 9.6)和已配置的Tomcat JDBC连接池,我给你几个具体的排查和解决方向:

1. 先确认数据库端的连接情况

首先要搞清楚数据库的总连接上限和当前实际占用数,这是定位问题的基础:

  • 登录PostgreSQL执行以下SQL:
-- 查看数据库允许的最大连接数
SHOW max_connections;
-- 查看当前所有活跃连接数
SELECT count(*) FROM pg_stat_activity;
-- 查看连接来源(IP/应用),找到占用最多的对象
SELECT client_addr, application_name, count(*) 
FROM pg_stat_activity 
WHERE state = 'active' 
GROUP BY client_addr, application_name;

默认PostgreSQL的max_connections是100,superuser_reserved_connections(留给超级用户的预留连接)默认是3。如果你的Tomcat连接池maxActive=70,再加上其他可能的连接(比如其他应用、数据库工具、maven构建过程中的临时连接),很容易接近或达到100的上限。

2. 检查Tomcat连接池的配置有效性和连接泄漏

你已经配置了Tomcat JDBC连接池的removeAbandonedlogAbandoned等参数,接下来要验证这些配置是否真的在工作:

  • 查看Tomcat的日志文件,找有没有包含AbandonedConnection关键字的日志。如果有,日志会告诉你哪个线程、哪个代码位置没有正确释放连接——这就是连接泄漏的源头。
  • 确认连接池的maxActive设置是否合理:建议将maxActive调整为max_connections - superuser_reserved_connections - 其他固定连接数,比如如果数据库max_connections是100,那maxActive设为80左右比较安全,避免占满所有连接槽。
  • 检查minEvictableIdleTimeMillistestWhileIdle的配合:你的配置是30秒空闲回收+空闲时验证,这个没问题,但可以通过JMX查看连接池的统计数据(比如空闲连接数、活跃连接数的变化),确认Tomcat是否在定期回收空闲连接。

3. 排查maven install时的连接累积问题

连续两次maven install出现问题,大概率是旧应用进程没有完全退出,导致旧的连接池还在占用数据库连接:

  • 执行ps aux | grep java(Linux)或打开任务管理器(Windows),看看有没有多余的Tomcat/Java进程。如果有,手动杀掉这些进程,释放它们占用的数据库连接。
  • 检查Tomcat的热部署配置:如果开启了热部署,确保应用卸载时能正确销毁DataSource,释放连接池中的所有连接。如果是Spring配置的DataSource,可以添加destroy-method="close"到bean定义,确保容器销毁时关闭连接池。

4. 代码层面检查连接泄漏

即使使用了连接池,代码中的不当操作也会导致连接泄漏:

  • 确保所有数据库操作都使用try-with-resources语法(Java 7+支持),自动关闭Connection、Statement、ResultSet:
try (Connection conn = dataSource.getConnection();
     PreparedStatement stmt = conn.prepareStatement("SELECT * FROM table");
     ResultSet rs = stmt.executeQuery()) {
    // 处理查询结果
} catch (SQLException e) {
    // 异常处理
}
  • 如果你用的是Spring的JdbcTemplate,它会自动管理连接的获取和释放,尽量避免手动获取Connection的操作,减少泄漏风险。

5. 临时缓解(治标不治本)

如果需要快速恢复服务,可以临时调大PostgreSQL的max_connections参数:

  • 修改postgresql.conf文件中的max_connections值(比如改为200),然后重启PostgreSQL服务。但这只是临时解决,一定要找到连接泄漏的根本原因,否则问题还会复发。

内容的提问来源于stack exchange,提问作者ines farhani

火山引擎 最新活动