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;
}
}
一、基本概念:
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 ORA-01000: maximum open cursors exceeded问题的解决方法
- 关于ORACLE游标的问题(ORA-01000: maximum open cursors exceeded)
- 关于ORACLE游标的问题(ORA-01000: maximum open cursors exceeded)
- oracle ORA-01000: maximum open cursors exceeded问题的解决方法
- How to resolve maximum open cursors exceeded on Oracle(ORA-01000)-- 1
- 关于ORACLE游标的问题(ORA-01000: maximum open cursors exceeded)
- oracle ORA-01000: maximum open cursors exceeded问题的解决方法
- oracle ORA-01000:maximum open cursors exceeded
- 关于 ORACLE游标的问题(ORA-01000: maximum open cursors exceeded)
- [JDBC]ORA-01000: 超出打开游标的最大数(ORA-01000: maximum open cursors exceeded)
- 处理超出打开游标的最大数异常(ORA-01000: maximum open cursors exceeded)
- ORA-01000: maximum open cursors exceeded 超出打开游标的最大数的原因和解决方案
- ORA-01000: maximum open cursors exceeded
- 出错"ORA-01000: maximum open cursors exceeded" 问题分析
- ora-01000:maximum open cursors exceeded ---dblink
- 循环执行sql语句时报 ORA-01000 maximum open cursors exceeded 超出打开游标的最大数的原因和解决方案
- Errorstack诊断ORA-01000: maximum open cursors exceeded
- Java程序异常 open cussors查询 ORA-01000: maximum open cursors exceeded ORA-06512: at "××××××", line ×× 通
- ORA-01000: maximum open cursors exceeded
- 处理超出打开游标的最大数异常(ORA-01000: maximum open cursors exceeded)