PostgreSQL Kilit Zinciri ve Bloklama: Kök Bloklayıcıyı Bulma ve Çözme
Birbirini bekleyen oturumlardan oluşan kilit zincirinin başındaki oturumu bulur ve güvenle çözer. DDL kuyruğu tuzağını ve önleme yöntemlerini anlatır.
Operasyonel Güvenlik ve Risk Uyarısı
Bu runbook müdahale adımları içerir; birçok adım yazma etkilidir (KILL, terminate, DROP, RESIZE). Önce test ortamında deneyin, üretimde adımları sırayla ve doğrulayarak uygulayın.
1. Belirti / Symptom
- Sorgular uzun süre bekliyor, uygulamada zaman aşımı.
- `pg_stat_activity` içinde `wait_event_type = 'Lock'` olan çok sayıda oturum.
- M8 (kilit bekleyen oturum) eşiği aşıldı.
2. Etki / Impact
Etkilenen tablolara okuma/yazma gecikir veya durur. Zincir uzadıkça bağlantı havuzu dolar ve `pg-too-many-connections` senaryosuna dönüşebilir.
3. Teşhis / Diagnosis
SELECT blocked.pid AS blocked_pid, left(blocked.query,100) AS blocked_query,
blocker.pid AS blocking_pid, blocker.state AS blocking_state,
left(blocker.query,100) AS blocking_query,
now() - blocker.xact_start AS blocker_tx_age
FROM pg_stat_activity blocked
JOIN LATERAL unnest(pg_blocking_pids(blocked.pid)) AS b(pid) ON true
JOIN pg_stat_activity blocker ON blocker.pid = b.pid;- `idle in transaction`: uygulama transaction'ı açık unutmuş. En sık neden.
- `active` ve uzun: ağır bir DDL veya toplu güncelleme çalışıyor.
- `ALTER TABLE` bekliyor olabilir (aşağıdaki tuzağa bakın).
SELECT l.pid, l.locktype, l.mode, l.granted, l.relation::regclass
FROM pg_locks l WHERE NOT l.granted OR l.pid = <kok_pid>;4. Müdahale / Response
SELECT pg_cancel_backend(<kok_pid>);SELECT pg_terminate_backend(<kok_pid>);3. Sonlandırmadan önce **sorgu sahibini** (`usename`, `application_name`) ve işin kritikliğini kontrol edin. Veri taşıma veya fatura kesimi gibi işleri körlemesine kesmeyin.
4. **DDL kuyruğu tuzağı:** Uzun bir okuma transaction'ı varken `ALTER TABLE` gelirse, DDL `ACCESS EXCLUSIVE` kilidini bekler ve **arkasından gelen tüm basit SELECT'ler de DDL'in arkasında kuyruğa girer.** Çözüm: bekleyen DDL'i iptal edin (`pg_cancel_backend`), tüm tablo trafiği normale döner.
5. **Önleme:**
-- Migration oturumunda:
SET lock_timeout = '3s';
SET statement_timeout = '5min';
-- Genel güvenlik ağı:
ALTER SYSTEM SET idle_in_transaction_session_timeout = '5min';Migration'larda `CREATE INDEX CONCURRENTLY` ve kısa transaction kullanın.
5. Doğrulama / Verification
- Adım 1 sorgusu boş dönüyor, M8 normale döndü.
- Bekleyen uygulama sorguları tamamlandı, hata oranı düştü.
- Kök nedenin (açık kalan transaction, uygulama hatası, migration) kaydı tutuldu.
6. Geri Alma / Rollback
- `pg_cancel_backend` ve `pg_terminate_backend` geri alınamaz; ilgili işlem rollback olur ve uygulama tarafından yeniden denenmelidir.
- `lock_timeout` değişikliği oturum bazlıysa oturum kapanınca kendiliğinden kalkar.