DBCP鏈接池介紹

DBCP鏈接池介紹

-----------------------------html

目前 DBCP 有兩個版本分別是 1.3 和 1.4。java

DBCP 1.3 版本須要運行於 JDK 1.4-1.5 ,支持 JDBC 3。mysql

DBCP 1.4 版本須要運行於 JDK 1.6 ,支持 JDBC 4。web

1.3和1.4基於同一套源代碼,含有全部的bug修復和新特性。所以在選擇DBCP版本的時候,要看你用的是什麼JDK版本。spring

DBCP1.2版本性能通常,比c3p0差挺多。DBCP1.4和1.3,配合(依賴)commons pool 1.6的jar包,各方面功能、性能推動到新的高峯。相對1.2版本提升很多。超越(或至關)了c3p0.建議使用DBCP1.4或1.3 +  commons pool 1.6sql

Tomcat7 中保留DBCP鏈接池,以兼容已有應用。並提供了新的Tomcat JDBC pool做爲DBCP的可選替代。新出的Tomcat JDBC pool,聽說比DBCP 1.4要好,未接觸,也不在本文討論範圍內。數據庫

DBCP鏈接池配置參數講解

-----------------------------apache

1、Apache官方DBCP文檔給出的配置示例:tomcat

可參見:http://tomcat.apache.org/tomcat-6.0-doc/jndi-datasource-examples-howto.html服務器

<Context>

  <Resource name="jdbc/TestDB" auth="Container" type="javax.sql.DataSource"

               maxActive="100" maxIdle="30" maxWait="10000"

               username="javauser" password="javadude" driverClassName="com.mysql.jdbc.Driver"

               url="jdbc:mysql://localhost:3306/javatest"/>

</Context>

2、經常使用參數說明:

可參見:http://elf8848.iteye.com/blog/337981

<Resource

name="jdbc/TestDB"  JNDI數據源的name

type="javax.sql.DataSource"

driverClassName="com.mysql.jdbc.Driver" JDBC驅動類

url=""

username="" 訪問數據庫用戶名

password="" 訪問數據庫的密碼

maxActive="80" 最大活動鏈接

initialSize="10"  初始化鏈接

maxIdle="60"   最大空閒鏈接

minIdle="10"   最小空閒鏈接

maxWait="3000" 從池中取鏈接的最大等待時間,單位ms.

    validationQuery = "SELECT 1"  驗證使用的SQL語句

    testWhileIdle = "true"      指明鏈接是否被空閒鏈接回收器(若是有)進行檢驗.若是檢測失敗,則鏈接將被從池中去除.

    testOnBorrow = "false"   借出鏈接時不要測試,不然很影響性能

    timeBetweenEvictionRunsMillis = "30000"  每30秒運行一次空閒鏈接回收器

    minEvictableIdleTimeMillis = "1800000"  池中的鏈接空閒30分鐘後被回收

    numTestsPerEvictionRun="3" 在每次空閒鏈接回收器線程(若是有)運行時檢查的鏈接數量

    removeAbandoned="true"  鏈接泄漏回收參數,當可用鏈接數少於3個時才執行

    removeAbandonedTimeout="180"  鏈接泄漏回收參數,180秒,泄露的鏈接能夠被刪除的超時值

/>

DBCP鏈接池的自我檢測

-----------------------------

默認配置的DBCP鏈接池,是不對池中的鏈接作測試的,有時鏈接已斷開了,但DBCP鏈接池不知道,還覺得鏈接是好的呢。

應用從池中取出這樣的鏈接訪問數據庫必定會報錯。這也是好多人不喜歡DBCP的緣由。

問題例一:

MySQL8小時問題,Mysql服務器默認鏈接的「wait_timeout」是8小時,也就是說一個connection空閒超過8個小時,Mysql將自動斷開該 connection。

可是DBCP鏈接池並不知道鏈接已經斷開了,若是程序正巧使用到這個已經斷開的鏈接,程序就會報錯誤。

