数据库自动重连
来源: http://www.zyhowe.com/index/topicDetail.aspx?type=200300&topicid=4284.2.10 数据库自动重连
DBCP使用apache的对象池ObjectPool作为连接池的实现,在构造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语句执行通过就可以了。
举例:
ObjectPool connectionPool = new GenericObjectPool(null, maxActive,
GenericObjectPool.DEFAULT_WHEN_EXHAUSTED_ACTION, maxIdle,maxWait);ConnectionFactory connectionFactory = new DriverManagerConnectionFactory(
"jdbc:jtds:sqlserver://" + hostName +":"+portnum+ "/" + sid,userName,passWord);((GenericObjectPool)connectionPool).setTestOnBorrow(true);//设置取从连接池取的连接前对连接进行测试,保证断网后连接池能继续运行。PoolableConnectionFactory poolableConnectionFactory =
new PoolableConnectionFactory(connectionFactory, connectionPool,
null, null, false, true);poolableConnectionFactory.setValidationQuery("SELECT 1");