org.apache.commons.dbcp.SQLNestedException: Cannot get a connection, pool ex

原文鏈接org.apache.commons.dbcp.SQLNestedException: Cannot get a connection, pool ex

今天同事在測試文件同步功能時,發現當刪除一個文件夾目錄,裏面含有很多文檔的時候就報:

Caused by: org.apache.commons.dbcp.SQLNestedException: Cannot get a connection, pool exhausted
at org.apache.commons.dbcp.PoolingDataSource.getConnection(PoolingDataSource.java:103)
at org.apache.commons.dbcp.BasicDataSource.getConnection(BasicDataSource.java:540)
at org.springframework.orm.hibernate3.LocalDataSourceConnectionProvider.getConnection(LocalDataSourceConnectionProvider.java:81)
at org.hibernate.jdbc.ConnectionManager.openConnection(ConnectionManager.java:423)
... 154 more
Caused by: java.util.NoSuchElementException: Timeout waiting for idle object
at org.apache.commons.pool.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:756)
at org.apache.commons.dbcp.AbandonedObjectPool.borrowObject(AbandonedObjectPool.java:74)
at org.apache.commons.dbcp.PoolingDataSource.getConnection(PoolingDataSource.java:95)
... 157 more
2010-3-11 9:34:40 org.apache.catalina.core.ApplicationContext log
信息: org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is org.apache.commons.dbcp.SQLNestedException: Cannot get a connection, pool exhausted
[DATAMANAGER] ERROR 2010-03-11 09:34:41,859 [http-8080-2] JDBCExceptionReporter.logExceptions(78) | Cannot get a connection, pool exhausted
[DATAMANAGER] ERROR 2010-03-11 09:34:41,859 [http-8080-2] JDBCExceptionReporter.logExceptions(78) | Cannot get a connection, pool exhausted
org.hibernate.exception.GenericJDBCException: Cannot open connection
......

初看org.apache.commons.dbcp.SQLNestedException: Cannot get a connection, pool exhausted知道是連接池已經耗盡了。

心想不會是在刪除的過程中,定時器已經啓動了建索引進程,由於未控制線程數而導致連接池耗盡?

但是看到同事的測試目錄下文件數也不是很多,全部是圖片,大概也有三四十張。但是建索引也不至於,平時會索引整個數據庫文檔表建索引那時的數量比這裏大多了。

網上一查:

A、Cannot get a connection, pool exhausted解決辦法

轉自:http://chivas2008.blogbus.com/logs/28735149.html

解決的辦法有3個

1重啓你的服務器

2在content.xml中,將maxActive設置爲零,或者調高它的值

3在你的程序中正確關閉connections 這裏有一點要注意要把關閉的語句寫在finally中,如果你寫在try{}中出現異常的話是無法正確關閉的。

要象這樣

} catch (SQLException e) {
/** Exception handling **/
} finally {
try {
if (stmt != null)
stmt.close();
if (dbConnection != null)
dbConnection.close();
} catch (SQLException e) {
/** Exception handling **/
}
}
當然這3個方法裏前兩個並不能從根本上解決你的問題,所以還是要好好研究你的程序,一定要將用完的connection放回到池中。

1 問題描述
Web程序在tomcat剛開始運行時速度很快,但過一段時間後發現速度變得很慢。
檢查日誌輸出,發現異常如下:
org.apache.commons.dbcp.SQLNestedException: Cannot get a connection, pool exhausted, cause:
java.util.NoSuchElementException: Timeout waiting for idle object
同時在SQLServer事件探查器中發現,每執行一次sql語句都要產生Audit login事件,語句執行後產生
Audit logout事件。說明每一次tomcat都是重新打開新的連接。
2 問題解決
tomcat 的數據源定義提供了三個參數:
a. 如果設爲true則tomcat自動檢查恢復重新利用,沒有正常關閉的Connection.(默認是false)
<parameter>
<name>removeAbandoned</name>
<value>true</value>
</parameter>
b. 設定連接在多少秒內被認爲是放棄的連接,即可進行恢復利用。
<parameter>
<name>removeAbandonedTimeout</name>
<value>60</value>
</parameter>
c.輸出回收的日誌,可以詳細打印出異常從而發現是在那裏發生了泄漏
<parameter>
<name>logAbandoned</name>
<value>true</value>
</parameter>
B、Timeoutwaitingforidleobject

轉自:http://203.208.37.132/search?q=cache:9TmBcAJrYhQJ:jiangzi87.blog.ccidnet.com/blog.php%3Fdo%3Dshowone%26itemid%3D474468%26typ%3Dblog+java.util.NoSuchElementException:+Timeout+waiting+for+idle+object&cd=5&hl=zh-CN&ct=clnk&gl=cn&st_usg=ALhdy2-dZRxeN0j7d6MJ0Shp7tXcjwyumQ

1、request too large錯誤

在我們應用系統中,有些用戶反映在填寫申請表的時候,有時會出現request too large 的錯誤,導致操作失敗.經查看原因是: 用戶在填寫申請表的時候.我們會擱一定的時間,朝cookies裏保存數據.如果cookies裏數據過大,就會導致request too large 的錯誤,清除cookies,問題就可以解決..
2、Timeoutwaitingforidleobject錯誤
org.apache.commons.dbcp.SQLNestedException: Cannot get a connection, pool exhausted, cause:
java.util.NoSuchElementException:Timeoutwaitingforidleobject
是因爲連接沒有關閉,導致其他的連接去連接這個老的連接。導致出錯
檢查是否沒有關閉數據庫連接

看到我對於A中紅色顯示的部分,這個參數對於查找原因真的很重要。初看上面的報錯真得讓我一頭霧水,後來配置上這個參數,再運行控制檯的報錯信息更加明確,從報錯信息中我找到了運行該功能存在兩個地方連接池泄漏問題:

at com.xxx.action.DoccatalogAction.getDocCatalogListByCatCode(DoccatalogAction.java:1178)


at com.xxx.organization.dao.hibernate.UserHibernateDAOBean.getUserByName(UserHibernateDAOBean.java:54)
at com.xxx.doc.desktopapp.action.DesktopAppAction.removeAllDataByCategoryList(DesktopAppAction.java:564)

從中可以知道是在哪個方法,哪一行的代碼存在連接池泄漏問題。

【原因】:

原來真的是同事寫的代碼中未對session,Connection,Statement等與數據庫相關的連接未釋放。

【解決方法】:

1、對於session的部分全部加上

//避免未釋放連接導致連接池耗盡
Session session = this.getSession();
try{
//執行代碼 ...
}finally{
this.releaseSession(session);
}

2、對於數據庫連接

Session session = listHelper.getSessionFactory().openSession();
Connection cnn = null;
Statement state = null;
ResultSet rs = null;
try{
cnn = session.connection();
state = cnn.createStatement(
ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
String strSQL="";
strSQL+=" select d.* from tb_datapriv_grant g , tb_datapriv d where g.member_id='"+userid+"' ";

rs = state.executeQuery(strSQL);//查詢目錄用戶是否有權限
......
}finally{

//關閉rs
if(null!=rs){
rs.close();
rs = null;
}
//關閉state
if(null!=state){
state.close();
state = null;
}
//關閉cnn
if(null!=cnn){
cnn.close();
cnn = null;
}
//關閉session
if(null!=session){
session.close();
session = null;
}
}

當然,可能你的項目裏獲取session和釋放session的方法和我的並不一樣,因爲有的類方法是我們封裝好的。但是相同的是一定要記得釋放。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章