問題例二:

    之前還使用Sybase數據庫,因爲某種緣由,數據庫死了後重啓、或斷網後恢復。

    等了約10分鐘後,DBCP鏈接池中的鏈接還都是不能使用的(斷開的),訪問數據應用一直報錯,最後只能重啓Tomcat問題才解決 。

解決方案:

    方案一、定時對鏈接作測試,測試失敗就關閉鏈接。

    方案二、控制鏈接的空閒時間達到N分鐘,就關閉鏈接,(而後可再新建鏈接)。

    以上兩個方案使用任意一個就能夠解決以述兩類問題。若是隻使用方案2,建議 N <= 5分鐘。鏈接斷開後最多5分鐘後可恢復。

    也可混合使用兩個方案,建議 N = 30分鐘。

    下面就是DBCP鏈接池,同時使用了以上兩個方案的配置配置

    validationQuery = "SELECT 1"  驗證鏈接是否可用,使用的SQL語句

    testWhileIdle = "true"      指明鏈接是否被空閒鏈接回收器(若是有)進行檢驗.若是檢測失敗,則鏈接將被從池中去除.

    testOnBorrow = "false"   借出鏈接時不要測試,不然很影響性能

    timeBetweenEvictionRunsMillis = "30000"  每30秒運行一次空閒鏈接回收器

    minEvictableIdleTimeMillis = "1800000"  池中的鏈接空閒30分鐘後被回收,默認值就是30分鐘。

    numTestsPerEvictionRun="3" 在每次空閒鏈接回收器線程(若是有)運行時檢查的鏈接數量,默認值就是3.

    解釋:

    配置timeBetweenEvictionRunsMillis = "30000"後,每30秒運行一次空閒鏈接回收器(獨立線程)。並每次檢查3個鏈接,若是鏈接空閒時間超過30分鐘就銷燬。銷燬鏈接後,鏈接數量就少了,若是小於minIdle數量,就新建鏈接,維護數量很多於minIdle,過行了新老更替。

    testWhileIdle = "true" 表示每30秒,取出3條鏈接,使用validationQuery = "SELECT 1" 中的SQL進行測試 ,測試不成功就銷燬鏈接。銷燬鏈接後,鏈接數量就少了,若是小於minIdle數量,就新建鏈接。

    testOnBorrow = "false" 必定要配置,由於它的默認值是true。false表示每次從鏈接池中取出鏈接時,不須要執行validationQuery = "SELECT 1" 中的SQL進行測試。若配置爲true,對性能有很是大的影響,性能會降低7-10倍。所在必定要配置爲false.

    每30秒,取出numTestsPerEvictionRun條鏈接(本例是3,也是默認值),發出"SELECT 1" SQL語句進行測試 ,測試過的鏈接不算是「被使用」了,還算是空閒的。鏈接空閒30分鐘後會被銷燬。

DBCP鏈接池配置參數注意事項 

-----------------------------

maxIdle值與maxActive值應配置的接近。

由於,當鏈接數超過maxIdle值後,剛剛使用完的鏈接(剛剛空閒下來)會當即被銷燬。而不是我想要的空閒M秒後再銷燬起一個緩衝做用。這一點DBCP作的可能與你想像的不同。

若maxIdle與maxActive相差較大,在高負載的系統中會致使頻繁的建立、銷燬鏈接,鏈接數在maxIdle與maxActive間快速頻繁波動,這不是我想要的。

高負載系統的maxIdle值能夠設置爲與maxActive相同或設置爲-1(-1表示不限制),讓鏈接數量在minIdle與maxIdle間緩衝慢速波動。

timeBetweenEvictionRunsMillis建議設置值

initialSize="5",會在tomcat一啓動時,建立5條鏈接,效果很理想。

但同時咱們還配置了minIdle="10",也就是說,最少要保持10條鏈接,那如今只有5條鏈接,哪何時再建立少的5條鏈接呢?

一、等業務壓力上來了, DBCP就會建立新的鏈接。

二、配置timeBetweenEvictionRunsMillis=「時間」,DBCP會啓用獨立的工做線程定時檢查,補上少的5條鏈接。銷燬多餘的鏈接也是同理。

鏈接銷燬的邏輯

------------------------------

