Oracle
 sql >> Teknologi Basis Data >  >> RDS >> Oracle

Oracle 19c Open_cursor melebihi masalah

Saya tidak dapat memberi tahu Anda apa yang menyebabkan masalah kursor terbuka maksimum Anda, tetapi saya memberi tahu Anda cara menemukan penyebabnya dengan mengidentifikasi sesi terkait dan pernyataan SQL menggunakan GV$OPEN_CURSOR .

Jika Anda beruntung, Anda dapat segera menemukan masalahnya dengan kueri sederhana yang menghitung jumlah kursor terbuka per sesi. Ada banyak kolom dalam kueri di bawah ini, gunakan IDE agar Anda dapat dengan mudah menelusuri semua data. Dalam pengalaman saya, hanya melirik kolom seperti USER_NAME dan SQL_TEXT sudah cukup untuk mengidentifikasi pelakunya.

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;

Ingatlah bahwa akan ada banyak pertanyaan aneh dalam tampilan itu yang mungkin membuat jumlah lebih besar dari yang Anda perkirakan. Dengan semua kueri rekursif dan cache, bukan hal yang aneh jika sesi "membosankan" menggunakan 50 kursor. Anda sedang mencari sesi dengan ratusan kursor terbuka. (Kecuali seseorang dengan bodohnya menurunkan nilai parameter di bawah default.)

Sayangnya, GV$OPEN_CURSOR tidak berisi data historis, dan masalah ini dapat dimulai dan dihentikan dengan cepat jika ada pengecualian di dalam loop ketat yang dengan cepat membuka banyak kursor. Blok PL/SQL di bawah ini berjalan hingga menemukan sesi dengan sejumlah besar kursor terbuka, menyimpan data, dan keluar. Blok PL/SQL ini mahal, dan akan menghabiskan seluruh sesi pemrosesan menunggu saat yang tepat, jadi gunakan hanya sekali untuk menemukan masalahnya.

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

Jika Anda ingin menguji pemantauan, Anda dapat menggunakan blok PL/SQL di bawah ini untuk membuka sejumlah besar kursor.

--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. Pemicu untuk menegakkan hubungan M-M

  2. String dipisahkan koma ke daftar

  3. Pernyataan Hapus Oracle:berapa banyak baris yang telah dihapus oleh penghapusan kaskade

  4. TAN() Fungsi di Oracle

  5. .NET / Oracle:Cara mengeksekusi skrip dengan pernyataan DDL secara terprogram