Uygulama "bir şey yavaş" diyor, ama CPU boş, disk boş. Klasik tablo: bir session bir satırı kilitledi, COMMIT atmadı, geri kalan herkes onun arkasında bekliyor. Oracle'da bu zinciri bulmak için üçüncü parti araca gerek yok — v$session sana kimin kimi beklettiğini doğrudan söyler.

blocking_session: kim engelliyor?

v$session içindeki blocking_session kolonu, bir session'ı bekleten session'ın SID'sini verir. Bekleyenleri ve engelleyeni tek sorguda çıkar:

sql
Oracle 19c
SELECT s.sid,
       s.serial#,
       s.username,
       s.status,
       s.blocking_session       AS engelleyen_sid,
       s.event                  AS bekleme_olayi,
       s.seconds_in_wait        AS bekleme_sn
FROM   v$session s
WHERE  s.blocking_session IS NOT NULL
ORDER  BY s.seconds_in_wait DESC;

event genelde enq: TX - row lock contention olur — satır kilidi. engelleyen_sid ise topun kimde olduğunu söyler.

Engelleyen ne yapıyor?

Engelleyen SID'yi bulduktan sonra onun çalıştırdığı (ya da son çalıştırdığı) SQL'e bak — çoğu zaman "commit unutulmuş bir transaction" ya da "elle açık kalmış bir oturum" çıkar:

sql
Oracle 19c
SELECT s.sid, s.serial#, s.username, s.machine, s.program,
       q.sql_text
FROM   v$session s
LEFT JOIN v$sql q ON q.sql_id = s.prev_sql_id
WHERE  s.sid = &engelleyen_sid;

Kilit zincirini ağaç halinde görmek istersen v$lock yerine hazır görünüm dba_blockers / dba_waiters de vardır; ama blocking_session çoğu vakayı tek sorguda çözer.

Dikkat

Engelleyen session'ı ALTER SYSTEM KILL SESSION 'sid,serial#' ile öldürmek, o session'ın açık transaction'ını geri alır (rollback) — dakikalarca sürebilir ve iş kaybına yol açabilir. Öldürmeden önce kök nedeni anla: uygulama commit'i mi unutuyor, bir batch mi uzun tutuyor, yoksa biri SQL Developer'da SELECT ... FOR UPDATE açıp öğle yemeğine mi gitti? Kör "kill" semptomu susturur, sebebi değil.

RAC'taysan: gv$ kullan

Tek instance'ta v$session yeter. Real Application Clusters'ta kilit başka bir node'daki session'dan gelebilir; o yüzden global görünümleri kullan:

sql
Oracle 19c
SELECT inst_id, sid, serial#, blocking_session, blocking_instance, event
FROM   gv$session
WHERE  blocking_session IS NOT NULL;

Hızlı karar tablosu

| Belirti | Bak | Anlamı | |---|---|---| | Sorgular bekliyor, CPU boş | v$session.blocking_session | Satır/tablo kilidi zinciri | | event = enq: TX - row lock | Engelleyenin prev_sql_id'si | Commit'siz bir transaction | | Çok node (RAC) | gv$session + blocking_instance | Kilit başka instance'ta | | Engelleyen INACTIVE | Uygulama/pool bağlantısı | Açık kalmış oturum, commit yok |

Özet

Oracle'da "bir şey kilitli" belirsizliğini v$session.blocking_session netleştirir: bekleyenleri listele, engelleyeni bul, onun son SQL'ine bak. Neredeyse her zaman kök neden commit unutan bir transaction ya da elle açık kalmış bir oturumdur. Session'ı öldürmeden önce sebebi anla — rollback maliyeti gerçek. RAC'ta gv$session'a geçmeyi unutma.