Oracle
 sql >> база данни >  >> RDS >> Oracle

Oracle 19c Open_cursor превишен проблем

Не мога да ви кажа какво причинява проблема ви с максимално отворени курсори, но ви казвам как да намерите причината, като идентифицирате свързаните сесии и SQL оператор с помощта на GV$OPEN_CURSOR .

Ако имате късмет, можете веднага да откриете проблема с проста заявка, която отчита броя на отворените курсори на сесия. Има много колони в заявката по-долу, използвайте IDE, за да можете лесно да разглеждате всички данни. Според моя опит, само един поглед към колони като USER_NAME и SQL_TEXT е достатъчен, за да идентифицира виновника.

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 блок е скъп и ще използва цяла сесия на обработка в очакване на подходящия момент, така че го използвайте само веднъж, за да откриете проблема.

--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 по-долу, за да отворите голям брой курсори.

--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. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Заявка за данни от XML

  2. Нуждаят ли се процедурите от отделни права за достъп върху таблиците?

  3. Ограничете SQL заявката само до първите два броя на група

  4. Автоматично увеличаване на първичния ключ в базата данни на Oracle

  5. Актуализирайте колоната на набора от таблици, равна на това да изберете къде ID съвпада извън заявката в Oracle