sql >> Databasteknik >  >> RDS >> Oracle

Oracle 19c Open_cursor överskred problemet

Jag kan inte berätta vad som orsakar ditt problem med maximalt öppna markörer, men jag berättar hur du hittar orsaken genom att identifiera relaterade sessioner och SQL-sats med GV$OPEN_CURSOR .

Om du har tur kan du hitta problemet direkt med en enkel fråga som räknar antalet öppna markörer per session. Det finns många kolumner i frågan nedan, använd en IDE så att du enkelt kan bläddra i alla data. Enligt min erfarenhet räcker det att bara titta på kolumner som USER_NAME och SQL_TEXT för att identifiera den skyldige.

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;

Tänk på att det kommer att finnas många konstiga frågor i den vyn som kan göra antalet större än du förväntade dig. Med alla rekursiva och cachade frågor är det inte ovanligt att ha en "tråkig" session med 50 markörer. Du letar efter sessioner med hundratals öppna markörer. (Om inte någon dumt har sänkt parametervärdet under standardvärdet.)

Tyvärr, GV$OPEN_CURSOR innehåller inga historiska data, och dessa problem kan starta och sluta snabbt om det finns ett undantag i en tight loop som snabbt öppnar många markörer. PL/SQL-blocket nedan körs tills det hittar en session med ett stort antal öppna markörer, lagrar data och avslutar. Detta PL/SQL-block är dyrt och kommer att använda upp en hel session av bearbetning i väntan på rätt ögonblick, så använd det bara en gång för att hitta problemet.

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

Om du vill testa övervakningen kan du använda PL/SQL-blocket nedan för att öppna ett stort antal markörer.

--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. Bästa praxis för att lagra datumet i MySQL från PHP

  2. Summan av kolumn i att använda mysqli och php

  3. skapa ett bildspel med bilder i bootstrap modal dynamiskt med PHP

  4. Är detta det bästa sättet att skapa ett revisionsspår?