1. 程式人生 > >tomcat7使用dbcp連線池遇到的坑

tomcat7使用dbcp連線池遇到的坑

專案部署在tomcat後每隔一段時間便會報錯


 Cause: java.sql.SQLException: Could not retrieve transation read-only status server
; SQL []; Could not retrieve transation read-only status server; nested exception is java.sql.SQLException: Could not retrieve transation read-only status server

開始以為是資料庫事務級別過高,後來發現是每隔一天沒操作便會丟失連結,於是找到原因


MySQL 的預設設定下,當一個連線的空閒時間超過8小時後,MySQL 就會斷開該連線,而 c3p0/dbcp 連線池則以為該被斷開的連線依然有效。在這種情況下,如果客戶端程式碼向c3p0/dbcp 連線池請求連線的話,連線池就會把已經失效的連線返回給客戶端,客戶端在使用該失效連線的時候即丟擲異常。

於是簡單的修改了mysql的設定


    #my.cnf
    wait_timeout=31536000  
    interactive_timeout=31536000  

但是這樣改動的話wait_timeout太大了,會保留太多的無效連結,於是就從連線池上採取改動。在spring 連線池配置中加入定時檢測,配置欄位如下


maxWait="3000" 從池中取連線的最大等待時間,單位ms.  
initialSize="10"  初始化連線  
maxIdle="60"   最大空閒連線  
minIdle="10"   最小空閒連線  
maxActive="80" 最大活動連線  
   
validationQuery = "SELECT 1"  驗證使用的SQL語句  
testWhileIdle = "true"      指明連線是否被空閒連接回收器(如果有)進行檢驗.如果檢測失敗,則連線將被從池中去除.  
testOnBorrow = "false"   借出連線時不要測試,否則很影響效能  
timeBetweenEvictionRunsMillis = "30000"  每30秒執行一次空閒連接回收器  
minEvictableIdleTimeMillis = "1800000"  池中的連線空閒30分鐘後被回收,,預設值就是30分鐘
numTestsPerEvictionRun="10" 在每次空閒連接回收器執行緒(如果有)執行時檢查的連線數量,預設值就是3.  
      
removeAbandoned="true"  連線洩漏回收引數,當可用連線數少於3個時才執行  
removeAbandonedTimeout="180"  連線洩漏回收引數,180秒,洩露的連線可以被刪除的超時值

配置後問題得到解決。

檢視資料的過程中發現dbcp連線池是有兩種的:Tomcat JDBC連線池與Apache Commons DBCP連線池。下面是兩者的區別


1.Commons DBCP 1.x是單執行緒。在分配物件或物件返回的時候,會鎖定全部連線池。(不適用於Commons DBCP 2.x)

2.Commons DBCP 1.x在邏輯cpu數量增加或者併發縣城增加時,效能可能會變的很慢。高併發系統受到的影響會更加明顯(不適用於Commons DBCP 2.x)

3.Commons DBCP 擁有60多個類。tomcat-jdbc-pool核心只有8個類,而未來如果需求變更,那麼tomcat JDBC連線池會改動更少。

4.Commons DBCP使用靜態介面,需要對應的jre需要對應的DBCP 版本,否則會丟擲 NoSuchMethodException異常

5.Tomcat JDBC連線池無需為庫本身新增額外執行緒,就能獲取非同步連線。

6.Tomcat JDBC連線池使用 javax.sql.PooledConnection介面獲取底層連線

7.Tomcat JDBC連線池 可以防止飢餓。如果池變空,執行緒將等待一個連線。當連線返回時,池就將喚醒正確的等待執行緒。

配置tomcat-dbcp是在tomcat安裝路徑下配置的

配置Tomcat-DBCP

Tomcat預設使用的是DBCP資料庫連線池,其實從本質上講,Tomcat是利用Apache Commons DBCP來實現的,只不過把特定的功能整合到了tomcat-dbcp.jar包中,這個包在tomcat的lib裡面.

1.配置context.xml

    注意:(1)不是Context.xml,這個需要看你tomcat裡面conf目錄下是context.xml還是Context.xml,和這個一樣就行.

        (2)這個配置即可以在${CATALINA_HOME}/conf/context.xml裡配置,(CATALINA_HOME是你tomcat的安裝目錄)

        也可以在${CATALINA_HOME}/webapps/專案名/META-INF/context.xml裡,(專案名就是webapps下的一些目錄名稱,

        比如:ROOT.如果ROOT下沒有META-INF,那麼建立一個就行,然後再在META-INF裡建立文件context.xml)

如何將tomcat-dbcp資料來源使用到專案中呢 有如下配置

在web專案的web.xml中加入資源引用:(可省略)

<resource-ref>
<description>JNDI DataSource</description>
<res-ref-name>jndi/testdb</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>

啟動的時候載入tomcat配置的JNDI 公開資料來源,其中res-ref-name值要和server.xml 、context.xml的name值一致。


在web專案中配置spring資料來源bean資訊:

<bean id="dataSource"class="org.springframework.jndi.JndiObjectFactoryBean">
<propertyname="jndiName">
<value>java:comp/env/jndi/testdb</value>
 </property>
</bean>
直接替換專案WEB-INF/conf/data-access-config.xml檔案中 beanid=”dataSource” 的節點即可使用

但是由於考慮到使用jndi配置資料來源對已有程式影響較大,所以最後只是升級了common-dbcp版本來獲取更高的效能。以上就是解決這個問題大致的過程。
參考:
https://blog.csdn.net/lzwglor...
http://elf8848.iteye.com/blog...
https://blog.csdn.net/Jacabe/...
https://blog.csdn.net/acoolpe...
https://blog.csdn.net/u011487...

原文地址:https://segmentfault.com/a/1190000017065607