Cause: java.sql.SQLException: connection closed问题排查、解决

connection closed 获取到的连接已经失效,导致抛出异常:
message:com.framework.smart.admin.common.exception.AdminExceptionHandler.handleException:76 - 【exception】:

org.springframework.jdbc.UncategorizedSQLException:

Error querying database. Cause: java.sql.SQLException: connection closed

The error may exist in URL [jar:file:/usr/local/smart-admin/smart-admin.jar!/BOOT-INF/lib/smart-admin-service-0.0.1-SNAPSHOT.jar!/mapper/MmChanceMapper.xml]

The error may involve com.framework.smart.admin.service.mapper.MmChanceMapper.selectChanceReport_COUNT

The error occurred while executing a query

SQL: SELECT count(0) FROM mm_chance WHERE state BETWEEN 0 AND 1 AND is_deleted = 0

Cause: java.sql.SQLException: connection closed

; uncategorized SQLException; SQL state [null]; error code [0]; connection closed; nested exception is java.sql.SQLException: connection closed
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:89)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81)…

Caused by: java.sql.SQLException: connection closed
at com.alibaba.druid.pool.DruidPooledConnection.checkStateInternal(DruidPooledConnection.java:1163)
at com.alibaba.druid.pool.DruidPooledConnection.checkState(DruidPooledConnection.java:1154)
at com.alibaba.druid.pool.DruidPooledConnection.prepareStatement(DruidPooledConnection.java:337)

1.testOnBorrow含义
testOnBorrow:如果为true(默认为false),当应用向连接池申请连接时,连接池会判断这条连接是否是可用的。

testOnBorrow=false可能导致问题
假如连接池中的连接被数据库关闭了,应用通过连接池ge tConnection时,都可能获取到这些不可用的连接,且这些连接如果不被其他线程回收的话;它们不会被连接池废除,也不会重新被创建,占用了连接池的名额,项目如果是服务端,数据库链接被关闭,客户端调用服务端就会出现大量的timeout,客户端设置了超时时间,会主动断开,服务端就会出现close_wait。

连接池如何判断连接是否有效的?
常用数据库:使用${DBNAME}ValidConnectionChecker进行判断,比如Mysql数据库,使用MySqlValidConnectionChecker的isValidConnection进行判断
其他数据库:则使用validationQuery判断
验证不通过则会直接关闭连接,并重新从连接池获取下一条连接。
综上:
<1>.testOnBorrow能够确保我们每次都能获取到可用的连接,但是如果设置为true,则每次获取连接时候都要到数据库验证连接有效性,这在高并发的时候会造成性能下降,可以将testOnBorrow设置成false,testWhileIdle设置成true这样能获得比较好的性能。

<2>.testOnBorrow和testOnReturn在生产环境一般是不开启的,主要是性能考虑。失效连接主要通过testWhileIdle保证,如果获取到了不可用的数据库连接,一般由应用处理异常。

TestOnBorrow什么时候会用到?

这个参数主要在DruidDataSource的getConnection方法中用到
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
连接池是如何判断连接是否有效的?
如果是常用的数据库,则使用${DBNAME}ValidConnectionChecker进行判断,比如Mysql数据库,使用MySqlValidConnectionChecker的isValidConnection进行判断;
如果是其他数据库,则使用validationQuery判断;
在这里插入图片描述

如果验证不通过怎么办?
验证不通过则会直接关闭该连接,并重新从连接池获取下一条连接;
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

获取到连接后:在DruidPooledConnection中

在这里插入图片描述
testOnBorrow能够确保我们每次都能获取到可用的连接,但如果设置成true,则每次获取连接的时候都要到数据库验证连接有效性,这在高并发的时候会造成性能下降,可以将testOnBorrow设成false,testWhileIdle设置成true这样能获得比较好的性能。

validationQuery是什么意思?
validationQuery:Druid用来测试连接是否可用的SQL语句,默认值每种数据库都不相同:
Mysql:SELECT 1;
SQLSERVER:SELECT 1;
ORACLE:SELECT ‘x’ FROM DUAL;
PostGresql:SELECT ‘x’;

validationQuery什么时候会起作用?
当Druid遇到testWhileIdle,testOnBorrow,testOnReturn时,就会验证连接的有效性,验证规则如下:
如果有相关数据库的ValidConnectionChecker,则使用ValidConnectionChecker验证(Druid提供常用数据库的ValidConnectionChecker,包括MSSQLValidConnectionChecker,MySqlValidConnectionChecker,OracleValidConnectionChecker,PGValidConnectionChecker);

如果没有ValidConnectionChecker,则直接使用validationQuery验证;

