最近在一个项目中出现一个问题:
系统使用spring+c3p0管理数据库的连接池,项目中一共用到了4个数据源。在启动项目时,如果其中有某一个或几个数据源连不上时,后台就会无限次尝试连接,导致整项目无法启动。
而实际上,我们想要的结果是,如果某个数据源无法连接使用时,跳过该数据源的连接,继续加载下面的项目。于是查了一下c3p0连接池配置,发现经过如下配置后即可达到理想的效果。
在数据源配置时,加上如下三项内容:
<property name="breakAfterAcquireFailure" value="true" />
<property name="checkoutTimeout" value="100"/>
<property name="acquireRetryAttempts" value="0"/>
其中:
- checkoutTimeout:当连接池用完时客户端调用getConnection()后等待获取新连接的时间,超时后将抛出 SQLException,如设为0则无限期等待。单位毫秒。Default: 0
- breakAfterAcquireFailure :true表示pool向数据库请求连接失败后标记整个pool为block并close,就算后端数据库恢复正常也不进行重连,客户端对pool的请求都拒绝掉。false表示不会标记 pool为block,新的请求都会尝试去数据库请求connection。默认为false。因此,如果想让数据库和网络故障恢复之后,pool能继续请求正常资源必须把此项配置设为false
- acquireRetryAttempts:定义在从数据库获取新连接失败后重复尝试的次数。Default: 30
最后,一个完整的数据源配置如下:
<bean id="iamsDB" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="${iamsDB.driverClass}" />
<property name="jdbcUrl" value="${iamsDB.url}" />
<property name="user" value="${iamsDB.user}" />
<property name="password" value="${iamsDB.password}" />
<property name="maxPoolSize" value="${iamsDB.maxPoolSize}" />
<property name="minPoolSize" value="${iamsDB.minPoolSize}" />
<property name="maxIdleTime" value="${iamsDB.maxIdleTime}" />
<property name="initialPoolSize" value="${iamsDB.initialPoolSize}" />
<property name="acquireIncrement" value="${iamsDB.acquireIncrement}" />
<property name="maxStatements" value="${iamsDB.maxStatements}" />
<property name="idleConnectionTestPeriod" value="${iamsDB.idleConnectionTestPeriod}" />
<property name="acquireRetryAttempts" value="${iamsDB.acquireRetryAttempts}" />
<property name="breakAfterAcquireFailure" value="true" />
<property name="checkoutTimeout" value="100"/>
<property name="acquireRetryAttempts" value="0"/>
</bean>