首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Oracle 19c Open_cursor超出问题

Oracle 19c Open_cursor超出问题
EN

Stack Overflow用户
提问于 2020-10-01 04:06:05
回答 1查看 990关注 0票数 2

我们在Oracle 10g和19c中有相同存储过程,具有相同的数据集和设置。该过程执行了如此多的数据获取和操作。当我们使用相同的数据集(假设10000条记录)执行时,它在10g中运行良好,时间更短,但在19c中,它需要很长时间,一段时间后,它会抛出"Open cursor limit exceeded“错误。我们从OPEN_CURSOR和CACHED_CURSOR大小相同的两个数据库中进行了基本比较。

为了解决这个问题,我们还可以从服务器端比较哪些参数或设置?

EN

回答 1

Stack Overflow用户

发布于 2020-11-20 11:51:45

我不能告诉您是什么导致了最大打开游标的问题,但是我告诉您如何通过使用GV$OPEN_CURSOR识别相关的会话和SQL语句来查找原因。

如果幸运的话,您可以通过一个简单的查询来立即发现问题,该查询计算每个会话打开的游标的数量。下面的查询中有很多列,使用IDE可以轻松地浏览所有数据。根据我的经验,只要看一眼像USER_NAME和SQL_TEXT这样的专栏就足以找到罪魁祸首。

代码语言:javascript
复制
select count(*) over (partition by inst_id, sid) cursors_per_session, gv$open_cursor.*
from gv$open_cursor
order by cursors_per_session desc, inst_id, sid;

请记住,该视图中将有许多奇怪的查询,这可能会使计数比您预期的更大。对于所有的递归和缓存查询,“无聊的”会话使用50个游标并不少见。您正在寻找具有数百个打开的游标的会话。(除非有人愚蠢地将参数值降低到默认值以下。)

不幸的是,GV$OPEN_CURSOR不包含历史数据,如果在快速打开大量游标的紧凑循环中出现异常,这些问题可能很快就会开始和停止。下面的PL/SQL块将一直运行,直到找到具有大量打开的游标的会话、存储数据并退出。此PL/SQL块的开销很大,并且会在等待合适的时机时耗尽整个处理会话,因此只需使用它一次即可找到问题。

代码语言:javascript
复制
--Create table to hold the results.
create table too_many_cursors as
select 1 cursors_per_session, gv$open_cursor.*
from gv$open_cursor
where 1 = 0;


--Write the open cursor data when a session gets more than N open cursors.
declare
    v_open_cursor_threshold number := 50;
    v_count number;
begin
    --Loop forever until the problem is found.
    loop
        --Count the largest numbe of open cursors.
        select max(the_count)
        into v_count
        from
        (
            select count(*) the_count
            from gv$open_cursor
            group by inst_id, sid
        );

        --If the threshold is reached, write the data, commit it, and quit the program.
        if v_count >= v_open_cursor_threshold then

            insert into too_many_cursors
            select *
            from
            (
                select count(*) over (partition by inst_id, sid) cursors_per_session, gv$open_cursor.*
                from gv$open_cursor
            )
            where cursors_per_session >= v_open_cursor_threshold;
            
            commit;
            
            exit;
        end if;
        
    end loop;
end;
/


--Your problem should now be in this table:
select * from too_many_cursors;

如果要测试监视,可以使用下面的PL/SQL块打开大量游标。

代码语言:javascript
复制
--Open a large number of cursors in and wait for 20 seconds.
--(Done by creating a dynamic PL/SQL block with many "open" commands with a "sleep" at the end.
declare
    v_number_of_open_cursors number := 200;
    v_declarations clob;
    v_opens clob;
    v_sql clob;
begin
    for i in 1 .. v_number_of_open_cursors loop
        v_declarations := v_declarations || 'v_cursor'|| i ||' sys_refcursor;' || chr(10);
        v_opens := v_opens || 'open v_cursor' || i || ' for select * from dual;';
    end loop;

    v_sql :=
        'declare '||chr(10)||v_declarations||chr(10)||
        'begin'||chr(10)||v_opens||chr(10)||
        'dbms_lock.sleep(20);'||chr(10)||'end;';

    --Print for debugging.
    --dbms_output.put_line(v_sql);

    execute immediate v_sql;
end;
/
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64144953

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档