2011-10-19 29 views
4

在最新版本的DBCP和C3P0上,使用Spring的Ibatis支持,我遇到了兩個泄漏連接的問題。帶C3P0或DBCP的Spring ORM正在泄漏連接

該方案是有一個運行SQL的日誌鎖定多個表。這會導致我的池中的連接在用戶觸發鎖定表的查詢時最大化。最後,管理員進入MySQL並在長時間運行的SQL上執行kill query <id>

如果有足夠的線程(在我的周圍50個或更多的情況下),它正在等待繞了DB線程在游泳池進行檢查回來,然後我看到類似線程轉儲如下:

java.lang.Thread.State: WAITING (on object monitor) 
    at java.lang.Object.wait(Native Method) 
    at com.mchange.v2.resourcepool.BasicResourcePool.awaitAvailable(BasicResourcePool.java:1315) 
    at com.mchange.v2.resourcepool.BasicResourcePool.prelimCheckoutResource(BasicResourcePool.java:557) 
    - locked <0x00002aaacbb01118> (a com.mchange.v2.resourcepool.BasicResourcePool) 
    at com.mchange.v2.resourcepool.BasicResourcePool.checkoutResource(BasicResourcePool.java:477) 
    at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool.checkoutPooledConnection(C3P0PooledConnectionPool.java:525) 
    at com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource.getConnection(AbstractPoolBackedDataSource.java:128) 
    at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:113) 
    at 

java.lang.Thread.State: WAITING (on object monitor) 
    at java.lang.Object.wait(Native Method) 
    at java.lang.Object.wait(Object.java:485) 
    at org.apache.commons.pool.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:1104) 
    - locked <0x00002aab0f030620> (a org.apache.commons.pool.impl.GenericObjectPool$Latch) 
    at org.apache.commons.dbcp.PoolingDataSource.getConnection(PoolingDataSource.java:106) 
    at org.apache.commons.dbcp.BasicDataSource.getConnection(BasicDataSource.java:1044) 
    at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:113) 
    at 

和這些線程等待撒手人寰。

如果該池已最大化,並且只有少數(約5個)線程正在等待池中的空閒連接,則不會發生這種情況。

我知道有配置可以解決這個問題(設置超時等),但我有興趣爲什麼這是發生在第一個地方?爲什麼當有50個或更多的線程在等待連接,並且我終止了長時間運行的SQL時,活動線程不會返回到池中?

更新:我應該明確表示,我使用Spring 3.0.2和 ibatis的2.3。我使用SqlMapClientTemplate,它爲我管理我的 連接。此時,我開始認爲它是 Ibatis 2.3沒有正確處理重負載。

+3

您是否在執行查詢後關閉連接? – BalusC

+0

@BalusC我對Spring使用ComboPooledDataSource或BasicDataSource,所以我不管理在我的Java代碼中關閉這些連接的open c。也許春天是問題。 – stevebot

+0

你應該顯示一些你如何使用連接的代碼。僅僅因爲你使用Spring來管理數據源,並不意味着它會爲你關閉連接。 – Nick

回答

2

很像@BalusC問,你關閉你的連接嗎?他們應該在您的Java try-catch-finallyfinally條款中關閉。每一個的環繞connection.close()方法在自己的try { con.close() } catch (Exception ignore) {}

可選,你應該這樣做的ResultSet然後Statement然後Connection的順序。在您的初始try塊之外聲明您的Connection,StatementResultSet作爲null並在您的try塊中實例化。

Connection con = null; 
Statement stmt = null; 
ResultSet rs = null; 

try { 

    con = getConnectionFromPoolMethod(); 

    // ... 
    // instantiate your statement and result set as normal 
    // make your sql call; 
    // extract data from result set to appropriate POJO 

} catch (Exception ex) { 
    // handle your exception, log, wrap, enhance or rethrow or whatever 
} finally { 
    if (rs != null) try { rs.close(); } catch (Exception ignore) {} 
    if (stmt != null) try { stmt.close(); } catch (Exception ignore) {} 
    if (con != null) try { con.close(); } catch (Exception ignore) {} 
} 

如果你爲它,而不是在每個finally一個封裝了SQL調用所有上面的代碼,你可以選擇使用DbUtils實用類Apache Commons DbUtils

import org.apache.commons.dbutils.DbUtils; 

並應用closeQuietly方法。該finally塊看起來是這樣,而不是:

} finally { 
    DbUtils.closeQuietly(con, stmt, rs); 
} 
+0

+1沒問題 - 很好的答案。不要吝嗇挑剔,但捕捉特定的檢查異常,比如「SQLException」比捕捉純粹的Exception更好。 –

+0

這是更好的做法,但是如果我猜測他是新人,他可能不會考慮導入另一個班級。暫時編輯添加選項以使用DbUtils。 – JoshDM

+0

@FredCheese我的Java代碼沒有管理這些連接。我創建數據源,然後將其傳遞給SqlMapClientTemplate,它是一個Spring對象。因此,我從來不需要管理關閉連接。 – stevebot

2

只需添加到@ BalusC的評論和@JoshDM's answer,當你調用在你的Java代碼Connectionclose(),幕後這實際上只是檢查連接回您的連接池而不是物理上關閉它。這就是爲什麼始終通過Java代碼關閉連接非常重要的原因,無論底層JDBC驅動程序是否將它們集中在一起。這個在this post

更多的討論。

4

當使用C3PO,我強烈建議嘗試這種feature。當您在事務外執行數據庫修改時,通常會出現連接泄漏。與未完成寫入的連接無法重用並從池中丟失。如果在相當長的超時時間內啓用此調試,您將能夠看到具有可疑數據庫操作的堆棧跟蹤。

確保在堆棧跟蹤看到的操作正確管理事務。還可以通過將c3p0記錄器設置爲調試級別來監視連接池的使用情況。

+0

謝謝,DBCP也有一個名爲removeAbandoned的類似配置。當我將其刪除時,我看到我失去了聯繫。我仍然不知道爲什麼應用程序正在丟失這些連接。 – stevebot

+0

我對dbcp不熟悉,但是我通過c3p0 debugUnreturnedConnectionStackTraces跟蹤了很多連接泄漏。請記住,您將看到的堆棧跟蹤是在從池中取出連接時生成的。這意味着您將看到導致連接丟失的確切呼叫。然後確保在上面的sql調用中有@Transactional或同等變更數據庫。 – mrembisz

+0

謝謝,c3p0可能比dbcp更冗長。可悲的是,這部分代碼不支持事務。 – stevebot