您好,欢迎访问一九零五行业门户网

关于DBCP断网数据库连接失效的解决方案

欢迎进入java社区论坛,与200万技术人员互动交流 >>进入 问题 网上很多评论说dbcp有很多bug,但是都没有指明是什么bug,只有一部分人说数据库如果因为某种原因断掉后再dbcp取道的连接都是失效的连接,而没有重新
欢迎进入java社区论坛,与200万技术人员互动交流 >>进入
问题
网上很多评论说dbcp有很多bug,但是都没有指明是什么bug,只有一部分人说数据库如果因为某种原因断掉后再dbcp取道的连接都是失效的连接,而没有重新取。就此研读了一下dbcp的代码,共享之。
分析
dbcp使用apache的对象池objectpool作为连接池的实现,有以下主要的方法:
1. object borrowobject() throws exception;从对象池取得一个有效对象
2. void returnobject(object obj) throws exception;使用完的对象放回对象池
3. void invalidateobject(object obj) throws exception;使对象失效
4. 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语句执行通过就可以了。
注意事项
所以使用dbcp连接池放必须注意构造genericobjectpool对象时
validationquery:select count(*) from dual
_testonborrow、_testonreturn、_testwhileidle:最好都设为true
_minevictableidletimemillis:大于0 ,进行连接空闲时间判断,或为0,对空闲的连接不进行验证
_timebetweenevictionrunsmillis:失效检查线程运行时间间隔,如果小于等于0,不会启动检查线程
其它类似信息

推荐信息