java 数据库连接池比较(c3p0,dbcp和proxool)

现在常用的开源数据连接池主要有c3p0,dbcp和proxool三种,其中: 
¨         hibernate开发组推荐使用c3p0; 
¨         spring开发组推荐使用dbcp (dbcp连接池有weblogic连接池同样的问题,就是强行关闭连接或数据库重启后,无法reconnect ,告诉连接被重置,这个设置可以解决); 
¨         hibernate in action推荐使用c3p0和proxool; 
下面具体就每种连接池的调研结果进行说明:

1. Apache-DBCP

Ø BasicDataSource 相关的参数说明 
dataSource: 要连接的 datasource (通常我们不会定义在 server.xml) 
defaultAutoCommit: 对于事务是否 autoCommit, 默认值为 true 
defaultReadOnly: 对于数据库是否只能读取, 默认值为 false 
driverClassName:连接数据库所用的 JDBC Driver Class, 
maxActive: 可以从对象池中取出的对象最大个数,为0则表示没有限制,默认为8 
maxIdle: 最大等待连接中的数量,设 0 为没有限制 (对象池中对象最大个数) 
minIdle:对象池中对象最小个数 
maxWait: 最大等待秒数, 单位为 ms, 超过时间会丟出错误信息 
password: 登陆数据库所用的密码 
url: 连接数据库的 URL 
username: 登陆数据库所用的帐号 
validationQuery: 验证连接是否成功, SQL SELECT 指令至少要返回一行 
removeAbandoned: 是否自我中断, 默认是 false 
removeAbandonedTimeout: 几秒后会自我中断, removeAbandoned 必须为 true 
logAbandoned: 是否记录中断事件, 默认为 false 
minEvictableIdleTimeMillis:大于0 ,进行连接空闲时间判断,或为0,对空闲的连接不进行验证;默认30分钟 
timeBetweenEvictionRunsMillis:失效检查线程运行时间间隔,如果小于等于0,不会启动检查线程,默认-1 
testOnBorrow:取得对象时是否进行验证,检查对象是否有效,默认为false 
testOnReturn:返回对象时是否进行验证,检查对象是否有效,默认为false 
testWhileIdle:空闲时是否进行验证,检查对象是否有效,默认为false 
Ø 在使用DBCP的时候,如果使用默认值,则数据库连接因为某种原因断掉后,再从连接池中取得连接又不进行验证,这时取得的连接实际上就会是无效的数据库连接。因此为了防止获得的数据库连接失效,在使用的时候最好保证: 
username: 登陆数据库所用的帐号 
validationQuery:SELECT COUNT(*) FROM DUAL 
testOnBorrow、testOnReturn、testWhileIdle:最好都设为true 
minEvictableIdleTimeMillis:大于0 ,进行连接空闲时间判断,或为0,对空闲的连接不进行验证 
timeBetweenEvictionRunsMillis:失效检查线程运行时间间隔,如果小于等于0,不会启动检查线程 
Ø PS:在构造GenericObjectPool [BasicDataSource在其createDataSource () 方法中也会使用GenericObjectPool]时,会生成一个内嵌类Evictor,实现自Runnable接口。如果timeBetweenEvictionRunsMillis大于0,每过timeBetweenEvictionRunsMillis毫秒Evictor会调用evict()方法,检查对象的闲置时间是否大于minEvictableIdleTimeMillis毫秒(_minEvictableIdleTimeMillis小于等于0时则忽略,默认为30分钟),是则销毁此对象,否则就激活并校验对象,然后调用ensureMinIdle方法检查确保池中对象个数不小于_minIdle。在调用returnObject方法把对象放回对象池,首先检查该对象是否有效,然后调用PoolableObjectFactory的passivateObject方法使对象处于非活动状态。再检查对象池中对象个数是否小于maxIdle,是则可以把此对象放回对象池,否则销毁此对象 
Ø 上述特性的可设置性已在代码中验证,具体性能是否能实现有待实际验证

在Tomcat的Server.xml,我们可以看看下面的这个例子:

 <Resource name="lda/raw"
              type="javax.sql.DataSource"
               password="lda_master"
               driverClassName="oracle.jdbc.driver.OracleDriver"
               maxIdle="30" minIdle="2" maxWait="60000" maxActive="1000" 
               testOnBorrow="true" testWhileIdle="true" validationQuery="select 1 from dual"
               username="lda_master" url="jdbc:oracle:thin:@192.160.100.107:15537:lcststd"/>

 这样的话,就可以避免产生Connection Reset的错误了.

这样一来,就能够解决Connect Reset的问题了。刚才说了,其实很多App Server都会有相应的配置地方,只是大型的服务器正好提供了Admin Console,上面可以显式的配置Connection Pool,也有明显的属性选择,这里就不一一详述了,都是眼见的功夫。

2. C3P0 
Ø C3P0的官方example中使用的数据源为ComboPooledDataSource,网上一篇文章详细介绍了C3P0连接池配置中各项含义[这些配置项的含义在下载解压c3p0的压缩包之后目录的doc\index.html中的Configuration部分也有详细的介绍,这里偷下懒:P],现摘录如下: 
<c3p0-config> 
<default-config> 
<!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3 --> 
<property name="acquireIncrement">3</property> 

