文档章节

DBCP数据库连接失效的解决方法(Io 异常:Connection reset)

singhoo
 singhoo
发布于 2016/04/07 16:47
字数 896
阅读 36
收藏 0

网上很多评论说DBCP有很多BUG,但是都没有指明是什么BUG,只有一部分人说数据库如果因为某种原因断掉后再DBCP取道的连接都是失效的连接,而没有重新取。有的时候会报Io 异常:Connection reset。 解决方法:

spring中datasource的配置如下: <bean id="dispatchdataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" /> <property name="url" value="jdbc:oracle:thin:@127.0.0.1 :1521:myserver" /> <property name="username" value="user1" /> <property name="password" value="pwd" /> <property name="maxActive" value="10000" /> <property name="maxIdle" value="30" /> <property name="minIdle" value="2" /> <property name="maxWait" value="600000" /> <property name="testOnBorrow" value="true"/> <property name="testWhileIdle" value="true"/> <property name="validationQuery" value="select 1 from dual"/> </bean>

分析:

DBCP使用apache的对象池ObjectPool作为连接池的实现,有以下主要的方法

Object borrowObject() throws Exception;从对象池取得一个有效对象

void returnObject(Object obj) throws Exception;使用完的对象放回对象池

void invalidateObject(Object obj) throws Exception;使对象失效

void addObject() throws Exception;生成一个新对象

ObjectPool的一个实现就是GenericObjectPool,这个类使用对象工厂PoolableObjectFactory实现对象的生成,失效检查等等功能,以其实现数据库连接工厂PoolableConnectionFactory做以说明,主要方法:

 Object makeObject() throws Exception; 使用ConnectionFactory生成新连接

 void destroyObject(Object obj) throws Exception;关闭连接

 boolean validateObject(Object obj); 验证连接是否有效,如果_validationQuery不空,则使用该属性作为验证连接是否有效的sql语句,查询数据库

 void activateObject(Object obj) throws Exception;激活连接对象

 void passivateObject(Object obj) throws Exception; 关闭连接生成过的Statement和ResultSet,使连接处于非活动状态

而GenericObjectPool有几个主要属性

 _timeBetweenEvictionRunsMillis:失效检查线程运行时间间隔,默认-1

 _maxIdle:对象池中对象最大个数

 _minIdle:对象池中对象最小个数

 _maxActive:可以从对象池中取出的对象最大个数,为0则表示没有限制,默认为8



 在构造GenericObjectPool时,会生成一个内嵌类Evictor,实现自Runnable接口。如果 _timeBetweenEvictionRunsMillis大于0,每过_timeBetweenEvictionRunsMillis毫秒 Evictor会调用evict()方法,检查对象的闲置时间是否大于 _minEvictableIdleTimeMillis毫秒(_minEvictableIdleTimeMillis小于等于0时则忽略,默认为30 分钟),是则销毁此对象,否则就激活并校验对象,然后调用ensureMinIdle方法检查确保池中对象个数不小于_minIdle。在调用 returnObject方法把对象放回对象池,首先检查该对象是否有效,然后调用PoolableObjectFactory 的passivateObject方法使对象处于非活动状态。再检查对象池中对象个数是否小于_maxIdle,是则可以把此对象放回对象池,否则销毁此对象。



 还有几个很重要的属性,_testOnBorrow、_testOnReturn、_testWhileIdle,这些属性的意义是取得、返回对象和空闲时是否进行验证,检查对象是否有效,默认都为false即不验证。所以当使用DBCP时,数据库连接因为某种原因断掉后,再从连接池中取得连接又不进行验证,这时取得的连接实际已经时无效的数据库连接了。网上很多说 DBCP的bug应该都是如此吧,只有把这些属性设为true,再提供_validationQuery语句就可以保证数据库连接始终有效了,oracle数据库可以使用SELECT COUNT(*) FROM DUAL,不过DBCP要求_validationQuery语句查询的记录集必须不为空,可能这也可以算一个小小的BUG,其实只要_validationQuery语句执行通过就可以了。

本文转载自:http://my.oschina.net/sansom/blog/149068?fromerr=2uRSefAy

singhoo
粉丝 0
博文 6
码字总数 1387
作品 0
武汉
私信 提问

暂无文章

多线程同时加载缓存实现

import com.google.common.cache.Cache;import com.google.common.cache.CacheBuilder;import java.util.concurrent.ExecutionException;import java.util.concurrent.ExecutorServi......

暗中观察
3分钟前
0
0
解决Windows和Ubuntu时间不一致的问题

解决Windows和Ubuntu时间不一致的问题 问题原因是使用的时间不一致导致的。win10直接从bios读出来的时间认为就是实际时间,ubuntu认为加上8个小时 后的才是。win10用的rtc ,ubuntu用的utc 在...

shzwork
6分钟前
0
0
mysql mysql三种插入数据语句和增删改方法

点开题目是不是有点懵X,因为你只知道insert...values这一种,重来没有听说过三种,现在来介绍一下。 插入数据三种方式: insert into 表名(字段名) values(插入值); 最常用的插入语句 inse...

edison_kwok
8分钟前
0
0
利用VisualVM 内存查看

准备工作,建几个测试类。等下就是要查看这几个类里面的属性 package visualvm;public class MultiObject { private String str; private int i; MultiObject(String str...

冷基
19分钟前
0
0
组装一台工作游戏两用机

一、配置清单如下: 分类 项目 价格(元) 主板 华硕(ASUS)TUF Z370-PLUS GAMING II 电竞特工 Z370二代 支持9代CPU 1049 CPU 英特尔(Intel) i7 8700K 酷睿六核 盒装CPU处理器 2640 风扇 九...

mbzhong
26分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部