ValidConnectionChecker是如何验证的?
MySqlValidConnectionChecker会使用Mysql独有的ping方式进行验证,其他数据库其实也都是使用validationQuery进行验证

MySqlValidConnectionChecker验证方式如上图;不同数据库的默认值不同;
如果是Mysql数据库,则validationQuery不会起作用,Mysql会使用ping的方式验证;

<think>好的,我现在需要解决用户遇到的HikariDataSource关闭后无法获取JDBC连接的问题,具体错误是org.springframework.jdbc.CannotGetJdbcConnectionException。首先,我得仔细分析可能的原因,然后根据用户提供的引用信息来寻找解决方案。 根据用户提供的引用[1],错误信息明确提到HikariDataSource已经被关闭,导致无法获取数据库连接。这可能发生在数据源被显式关闭后,或者在应用关闭过程中尝试访问数据库的情况下。需要检查是否有代码主动调用了close()方法,或者在配置中设置了自动关闭。 引用[2]提到在Spring Web启动失败后,进程无法结束,并且一直报数据库连接失败的问题。用户尝试在启动类的main方法中启动线程,但可能因为应用启动失败导致数据源未正确初始化就被关闭了。这说明应用启动顺序或生命周期管理可能存在问题,需要确保数据源初始化完成后再进行其他操作。 引用[3]指出百度云服务器可能会休眠未活跃的服务,导致连接被中断。这种情况下,可能需要调整服务器配置或增加心跳机制保持连接活跃。 接下来,我需要综合这些信息,整理出可行的解决方案。可能的解决方案包括检查数据源配置、确保应用正确关闭、处理服务器休眠策略等。同时,需要验证这些方案的合理性和实施步骤,确保用户能够逐步操作解决问题。</think>### 解决方案:HikariDataSource关闭导致无法获取JDBC连接 #### 1. **检查数据源关闭原因** - **显式关闭调用**:排查代码中是否主动调用了`HikariDataSource.close()`方法。例如,在`@PreDestroy`方法或手动关闭上下文的逻辑中误操作了数据源[^1]。 - **配置问题**:检查`application.properties`中是否配置了`spring.datasource.hikari.allow-pool-suspension=false`(默认值),若设置为`true`可能导致连接池异常关闭。 #### 2. **处理应用生命周期** - **启动失败后资源释放**:若Spring Boot启动失败(如端口冲突),需确保未初始化的数据源不会残留。可通过在启动类中增加异常捕获逻辑,强制释放资源: ```java public static void main(String[] args) { try { SpringApplication.run(XxxxApplication.class, args); } catch (Exception e) { // 记录日志并关闭已初始化的资源 if (HikariDataSourceHolder.getDataSource() != null) { HikariDataSourceHolder.getDataSource().close(); } System.exit(1); } } ``` - **避免在启动失败后执行依赖代码**:如引用[2]中提到的线程启动逻辑,应在确认Spring上下文加载成功后再执行: ```java @SpringBootApplication public class XxxxApplication { public static void main(String[] args) { ConfigurableApplicationContext context = SpringApplication.run(XxxxApplication.class, args); startAutoUpdateThread(context); // 通过上下文获取Bean } } ``` #### 3. **应对服务器休眠策略** - **保持数据库连接活跃**:针对引用[3]中服务器休眠问题,配置HikariCP的保活参数: ```properties spring.datasource.hikari.keepaliveTime=30000 # 每30秒发送心跳 spring.datasource.hikari.max-lifetime=1800000 # 连接最大存活时间30分钟 ``` - **服务器端优化**:联系云服务提供商调整休眠策略,或部署定时任务定期访问服务以维持活跃状态。 #### 4. **验证数据源状态** - **注入DataSource并检查**:在关键代码段中验证数据源是否已关闭: ```java @Autowired private DataSource dataSource; public void checkDataSource() { if (dataSource instanceof HikariDataSource) { HikariDataSource hikariDS = (HikariDataSource) dataSource; if (hikariDS.isClosed()) { throw new IllegalStateException("数据源已关闭!"); } } } ``` #### 5. **日志与监控** - **启用HikariCP日志**:在`application.properties`中添加: ```properties logging.level.com.zaxxer.hikari=DEBUG ``` - **监控连接池状态**:通过HikariCP的`HikariPoolMXBean`实时获取活跃连接数、空闲连接数等指标。 --- ### 相关问题 1. **如何配置HikariCP连接池参数以优化性能?** 2. **Spring Boot启动失败时如何优雅释放资源?** 3. **云服务器休眠导致服务不可用有哪些通用解决方案?** [^1]: 错误信息表明数据源被关闭后仍尝试获取连接 [^2]: 启动失败后的线程管理问题可能导致资源未正确初始化 [^3]: 服务器休眠策略可能中断数据库连接
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值