奇奇怪怪的问题-Druid+Oracle连接超时关闭问题

简介: SpringBoot+Druid+Oracle连接超时关闭问题

记录一下生产环境遇到的问题

生产上的一个程序跑了一段时间后,老是出现 Closed Connection异常,往上追溯错误,发现有关闭连接失败异常

该应用环境:

Oracle + Druid + Spirngboot 2.2.9.RELEASE

先搭建本地环境还原报错

环境搭建

引入依赖

主要是druid oracle springboot依赖

<?xmlversion="1.0" encoding="UTF-8"?><projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.example</groupId><artifactId>demo1</artifactId><version>0.0.1-SNAPSHOT</version><name>demo1</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version><spring.boot-version>2.2.9.RELEASE</spring.boot-version></properties><dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>${spring.boot-version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.2.8</version></dependency><dependency><groupId>com.oracle</groupId><artifactId>ojdbc6</artifactId><version>11.2.0.3</version></dependency><dependency><groupId>tk.mybatis</groupId><artifactId>mapper-spring-boot-starter</artifactId><version>2.1.5</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>



配置文件

#spring:
#profiles:
#active: testspring:
datasource:
driver-class-name: oracle.jdbc.OracleDriverusername: testpassword: testurl: jdbc:oracle:thin:@192.168.164.110:1521:helowintype: com.alibaba.druid.pool.DruidDataSourcedruid:
initial-size: 10max-active: 10validationQuery: SELECT1FROMDUALtestWhileIdle: truetestOnBorrow: falsetestOnReturn: falsebreakAfterAcquireFailure: truetimeBetweenConnectErrorMillis: 30000min-evictable-idle-time-millis: 30000#超过此时间关闭除去最小空闲连接之外超过此时间的空闲连接max-evictable-idle-time-millis: 50000#超过此时间关闭除去所有的空闲连接timeBetweenEvictionRunsMillis: 180000#监测空闲连接的时间间隔min-idle: 4


模拟程序

使用mybatis开发一个定时1s查询一次数据库的程序即可

packagecom.example.demo.controller;
importcom.example.demo.domain.User;
importcom.example.demo.mapper.UserMapper;
importlombok.extern.slf4j.Slf4j;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.scheduling.annotation.Scheduled;
importorg.springframework.web.bind.annotation.RestController;
importjava.util.List;
/*** @Author: Zy* @Date: 2021/11/26 14:55*/@RestController@Slf4jpublicclassTimerTestController {
@AutowiredUserMapperuserMapper;
@Scheduled(cron="*/1 * * * * ?")
publicvoidtest() {
Useruser=newUser();
user.setUserName("test");
List<User>select=userMapper.select(user);
log.info(select.toString());
    }
}




测试

猜想

测试前先对报错原因进行猜想,首先从生产环境的报错位置:

#com.alibaba.druid.util.JdbcUtils$close(Connection x)方法

publicstaticvoidclose(Connectionx) {
if (x!=null) {
try {
x.close();
            } catch (Exceptionvar2) {
LOG.debug("close connection error", var2);
            }
        }
    }


此方法调用时机为关闭druid连接池种的连接时调用,此方法内部再调用Connection.Close方法关闭数据库连接

那么猜想出现此报错的原因是调用Connection.close方法时该数据库连接已关闭,是否是因为已关闭的连接再次调用Close方法导致的问题?

测试

启动应用程序

观察日志,确认每次都查询正常


数据库

查看数据库连接数,发现与服务启动时初始化的druid连接数一致.

select sid, username, paddr, status,program,serial# from v$session t where username ='TEST'and status ='INACTIVE'



杀死数据库连接

为了验证猜想,我们模拟数据库关闭连接,即直接杀掉jdbc连接

-- 生成杀session报文select replace(wm_concat('alter system kill session '''||sid||','||serial#||''';'),',','')from v$session where  username ='TEST'and status ='INACTIVE'and program ='JDBC Thin Client'-- 执行杀死开启的数据库连接



观察应用日志




总结

经过分析,可以得出结论,出现该异常的原因是:

连接池中初始化了大量的空闲连接,这些连接在一段时间后,超过了数据库的连接超时时间,此时数据库就会单方面关闭这些连接,但是应用中连接池中的连接并没有关闭,等到有新的请求到达,从连接池中获取连接时,该连接其实已经被数据库关闭,此时就会出现该错误

或者,druid每隔一段时间,就会对连接池中的连接进行有效性检查,如果该连接超过了配置的空闲连接时间,就会调用JdbcUtils.close()方法,但是该连接已经被数据库关闭了,此时就会报错 closed connection

跟此次问题相关的druid连接池配置详解

min-evictable-idle-time-millis: 30000#超过此时间关闭除去最小空闲连接之外超过此时间的空闲连接max-evictable-idle-time-millis: 50000#超过此时间关闭除去所有的空闲连接timeBetweenEvictionRunsMillis: 180000#监测空闲连接的时间间隔


解决办法

复现了问题,来记录下解决办法

  1. 调整oracle数据库的超时连接配置,配置为无限制
  1. oracle数据库修改用户profiles的idle_time  mysql数据库修改数据库配置 wait_time
  1. 修改druid连接池配置
  1. 调低 timeBetweenEvictionRunsMillis 扫描间隔, 这意味着druid会更频繁的扫描连接池中的无效连接
  2. 调低 min-evictable-idle-time-millis/max-evictable-idle-time-millis  这意味着连接池中的空闲连接在更短的时间内就会被关闭

建议采取第二种方式,原则如下:

timeBetweenEvictionRunsMillis + min-evictable-idle-time-millis < 数据库连接超时时间

max-evictable-idle-time-millis 可以配置的跟 min-evictable-idle-time-millis 一致

目录
相关文章
|
9月前
|
Oracle 关系型数据库 流计算
Flink CDC不支持直接连接到Oracle ADG备库进行数据同步
Flink CDC不支持直接连接到Oracle ADG备库进行数据同步
200 1
|
8月前
|
SQL Oracle 关系型数据库
本机不安装Oracle客户端,使用PL/SQL Developer连接远程数据库
本机不安装Oracle客户端,使用PL/SQL Developer连接远程数据库
183 0
|
1月前
|
Oracle 关系型数据库 数据库
已解决:idea 连接 oracle 数据库 避雷
已解决:idea 连接 oracle 数据库 避雷
30 2
|
1月前
|
Oracle 数据可视化 关系型数据库
Oracle数据库安装及使用Navicat连接oracle2
Oracle数据库安装及使用Navicat连接oracle
34 1
|
1月前
|
Oracle 关系型数据库 数据库
实时计算 Flink版产品使用问题之连接到Oracle数据库但无法读取到数据,是什么导致的
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
|
1月前
|
Oracle 安全 关系型数据库
Oracle数据库安装及使用Navicat连接oracle1
Oracle数据库安装及使用Navicat连接oracle
36 0
|
2月前
|
Oracle Java 关系型数据库
【服务器】python通过JDBC连接到位于Linux远程服务器上的Oracle数据库
【服务器】python通过JDBC连接到位于Linux远程服务器上的Oracle数据库
40 6
|
2月前
|
消息中间件 Oracle 关系型数据库
实时计算 Flink版操作报错合集之在连接Oracle 19c时报错如何解决
在使用实时计算Flink版过程中,可能会遇到各种错误,了解这些错误的原因及解决方法对于高效排错至关重要。针对具体问题,查看Flink的日志是关键,它们通常会提供更详细的错误信息和堆栈跟踪,有助于定位问题。此外,Flink社区文档和官方论坛也是寻求帮助的好去处。以下是一些常见的操作报错及其可能的原因与解决策略。
65 0
|
2月前
|
Oracle Java 关系型数据库
SpringBoot整合Mybatis连接Oracle数据库
SpringBoot整合Mybatis连接Oracle数据库
SpringBoot整合Mybatis连接Oracle数据库
|
2月前
|
Oracle 关系型数据库 MySQL
Flink CDC产品常见问题之使用cdc-Oracle连接器报错如何解决
Flink CDC(Change Data Capture)是一个基于Apache Flink的实时数据变更捕获库,用于实现数据库的实时同步和变更流的处理;在本汇总中,我们组织了关于Flink CDC产品在实践中用户经常提出的问题及其解答,目的是辅助用户更好地理解和应用这一技术,优化实时数据处理流程。
Flink CDC产品常见问题之使用cdc-Oracle连接器报错如何解决