<!--定义在从数据库获取新连接失败后重复尝试的次数。Default: 30 --> 
<property name="acquireRetryAttempts">30</property> 

<!--两次连接中间隔时间,单位毫秒。Default: 1000 --> 
<property name="acquireRetryDelay">1000</property> 

<!--连接关闭时默认将所有未提交的操作回滚。Default: false --> 
<property name="autoCommitOnClose">false</property> 

<!--c3p0将建一张名为Test的空表,并使用其自带的查询语句进行测试。如果定义了这个参数那么 
属性preferredTestQuery将被忽略。你不能在这张Test表上进行任何操作,它将只供c3p0测试 
使用。Default: null--> 
<property name="automaticTestTable">Test</property> 

<!--获取连接失败将会引起所有等待连接池来获取连接的线程抛出异常。但是数据源仍有效 
保留,并在下次调用getConnection()的时候继续尝试获取连接。如果设为true,那么在尝试 
获取连接失败后该数据源将申明已断开并永久关闭。Default: false--> 
<property name="breakAfterAcquireFailure">false</property> 

<!--当连接池用完时客户端调用getConnection()后等待获取新连接的时间,超时后将抛出 
SQLException,如设为0则无限期等待。单位毫秒。Default: 0 --> 
<property name="checkoutTimeout">100</property> 

<!--通过实现ConnectionTester或QueryConnectionTester的类来测试连接。类名需制定全路径。 
Default: com.mchange.v2.c3p0.impl.DefaultConnectionTester--> 
<property name="connectionTesterClassName"></property> 

<!--指定c3p0 libraries的路径,如果(通常都是这样)在本地即可获得那么无需设置,默认null即可 
Default: null--> 
<property name="factoryClassLocation">null</property> 

<!--Strongly disrecommended. Setting this to true may lead to subtle and bizarre bugs. 
(文档原文)作者强烈建议不使用的一个属性--> 
<property name="forceIgnoreUnresolvedTransactions">false</property> 

<!--每60秒检查所有连接池中的空闲连接。Default: 0 --> 
<property name="idleConnectionTestPeriod">60</property> 

<!--初始化时获取三个连接,取值应在minPoolSize与maxPoolSize之间。Default: 3 --> 
<property name="initialPoolSize">3</property> 

<!--最大空闲时间,60秒内未使用则连接被丢弃。若为0则永不丢弃。Default: 0 --> 
<property name="maxIdleTime">60</property> 

<!--连接池中保留的最大连接数。Default: 15 --> 
<property name="maxPoolSize">15</property> 

<!--JDBC的标准参数,用以控制数据源内加载的PreparedStatements数量。但由于预缓存的statements 
属于单个connection而不是整个连接池。所以设置这个参数需要考虑到多方面的因素。 
如果maxStatements与maxStatementsPerConnection均为0,则缓存被关闭。Default: 0--> 
<property name="maxStatements">100</property> 

<!--maxStatementsPerConnection定义了连接池内单个连接所拥有的最大缓存statements数。Default: 0 --> 
<property name="maxStatementsPerConnection"></property> 

<!--c3p0是异步操作的,缓慢的JDBC操作通过帮助进程完成。扩展这些操作可以有效的提升性能 
通过多线程实现多个操作同时被执行。Default: 3--> 
<property name="numHelperThreads">3</property> 

<!--当用户调用getConnection()时使root用户成为去获取连接的用户。主要用于连接池连接非c3p0 
的数据源时。Default: null--> 
<property name="overrideDefaultUser">root</property> 

<!--与overrideDefaultUser参数对应使用的一个参数。Default: null--> 
<property name="overrideDefaultPassword">password</property> 

<!--密码。Default: null--> 
<property name="password"></property> 

<!--定义所有连接测试都执行的测试语句。在使用连接测试的情况下这个一显著提高测试速度。注意: 
测试的表必须在初始数据源的时候就存在。Default: null--> 
<property name="preferredTestQuery">select id from test where id=1</property> 

<!--用户修改系统配置参数执行前最多等待300秒。Default: 300 --> 
<property name="propertyCycle">300</property> 

<!--因性能消耗大请只在需要的时候使用它。如果设为true那么在每个connection提交的 
时候都将校验其有效性。建议使用idleConnectionTestPeriod或automaticTestTable 
等方法来提升连接测试的性能。Default: false --> 
<property name="testConnectionOnCheckout">false</property> 

<!--如果设为true那么在取得连接的同时将校验连接的有效性。Default: false --> 
<property name="testConnectionOnCheckin">true</property> 

<!--用户名。Default: null--> 
<property name="user">root</property> 

<!--早期的c3p0版本对JDBC接口采用动态反射代理。在早期版本用途广泛的情况下这个参数 
允许用户恢复到动态反射代理以解决不稳定的故障。最新的非反射代理更快并且已经开始 
广泛的被使用,所以这个参数未必有用。现在原先的动态反射与新的非反射代理同时受到 
支持,但今后可能的版本可能不支持动态反射代理。Default: false--> 
<property name="usesTraditionalReflectiveProxies">false</property> 
<property name="automaticTestTable">con_test</property> 
    <property name="checkoutTimeout">30000</property> 
    <property name="idleConnectionTestPeriod">30</property> 
    <property name="initialPoolSize">10</property> 
    <property name="maxIdleTime">30</property> 
    <property name="maxPoolSize">25</property> 
    <property name="minPoolSize">10</property> 
    <property name="maxStatements">0</property> 
    <user-overrides user="swaldman"> 
    </user-overrides> 
