sql >> Database >  >> RDS >> Oracle

Oracle 19c Open_cursor overschreden probleem

Ik kan u niet vertellen wat uw maximale open cursors-probleem veroorzaakt, maar ik vertel u hoe u de oorzaak kunt vinden door de gerelateerde sessies en SQL-instructie te identificeren met behulp van GV$OPEN_CURSOR .

Als je geluk hebt, kun je het probleem onmiddellijk vinden met een eenvoudige zoekopdracht die het aantal geopende cursors per sessie telt. Er zijn veel kolommen in de onderstaande query, gebruik een IDE zodat u gemakkelijk door alle gegevens kunt bladeren. In mijn ervaring is een blik op kolommen als USER_NAME en SQL_TEXT voldoende om de boosdoener te identificeren.

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;

Houd er rekening mee dat er in die weergave veel vreemde zoekopdrachten zullen zijn die de tellingen groter kunnen maken dan u had verwacht. Met alle recursieve en in de cache opgeslagen zoekopdrachten is het niet ongebruikelijk dat een "saaie" sessie 50 cursors gebruikt. U zoekt naar sessies met honderden open cursors. (Tenzij iemand dwaas de parameterwaarde onder de standaardwaarde heeft verlaagd.)

Helaas, GV$OPEN_CURSOR bevat geen historische gegevens en deze problemen kunnen snel beginnen en stoppen als er een uitzondering is in een strakke lus die snel veel cursors opent. Het onderstaande PL/SQL-blok wordt uitgevoerd totdat het een sessie met een groot aantal open cursors vindt, de gegevens opslaat en afsluit. Dit PL/SQL-blok is duur en zal een hele verwerkingssessie in beslag nemen, wachtend op het juiste moment, dus gebruik het maar één keer om het probleem te vinden.

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

Als u de monitoring wilt testen, kunt u het onderstaande PL/SQL-blok gebruiken om een ​​groot aantal cursors te openen.

--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. Een tijdelijke tabel maken op basis van een andere tabel in SQL Server

  2. Is Django dubbele codering van een Unicode (utf-8?) string?

  3. installeer mysql via marionet

  4. De naam van een mysql-procedure wijzigen