java.sql.SQLException:-ORA-01000:超出最大打开游标数
我收到一个ORA-01000 SQL异常。所以我有一些相关的疑问java.sql.SQLException:-ORA-01000:超出最大打开游标数,java,oracle,jdbc,Java,Oracle,Jdbc,我收到一个ORA-01000 SQL异常。所以我有一些相关的疑问 最大打开游标数是否与JDBC连接数完全相关,或者它们是否也与我们为单个连接创建的语句和结果集对象相关?(我们正在使用连接池) 有没有办法配置数据库中语句/结果集对象的数量(如连接) 建议在单线程环境中使用实例变量语句/resultset对象而不是方法局部语句/resultset对象吗 在循环中执行准备好的语句是否会导致此问题?(当然,我可以使用sqlBatch)注意:一旦循环结束,pStmt就会关闭 { //method try
{ //method try starts
String sql = "INSERT into TblName (col1, col2) VALUES(?, ?)";
pStmt = obj.getConnection().prepareStatement(sql);
pStmt.setLong(1, subscriberID);
for (String language : additionalLangs) {
pStmt.setInt(2, Integer.parseInt(language));
pStmt.execute();
}
} //method/try ends
{ //finally starts
pStmt.close()
} //finally ends
[oracle@db01 ~]$ sqlplus / as sysdba
然后跑
SELECT A.VALUE,
S.USERNAME,
S.SID,
S.SERIAL#
FROM V$SESSTAT A,
V$STATNAME B,
V$SESSION S
WHERE A.STATISTIC# = B.STATISTIC#
AND S.SID = A.SID
AND B.NAME = 'opened cursors current'
AND USERNAME = 'VELU';
如果可能,请阅读您是否将自动提交设置为true?如果没有,请尝试以下操作:
{ //method try starts
String sql = "INSERT into TblName (col1, col2) VALUES(?, ?)";
Connection conn = obj.getConnection()
pStmt = conn.prepareStatement(sql);
for (String language : additionalLangs) {
pStmt.setLong(1, subscriberID);
pStmt.setInt(2, Integer.parseInt(language));
pStmt.execute();
conn.commit();
}
} //method/try ends {
//finally starts
pStmt.close()
} //finally ends
ORA-01000是最大开放游标错误,是Oracle数据库开发中极为常见的错误。在Java环境中,当应用程序试图打开的结果集多于数据库实例上配置的游标时,就会发生这种情况 常见的原因有:
- 应用程序中查询数据库的线程比数据库中的游标多。一种情况是,连接和线程池大于数据库上的游标数
- 您有许多开发人员或应用程序连接到同一个DB实例(可能会包含许多模式),并且一起使用的连接太多
- 解决方案:
- 在数据库上(如果资源允许)或
- 减少应用程序中的线程数
- 应用程序没有关闭结果集(在JDBC中)或游标(在数据库的存储过程中)
- 解决方案:光标泄漏是错误;增加DB上的游标数量只会延迟不可避免的故障。可以使用、或应用程序级日志记录和查找泄漏李>
ALTER SYSTEM SET OPEN_CURSORS=1337 SID='*' SCOPE=BOTH;
将JVM中的JDBC与DB上的游标关联
下面的JDBC对象与以下数据库概念紧密耦合:
- JDBC连接是数据库会话的客户端表示,并提供数据库事务。一个连接在任何时候只能打开一个事务(但事务可以嵌套)
- 数据库上的单个游标支持JDBC结果集。在结果集上调用close()时,将释放光标
- JDBC CallableStatement调用数据库上的存储过程,通常用PL/SQL编写。存储过程可以创建零个或多个游标,并可以将游标作为JDBC结果集返回
Statement stmt = conn.createStatement();
try {
ResultSet rs = stmt.executeQuery( "SELECT FULL_NAME FROM EMP" );
try {
while ( rs.next() ) {
System.out.println( "Name: " + rs.getString("FULL_NAME") );
}
} finally {
try { rs.close(); } catch (Exception ignore) { }
}
} finally {
try { stmt.close(); } catch (Exception ignore) { }
}
注意finally子句如何忽略close()引发的任何异常:
- 如果只关闭结果集而不使用try{}catch{},则可能会失败并阻止关闭语句
- 我们希望允许在函数体中引发的任何异常尝试传播到调用方。 如果有循环,例如创建和执行语句,请记住关闭循环中的每个语句
try
{ //method try starts
String sql = "INSERT into TblName (col1, col2) VALUES(?, ?)";
pStmt = obj.getConnection().prepareStatement(sql);
pStmt.setLong(1, subscriberID);
for (String language : additionalLangs) {
pStmt.setInt(2, Integer.parseInt(language));
pStmt.execute();
}
} //method/try ends
finally
{ //finally starts
pStmt.close()
}
class obj{
public Connection getConnection(){
return new ConnectionDelegator(...here create your connection object and put it into ...);
}
}
class ConnectionDelegator implements Connection{
Connection delegates;
public ConnectionDelegator(Connection con){
this.delegates = con;
}
public Statement prepareStatement(String sql){
return delegates.prepareStatement(sql);
}
public void close(){
try{
delegates.close();
}finally{
log.debug(delegates.toString() + " was closed");
}
}
}
[oracle@db01 ~]$ sqlplus / as sysdba
alter session set session_cached_cursors=0
select * from V$PARAMETER where name='session_cached_cursors'
SELECT max(a.value) as highest_open_cur, p.value as max_open_cur FROM v$sesstat a, v$statname b, v$parameter p WHERE a.statistic# = b.statistic# AND b.name = 'opened cursors current' AND p.name= 'open_cursors' GROUP BY p.value;
SELECT a.value, s.username, s.sid, s.serial#
FROM v$sesstat a, v$statname b, v$session s
WHERE a.statistic# = b.statistic# AND s.sid=a.sid
AND b.name = 'opened cursors current' AND username = 'SCHEMA_NAME_IN_CAPS'
SELECT oc.sql_text, s.sid
FROM v$open_cursor oc, v$session s
WHERE OC.sid = S.sid
AND s.sid=1604
AND OC.USER_NAME ='SCHEMA_NAME_IN_CAPS'
SELECT s.machine, oc.user_name, oc.sql_text, count(1)
FROM v$open_cursor oc, v$session s
WHERE oc.sid = s.sid
and S.USERNAME='XXXX'
GROUP BY user_name, sql_text, machine
HAVING COUNT(1) > 2
ORDER BY count(1) DESC
java.sql.SQLException: - ORA-01000: maximum open cursors exceeded