</default-config> 
<named-config name="dumbTestConfig"> 
    <property name="maxStatements">200</property> 
    <user-overrides user="poop"> 
      <property name="maxStatements">300</property> 
    </user-overrides> 
   </named-config> 
</c3p0-config> 
Ø 上述特性的可设置性已在代码中验证,具体性能是否能实现有待实际验证 
Ø 从配置项的内容来看,C3P0和DBCP都有比较详细的有关连接检测保证的配置,我们可以看到C3P0可以控制数据源内加载的PreparedStatements数量,并且可以设置帮助线程的数量来提升JDBC操作的速度,这些是DBCP未提供的;另外从网络上的评价来看,DBCP出现Bug的频率要大于C3P0,不过这一点有待于我们自己实际的检测。

 

3. Proxool


Ø Proxool的使用和dbcp以及c3p0稍有不同,我们需要并且只需要在使用基本的java.sql.DriverManager之前加载org.logicalcobwebs.proxool.ProxoolDriver驱动类,并且按照proxool定义的url格式 ["proxool." + alias + ":" + driverClass + ":" + driverUrl ,其中alias是为连接池自定义的别名] 来获得connection;具体的可以参看proxool doc下的UserGuide,或本文所附的示例代码。下面对连接池的特性配置作详细说明 [这个是自己翻译的,不一定准确,有问题时请参看doc下的Properties ~]。 
n fatal-sql-exception 
以逗号隔开的异常列表,当设置了此项之后,每当出现SQLException时都将与列表中异常项作比较,如果匹配则认为出现fatal异常,这将导致connection被丢弃,并且不论出现任何情况该异常将被重抛一次以通知用户发生的情况。默认值为null 
n fatal-sql-exception-wrapper-class 
如果配置了fatal-sql-exception,则默认的操作是丢弃引起SQLException的原因而只是抛出原始异常。使用fatal-sql-exception-wrapper-class这个特性可以将SQLException包装到继承SQLException或RunTimeException的任何异常类里。Proxool提供了两个类供使用FatalSQLException和FatalRunTimeException;使用这两个类的话就将该选项设置为'org.logicalcobwebs.proxool.FatalSQLException'或者'org.logicalcobwebs.proxool.FatalRuntimeException'。默认值为null 
n house-keeping-sleep-time 
proxool自动侦察各个连接状态的时间间隔(毫秒),侦察到空闲的连接就马上回收,超时的销毁,默认值为30秒 
n house-keeping-test-sql 
如果侦察线程发现闲置连接,则会使用这个SQL语句来对这些连接进行检查;这项设置的语句应该能够被很快的执行,例如查询当前时间 [info.setProperty("proxool.house-keeping-test-sql", "select CURRENT_DATE");] 。如果不设置则该选项被忽略 
n injectable-connection-interface、injectable-statement-interface、injectable-prepared-statement-interface、injectable-callable-statement-interface 
n jmx 
如果此项设为true,则连接池将被以名称"Proxool:type=Pool, name=<alias>"注册为JMS Server的MBean。默认值为false 
n jmx-agent-id 
当且仅当jmx选项设为true时使用,为以逗号分隔的连接持注册到的JMS代理名称列表;如果不设置则所有注册的JMX Server都将被使用 
n maximum-active-time 
线程最大存活时间,超过此时间的线程将被守护线程kill掉,默认值为5分钟 
n maximum-connection-count 
到数据库的最大连接数,超过了这个连接,再有请求时,就排在队列中等候,最大的等待请求数由simultaneous-build-throttle决定;默认值为15 
n maximum-connection-lifetime 
连接最大存活时间,毫秒为单位,默认值为4小时 
n minimum-connection-count 
不管是否被使用都保持开放的最小连接数,默认值为5 
n overload-without-refusal-lifetime 
用来判断连接池状态,如果在此选项设置时间内(毫秒为单位)拒绝了连接,则认为过负载。默认值为60秒 
n prototype-count 
最少保持的空闲连接数,注意与minimum-connection-count区分。默认值为0 
n simultaneous-build-throttle 
最大的等待请求数,默认值为10 
n test-before-use 
如果设为true则connection在使用前将以house-keeping-test-sql设置的语句测试,如果测试不通过则该connection被丢弃并会重新分配一个connection。默认为false 
n test-after-use 
如果设为true则connection在关闭(放回连接池)前将以house-keeping-test-sql设置的语句测试,如果测试不通过connection将被丢弃。默认值为false 
Ø 与其它连接池特性的设置方法不同,Proxool不提供相应的set方法,所有特性都要以诸如info.setProperty("proxool.jmx", "false");方式设定 
Ø 上述特性的可设置性已在代码中验证,具体性能是否能实现有待实际验证 
Ø Proxool与DBCP以及C3P0的性能比较,网上众说纷纭,有待我们自己的测试

 

 

 

 

总结spring下配置dbcp,c3p0,proxool数据源链接池

 

applicationContext-datasource-jdbc.xml

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE beans PUBLIC
    "-//SPRING//DTD BEAN//EN"
    "http://www.springframework.org/dtd/spring-beans.dtd">

