您的位置:首页 > 数据库 > Oracle

Oracle: ORA-01000: maximum open cursors exceed

2014-05-07 11:40 169 查看
Oracle的异常在系统开发中经常遇到 游标达到上限而报错 

一、基本概念:

1. 游标是依附于statement 每一次statement的执行都会产生一个游标 如果具备良好的编码习惯 本异常是不会出现的 因为cursor在statement.close()后就会被释放了 所以主要的问题是statement的及时关闭 无论是在什么地方

2. Oracle数据库可以设置游标上限 open_cursor, 此上限是基于一个connection/session,如果一个connection的游标超限 异常就跑出来了

二、相关查询语句

(1)查看opened 游标:

select * from v$sesstat a,v$statname b where a.STATISTIC#=b.STATISTIC# and b.NAME='opened cursors current';

(2) 查看session:

select * from v$session where username is not null;

(3)配置增加cursor的上限

alter system set open_cursor 800, scope both;

三. 遇到的问题

描述:系统中有个业务比较复杂,首先建立一些临时表 然后伴随着增删查的操作 最后把connection放到session中缓存 期间执行的数据库语句有成百上千次 在增删改查的过程中 报出了这个错误 

(1) .首先去检查是否有rs, statement没有close

(2). 配合查询游标sql看一下是哪些code导致游标不断增长而不释放

结果:最后发现是操作临时表的时候虽然执行了statement.close();但是其游标并没有被释放

自己写了个临时程序去印证了这一点 参见文章最后代码TestCursorOracle.java

为什么cursor不释放呢 我去找相关的资料 不过还是不知道为什么 大牛知道的话麻烦解释下 谢谢

四. 解决:

由于系统用的WAS 容器可以配置一些参数去管理数据库的连接 其中有个参数叫statement cache size 可以设置的小一些 个人理解 当statement达到一定数量的时候 容器回去关闭最久最少不用的 cursor就跟着释放了

然后增大数据库cursor的上限

另外tomcat的话可以参照poolPreparedStatements的变量 

五. 总结:问题解决不完美 有点遗憾 不过时间有限 限记录下

注意:

1. statement、resultset、connection及时关闭

2. 避免循环中多次createstatement, preparestatement, 尽量在循环外

3. 不喜欢临时表

附代码:

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.PreparedStatement;

import java.sql.ResultSet;

import java.sql.SQLException;

import java.sql.Statement;

public class TestCursorOracle {
public static void main(String args[]) {

Connection connection = getConnection();
if (connection == null) {
System.out.println("Failed to get the connection.");
return;
}
StringBuffer sbCreateTempTable = new StringBuffer()
.append("create global temporary table schema.test101 ")
.append(" \n").append(" (ID CHARACTER(1) NOT NULL ) \n")
.append(" ON COMMIT PRESERVE ROWS");

// Create temp table
Statement statement = null;
try {
statement = connection.createStatement();
statement.executeUpdate(sbCreateTempTable.toString());
} catch (Exception e) {
e.printStackTrace();
} finally {
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
// Select the temp table

for (int i = 0; i < 400; i++) {
PreparedStatement statementSelect = null;
ResultSet rs = null;
try {
statementSelect = connection.prepareStatement("select * from schema.test101");
rs = statementSelect.executeQuery();
while (rs.next()) {
System.out.println(rs.getString(1));
}

} catch (Exception e) {
e.printStackTrace();
break;
} finally {
try {
if (rs != null) {
rs.close();
}
if (statement != null) {
statement.close();
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

}

private static Connection getConnection() {
Connection connection = null;
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
connection = DriverManager.getConnection(
"jdbc:oracle:thin:@9.119.84.184:1521:XE", "username",
"password");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}

return connection;
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  oracle 数据库 异常