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的性能明顯優於其它三種.
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章