<beans default-autowire="no" default-lazy-init="true"
default-dependency-check="none">
<description>datasource</description>
<!--    
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
   <property name="driverClassName"><value>${jdbc.driverClassName}</value></property>
   <property name="url"><value>${jdbc.url}</value></property>
   <property name="username"><value>${jdbc.username}</value></property>
   <property name="password"><value>${jdbc.password}</value></property>
</bean>
-->


<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName"><value>${jdbc.driverClassName}</value></property>
    <property name="url"><value>${jdbc.url}</value></property>
    <property name="username"><value>${jdbc.username}</value></property>
    <property name="password"><value>${jdbc.password}</value></property>
    <property name="maxActive"><value>80</value></property>  
   <property name="maxIdle"><value>20</value></property>  
    <property name="maxWait"><value>3000</value></property>  
    
</bean>

<!--bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
        <property name="driverClass"><value>${jdbc.driverClassName}</value></property>
        <property name="jdbcUrl"><value>${jdbc.url}</value></property>
        <property name="user"><value>${jdbc.username}</value></property>
        <property name="password"><value>${jdbc.password}</value></property>  
        <property name="acquireIncrement"><value>5</value></property>
        <property name="idleConnectionTestPeriod"><value>3000</value></property>
        <property name="checkoutTimeout"><value>3000</value></property>
        <property name="maxPoolSize"><value>80</value></property>
        <property name="minPoolSize"><value>1</value></property>
        <property name="maxStatements"><value>6000</value></property>
        <property name="initialPoolSize"><value>5</value></property>
</bean-->

<!--
ComboPooledDataSource 参数说明

maxIdleTime:
最大空闲时间,60秒内未使用则连接被丢弃。若为0则永不丢弃。Default: 0 
acquireIncrement:
当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3 
maxStatements:
JDBC的标准参数,用以控制数据源内加载的PreparedStatements数量。但由于预缓存的statements
属于单个connection而不是整个连接池。所以设置这个参数需要考虑到多方面的因素。
如果maxStatements与maxStatementsPerConnection均为0,则缓存被关闭。Default: 0
idleConnectionTestPeriod:
每60秒检查所有连接池中的空闲连接。Default: 0 
acquireRetryAttempts: 
定义在从数据库获取新连接失败后重复尝试的次数。Default: 30 
breakAfterAcquireFailure: 
获取连接失败将会引起所有等待连接池来获取连接的线程抛出异常。但是数据源仍有效
保留,并在下次调用getConnection()的时候继续尝试获取连接。如果设为true,那么在尝试
获取连接失败后该数据源将申明已断开并永久关闭。Default: false
testConnectionOnCheckout:
因性能消耗大请只在需要的时候使用它。如果设为true那么在每个connection提交的
时候都将校验其有效性。建议使用idleConnectionTestPeriod或automaticTestTable
等方法来提升连接测试的性能。Default: false
-->

<!--bean id="dataSource" class="org.logicalcobwebs.proxool.ProxoolDataSource">
   <property name="driver"><value>${jdbc.driverClassName}</value></property>
   <property name="driverUrl"><value>${jdbc.url}</value></property>
   <property name="user"><value>${jdbc.username}</value></property>
   <property name="password"><value>${jdbc.password}</value></property>
   <property name="alias"><value>test</value></property>
   <property name="houseKeepingSleepTime"><value>90000</value></property>
   <property name="prototypeCount"><value>10</value></property>
   <property name="maximumConnectionCount"><value>100</value></property>
   <property name="minimumConnectionCount"><value>10</value></property>
   <property name="trace"><value>true</value></property>
   <property name="verbose"><value>true</value></property>
</bean>
-->

</beans>

jdbc.properties


#jdbc.driverClassName=net.sourceforge.jtds.jdbc.Driver
#jdbc.url=jdbc:jtds:sybase://192.168.1.1:5000/test;charset=eucgb
#jdbc.username=yinxiao
#jdbc.password=yinxiao


#jdbc.driverClassName=org.hsqldb.jdbcDriver
#jdbc.url=jdbc:hsqldb:file:hsqldb/test
#jdbc.username=sa
#jdbc.password=


jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test?user=root&password=root&useUnicode=true&characterEncoding=UTF-8&characterSetResults=UTF-8
jdbc.username=root
jdbc.password=root

#jdbc.url=jdbc:mysql://localhost:3306/test?user=root&amp;password=root&amp;useUnicode=true&amp;characterEncoding=UTF-8&amp;characterSetResults=UTF-8

#jdbc.driverClassName=net.sourceforge.jtds.jdbc.Driver
#jdbc.url=jdbc:jtds:sqlserver://localhost:1433/test;useUnicode=true&amp;characterEncoding=GBK&amp;characterSetResults=GBK
#jdbc.username=sa
#jdbc.password=sa

#jndi
jndi.factory.initial=weblogic.jndi.WLInitialContextFactory
jndi.provider.url=t3://127.0.0.1:7001
jndi.jndiName=jdbc/test


hibernate.properties


