奇奇怪怪的问题-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 一致

目录
相关文章
|
5月前
|
SQL Oracle 关系型数据库
本机不安装Oracle客户端,使用PL/SQL Developer连接远程数据库
本机不安装Oracle客户端,使用PL/SQL Developer连接远程数据库
142 0
|
6月前
|
Oracle 关系型数据库 流计算
Flink CDC不支持直接连接到Oracle ADG备库进行数据同步
Flink CDC不支持直接连接到Oracle ADG备库进行数据同步
110 1
|
1月前
|
Oracle Java 关系型数据库
SpringBoot整合Mybatis连接Oracle数据库
SpringBoot整合Mybatis连接Oracle数据库
SpringBoot整合Mybatis连接Oracle数据库
|
1月前
|
Oracle 关系型数据库 MySQL
Flink CDC产品常见问题之使用cdc-Oracle连接器报错如何解决
Flink CDC(Change Data Capture)是一个基于Apache Flink的实时数据变更捕获库,用于实现数据库的实时同步和变更流的处理;在本汇总中,我们组织了关于Flink CDC产品在实践中用户经常提出的问题及其解答,目的是辅助用户更好地理解和应用这一技术,优化实时数据处理流程。
Flink CDC产品常见问题之使用cdc-Oracle连接器报错如何解决
|
4月前
|
SQL Oracle 关系型数据库
[已解决]使用sqlplus连接oracle,提示ORA-01034和ORA-27101
[已解决]使用sqlplus连接oracle,提示ORA-01034和ORA-27101
55 0
|
4月前
|
Oracle 小程序 关系型数据库
laravel5.8(十四)连接oracle数据库
首先确定你的PHP已经支持oracle数据库的链接。PHP需要安装OCI8扩展。 确定PHP可以链接ORACLE数据库之后。我们使用composer安装laravel支持oracle链接的插件 yajra/laravel-oci8 欢迎访问个人博客 guanchao.site 欢迎访问我的小程序:打开微信->发现->小程序->搜索“时间里的” 一:使用composer安装 yajra/laravel-oci8 1 :运行如下命令: bash 复制代码 composer require yajra/laravel-oci8 2 :安装过程中可能会报错,不要纠结那些报错,最简单的解决办法:
70 0
|
4月前
|
Oracle 关系型数据库 Python
python连接oracle12c
python连接oracle12c
34 0
|
5月前
|
Oracle 关系型数据库 数据库
Navicat连接Oracle报错:Oracle library is not loaded
Navicat连接Oracle报错:Oracle library is not loaded
106 0
|
5月前
|
Oracle 关系型数据库 数据库
Navicat连接Oracle数据库
Navicat连接Oracle数据库
|
5月前
|
Oracle 关系型数据库 Java
thin/oci两种方式连接Oracle数据库
thin/oci两种方式连接Oracle数据库
61 0