open_cursors :ORA-01000 maximum open cursors exceeded

select sid,count(*)    from    v$open_cursor   group by sid; 

 

--------------------------------------------------------------------------------------------------------------------------------------------- 

 

数据库环境9.2.0.4 RAC两个节点
错误现象:
ORA-00604: error occurred at recursive SQL level 1 ORA-01000: maximum open cursors exceeded

问题描述:最近发布了多个大的应用程序后发现open_cursors不够,而且跟recursive SQL有关,我就怀疑可能是跟触发器或者跟什么表的约束有关(注意我们的表空间设置基本都是设置Uniform),后来查看,发现涉及到有个触发器,并且涉及到删除某个有约束的表,但是现在还不能完全确定。
我用select sid,count(*) from v$open_cursor group by sid;

   SID COUNT(*)
---------- ----------
       16       39
       20       11
       21       55
       26       3
       27       49
       29       5
       30       5
       31       54
       32       22
       33       17
       39       23


SQL>   show parameter open_cursor

NAME                               VALUE
------------------------------------ ------------------------------
open_cursors                      200

.....
没有发现很大的值
我现在打算用alter system set open_cursors=300 scope=both;暂时增加这个open_cursors。
然后用alter session set events '604 trace name errorstack level 10';
alter session set events '1000 trace name errorstack level 3';
跟踪一下错误,查查究竟是什么原因。如果再发生错误,等会给大家发信息上来。

我们先看看open_cursors的概念:
open_cursors--每个用户同一时刻最多在使用的cursor数

可以有两种级别来调整:
1.Tuning at the DATABASE LEVEL
可能是由于程序过多申请cursor,修改程序,如果实在不够,那么就
alter system set open_cursors=300 scope=both;
增加他。
也有可能是由于大的insert等,而被cancel掉时,或者是一个死连接,查看sqlnet.expire_time
> 0
但是盲目增大他不是一个解决办法,因为不能更好的识别所有的cursor,而且会多使用一些内存,但对性能影响多大,谁有这方面的经验。

2. Tuning at the APPLICATION LEVEL

HOLD_CURSOR是保持静态cursor(program cursor被预编译的),保持这些静态cursor可以减少重解析次数
RELEASE_CURSOR 是一些动态的cursor(oracle cursor) ,用于释放这些资源,也可以减少重解析次数。
是基于cursor cache的使用规则
我们可以通过设置HOLD_CURSOR=NO和RELEASE_CURSOR =YES来调整对open_cursors的要求。

我们来看看tom的实例来了解一下,来了解一下open_cursors 的变化:但我在后面有一些疑惑,大家一起来讨论

ops$tkyte@ORA920> @mystat cursor
ops$tkyte@ORA920> select a.name, b.value
   2   from v$statname a, v$mystat b
   3   where a.statistic# = b.statistic#
   4   and lower(a.name) like '%' || lower('&1')||'%'
   5   /
old 4: and lower(a.name) like '%' || lower('&1')||'%'
new 4: and lower(a.name) like '%' || lower('cursor')||'%'

NAME                                VALUE
------------------------------ ----------
opened cursors cumulative              26
opened cursors current                9
session cursor cache hits             0
session cursor cache count          13
cursor authentications                1


ops$tkyte@ORA920> declare
   2       type rc is ref cursor;
   3
   4       l_cursor rc;
   5   begin
   6       for i in 1 .. 100
   7       loop
   8                for j in 1 .. 5
   9                loop
10                          open l_cursor for 'select * from dual xx' || i;
11                          close l_cursor;
12                end loop;
13       end loop;
14   end;
15   /

PL/SQL procedure successfully completed.

ops$tkyte@ORA920>
ops$tkyte@ORA920> @mystat cursor
ops$tkyte@ORA920> select a.name, b.value
   2   from v$statname a, v$mystat b
   3   where a.statistic# = b.statistic#
   4   and lower(a.name) like '%' || lower('&1')||'%'
   5   /
old 4: and lower(a.name) like '%' || lower('&1')||'%'
new 4: and lower(a.name) like '%' || lower('cursor')||'%'

NAME                                VALUE
------------------------------ ----------
opened cursors cumulative          529
opened cursors current                9
session cursor cache hits          400
session cursor cache count          100
cursor authentications                1