DBCP的鏈接數會在  0 - minIdle - maxIdle - maxActive  之間變化。變化的邏輯描述以下:

默認未配置initialSize(默認值是0)和timeBetweenEvictionRunsMillis參數時,剛啓動tomcat時,鏈接數是0。當應用有一個併發訪問數據庫時DBCP建立一個鏈接。

目前鏈接數量還未達到minIdle,但DBCP也不自動建立新鏈接已使數量達到minIdle數量(沒有一個獨立的工做線程來檢查和建立)。

隨着應用併發訪問數據庫的增多,鏈接數也增多,但都與minIdle值無關,很快minIdle被超越,minIdle值一點用都沒有。

直到鏈接的數量達到maxIdle值,這時的鏈接都是隻增不減的。 再繼續發展,鏈接數再增多並超過maxIdle時,使用完的鏈接(剛剛空閒下來的)會當即關閉,整體鏈接的數量穩定在maxIdle但不會超過maxIdle。

但活動鏈接(在使用中的鏈接)可能數量上瞬間超過maxIdle,但永遠不會超過maxActive。

這時若是應用業務壓力小了,訪問數據庫的併發少了,鏈接數也不會減小(沒有一個獨立的線程來檢查和銷燬),將保持在maxIdle的數量。

默認未配置initialSize(默認值是0),但配置了timeBetweenEvictionRunsMillis=「30000」(30秒)參數時,剛啓動tomcat時,鏈接數是0。立刻應用有一個併發訪問數據庫時DBCP建立一個鏈接。

目前鏈接數量還未達到minIdle,每30秒DBCP的工做線程檢查鏈接數是否少於minIdle數量,若少於就建立新鏈接直到達到minIdle數量。

隨着應用併發訪問數據庫的增多,鏈接數也增多,直到達到maxIdle值。這期間每30秒DBCP的工做線程檢查鏈接是否空閒了30分鐘,如果就銷燬。但此時是業務的高峯期,是不會有長達30分鐘的空閒鏈接的,工做線程查了也是白查,但它在工做。到這裏鏈接數量一直是呈現增加的趨勢。

當鏈接數再增多超過maxIdle時,使用完的鏈接(剛剛空閒下來)會當即關閉,整體鏈接的數量穩定在maxIdle。中止了增加的趨勢。但活動鏈接(在使用中的鏈接)可能數量上瞬間超過maxIdle,但永遠不會超過maxActive。

這時若是應用業務壓力小了,訪問數據庫的併發少了,每30秒DBCP的工做線程檢查鏈接(默認每次查3條)是否空閒達到30分鐘(這是默認值),若鏈接空閒達到30分鐘,就銷燬鏈接。這時鏈接數減小了,呈降低趨勢,將從maxIdle走向minIdle。當小於minIdle值時,則DBCP建立新鏈接已使數量穩定在minIdle,並進行着新老更替。

配置initialSize=「10」時,tomcat一啓動就建立10條鏈接。其它同上。

minIdle要與timeBetweenEvictionRunsMillis配合使用纔有用,單獨使用minIdle不會起做用。

Tomcat中配置DBCP鏈接池

-----------------------------

Tomcat自帶DBCP的包,是$CATALINA_HOME/lib/tomcat-dbcp.jar。

tomcat-dbcp.jar含有commons pool、commons DBCP兩個包的內容。但只含有與鏈接池有關的類。

數據源配置在context.xml文件中, 要在tomcat的lib目錄中放jdbc 驅動包

數據源配置在server.xml的host中,不須要在tomcat的lib目錄中放jdbc 驅動包,只使用工程中的jdbc驅動包

JNDI配置:更改tomcat的server.xml或context.xml

    全局的數據源:

    若是須要配置全局的 Resource,則在server.xml的GlobalNamingResources節點裏加入Resource,再在Context節點裏加入ResourceLink的配置。

    全局的resource只是爲了重用,方便全部該tomcat下的web工程的數據源管理,但若是你的tomcat不會同時加載多個web工程,也就是說一個tomcat只加載一個web工程時,是沒有必要配置全局的resource的。

每一個web工程一個數據源:

