sql >> Databáze >  >> RDS >> Oracle

Oracle 19c Open_cursor překročil problém

Nemohu vám říci, co způsobuje váš problém s maximálním otevřeným kurzorem, ale řeknu vám, jak najít příčinu identifikací souvisejících relací a příkazu SQL pomocí GV$OPEN_CURSOR .

Pokud budete mít štěstí, můžete problém okamžitě najít pomocí jednoduchého dotazu, který počítá počet otevřených kurzorů na relaci. V níže uvedeném dotazu je mnoho sloupců, použijte IDE, abyste mohli snadno procházet všechna data. Podle mých zkušeností stačí k identifikaci viníka pouhý pohled na sloupce jako USER_NAME a 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;

Mějte na paměti, že v tomto zobrazení bude mnoho podivných dotazů, které mohou způsobit větší počty, než jste očekávali. U všech rekurzivních a uložených dotazů není neobvyklé, že „nudná“ relace používá 50 kurzorů. Hledáte relace se stovkami otevřených kurzorů. (Pokud někdo hloupě nesnížil hodnotu parametru pod výchozí hodnotu.)

Bohužel GV$OPEN_CURSOR neobsahuje historická data a tyto problémy se mohou rychle spustit a zastavit, pokud v těsné smyčce existuje výjimka, která rychle otevře mnoho kurzorů. Níže uvedený blok PL/SQL běží, dokud nenajde relaci s velkým počtem otevřených kurzorů, uloží data a neukončí se. Tento blok PL/SQL je drahý a zabere celou relaci zpracování čekání na správný okamžik, takže jej použijte pouze jednou, abyste našli problém.

--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;

Pokud chcete monitorování otestovat, můžete použít níže uvedený blok PL/SQL k otevření velkého počtu kurzorů.

--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. Servicestack:Zacházet s indexy, automatickým přírůstkem atd. bez atributů?

  2. jak mohu vytvořit počítadlo návštěvníků v php?

  3. vložte data z JSON do mysql pomocí php

  4. Chyba:ORA-00907:chybí pravá závorka