使用druid連接池帶來的坑testOnBorrow=false


首先說一下自己程序中遇到的問題,前一段時間新寫了一個項目,主要架構改進,為前端提供接口(spring +springmvc+mybatis) 在新項目中使用的是阿里的druid連接池,配置簡單,除了數據庫地址,驅動類,用戶名和密碼其他一起都是默認,開始的時候由於項目更新上線頻率比較多,沒有出現太多的問題,后來換庫了 。導致之前的鏈接失效了,請求的時候時好時壞,跟了一下代碼以及其他項目的配置,其中有一個屬性 testOnBorrow設置為false(默認設置為false) testOnBorrow=false由於不檢測池里連接的可用性,

 

於是假如連接池中的連接被數據庫關閉了,應用通過連接池getConnection時,都可能獲取到這些不可

用的連接,且這些連接如果不被其他線程回收的話,它們不會被連接池被廢除,也不會重新被創建,

占用了連接池的名額,項目本身作為服務端,數據庫鏈接被關閉,客戶端調用服務端就會出現大量的timeout,客戶端設置了超時時間,然而主動斷開,服務端必然出現close_wait ,由於tomcat 默認最大線程數是200,很快就掛掉,雖說多數源,沒有問題的數據源,鏈接並發過來也會死掉,所以說加大tomcat 默認線程(server.tomcat.max-threads=3000)只是短時間內其他數據源鏈接不會死掉。

 

默認的配置不適用所有場景,所以使用的時候需要配合場景使用。

 但是這也不能全怪druid,畢竟testOnborrow =true 很大的消耗性能,為了保證服務器的穩定,可以配合其他配置來避免這一點,配合testWhileIdle=true(但是默認為false) 和timeBetweenEvictionRunsMillis來避免這種問題,所以testOnborrow =false是可以提高效率的

廢話不多說直接上圖:

 

 

此圖其中的

logAbandoned="true"  

removeAbandoned="true"

 removeAbandonedTimeout="1800"

就是用來配置數據庫斷開后自動連接的。

 

 

由於數據庫連接池會在啟動時就建立所需的若干連接,並一直保持連接狀態,

但是當數據庫服務停止后,這些連接就被外部因素給中斷了

網上優化了的配置信息:

 

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">  

<property name="driverClassName" value="${db.driverClassName}"/>  

<property name="url" value="${db.url}"/>  

<property name="username" value="${db.username}"/>  

<property name="password" value="${db.password}"/>  

<!--initialSize: 初始化連接-->  

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

<!--maxIdle: 最大空閑連接-->  

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

<!--minIdle: 最小空閑連接-->  

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

<!--maxActive: 最大連接數量-->  

<property name="maxActive" value="15"/>  

<!--removeAbandoned: 是否自動回收超時連接-->  

<property name="removeAbandoned" value="true"/>  

<!--removeAbandonedTimeout: 超時時間(以秒數為單位)-->  

<property name="removeAbandonedTimeout" value="180"/>  

<!--maxWait: 超時等待時間以毫秒為單位 6000毫秒/1000等於60秒-->  

<property name="maxWait" value="3000"/>  

<property name="validationQuery">  

<value>SELECT 1</value>  

</property>  

<property name="testOnBorrow">  

<value>true</value>  

</property>  

</bean>  

參數  描述

username  傳遞給JDBC驅動的用於建立連接的用戶名

password  傳遞給JDBC驅動的用於建立連接的密碼

url  傳遞給JDBC驅動的用於建立連接的URL

driverClassName  使用的JDBC驅動的完整有效的Java 類名

connectionProperties  當建立新連接時被發送給JDBC驅動的連接參數,

格式必須是 [propertyName=property;]*

注意 :參數user/password將被明確傳遞,所以不需要包括在這里。

 

參數  默認值  描述

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

 

參數  默認值  描述

initialSize  0  初始化連接:連接池啟動時創建的初始化連接數量,1.2版本后支持

maxActive  8  最大活動連接:連接池在同一時間能夠分配的最大活動連接的數量, 

如果設置為非正數則表示不限制

maxIdle  8  最大空閑連接:連接池中容許保持空閑狀態的最大連接數量,超過的空閑連接將被釋放,

