2009-12-14 71 views
4

我有一種情況,我正在使用的第三方開源產品中Oracle中的遊標用完並收到錯誤:java.sql.SQLException:ORA-01000:最大打開遊標超出使用jdbc解釋oracle中的遊標

我最大的遊標設置爲1000,我試圖弄清楚是否達到這個限制的代碼做錯了什麼,或者如果我只是需要增加我的限制。

經過一番調查後,我發現創建了一個ResultSet的代碼中的一個點,從而增加了我的打開遊標計數1.但是,使用後,該ResultSet很快關閉....但遊標數保持在它的位置是。我能夠在第三方開源項目之外的簡單JDBC應用程序中重現邏輯。

package gov.nyc.doitt.cursor; 

import java.sql.Connection; 
import java.sql.DriverManager; 
import java.sql.PreparedStatement; 
import java.sql.ResultSet; 
import java.sql.SQLException; 

public class CursorTest { 
    public static void main(String[] args) { 
     Connection conn = null; 
     PreparedStatement ps = null; 
     ResultSet rs = null; 

     try { 
      Class.forName("oracle.jdbc.driver.OracleDriver"); 
      conn = DriverManager.getConnection("jdbc:oracle:thin:@myhost:1537:mydb", "username", "password"); 

      // as expected: there are 0 cursors associated with my session at this point 

      ps = conn.prepareStatement("select my_column from my_table where my_id = ?"); 
      ps.setInt(1, 86); 

      // as expected: there are 0 cursors associated with my session at this point 

      rs = ps.executeQuery(); // opens 1 cursor 

      // as expected: there is 1 open cursor associated with my session at this point 
     } catch (Throwable t) { 
      t.printStackTrace(); 
     } finally { 
      // as expected: there is 1 open cursor associated with my session at this point 
      try { 
       rs.close(); 
      } catch (SQLException e) { 
       System.err.println("Unable to close rs"); 
      } 
      // not expected: there is still 1 open cursor associated with my session at this point 
      try { 
       ps.close(); 
      } catch (SQLException e) { 
       System.err.println("Unable to close simplePs"); 
      } 
      // not expected: there is still 1 open cursor associated with my session at this point 
      try { 
       conn.close(); 
      } catch (SQLException e) { 
       System.err.println("Unable to close conn"); 
      } 
      // as expected: at this point my session is dead and so are all the associated cursors 
     } 
    } 
} 

我發現,使我相信,所有打開的遊標將被關閉,如果關閉了我們的ResultSet和預處理語句,但我打開的遊標似乎遊逛一些Oracle文檔。請參閱此FAQ(http://download.oracle.com/docs/cd/B10501_01/java.920/a96654/basic.htm#1006509),其中顯示「關閉結果集或語句釋放數據庫中相應的遊標。」只基於我的測試,似乎並沒有發生,所以我必須缺乏一些基本的瞭解。

任何人都可以解釋Oracle如何處理遊標或指向我的一些文檔,將啓發我?

謝謝!

+0

該代碼看起來不錯,我認爲。是否使用由oracle本身提供的驅動程序。 – Rajat 2009-12-14 20:13:37

+0

你的代碼看起來非常好。 – 2009-12-14 20:19:21

回答

3

很久以前我遇到過類似的問題。據我記得,這個問題是在延遲垃圾收集。在垃圾回收器找到並釋放適當的對象之前,數據庫遊標不會關閉。如果經常創建語句,則可能會遇到此問題。嘗試手動調用垃圾收集器:

Runtime r = Runtime.getRuntime(); 
r.gc(); 

只是爲了檢查這個假設。

+1

如果將所有PreparedStatement和ResultSet邏輯移入單獨的方法,則在PreparedStatement和ResultsSet關閉後,但在連接關閉之前(換句話說,一旦它們超出範圍),遊標就會消失。謝謝! – 2009-12-14 20:54:57

+0

這聽起來像是所使用的JDBC驅動程序中的一個錯誤。如果可以,請將JDBC驅動程序升級到最新的兼容版本。這在修改JDBC編碼以適應實現特定(錯誤)行爲之前是首選。 – BalusC 2009-12-14 21:10:00

+0

我正在使用最新的驅動程序。這只是測試代碼,以幫助我瞭解它是如何工作的,因此不需要進行任何編碼更改以適應任何事情。 – 2009-12-15 14:15:58