Oracle
 sql >> Baza danych >  >> RDS >> Oracle

Oracle 19c Open_cursor przekroczył problem

Nie mogę powiedzieć, co powoduje problem z maksymalną liczbą otwartych kursorów, ale powiem Ci, jak znaleźć przyczynę, identyfikując powiązane sesje i instrukcję SQL za pomocą GV$OPEN_CURSOR .

Jeśli masz szczęście, możesz natychmiast znaleźć problem za pomocą prostego zapytania, które zlicza liczbę otwartych kursorów na sesję. W poniższym zapytaniu jest wiele kolumn, użyj IDE, aby łatwo przeglądać wszystkie dane. Z mojego doświadczenia wynika, że ​​wystarczy spojrzeć na kolumny takie jak USER_NAME i SQL_TEXT, aby zidentyfikować winowajcę.

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;

Pamiętaj, że w tym widoku pojawi się wiele dziwnych zapytań, które mogą sprawić, że liczby będą większe niż przewidywałeś. W przypadku wszystkich zapytań rekurencyjnych i buforowanych nie jest niczym niezwykłym, że "nudna" sesja używa 50 kursorów. Szukasz sesji z setkami otwartych kursorów. (Chyba że ktoś nierozsądnie obniżył wartość parametru poniżej domyślnej).

Niestety, GV$OPEN_CURSOR nie zawiera danych historycznych, a te problemy mogą się szybko rozpocząć i zakończyć, jeśli w ciasnej pętli znajduje się wyjątek, który szybko otwiera wiele kursorów. Poniższy blok PL/SQL działa, dopóki nie znajdzie sesji z dużą liczbą otwartych kursorów, przechowa dane i zakończy działanie. Ten blok PL/SQL jest drogi i zużyje całą sesję przetwarzania czekając na odpowiedni moment, więc użyj go tylko raz, aby znaleźć problem.

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

Jeśli chcesz przetestować monitorowanie, możesz użyć poniższego bloku PL/SQL, aby otworzyć dużą liczbę kursorów.

--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. Zapytanie o lewe złącze zewnętrzne Oracle

  2. Jak sprawdzić, czy ciąg zawiera liczbę?

  3. Alternatywa LITAGG w Oracle 10g

  4. Jak przekierować wyjście DBMS_OUTPUT.PUT_LINE do pliku?

  5. Błąd-ORA-22835:Bufor jest zbyt mały dla konwersji CLOB na CHAR lub BLOB na RAW