Bilgi Bankası
PostgreSQLPerformans ve kapasite 16 dk 14.06.2026

PostgreSQL kilit beklemeleri: idle in transaction, deadlock ve uzun transaction nasıl çözülür?

PostgreSQL’de kilit sorunu çoğu zaman “veritabanı yavaşladı” diye görünür. Oysa bazen tek bir açık transaction, bütün sipariş akışını bekletebilir. Bu yazı, kilidi kimin tuttuğunu ve kimi beklettiğini sakin şekilde bulmayı anlatır.

Bu yazı sana şu durumda yardımcı olur
  • UPDATE veya DELETE sorguları bekliyor
  • deadlock detected hatası görülüyor
  • idle in transaction oturumları uzun süre açık kalıyor
  • API tarafında zaman aşımı artıyor
  • VACUUM veya migration işlemi bitmiyor
Yazıyı bitirince

pg_stat_activity ve pg_locks çıktısıyla bekleyen ve kilit tutan oturumları ayırabileceksiniz. Hangi oturumun güvenle sonlandırılabileceğini, hangi kod davranışının düzeltilmesi gerektiğini ve tekrarını nasıl azaltacağınızı netleştireceksiniz.

TürkDB açısından ürünleşme notu

Bu bölüm, TürkDB’nin ilgili problemi hangi ürün ilkeleri ve kontrol noktalarıyla ele alacağını anlatır. Kapsam, gerçek iş yükü ve ihtiyaçla birlikte netleşir.

TürkDB’nin burada hedefi, cluster olayları, yavaş sorgular ve bağlantı davranışı gibi kanıtları aynı bağlamda göstermektir. Kilit kararının kendisi yine PostgreSQL çıktısıyla verilir; platform yalnızca doğru kanıta daha hızlı ulaşmayı kolaylaştırmalıdır.

Kilit beklemesi yavaş sorgudan farklıdır

Bir sorgu kendi başına yavaş olabilir; çok satır okur, kötü indeks kullanır veya diskten veri çeker. Kilit beklemesi ise başka bir işlemin kapıyı tutmasıdır. Sorgunuz aslında hızlı çalışacakken sırada bekler.

Bu ayrımı yapmadan indeks eklemek, makine büyütmek veya bağlantı sayısını artırmak çoğu zaman işe yaramaz. Önce sorgu CPU mu yakıyor, yoksa başka bir transaction yüzünden mi bekliyor bunu anlamak gerekir.

  • Uzun transaction satır veya tablo kilidini gereğinden uzun tutabilir.
  • idle in transaction, uygulamanın transaction açıp işi bitirmeden beklediğini gösterir.
  • Deadlock, iki işlemin birbirini beklemesi ve PostgreSQL’in birini iptal etmesidir.
  • Migration veya toplu veri düzeltme işleri kilit etkisini büyütebilir.

Bekleyen ve bekleten oturumu bulun

İlk bakılacak yer pg_stat_activity ve pg_locks çıktısıdır. Ama amaç sadece uzun süren sorguyu görmek değildir; kimin beklediğini ve kimin kilidi tuttuğunu aynı ekranda yakalamaktır.

Aşağıdaki sorgu canlı ortamda dikkatle kullanılabilecek bir başlangıçtır. Size bekleyen oturumun sorgusunu, ne kadar süredir beklediğini ve onu engelleyen oturum kimliğini gösterir.

PostgreSQL kilit bekleme teşhisi

postgres-lock-wait.sql
SELECT
  blocked.pid AS blocked_pid,
  blocked.usename AS blocked_user,
  now() - blocked.query_start AS blocked_for,
  blocked.query AS blocked_query,
  blocking.pid AS blocking_pid,
  blocking.usename AS blocking_user,
  now() - blocking.query_start AS blocking_for,
  blocking.query AS blocking_query
FROM pg_stat_activity blocked
JOIN pg_locks blocked_locks
  ON blocked_locks.pid = blocked.pid
JOIN pg_locks blocking_locks
  ON blocking_locks.locktype = blocked_locks.locktype
 AND blocking_locks.database IS NOT DISTINCT FROM blocked_locks.database
 AND blocking_locks.relation IS NOT DISTINCT FROM blocked_locks.relation
 AND blocking_locks.page IS NOT DISTINCT FROM blocked_locks.page
 AND blocking_locks.tuple IS NOT DISTINCT FROM blocked_locks.tuple
 AND blocking_locks.transactionid IS NOT DISTINCT FROM blocked_locks.transactionid
 AND blocking_locks.pid <> blocked_locks.pid
JOIN pg_stat_activity blocking
  ON blocking.pid = blocking_locks.pid
WHERE NOT blocked_locks.granted
ORDER BY blocked_for DESC;

idle in transaction genellikle uygulama davranışıdır

idle in transaction gördüğünüzde veritabanını suçlamadan önce uygulama koduna bakın. Transaction açılmış, bir sorgu çalışmış, sonra kod dış servis çağrısı, dosya işlemi veya kullanıcıdan cevap bekleme gibi veritabanı dışı bir işte kalmış olabilir.

Bu sırada PostgreSQL transactionın tuttuğu kilitleri bırakamaz. En kötü durumda küçük bir kod ihmali, bütün ödeme veya stok güncelleme akışını bekletebilir.

Uzun süren açık transactionları bulma

idle-in-transaction.sql
SELECT
  pid,
  usename,
  application_name,
  client_addr,
  state,
  now() - xact_start AS transaction_age,
  query
FROM pg_stat_activity
WHERE xact_start IS NOT NULL
  AND now() - xact_start > INTERVAL '2 minutes'
ORDER BY transaction_age DESC;

Ne zaman oturum sonlandırılır?

Kilit tutan oturumu hemen öldürmek cazip gelir ama bu karar kör verilmemeli. Oturum bir migration, ödeme yazımı veya stok azaltma işlemi olabilir. Önce kullanıcı, uygulama adı, sorgu metni ve transaction süresi okunmalıdır.

Sonlandırma kararı gerekiyorsa bunu olay notuna yazın: hangi pid, hangi sorgu, neden sonlandırıldı, kullanıcı etkisi neydi? Böylece aynı sorun tekrarlandığında yalnızca kahramanlık hikâyesi değil, öğrenilmiş bir karar kalır.

Son çare olarak oturum sonlandırma

terminate-blocker.sql
-- Önce blocking_pid değerini ve sorgu bağlamını doğrulayın.
SELECT pg_terminate_backend(12345);

Bu komut veri tutarlılığı ve uygulama davranışı açısından riskli olabilir. Önce sorgu bağlamını ve geri dönüş etkisini anlayın.

Devam etmek istersen

Sorunu motor bazında derinleştirin

Benzer belirtiler farklı motorlarda farklı nedenlere dayanır; yayınlanan tüm rehberleri ana sayfadan takip edebilirsiniz.

Tüm makaleler