在$CATALINA_HOME/conf/context.xml的根節點Context里加入Resource配置。這種配置方法,你在context.xml配置了一個數據源,但Tomcat中有同時運行着5個工程,那了就壞事兒了,這個在Tomcat啓動時數據源被建立了5份,每一個工程1份數據源。鏈接數會是你配置的參數的5倍。

只有在你的Tomcat只加載一個web工程時,才能夠直接以context.xml配置數據源。

<Resource name="jdbc/testDB"       //指定的jndi名稱,會用於spring數據源bean的配置和ResourceLink的配置

               type="javax.sql.DataSource"   //數據源牀型,使用標準的javax.sql.DataSource

               driverClassName="com.mysql.jdbc.Driver"    //JDBC驅動器

               url="jdbc:mysql://localhost:3306/test" //數據庫URL地址            

               username="test"     //數據庫用戶名

               password="test"   //數據庫密碼

               maxIdle="40"   //最大的空閒鏈接數

               maxWait="4000" //當池的數據庫鏈接已經被佔用的時候,最大等待時間

               maxActive="40" //鏈接池當中最大的數據庫鏈接

               removeAbandoned="true"

               removeAbandonedTimeout="180"

               logAbandoned="true" //被丟棄的數據庫鏈接是否作記錄,以便跟蹤

               factory="org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory" />

      這裏的factory指的是該Resource 配置使用的是哪一個數據源配置類,這裏使用的是tomcat自帶的標準數據源Resource配置類,這個類也能夠本身寫,實現javax.naming.spi.ObjectFactory 接口便可。某些地方使用的commons-dbcp.jar中的org.apache.commons.dbcp.BasicDataSourceFactory,若是使用這個就需把commons-dbcp.jar及其依賴的jar包,都放在tomcat的lib下,光放在工程的WEB-INF/lib下是不夠的。

     ResourceLink 的配置有多種:

     1)tomcat安裝目錄下的conf/context.xml,把全局的resource直接公開給該tomcat下的全部web工程,在Context節點中加入:

<ResourceLink global="jdbc/testMDB" name="jdbc/testMDB" type="javax.sql.DataSource"/>  

不建議在此文件中,不使用<ResourceLink/>,而使用<Resource/>直接配置數據源,緣由上面已說明了。  

     2)tomcat安裝目錄下的conf/server.xml,該方法能夠指定把哪些source綁定到哪一個web工程下。

<!-- 新增,第一行爲加載的工程配置,第二行是該工程須要的ResourceLink配置 -->

<context docBase="/web/webapps/phoenix" path="" reloadable="false">

      <ResourceLink global="jdbc/testMDB" name="jdbc/testMDB" type="javax.sql.DataSource"/>

</context>

也可在此文件中,不使用<ResourceLink/>,而使用<Resource/>直接配置數據源。

     3)安裝目錄下的conf/localhost/下創建一個xml文件,文件名是<yourAppName>.xml。好比工程名爲test,則該xml名爲test.xml。

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

<Context>  

    <ResourceLink global="jdbc/testMDB" name="jdbc/testMDB" type="javax.sql.DataSource"/>      

</context>

也可在此文件中,不使用<ResourceLink/>,而使用<Resource/>直接配置數據源。

     4)tomcat安裝目錄下的\webapps\test\META-INF\context.xml的Context節點中增長:

<ResourceLink global="jdbc/testMDB" name="jdbc/testMDB" type="javax.sql.DataSource"/>

也可在此文件中,不使用<ResourceLink/>,而使用<Resource/>直接配置數據源。

本文內容都在tomcat6.0上運行測試過,還下載了commons DBCP的源碼,加入了跟蹤日誌,用於驗證本文的理論。

鏈接池排名(純我的見解)

-----------------------------

Tomcat JDBC pool

DBCP 1.4

c3p0   速度不錯

BoneCP 速度不錯,但會啓用不少附加線程作回收、關閉工做。

Proxool 在高併發時出現異常

DBCP 1.2

DBPool 最差,墊底。

參考文檔《Java鏈接池評估報告》

相關文章
相關標籤/搜索