tomcat7使用dbcp連線池遇到的坑
阿新 • • 發佈:2018-11-19
專案部署在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...