#hibernate.dialect=org.hibernate.dialect.SQLServerDialect
hibernate.dialect=org.hibernate.dialect.MySQLInnoDBDialect
#hibernate.dialect=org.hibernate.dialect.HSQLDialect
hibernate.cache.use_query_cache=true
#hibernate.cache.provider_class=net.sf.hibernate.cache.EhCacheProvider
hibernate.cache.provider_class=org.hibernate.cache.EhCacheProvider
hibernate.show_sql=true
hibernate.format_sql=false
hibernate.transaction.auto_close_session=true
hibernate.connection.autocommit=false
hibernate.connection.isolation=2
hibernate.hbm2ddl.auto=update
hibernate.jdbc.fetch_size=50
hibernate.jdbc.batch_size=25
hibernate.default_batch_fetch_size=16
hibernate.transaction.factory_class=org.hibernate.transaction.JDBCTransactionFactory
#hibernate.transaction.factory_class=net.sf.hibernate.transaction.JDBCTransactionFactory
hibernate.query.factory_class=org.hibernate.hql.classic.ClassicQueryTranslatorFactory
hibernate.connection.release_mode=after_transaction
hibernate.cache.region_prefix=hibernate.cache.test
hibernate.default_schema=test

tomcat下配置数据库连接池DBCP、C3P0、Proxool

 

1、将连接池的jar文件拷贝到tomcat的lib目录下

(1)dbcp:

tomcat默认包含tomcat-dbcp.jar,如果使用tomcat自带的dbcp则不用拷贝jar文件。

如果要使用commons-dbcp连接池,则要将commons-dbcp-xxx.jar和commons-pool.jar拷贝到tomcat的lib目录下。

(2)c3p0:

拷贝c3p0-xx.jar到tomcat的lib目录下

(3)proxool:

拷贝proxool-xx.jar、proxool-cglib.jar、commons-logging-xxx.jar到tomcat的lib目录下

2、打开tomcat的context.xml,进行如下配置:

<!--dbcp-->
<Resource 
    name="jdbc/mysqlds-dbcp" 
    auth="Container" 
    type= "javax.sql.DataSource" 
factory="org.apache.commons.dbcp.BasicDataSourceFactory"<!--这里使用的commons-dbcp连接池-->

<!--tomcat的dbcp对应的factory为:将commons替换为tomcat,也可不用配置-->
    driverClassName="com.mysql.jdbc.Driver" 
    url="jdbc:mysql://localhost:3306/test"
    username="root" 
    password=""
    maxActive="100" 
    maxIdle="30"
    maxWait="10000" > 
</Resource> 
   <!--c3p0-->
<Resource auth="Container"
     description="DB Connection"
     driverClass="com.mysql.jdbc.Driver"
     maxPoolSize="100"
     minPoolSize="2"
     acquireIncrement="2"
     name="jdbc/mysqlds-c3p0"
     user="root"
     password=""
     factory="org.apache.naming.factory.BeanFactory"
     type="com.mchange.v2.c3p0.ComboPooledDataSource"
     jdbcUrl="jdbc:mysql://localhost:3306/test" />

<!--proxool-->

<Resource name="jdbc/mysqlds-proxool" 
     auth="Container"       
     type="javax.sql.DataSource" 
     factory="org.logicalcobwebs.proxool.ProxoolDataSource"       
     proxool.alias="test"       
     user="root"     
     password=""       
     delegateProperties="foo=1,bar=true" 
     proxool.jndi-name="mysqljndi"      
     proxool.driver-url="jdbc:mysql://127.0.0.1:3306/test"       
     proxool.driver-class="com.mysql.jdbc.Driver"     
     proxool.house-keeping-sleep-time="900000"     
     proxool.maximum-active-time="5" 
     proxool.prototype-count="3" 
     proxool.statistics="1m,15m,1d" 
     proxool.simultaneous-build-throttle="10" 
     proxool.minimum-connection-count="5" 
     proxool.maximum-connection-count="15"    
/>  

3、在web.xml中配置如下代码:

<resource-ref>   
<res-ref-name>jdbc/mysqlds-proxool</res-ref-name>   <!--与context.xml下的Resources的name属性一致-->
<res-type>javax.sql.DataSource</res-type>   
<res-auth>Container</res-auth>   
</resource-ref>

4、获取连接java代码:

   Context context = new InitialContext();
    ds = (DataSource) context.lookup("java:/comp/env/jdbc/mysqlds-proxool");//与context.xml下的Resources的name属性一致

5、常见问题:

      (1)create a new connection but it fail its test:

       在配置proxool连接池时,可能会包以上错误,可以看看你的context.xml配置,将

proxool.test-before-use="true"该行去掉即可,即在使用前不要进行测试

 

 

DBCP,C3P0,Proxool,BoneCP参数介绍

 

1 Apache-DBCP:

dataSource: 要连接的 datasource (通常我们不会定义在 server.xml) 
defaultAutoCommit: 对于事务是否 autoCommit, 默认值为 true 
defaultReadOnly: 对于数据库是否只能读取, 默认值为 false 
driverClassName:连接数据库所用的 JDBC Driver Class, 
maxActive: 可以从对象池中取出的对象最大个数,为0则表示没有限制,默认为8 
maxIdle: 最大等待连接中的数量,设 0 为没有限制 (对象池中对象最大个数) 
minIdle:对象池中对象最小个数 
maxWait: 最大等待秒数, 单位为 ms, 超过时间会丟出错误信息 
password: 登陆数据库所用的密码 
url: 连接数据库的 URL 
username: 登陆数据库所用的帐号 
validationQuery: 验证连接是否成功, SQL SELECT 指令至少要返回一行 
removeAbandoned: 是否自我中断, 默认是 false 
removeAbandonedTimeout: 几秒后会自我中断, removeAbandoned 必须为 true 
logAbandoned: 是否记录中断事件, 默认为 false 
minEvictableIdleTimeMillis:大于0 ,进行连接空闲时间判断,或为0,对空闲的连接不进行验证;默认30分钟 
timeBetweenEvictionRunsMillis:失效检查线程运行时间间隔,如果小于等于0,不会启动检查线程,默认-1 
testOnBorrow:取得对象时是否进行验证,检查对象是否有效,默认为false 
testOnReturn:返回对象时是否进行验证,检查对象是否有效,默认为false 
testWhileIdle:空闲时是否进行验证,检查对象是否有效,默认为false 
initialSize:初始化线程数

 

 

2 C3P0:

acquireIncrement: 当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3 
acquireRetryAttempts: 定义在从数据库获取新连接失败后重复尝试的次数。Default: 30 
acquireRetryDelay: 两次连接中间隔时间,单位毫秒。Default: 1000 
autoCommitOnClose: 连接关闭时默认将所有未提交的操作回滚。Defaul t: false 
automaticTestTable: c3p0将建一张名为Test的空表,并使用其自带的查询语句进行测试。如果定义了这个参数那么属性preferredTestQuery将被忽略。你不能在这张Test表上进行任何操作,它将只供c3p0测试使用。Default: null 
breakAfterAcquireFailure: 获取连接失败将会引起所有等待连接池来获取连接的线程抛出异常。但是数据源仍有效保留,并在下次调用getConnection()的时候继续尝试获取连接。如果设为true,那么在尝试获取连接失败后该数据源将申明已断开并永久关闭。Default: false 
checkoutTimeout:当连接池用完时客户端调用getConnection()后等待获取新连接的时间,超时后将抛出SQLException,如设为0则无限期等待。单位毫秒。Default: 0 
connectionTesterClassName: 通过实现ConnectionTester或QueryConnectionT ester的类来测试连接。类名需制定全路径。Default: com.mchange.v2.c3p0.impl.Def aultConnectionTester 
factoryClassLocation: 指定c3p0 libraries的路径,如果(通常都是这样)在本地即可获得那么无需设置,默认null即可Default: null 
idleConnectionTestPeriod: 每60秒检查所有连接池中的空闲连接。Defaul t: 0 
initialPoolSize: 初始化时获取三个连接,取值应在minPoolSize与maxPoolSize之间。Default: 3 
maxIdleTime: 最大空闲时间,60秒内未使用则连接被丢弃。若为0则永不丢弃。Default: 0 
maxPoolSize: 连接池中保留的最大连接数。Default: 15 
maxStatements: JDBC的标准参数,用以控制数据源内加载的PreparedSt atements数量。但由于预缓存的statements属于单个connection而不是整个连接池。所以设置这个参数需要考虑到多方面的因素。如果maxStatements与maxStatementsPerConnection均为0,则缓存被关闭。Default: 0 
maxStatementsPerConnection: maxStatementsPerConnection定义了连接池内单个连接所拥有的最大缓存statements数。Default: 0 
numHelperThreads:c3p0是异步操作的,缓慢的JDBC操作通过帮助进程完成。扩展这些操作可以有效的提升性能通过多线程实现多个操作同时被执行。Default: 3 
overrideDefaultUser:当用户调用getConnection()时使root用户成为去获取连接的用户。主要用于连接池连接非c3p0的数据源时。Default: null 
overrideDefaultPassword:与overrideDefaultUser参数对应使用的一个参数。Default: null 
password:密码。Default: null 
user:用户名。Default: null 
preferredTestQuery:定义所有连接测试都执行的测试语句。在使用连接测试的情况下这个一显著提高测试速度。注意:测试的表必须在初始数据源的时候就存在。Default: null 
propertyCycle:用户修改系统配置参数执行前最多等待300秒。Defaul t: 300 
testConnectionOnCheckout:因性能消耗大请只在需要的时候使用它。如果设为true那么在每个connection提交的时候都将校验其有效性。建议使用idleConnectio nTestPeriod或automaticTestTable等方法来提升连接测试的性能。Default: false 
testConnectionOnCheckin:如果设为true那么在取得连接的同时将校验连接的有效性。Default: false

 

 

3 Proxool:

 

acquireIncrement: 当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3 
fatal-sql-exception : 它是一个逗号分割的信息片段.当一个SQL异常发生时,他的异常信息将与这个信息片段进行比较.如果在片段中存在,那么这个异常将被认为是个致命错误(Fatal SQL Exception ).这种情况下,数据库连接将要被放弃.无论发生什么,这个异常将会被重掷以提供给消费者.用户最好自己配置一个不同的异常来抛出. 
fatal-sql-exception-wrapper-class : 正如上面所说,你最好配置一个不同的异常来重掷.利用这个属性,用户可以包装SQLException,使他变成另外一个异常.这个异常或者继承SQLException或者继承字RuntimeException.proxool 自带了2个实现:'org.logicalcobwebs.proxool .FatalSQLException' 和'org.logicalcobweb s.proxool .FatalRuntimeException' .后者更合适. 
house-keeping-sleep-time : house keeper 保留线程处于睡眠状态的最长时间,house keeper 的职责就是检查各个连接的状态,并判断是否需要销毁或者创建. 
house-keeping-test-sql : 如果发现了空闲的数据库连接.house keeper 将会用这个语句来测试.这个语句最好非常快的被执行.如果没有定义,测试过程将会被忽略。 
injectable-connection-interface : 允许proxool 实现被代理的connection对象法. 
injectable-statement-interface : 允许proxool 实现被代理的Statement 对象方法. 
injectable-prepared-statement-interface : 允许proxool 实现被代理的PreparedS tatement 对象方法. 
injectable-callable-statement-interface : 允许proxool 实现被代理的CallableStat ement 对象方法. 
jmx : 如果属性为true,就会注册一个消息Bean到jms服务,消息Bean对象名: "Proxool:type=Pool, name=<alias>". 默认值为false.
jmx-agent-id : 一个逗号分隔的JMX代理列表(如使用MbeanServerFactory .fi ndMBeanServer(String agentId)注册的连接池。)这个属性是仅当"jmx"属性设置为"true"才有效。所有注册jmx服务器使用这个属性是不确定的 
jndi-name : 数据源的名称 
maximum-active-time : 如果housekeeper 检测到某个线程的活动时间大于这个数值.它将会杀掉这个线程.所以确认一下你的服务器的带宽.然后定一个合适的值.默认是5分钟. 
maximum-connection-count : 最大的数据库连接数. 
maximum-connection-lifetime : 一个线程的最大寿命. 
minimum-connection-count : 最小的数据库连接数 
overload-without-refusal-lifetime : 这可以帮助我们确定连接池的状态。如果我们已经拒绝了一个连接在这个设定值(毫秒),然后被认为是超载。默认为60秒。 
prototype-count : 连接池中可用的连接数量.如果当前的连接池中的连接少于这个数值.新的连接将被建立(假设没有超过最大可用数).例如.我们有3个活动连接2个可用连接,而我们的prototype-count是4,那么数据库连接池将试图建立另外2个连接.这和minimum-connection-count不同. minimum-connect ion-count把活动的连接也计算在内.prototype-count 是spare connections 的数量. 
recently-started-threshold :这可以帮助我们确定连接池的状态,连接数少还是多或超载。只要至少有一个连接已开始在此值(毫秒)内,或者有一些多余的可用连接,那么我们假设连接池是开启的。默认为60秒 
simultaneous-build-throttle :这是我们可一次建立的最大连接数。那就是新增的连接请求,但还没有可供使用的连接。由于连接可以使用多线程,在有限的时间之间建立联系从而带来可用连接,但是我们需要通过一些方式确认一些线程并不是立即响应连接请求的,默认是10。 
statistics : 连接池使用状况统计。 参数“10s,1m,1d” 
statistics-log-level :日志统计跟踪类型。 参数“ERROR”或 “INFO” 
test-before-use : 如果为true,在每个连接被测试前都会服务这个连接,如果一个连接失败,那么将被丢弃,另一个连接将会被处理,如果所有连接都失败,一个新的连接将会被建立。否则将会抛出一个SQLException异常。 
test-after-use : 如果为true,在每个连接被测试后都会服务这个连接,使其回到连接池中,如果连接失败,那么将被废弃。 
trace : 如果为true,那么每个被执行的SQL语句将会在执行期被log记录(DEBUG LEVEL).你也可以注册一个ConnectionListener (参看ProxoolFacade)得到这些信息

 

 

4 BoneCP:

 

acquireIncrement: 当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3 
driveClass:数据库驱动 
jdbcUrl:响应驱动的jdbcUrl 
username:数据库的用户名 
password:数据库的密码 
idleConnectionTestPeriod:检查数据库连接池中控线连接的间隔时间,单位是分,默认值:240,如果要取消则设置为0 
idleMaxAge:连接池中未使用的链接最大存活时间,单位是分,默认值:60,如果要永远存活设置为0 
maxConnectionsPerPartition:每个分区最大的连接数 
minConnectionsPerPartition:每个分区最小的连接数 
partitionCount:分区数,默认值2,最小1,推荐3-4,视应用而定 
acquireIncrement:每次去拿数据库连接的时候一次性要拿几个,默认值:2 
statementsCacheSize:缓存prepared statements的大小,默认值:0 
releaseHelperThreads:每个分区释放链接助理进程的数量,默认值:3,除非你的一个数据库连接的时间内做了很多工作,不然过多的助理进程会影响你的性能

 

<bean id="mainDataSource" class="com.jolbox.bonecp.BoneCPDataSource" destroy-method="close">

<property name="driverClass" value="com.mysql.jdbc.Driver" />

<property name="jdbcUrl" value="jdbc:mysql://127.0.0.1/yourdb" />

<property name="username" value="root"/>

<property name="password" value="abcdefgh"/>

<property name="idleConnectionTestPeriod" value="60"/>

<property name="idleMaxAge" value="240"/>

<property name="maxConnectionsPerPartition" value="30"/>

<property name="minConnectionsPerPartition" value="10"/>

<property name="partitionCount" value="3"/>

<property name="acquireIncrement" value="5"/>

<property name="statementsCacheSize" value="100"/>

<property name="releaseHelperThreads" value="3"/>

</bean>

 

 

1 c3p0、dbcp、proxool、BoneCP比较

