PostgreSQL'de uzun süren bir sorgu her zaman yavaş plan nedeniyle beklemez; başka işlem tarafından tutulan kilidi bekliyor olabilir. Müdahaleden önce bekleyen PID'yi, onu bloklayan oturumu ve açık işlemin yaşını birlikte görmek gerekir.
Aktif ve bekleyen oturumları listeleyin
SELECT pid, usename, application_name, state,
wait_event_type, wait_event,
now() - query_start AS query_age,
now() - xact_start AS transaction_age,
query
FROM pg_stat_activity
WHERE datname = current_database()
ORDER BY query_start;
wait_event_type='Lock' kaydı kilit beklediğini gösterir. idle in transaction oturumları sorgu çalıştırmasa bile açık işlem nedeniyle kilit tutabilir.
Bloklayan PID'yi doğrudan bulun
SELECT waiting.pid AS waiting_pid,
pg_blocking_pids(waiting.pid) AS blocking_pids,
waiting.query AS waiting_query
FROM pg_stat_activity AS waiting
WHERE cardinality(pg_blocking_pids(waiting.pid)) > 0;
Bir bekleyen oturumun birden fazla bloklayıcısı olabilir. İlk görülen PID'yi otomatik sonlandırmayın.
Bloklayan sorgu ile kullanıcıyı eşleştirin
SELECT blocked.pid AS blocked_pid,
blocker.pid AS blocker_pid,
blocker.usename,
blocker.application_name,
now() - blocker.xact_start AS blocker_xact_age,
blocker.state,
blocker.query
FROM pg_stat_activity AS blocked
CROSS JOIN LATERAL unnest(pg_blocking_pids(blocked.pid)) AS b(pid)
JOIN pg_stat_activity AS blocker ON blocker.pid = b.pid;
İptal ile oturum sonlandırmayı ayırın
SELECT pg_cancel_backend(12345);
SELECT pg_terminate_backend(12345);
pg_cancel_backend çalışan sorguyu iptal eder. pg_terminate_backend oturumu kapatır ve açık işlemi geri alır; uygulamada hata ve yeniden deneme oluşturabilir. İş sahibini ve etkiyi doğrulamadan ikinci komutu kullanmayın.
Kök nedeni kalıcı olarak düzeltin
Uzun transaction, kullanıcı etkileşimi bekleyen uygulama akışı, eksik commit/rollback veya DDL işlemi tekrar eden kilitlerin yaygın nedenidir. lock_timeout ve statement_timeout beklemeyi sınırlayabilir; ancak hatalı transaction tasarımını düzeltmez.
Başvuru: PostgreSQL kilit izleme ve pg_locks görünümü.