2011-09-08 135 views
5

我們看到其中來自org.apache.commons.dbcp.BasicDataSource我們的數據庫連接是死亡與插座的寫入錯誤的情況:DBCP回報關閉連接

com.microsoft.sqlserver.jdbc.SQLServerException: Connection reset by peer: socket write error 

所有後續嘗試寫入連接失敗,當然,:

com.microsoft.sqlserver.jdbc.SQLServerException: The connection is closed. 

更新代碼以捕獲此類異常並在發生時請求新連接後,它再次失敗。我是否正確地懷疑調用DataSource#getConnection()實際上在每次調用時都沒有給出新連接?是不是隻是重新使用已關閉的現有連接?

如果我是正確的,扔掉舊連接並請求新連接的正確方法是什麼?

編輯:這是一個什麼樣的更succint版本,我想知道:

Connection c1, c2; 
c1 = DatabaseManager.getConnection(); 
// c1.close() not called 
c2 = DatabaseManager.getConnection(); 

成爲 「C1 C2 ==」 真正的聲明?或者分配了兩個連接?如果是後者,這樣的代碼會代表「連接池泄漏」:

Connection c1; 
c1 = DatabaseManager.getConnection(); 
// c1.close() not called 
c1 = DatabaseManager.getConnection(); 

回答

10

池中的連接已被數據庫關閉。這可能意味着2件事:

  1. 連接池保持連接打開時間過長。
  2. DB在太短的時間後關閉連接。

理論上,增加/減少雙方的超時以調整它應該可以解決問題。

在DBCP上,您最好的選擇是驗證連接,然後再返回testOnBorrow=truevalidationQuery設置。 SELECT 1。您可以在Tomcat JDBC data sources documentation中找到配置選項。


更新按您的更新:

這裏是想什麼,我更succint版本知道:

Connection c1, c2; 
c1 = DatabaseManager.getConnection(); 
// c1.close() not called 
c2 = DatabaseManager.getConnection(); 

成爲 「C1 C2 ==」 一真實的陳述?或者分配了兩個連接?

它是兩個不同的連接。只有當您撥打c1.close()時,c2纔有可能返回相同的連接。

而如果是後者,會像這樣的代碼表示「連接池泄漏」:因爲它從來沒有被返回到池中

Connection c1; 
c1 = DatabaseManager.getConnection(); 
// c1.close() not called 
c1 = DatabaseManager.getConnection(); 

是的,當然它會泄漏的第一個連接。您應該總是關閉try-finally塊中儘可能最短範圍內的所有數據庫資源。然而,一個體面的連接池可以被配置爲收穫被遺棄的連接,但是這絕對不應該被用作「解決方法」。

+0

我認爲連接因前面提到的套接字寫入錯誤而關閉?但是,一旦它關閉,調用getConnection()就會獲得一個新的連接? –

+0

不,關閉池連接只會將它返回池(這就是爲什麼你總是應該關閉'finally'中的連接,否則池可能會耗盡連接)。處理斷開連接的剩餘部分取決於您應該通過配置控制的池。但是,您應該意識到DBCP是一個執行不力的池。另請參閱http://stackoverflow.com/questions/520585/connection-pooling-options-with-jdbc-dbcp-vs-c3p0/3481821#3481821 – BalusC

+0

但是如果close()永遠不會被調用?如果代碼只是繼續調用getConnection()會怎麼樣?它是否仍然重新使用舊的關閉連接,還是從池中獲得新的連接? –

0

我還面臨同樣的問題。然後我意識到我正在導致多個異步ajax調用導致該問題。

我序列化了通話並解決了問題。

+0

請發佈任何相關代碼以供將來的答案搜索者使用。 – GibralterTop