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

kursor:pin S tunggu di X

Pada basis data RAC produksi utama saya, saya melihat periode kelambatan dan acara tunggu yang dominan, di seluruh sistem, adalah "kursor:pin S tunggu di X". Peristiwa itu datang dan pergi, tetapi saya melihatnya dari waktu ke waktu. Jadi saya harus mendapatkan bagian bawah ini. Perhatikan, bahwa ini bukan masalah RAC. Acara ini juga dapat dengan mudah dilihat pada database instance tunggal. Ketika saya melihat ini di beberapa instance dari database Oracle RAC saya, itu karena saya memiliki beberapa sesi dari aplikasi yang sama yang tersebar di antara instance, semuanya melakukan hal yang sama, sehingga semua memiliki masalah yang sama.

Pertama, tentang apa acara menunggu itu? Salah satu dari "kursor:" menunggu adalah kemacetan di Pool Bersama di Area SQL. Dahulu kala, bagian dari Kolam Bersama ini dilindungi oleh kait. Tetapi seperti halnya dengan banyak area Shared Pool, Oracle sekarang menggunakan mutex. Dengan perubahan mekanisme perlindungan, kami sekarang memiliki acara tunggu baru.

Dalam kasus acara tunggu khusus ini, kami memiliki kursor yang menginginkan pin Bersama tetapi harus menunggu sesi lain untuk merilis mutex eXclusive-nya. Kursor sedang mencoba untuk diurai. Tetapi tidak dapat diuraikan karena sesi lain memegang mutex yang sama.

Ada tiga penyebab utama sesi menunggu acara ini.

  • Penguraian keras yang tinggi
  • Banyak versi pernyataan SQL
  • Bug

Sayangnya, ada sejumlah bug yang terkait dengan acara tunggu ini. Sebagian besar yang saya lihat telah diperbaiki di 11.2.0.4 atau 12.1.0.1 jadi jika Anda tertinggal dalam versi, pertimbangkan untuk memutakhirkan ke salah satu versi Oracle yang lebih baru.

Jadi mari kita lihat apakah kita bisa melihat contoh untuk menentukan penyebab masalahnya. Untuk melakukannya, saya menggunakan kueri berikut:

select s.inst_id as inst,
       s.sid as blocked_sid, 
       s.username as blocked_user,
       sa.sql_id as blocked_sql_id,
       trunc(s.p2/4294967296) as blocking_sid,
       b.username as blocking_user,
       b.sql_id as blocking_sql_id
from gv$session s
join gv$sqlarea sa
  on sa.hash_value = s.p1
join gv$session b
  on trunc(s.p2/4294967296)=b.sid
 and s.inst_id=b.inst_id
join gv$sqlarea sa2
  on b.sql_id=sa2.sql_id
where s.event='cursor: pin S wait on X';

Menjalankan ini di salah satu database RAC produksi saya, saya mendapatkan output berikut:

INST BLOCKED_SID BLOCKED_USER BLOCKED_SQL_ID BLOCKING_SID BLOCKING_USER BLOCKING_SQL_ID
---- ----------- ------------ -------------- ------------ ------------- ---------------
   4         723 USER12345    cn7m7t6y5h77g          1226 USER12345     cn7m7t6y5h77g 
   4         723 USER12345    cn7m7t6y5h77g          1226 USER12345     cn7m7t6y5h77g 
   4         723 USER12345    cn7m7t6y5h77g          1226 USER12345     cn7m7t6y5h77g 
   4         723 USER12345    cn7m7t6y5h77g          1226 USER12345     cn7m7t6y5h77g 
   4        1226 USER12345    cn7m7t6y5h77g          1796 USER12345     cn7m7t6y5h77g 
   4        1226 USER12345    cn7m7t6y5h77g          1796 USER12345     cn7m7t6y5h77g 
   4        1226 USER12345    cn7m7t6y5h77g          1796 USER12345     cn7m7t6y5h77g 
   4        1226 USER12345    cn7m7t6y5h77g          1796 USER12345     cn7m7t6y5h77g

Hal pertama yang perlu diperhatikan adalah bahwa mutex hanya ada di dalam instance untuk database Oracle RAC. Untuk database instance tunggal, kueri di atas akan tetap berfungsi. Untuk Oracle RAC, output dari kueri ini akan menunjukkan instance mana yang bermasalah.

Dalam contoh di atas, kita memiliki sesi 723 yang diblokir oleh sesi 1226. Sesi 1226 selanjutnya diblokir oleh sesi 1796. Perhatikan bahwa ketiga sesi mengeluarkan kueri yang sama dengan ID SQL cn7m7t6y5h77g .

Sekarang setelah kita mengetahui ID SQL, kita dapat dengan mudah meminta V$SQL untuk menentukan pernyataan SQL yang terlibat dalam masalah. Saya menggunakan kueri ini untuk mendapatkan informasi lebih lanjut.

select sql_id,loaded_versions,executions,loads,invalidations,parse_calls
from gv$sql 
where inst_id=4 and sql_id='cn7m7t6y5h77g';

Output dari query V$SQL adalah sebagai berikut:

SQL_ID        LOADED_VERSIONS EXECUTIONS LOADS      INVALIDATIONS PARSE_CALLS
------------- --------------- ---------- ---------- ------------- -----------
cn7m7t6y5h77g               1        105        546           308        3513

Kita sekarang dapat melihat bahwa kueri ini hanya memiliki 1 versi di Area SQL. Jadi segera, kami telah menghilangkan salah satu area masalah potensial. Dalam posting blog mendatang, saya akan membahas kueri dengan jumlah versi yang tinggi di Area SQL. Tapi itu bukan masalah kita hari ini, jadi kita lanjutkan.

Harus jelas dari atas bahwa ada jumlah panggilan parse yang sangat tinggi. Kueri hanya dieksekusi 105 kali tetapi telah diuraikan 3513 kali. Astaga! Angka yang tinggi jika pembatalan mungkin ada hubungannya dengan ini juga.

Dalam contoh ini, kita sekarang memiliki ide bagus tentang apa masalahnya. Ini adalah masalah aplikasi. Aplikasi ini mem-parsing kueri secara berlebihan. Jadi kami akan mengirimkan ini kembali ke pengembangan dan menggali kode aplikasi. Alasan umum untuk over-parsing perlu diperiksa.

Jika jumlah versi rendah dan parsing/invalidasi/load yang berlebihan tidak menjadi masalah, maka saya akan mencurigai adanya bug dan mengajukan SR dengan Dukungan Oracle.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Apakah SQLDeveloper mendukung eksekusi skrip?

  2. Urutkan berdasarkan hari dalam seminggu dari Senin hingga Minggu

  3. if (pilih count(kolom) dari tabel)> 0 maka

  4. Skrip untuk menemukan dependensi multi level dari suatu paket

  5. Menghubungkan ke Oracle Database melalui C#?