druid 连接池出现 关闭的连接 异常处理
报错日志:
12:39:04.599 [Druid-ConnectionPool-Destroy-766221240] ERROR com.alibaba.druid.util.JdbcUtils - close statement error
java.sql.SQLRecoverableException: 关闭的连接
at oracle.jdbc.driver.PhysicalConnection.needLine(PhysicalConnection.java:5389) ~[ojdbc6-11.2.0.3.jar:11.2.0.3.0]
at oracle.jdbc.driver.OracleStatement.closeOrCache(OracleStatement.java:1578) ~[ojdbc6-11.2.0.3.jar:11.2.0.3.0]
at oracle.jdbc.driver.OracleStatement.close(OracleStatement.java:1563) ~[ojdbc6-11.2.0.3.jar:11.2.0.3.0]
at oracle.jdbc.driver.OracleStatementWrapper.close(OracleStatementWrapper.java:94) ~[ojdbc6-11.2.0.3.jar:11.2.0.3.0]
at com.alibaba.druid.util.JdbcUtils.close(JdbcUtils.java:84) [druid-1.1.10.jar:1.1.10]
at com.alibaba.druid.pool.vendor.OracleValidConnectionChecker.isValidConnection(OracleValidConnectionChecker.java:88) [druid-1.1.10.jar:1.1.10]
at com.alibaba.druid.pool.DruidAbstractDataSource.validateConnection(DruidAbstractDataSource.java:1346) [druid-1.1.10.jar:1.1.10]
at com.alibaba.druid.pool.DruidDataSource.shrink(DruidDataSource.java:2813) [druid-1.1.10.jar:1.1.10]
at com.alibaba.druid.pool.DruidDataSource$DestroyTask.run(DruidDataSource.java:2562) [druid-1.1.10.jar:1.1.10]
at com.alibaba.druid.pool.DruidDataSource$DestroyConnectionThread.run(DruidDataSource.java:2549) [druid-1.1.10.jar:1.1.10]
12:39:04.760 [Druid-ConnectionPool-Destroy-1073682365] ERROR com.alibaba.druid.util.JdbcUtils - close connection error
java.sql.SQLRecoverableException: IO 错误: Connection reset by peer: socket write error
at oracle.jdbc.driver.T4CConnection.logoff(T4CConnection.java:556) ~[ojdbc6-11.2.0.3.jar:11.2.0.3.0]
at oracle.jdbc.driver.PhysicalConnection.close(PhysicalConnection.java:3984) ~[ojdbc6-11.2.0.3.jar:11.2.0.3.0]
at com.alibaba.druid.filter.FilterChainImpl.connection_close(FilterChainImpl.java:186) ~[druid-1.1.10.jar:1.1.10]
at com.alibaba.druid.filter.stat.StatFilter.connection_close(StatFilter.java:261) ~[druid-1.1.10.jar:1.1.10]
at com.alibaba.druid.filter.FilterChainImpl.connection_close(FilterChainImpl.java:181) ~[druid-1.1.10.jar:1.1.10]
at com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl.close(ConnectionProxyImpl.java:115) ~[druid-1.1.10.jar:1.1.10]
at com.alibaba.druid.util.JdbcUtils.close(JdbcUtils.java:73) [druid-1.1.10.jar:1.1.10]
at com.alibaba.druid.pool.DruidDataSource.shrink(DruidDataSource.java:2797) [druid-1.1.10.jar:1.1.10]
at com.alibaba.druid.pool.DruidDataSource$DestroyTask.run(DruidDataSource.java:2562) [druid-1.1.10.jar:1.1.10]
at com.alibaba.druid.pool.DruidDataSource$DestroyConnectionThread.run(DruidDataSource.java:2549) [druid-1.1.10.jar:1.1.10]
Caused by: java.net.SocketException: Connection reset by peer: socket write error
at java.net.SocketOutputStream.socketWrite0(Native Method) ~[?:1.8.0_151]
at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:111) ~[?:1.8.0_151]
at java.net.SocketOutputStream.write(SocketOutputStream.java:155) ~[?:1.8.0_151]
at oracle.net.ns.DataPacket.send(DataPacket.java:210) ~[ojdbc6-11.2.0.3.jar:11.2.0.3.0]
at oracle.net.ns.NetOutputStream.flush(NetOutputStream.java:230) ~[ojdbc6-11.2.0.3.jar:11.2.0.3.0]
at oracle.net.ns.NetInputStream.getNextPacket(NetInputStream.java:312) ~[ojdbc6-11.2.0.3.jar:11.2.0.3.0]
at oracle.net.ns.NetInputStream.read(NetInputStream.java:260) ~[ojdbc6-11.2.0.3.jar:11.2.0.3.0]
at oracle.net.ns.NetInputStream.read(NetInputStream.java:185) ~[ojdbc6-11.2.0.3.jar:11.2.0.3.0]
at oracle.net.ns.NetInputStream.read(NetInputStream.java:102) ~[ojdbc6-11.2.0.3.jar:11.2.0.3.0]
at oracle.jdbc.driver.T4CSocketInputStreamWrapper.readNextPacket(T4CSocketInputStreamWrapper.java:124) ~[ojdbc6-11.2.0.3.jar:11.2.0.3.0]
at oracle.jdbc.driver.T4CSocketInputStreamWrapper.read(T4CSocketInputStreamWrapper.java:80) ~[ojdbc6-11.2.0.3.jar:11.2.0.3.0]
at oracle.jdbc.driver.T4CMAREngine.unmarshalUB1(T4CMAREngine.java:1137) ~[ojdbc6-11.2.0.3.jar:11.2.0.3.0]
at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:290) ~[ojdbc6-11.2.0.3.jar:11.2.0.3.0]
at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:192) ~[ojdbc6-11.2.0.3.jar:11.2.0.3.0]
at oracle.jdbc.driver.T4C7Ocommoncall.doOLOGOFF(T4C7Ocommoncall.java:61) ~[ojdbc6-11.2.0.3.jar:11.2.0.3.0]
at oracle.jdbc.driver.T4CConnection.logoff(T4CConnection.java:543) ~[ojdbc6-11.2.0.3.jar:11.2.0.3.0]
... 9 more
项目异常体现
项目是使用 tomcat 进行部署的,项目运行一段时间就出现应用僵死,然后在日志中也只看到上方的报错,无其他异常,重启 Tomcat 后又运行正常一段时间后又重复出现。
出现的原因:
网上查到资料说是:应用和数据库之间有一层防火墙。防火墙策略是有设置特定时间未使用的Socket连接将自动关闭。
当数据库连接池中的连接被创建而长时间不使用的情况下,该连接会自动回收并失效,但客户端并不知道,在进行数据库操作时仍然使用的是无效的数据库连接,这样,就导致客户端程序报“ java.sql.SQLException: Io 异常: Connection reset” 或“java.sql.SQLException 关闭的连接”异常。
解决办法:
druid 连接池的解决办法就是创建连接池是一下几个参数设置好:
spring.datasource.druid.testOnBorrow=false
spring.datasource.druid.testOnReturn=false
spring.datasource.druid.testWhileIdle=true
spring.datasource.druid.timeBetweenEvictionRunsMillis=60000
spring.datasource.druid.validationQuery=SELECT 1 FROM DUAL
解决办法中 druid 配置参数说明:
属性 | 默认值 | 备注 |
---|---|---|
testOnBorrow | false | 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能 |
testOnBorrow | false | 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。 |
testWhileIdle | false | 建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。 |
timeBetweenEvictionRunsMillis | 单位毫秒 | 有两个含义:1) Destroy线程会检测连接的间隔时间,如果连接空闲时间大于等于minEvictableIdleTimeMillis则关闭物理连接。2) testWhileIdle的判断依据,详细看testWhileIdle属性的说明 |
validationQuery | 用来测试连接是否可用的SQL语句 |
validationQuery:Druid用来测试连接是否可用的SQL语句,默认值每种数据库都不相同:
数据库类型 | sql语句 |
---|---|
Mysql | SELECT 1 |
SQLSERVER | SELECT 1 |
ORACLE | SELECT ‘x’ FROM DUAL |
PostGresql | SELECT ‘x’ |
注意:
连接池配置文件中以上参数都有进行配置,但是程序还是有报错;可以根据报错日志,错定位所使用的连接池,然后定位对应连接池创建的代码,看看是否是创建连接池的时候缺了以上对应的参数配置。
参考:
关于java.sql.SQLRecoverableException: Closed Connection异常的解决方案(转)
版权声明:本文为h_l_614原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。