that shows I've 100 cursors in my "cache" ready to be opened faster then
normal -- but I never exceeded my 50 open cursors at a time threshold.

ops$tkyte@ORA920> create or replace procedure p( p_more in boolean default
false
)
   2   as
   3       l_x number;
   4   begin
   5       select 1 into l_x from dual;
   6       select 2 into l_x from dual;
   7       select 3 into l_x from dual;
   8       select 4 into l_x from dual;
   9       select 5 into l_x from dual;
10       if ( p_more )
11       then
12                select 6 into l_x from dual;
13                select 7 into l_x from dual;
14                select 8 into l_x from dual;
15                select 9 into l_x from dual;
16                select 10 into l_x from dual;
17       end if;
18   end;
19   /

Procedure created.

ops$tkyte@ORA920> connect /
Connected.
ops$tkyte@ORA920> @mystat cursor
ops$tkyte@ORA920> select a.name, b.value
   2   from v$statname a, v$mystat b
   3   where a.statistic# = b.statistic#
   4   and lower(a.name) like '%' || lower('&1')||'%'
   5   /
old 4: and lower(a.name) like '%' || lower('&1')||'%'
new 4: and lower(a.name) like '%' || lower('cursor')||'%'

NAME                                VALUE
------------------------------ ----------
opened cursors cumulative             9
opened cursors current                1
session cursor cache hits             0
session cursor cache count              7
cursor authentications                0

ops$tkyte@ORA920> exec p

PL/SQL procedure successfully completed.

ops$tkyte@ORA920> @mystat cursor
ops$tkyte@ORA920> select a.name, b.value
   2   from v$statname a, v$mystat b
   3   where a.statistic# = b.statistic#
   4   and lower(a.name) like '%' || lower('&1')||'%'
   5   /
old 4: and lower(a.name) like '%' || lower('&1')||'%'
new 4: and lower(a.name) like '%' || lower('cursor')||'%'

NAME                                VALUE
------------------------------ ----------
opened cursors cumulative              17
opened cursors current                6     <<<<==== +5
session cursor cache hits             1
session cursor cache count              7
cursor authentications                5

ops$tkyte@ORA920> exec p( true )

PL/SQL procedure successfully completed.

ops$tkyte@ORA920> @mystat cursor
ops$tkyte@ORA920> select a.name, b.value
   2   from v$statname a, v$mystat b
   3   where a.statistic# = b.statistic#
   4   and lower(a.name) like '%' || lower('&1')||'%'
   5   /
old 4: and lower(a.name) like '%' || lower('&1')||'%'
new 4: and lower(a.name) like '%' || lower('cursor')||'%'

NAME                                VALUE
------------------------------ ----------
opened cursors cumulative              24
opened cursors current                 11 <<<==== +5 more
session cursor cache hits             2
session cursor cache count              7
cursor authentications                 10

ops$tkyte@ORA920> exec p( true )

PL/SQL procedure successfully completed.

ops$tkyte@ORA920> @mystat cursor
ops$tkyte@ORA920> select a.name, b.value
   2   from v$statname a, v$mystat b
   3   where a.statistic# = b.statistic#
   4   and lower(a.name) like '%' || lower('&1')||'%'
   5   /
old 4: and lower(a.name) like '%' || lower('&1')||'%'
new 4: and lower(a.name) like '%' || lower('cursor')||'%'

NAME                                VALUE
------------------------------ ----------
opened cursors cumulative              26
opened cursors current                 11 <<< === same +5
session cursor cache hits             3
session cursor cache count              7
cursor authentications                 11

我疑惑的是
select sid,count(*) from v$open_cursor group by sid;

   SID COUNT(*)
---------- ----------
       16       39
       20       11
       21       55
       26       3
       27       49
       29       5
       30       5
       31       54
       32       22
       33       17
       39       23

如何看这个cursor已经到达open_cursors200了,是opened cursors current吗?能通过 v$open_cursors看出什么名堂吗?
书上写的很模糊,open_cursors究竟是基于某个用户的一个session同一时刻的最大cursor数(一个session可能在不同时间分布cursor)还是某个用户同一时刻最大cursor数(可以是多个session),
同一时间段是怎么划分的。


 

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/35489/viewspace-628199/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/35489/viewspace-628199/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值