在之前的一次讨论中,有同行指出V$OPEN_CURSOR中列出的不是OPEN CURSOR而是SESSION CACHED CURSOR,原因是在一次ORA-01000(maximum open cursors exceeded)事故中他没有从V$OPEN_CURSOR中找到大量的打开游标。 对于这个问题,我们可以利用JAVA程序做一个演示来说明,以下为JAVA代码:
package javaapplication2; import java.util.logging.Level; import java.util.logging.Logger; import oracle.jdbc.*; import java.sql.*; public class Main { public static void main(String[] args) throws SQLException { try { Class.forName("oracle.jdbc.driver.OracleDriver"); }catch(Exception e ){} Connection cnn1=DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:G11R2", "maclean", "maclean"); // Connection m[]=new Connection[2000]; Connection myconn=DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:G11R2", "maclean", "maclean"); Statement stat1=myconn.createStatement(); ResultSet rst1=stat1.executeQuery("select * from v$version"); while(rst1.next()) { System.out.println(rst1.getString(1)); } rst1=stat1.executeQuery("select distinct sid from v$mystat"); while (rst1.next()){ System.out.println("MY SID IS "+rst1.getString(1)); } PreparedStatement s[]=new PreparedStatement[2000]; PreparedStatement p; //ResultSet r[]=new ResultSet[2000]; int i=0; while(i<2000){ // m[i]=DriverManager.getConnection("jdbc:oracle:thin:@192.168.1.121:1521:G10R2", "maclean", "maclean"); //s[i]=m[i].createStatement(); //m[i].setAutoCommit(false); //s[i].execute("insert into testjava values(1)"); p=myconn.prepareStatement("select /* FIND_ME_OPPO */ * from dual"); p.execute(); try { Thread.sleep(200); } catch (InterruptedException ex) { Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex); } i++; System.out.println(i+" cursor is ok !"); } } }以上JAVA代码会打个一个数据库会话,并在循环中不断以prepareStatement对象执行SQL语句,且我们不使用close()方法关闭prepareStatement所打开的游标,实际上这是很多JDBC应用产生ORA-01000问题的主要原因,开发人员在使用prepareStatement时不知道要使用close()方法以回收OPEN CURSOR资源。 注意这里在使用JDBC API时的表现(可能是目前最流行应用形式)和PL/SQL中的游标是存在区别的,在PL/SQL使用close cursor语句并不会真正意义上关闭游标。出于性能的考量,PL/SQL中的游标将被缓存以备将来使用,同时Oracle会维护一张cursor的LRU列表,但如果当本会话的游标数量即将达到open_cursors参数所定义的上限数量时,老的游标将被真正意义上close,以便open后来者。
The following is a technical explanation provided by Oracle Development: The server caches cursors opened by the PL/SQL engine. |
本文转自maclean_007 51CTO博客,原文链接:http://blog.51cto.com/maclean/1277838