如果設置為負數表示不限制

minIdle  0  最小空閑連接:連接池中容許保持空閑狀態的最小連接數量,低於這個數量將創建新的連接,

如果設置為0則不創建

maxWait  無限  最大等待時間:當沒有可用連接時,連接池等待連接被歸還的最大時間(以毫秒計數),

超過時間則拋出異常,如果設置為-1表示無限等待

 

參數  默認值  描述

validationQuery   SQL查詢,用來驗證從連接池取出的連接,在將連接返回給調用者之前.如果指定,

則查詢必須是一個SQL SELECT並且必須返回至少一行記錄

testOnBorrow  true  指明是否在從池中取出連接前進行檢驗,如果檢驗失敗,

則從池中去除連接並嘗試取出另一個.

注意: 設置為true后如果要生效,validationQuery參數必須設置為非空字符串

testOnReturn  false  指明是否在歸還到池中前進行檢驗

注意: 設置為true后如果要生效,validationQuery參數必須設置為非空字符串

testWhileIdle  false  指明連接是否被空閑連接回收器(如果有)進行檢驗.如果檢測失敗,

則連接將被從池中去除.

注意: 設置為true后如果要生效,validationQuery參數必須設置為非空字符串

timeBetweenEvictionRunsMillis  -1  在空閑連接回收器線程運行期間休眠的時間值,以毫秒為單位.

 如果設置為非正數,則不運行空閑連接回收器線程

numTestsPerEvictionRun  3  在每次空閑連接回收器線程(如果有)運行時檢查的連接數量

minEvictableIdleTimeMillis  1000 * 60 * 30  連接在池中保持空閑而不被空閑連接回收器線程

(如果有)回收的最小時間值,單位毫秒

 

參數  默認值  描述

poolPreparedStatements  false  開啟池的prepared statement 池功能

maxOpenPreparedStatements  不限制  statement池能夠同時分配的打開的statements的最大數量, 

如果設置為0表示不限制

 

 

這里可以開啟PreparedStatements池. 當開啟時, 將為每個連接創建一個statement池,

並且被下面方法創建的PreparedStatements將被緩存起來:

    * public PreparedStatement prepareStatement(String sql)

    * public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency)

注意: 確認連接還有剩余資源可以留給其他statement

參數  默認值  描述

accessToUnderlyingConnectionAllowed  false  控制PoolGuard是否容許獲取底層連接

 

 

如果容許則可以使用下面的方式來獲取底層連接:

    Connection conn = ds.getConnection();

    Connection dconn = ((DelegatingConnection) conn).getInnermostDelegate();

    ...

    conn.close();

 

默認false不開啟, 這是一個有潛在危險的功能, 不適當的編碼會造成傷害.

(關閉底層連接或者在守護連接已經關閉的情況下繼續使用它).請謹慎使用,

並且僅當需要直接訪問驅動的特定功能時使用.

注意: 不要關閉底層連接, 只能關閉前面的那個.

參數  默認值  描述

removeAbandoned  false  標記是否刪除泄露的連接,如果他們超過了removeAbandonedTimout的限制.

如果設置為true, 連接被認為是被泄露並且可以被刪除,如果空閑時間超過removeAbandonedTimeout. 

設置為true可以為寫法糟糕的沒有關閉連接的程序修復數據庫連接.

removeAbandonedTimeout  300  泄露的連接可以被刪除的超時值, 單位秒

logAbandoned  false  標記當Statement或連接被泄露時是否打印程序的stack traces日志。

被泄露的Statements和連接的日志添加在每個連接打開或者生成新的Statement,

因為需要生成stack trace。

 

 

如果開啟"removeAbandoned",那么連接在被認為泄露時可能被池回收. 這個機制在(getNumIdle() < 2)

 and (getNumActive() > getMaxActive() - 3)時被觸發.

舉例當maxActive=20, 活動連接為18,空閑連接為1時可以觸發"removeAbandoned".

但是活動連接只有在沒有被使用的時間超過"removeAbandonedTimeout"時才被刪除,默認300秒.

在resultset中游歷不被計算為被使用.

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM