2009-12-14 2 views
4

У меня возникла ситуация, когда сторонний продукт с открытым исходным кодом, который я использую, заканчивает курсоры в Oracle и получает ошибку: java.sql.SQLException: ORA-01000: максимальные открытые курсоры превышеныуточнение курсоров в oracle с jdbc

Мои максимальные курсоры установлены на 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 
     } 
    } 
} 

Я нашел документации Oracle, что заставило меня думать, что все открытые курсоры будут закрыты, если вы закрыли ResultSet и PreparedStatements, но, кажется, мои открытые курсоры будут торчать. См. Этот FAQ (http://download.oracle.com/docs/cd/B10501_01/java.920/a96654/basic.htm#1006509), в котором говорится: «Закрытие набора результатов или инструкции освобождает соответствующий курсор в базе данных». Только на основе моего теста, который, похоже, не происходит, поэтому мне не хватает базового понимания.

Может ли кто-нибудь объяснить, как Oracle обрабатывает курсоры или указывает мне на какую-то документацию, которая просветит меня?

Спасибо!

+0

Код выглядит прекрасно, я думаю. Вы используете драйвер, предоставленный самим oracle. – Rajat

+0

Ваш код выглядит отлично. –

ответ

3

Довольно давно я столкнулся с аналогичной проблемой. Насколько я помню, проблема заключалась в задержке сбора мусора. Курсор базы данных не будет закрыт, пока сборщик мусора не обнаружит и не выпустит соответствующий объект. Если утверждения создаются часто, вы можете столкнуться с этой проблемой. Попробуйте время от времени вызывать сборщик мусора:

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

просто для проверки этого предположения.

+1

Если я переведу все логики PreparedStatement и ResultSet в отдельный метод, курсоры исчезнут после закрытия PreparedStatement и ResultsSet, но до того, как соединение будет закрыто (другими словами, когда они выйдут из области видимости). Благодаря! –

+0

Это больше похоже на ошибку в драйвере JDBC. Если возможно, обновите драйвер JDBC до последней доступной версии. Это предпочтительнее, чем изменение кодирования JDBC, чтобы соответствовать конкретному (конкретному) поведению. – BalusC

+0

Я использую последний драйвер. Это всего лишь тестовый код, который поможет мне понять, как он работает, поэтому никаких изменений в кодировании не предпринимается, чтобы что-то учитывать. –

Смежные вопросы