java.sql.SQLException: ORA-00604: error occurred at recursive SQL level 1
ORA-01000: maximum open cursors exceeded
ORA-00604: error occurred at
recursive SQL level 1
1.查看数据库当前的游标数配置
show parameter open_cursors;
2. 通过sql查询session打开cursor的情况
SELECT s.inst_id,s.username,
o.sid,
osuser,
machine,
COUNT(*) num_curs
FROM gv$open_cursor o,
gv$session s
WHERE o.sid = s.sid
AND o.inst_id = s.inst_id
GROUP BY s.inst_id,s.username,
o.sid,
osuser,
machine
ORDER BY num_curs DESC;
3. 通过以下sql查询该会话的具体游标情况
SELECT oc.sql_text,
oc.sql_id,
COUNT(1) cnt
FROM gv$open_cursor oc
WHERE oc.sid = 578
AND oc.inst_id = 2
GROUP BY oc.sql_text,
oc.sql_id
ORDER BY cnt DESC;
select sid ,sql_text, user_name, count(*) as "OPEN CURSORS" from v$open_cursor where sid in ($SID) group by sid ,sql_text, user_name;
4.通过ash查询该会话的具体信息
SELECT *
FROM gv$active_session_history ash
WHERE ash.session_id = 578
AND ash.session_serial# = 34481
and ash.SQL_ID in ('231zgb2w57xgd')
ORDER BY ash.sample_time;
5. 查看该会话当前的状态
SELECT *
FROM gv$session s
WHERE s.sid = 578;
Every application using oracle database as backend repository runs several SQL statements.
For every SQL statement execution in oracle database, certain area in memory is allocated. Oracle PL/SQL allows you to name this area. This private SQL area is called
context area or cursor. These cursors take up space in the shared pool (essential memory component of oracle database), specifically in the library cache. To keep a
renegade session from filling up the library cache, or clogging the CPU with millions of parse requests, we set the parameter OPEN_CURSORS.
One defines the value/limit of these cursors as a DB parameter called OPEN_CUSRSORS in database instance.
OPEN_CURSORS DB parameter sets the maximum number of cursors each session can have open, per session. For example, if OPEN_CURSORS value is set to 1000,
then each session can have up to 1000 cursors open at one time.
使用Oracle数据库的时候,经常会碰到有ORA-01000: maximum open cursors exceeded的错误。实际上,这个错误的原因,主要还是代码问题引起的。 ora-01000: maximum open cursors exceeded:表示已经达到一个进程打开的最大游标数。
这样的错误很容易出现在Java代码中的主要原因是:Java代码在执行conn.createStatement()和conn.prepareStatement()的时候,实际上都是相当与在数据库中打开了一个cursor。
尤其是,如果你的createStatement和prepareStatement是在一个循环里面的话,就会非常容易出现这个问题。因为游标一直在不停的打开,而且没有关闭。
一般来说,我们在写Java代码的时候,createStatement和prepareStatement都应该要放在循环外面,而且使用了这些Statment后,及时关闭。
最好是在执行了一次executeQuery、executeUpdate等之后,如果不需要使用结果集(ResultSet)的数据,就马上将Statment关闭。
对于出现ORA-01000错误这种情况,单纯的加大open_cursors并不是好办法,那只是治标不治本。实际上,代码中的隐患并没有解除。而且,绝大部分情况下,open_cursors只需要设置一个比较小的值,就足够使用了,除非有非常特别的要求。
6. 解决方案
一、从源头上解决方案(建议)
将上述分析后的功能异常反馈给开发人员检查代码,把涉及到打开链接的地方,用完之后,千万别忘记关掉。
二、临时解决方案(不已建议)
通过修改oracle系统参数:将OPEN_CURSORS 的值设置得足够大,以避免应用程序用尽所有打开的游标。应用程序不同,该值也不同。即便会话打开的游标数未达 OPEN_CURSORS 指定的数量(即设置的值高于实际需要的值), 也不会增加系统开销
参考:
ORA01000 : Troubleshooting Open Cursors Issues (Doc ID 1477783.1)