深入理解資料庫連線池DBCP
1.DBCP簡介
DBCP(DataBase connection pool),資料庫連線池。是 apache 上的一個 java 連線池專案,也是 tomcat 使用的連線池元件。單獨使用dbcp需要2個包:commons-dbcp.jar,commons-pool.jar由於建立資料庫連線是一個非常耗時耗資源的行為,所以通過連線池預先同資料庫建立一些連線,放在記憶體中,應用程式需要建立資料庫連線時直接到連線池中申請一個就行,用完後再放回去。
Tomcat 的連線池正是採用該連線池來實現的。該資料庫連線池既可以與應用伺服器整合使用,也可由應用程式獨立使用。Tomcat通過JAR包tomcat-dbcp.jar集成了連線池DBCP的功能,通過在context.xml中配置連線池的方式引入DBCP連線池,也可以在server.xml檔案中配置全域性的連線池。
2.DBCP與DBCP2的區別
2.1 依賴的JAR包不同
(1)DBCP依賴的JAR包是commons-dbcp-1.*.jar和commons-pool-1.*.jar
(2)DBCP2依賴的JAR包是commons-dbcp2-2.*.jar和commons-pool2-2.*.jar
2.2 依賴的JDK版本不同
(1)DBCP2只在JAVA7下編譯和執行(JDBC4.1)
(2)DBCP1.4只在JAVA6下編譯和執行(JDBC4)
(3)DBCP1.3只在JAVA1.4~1.5下編譯和執行(JDBC3)
2.3 更強大的效能和支援更多的功能DBCP2基於commons-pool2,效能是會有提升,並且支援JMX
2.4 配置引數不同
比如maxActive 改成 maxTotal
3.DBCP2引數配置說明
3.1常用連結配置
引數 | 描述 |
---|---|
username | 傳遞給JDBC驅動的用於建立連線的使用者名稱 |
password | 傳遞給JDBC驅動的用於建立連線的密碼 |
url | 傳遞給JDBC驅動的用於建立連線的URL |
driverClassName | 使用的JDBC驅動的完整有效的java 類名 |
connectionProperties | 當建立新連線時被髮送給JDBC驅動的連線引數,格式必須是 [propertyName=property;]。 |
3.2 資料來源連線數量配置
引數 | 預設值 | 描述 |
---|---|---|
initialSize | 0 | 初始化連線:連線池啟動時建立的初始化連線數量,1.2版本後支援 |
maxTotal | 8 | 最大活動連線:連線池在同一時間能夠分配的最大活動連線的數量, 如果設定為非正數則表示不限制. dbcp1.X為maxActive |
maxIdle | 8 | 最大空閒連線:連線池中容許保持空閒狀態的最大連線數量,超過的空閒連線將被釋放,如果設定為負數表示不限制 |
minIdle | 0 | 最小空閒連線:連線池中容許保持空閒狀態的最小連線數量,低於這個數量將建立新的連線,如果設定為0則不建立 |
maxWaitMillis | 無限 | 最大等待時間:當沒有可用連線時,連線池等待連線被歸還的最大時間(以毫秒計數),超過時間則丟擲異常 ,如果設定為-1表示無限等待 dbcp1.X為maxWait |
3.3 事務屬性配置
引數 | 預設值 | 描述 |
---|---|---|
defaultAutoCommit | true | 連線池建立的連線的預設的auto-commit狀態 |
defaultReadOnly | driver default | 連線池建立的連線的預設的read-only狀態. 如果沒有設定則setReadOnly方法將不會被呼叫 .(某些驅動不支援只讀模式,比如:Informix) |
defaultTransactionIsolation | driver default | 連線池建立的連線的預設的TransactionIsolation狀態. 下面列表當中的某一個: (參考javadoc) NONE、READ_COMMITTED、READ_UNCOMMITTED、REPEATABLE_READ、SERIALIZABLE |
defaultCatalog | 連線池建立的連線的預設的catalog |
3.4 資料來源連線健康狀況檢查
引數 | 預設值 | 描述 |
---|---|---|
validationQuery | SQL查詢,用來驗證從連線池取出的連線,在將連線返回給呼叫者之前.如果指定, 則查詢必須是一個SQL SELECT並且必須返回至少一行記錄 | |
testOnBorrow | true | 指明是否在從池中取出連線前進行檢驗,如果檢驗失敗,則從池中去除連線並嘗試取出另一個. 注意: 設定為true後如果要生效,validationQuery引數必須設定為非空字串 |
testOnReturn | false | 指明是否在歸還到池中前進行檢驗. 注意: 設定為true後如果要生效,validationQuery引數必須設定為非空字串 |
testWhileIdle | false | 指明連線是否被空閒連接回收器(如果有)進行檢驗.如果檢測失敗,則連線將被從池中去除. 注意: 設定為true後如果要生效,validationQuery引數必須設定為非空字串 |
timeBetweenEvictionRunsMillis | -1 | 在空閒連接回收器執行緒執行期間休眠的時間值,以毫秒為單位.如果設定為非正數 ,則不執行空閒連接回收器執行緒 |
numTestsPerEvictionRun | 3 | 在每次空閒連接回收器執行緒(如果有)執行時檢查的連線數量 |
minEvictableIdleTimeMillis | 10006030 | 連線在池中保持空閒而不被空閒連接回收器執行緒(如果有)回收的最小時間值,單位毫秒 |
3.5 快取語句
引數 | 預設值 | 描述 |
---|---|---|
poolPreparedStatements | false | 開啟池的prepared statement 池功能 |
maxOpenPreparedStatements | 不限制 | statement池能夠同時分配的開啟的statements的最大數量, 如果設定為0表示不限制 |
3.6 連線洩露回收
引數 | 預設值 | 描述 |
removeAbandonedOnMaintenance | false | 標記是否刪除洩露的連線,如果他們超過了removeAbandonedTimout的限制.如果設定為true, 連線被認為是被洩露並且可以被刪除,如果空閒時間超過removeAbandonedTimeout. 設定為true可以為寫法糟糕的沒有關閉連線的程式修復資料庫連線. dbcp1.X為removeAbandoned |
removeAbandonedTimeout | 300 | 洩露的連線可以被刪除的超時值, 單位秒 |
logAbandoned | false | 標記當Statement或連線被洩露時是否列印程式的stack traces日誌。 被洩露的Statements和連線的日誌新增在每個連線開啟或者生成新的Statement, 因為需要生成stack trace。 |
注意:
•Java資料庫連線有“8小時問題”,所以destroy-method="close"一定要加上。“8小時問題”是指一個連線空閒8小時資料庫會自動關閉,而資料來源並不知道。•高併發下,可以testOnBorrow設定false,testWhileIdle設定為true,這樣就會定時對後臺空連結進行檢測發現無用連線就會清除掉,不會每次都去都去檢測是否8小時的空連結。
4.DBCP2原理
DBCP2在初始化時會從資料庫獲取指定數量的連線,把這些連線存放到空閒連線佇列LinkedBlockingDeque裡面,這個佇列是雙向鏈路阻塞型佇列,先進先出,每次要使用連線時就從這個佇列獲取頭部結點,獲取連線時使用的鎖是ReentrantLock.獲取到連線時,該連線節點出佇列,更改狀態並且存放到一個ConcurrentHashMap中,標識該連線已被使用,另外會有一個空閒連線檢測執行緒不斷去檢測ConcurrentHashMap中連線的狀態,如果連線已經關閉(不是資料庫連線關閉,而是連線在DBCP連線池中關閉),則把它從ConcurrentHashMap中刪除,並且回收到LinkedBlockingDeque裡面。
5.DBCP2的優缺點
5.1 優點
配置簡單
5.2 缺點
無論是空閒連線還是已使用的連線,都是存放加鎖的ConcurrentHashMap或LinkedBlockingDeque中,併發量低,效能不好,適用於小型系統。從資料庫獲取連線的過程中還加了synchronized同步鎖,如果網路容易中斷的場景下,一旦與資料庫建立的網路出現問題,容易導致死鎖。
本人在線上環境的使用情況看,存在連線無法正常關閉的問題,導致連線耗盡丟擲異常,需要配空閒連接回收執行緒去定時回收。