1.1 测试环境:

操作系统:windows xp sp3 
数据库:mysql 5.1

1.2 测试条件:

initialSize=30; 
maxSize=200; 
minSize=30; 
其余参数为默认值;

1.3 测试代码:

利用JAVA代码模拟多线程对这三种数据库连接池进行测试,通过花费的时间判断效率 
DBTest.java: 
public class DBTest implements Runnable /*extends Thread*/ { 
public long date1=0; 
private static Proxool proxool; 
public static int count = 0; 
public static void main(String[] args) throws Exception { 
//DBCP.init(); 
//C3P0.init(); 
//proxool = Proxool.getInstance(); 
BoneCPConn.init(); 
DBTest test = new DBTest(); 
test.startup(); 


public void startup() { 
for (int i = 0; i <5; i++) { 
Thread thread = new Thread(this); 
thread.start(); 



public void run() { 
if(date1==0) 

date1 = System.currentTimeMillis(); 
System.out.println(date1); 

for(int i=0 ; i<10 ; i++){ 
try { 
//Connection conn = DBCP.getConnection(); 
// Connection conn = C3P0.getConnection(); 
//Connection conn =proxool.getConnection(); 
Connection conn = BoneCPConn.getConnection(); 
if (conn != null) { 
Statement statement = conn.createStatement(); 
ResultSet rs = statement.executeQuery("select * from user where id=1"); 
while (rs.next()) { 
String username = rs.getString(2); 
System.out.println(username); 

rs.close(); 
statement.close(); 
conn.close(); 

} catch (SQLException e) { 
e.printStackTrace(); 


count++; 
if(count==5) 

long date2 = System.currentTimeMillis(); 
System.out.println(date2); 
System.out.println("运行完毕!耗时为:" + (date2 - date1) + "ms"); 



4.3.1 模拟5个线程循环10次并发访问数据库 
DBCP用时1181ms 
C3P0用时860ms 
Proxool用时1563ms 
BoneCP用时31ms 
4.3.2 模拟10个线程循环10次并发访问数据库 
DBCP用时1188ms 
C3P0用时953ms 
Proxool用时1625ms 
BoneCP用时63ms 
4.3.3 模拟20个线程循环10次并发访问数据库 
DBCP用时1204ms 
C3P0用时1000ms 
Proxool用时1640ms 
BoneCP用时110ms 
4.3.4 模拟30个线程循环10次并发访问数据库 
DBCP用时1250ms 
C3P0用时1047ms 
Proxool用时1657ms 
BoneCP用时156ms 
4.3.5 模拟50个线程循环10次并发访问数据库 
DBCP用时1406ms 
C3P0用时1343ms 
Proxool用时1843ms 
BoneCP用时172ms 
4.3.6 模拟100个线程循环10次并发访问数据库 
DBCP用时1641ms 
C3P0用时2703ms 
Proxool用时2031ms 
BoneCP用时532ms 
4.3.7 模拟200个线程循环10次并发访问数据库 
DBCP用时2093ms 
C3P0用时4891ms 
Proxool用时2406ms 
BoneCP用时936ms 
4.3.8 模拟500个线程循环10次并发访问数据库 
DBCP用时3219ms 
C3P0用时11703ms 
Proxool用时3343ms 
BoneCP用时1922ms 
4.3.9 模拟800个线程循环10次并发访问数据库 
DBCP用时4688ms 
C3P0用时12063ms 
Proxool用时4141ms 
BoneCP用时2859ms 
4.3.10 模拟1000个线程循环10次并发访问数据库 
DBCP用时5187ms 
C3P0用时12563ms 
Proxool用时4703ms 
BoneCP用时3610ms 
4.3.11 模拟3000个线程循环10次并发访问数据库 
DBCP用时14094ms 
C3P0用时16297ms 
Proxool用时11344ms 
BoneCP用时11391ms 
4.3.12 模拟5000个线程循环10次并发访问数据库 
DBCP用时23610ms 
C3P0用时22032ms 
Proxool用时20125ms 
BoneCP用时17125ms 

4.4测试结果分析:

         BoneCP一直保持性能最佳

4.5 测试结论

          通过对四种数据库连接池的性能测试发现,BoneCP的性能明显优于其它三种.




but

有同事推荐BoneCP,网上搜一下benchmark结果也很是惊人,最近用连接池想到换成BoneCP。但是,经过我自己的使用和测试,我又换回了c3p0,原因有二:

1.bonecp在高并发下的稳定性不如c3p0,其它完全一样的条件(web层Jersey,数据层postgresql),使用bonecp时的吞吐量多次测量结果的波动比c3p0明显要大,同时在性能上两者并没有本质区别,并没有出现bonecp明显胜出的情况,c3p0的连接池热身甚至更快一些。

2. bonecp的Datasource不支持自动重连(或许我没找到),这非常要命,我测试的时候手动重启了一下数据库,c3p0很正常地重连上了,bonecp就彻底没反应了。

据我所知,oschina曾经也尝试过切换到bonecp,后来据说因为一些bug换了回来。我自己的感觉与此类似,即使bonecp自称使用了更新的concurrent特性,因此有更好的性能,但是我自己得到的结果并不与之非常符合。

你可能感兴趣的:(java 数据库连接池比较(c3p0,dbcp和proxool))