PostgreSQL "canceling statement due to statement timeout" — Sorgu mu Yavaş, Kilit mi Bekliyor?
57014 kodunun arkasındaki dört farklı olay, pg_settings ile eşiğin kaynağını bulma ve timeout'u rol bazlı yönetme.
Operasyonel Doğrulama & Güvenilirlik Standardı
Hata mesajı semptomdur, kök neden değildir. Sunucuyu yeniden başlatmadan veya rastgele ayar değiştirmeden önce aşağıdaki "Nedeni ayırt eden tek sorgu"yu çalıştırarak gerçek senaryoyu netleştirin.
▸Belirti
ERROR: canceling statement due to statement timeoutAynı PostgreSQL SQLSTATE kodu olan 57014 (query_canceled) altında dört tamamen farklı olay yaşanabilir:
ERROR: canceling statement due to statement timeout
ERROR: canceling statement due to lock timeout
ERROR: canceling statement due to user request
ERROR: canceling statement due to conflict with recovery57014 kodunu görüp *"Sorgumuz yavaş çalışıyor, hemen yeni indeks ekleyelim"* demek, 4 senaryonun 3'ünde yanlış yerde zaman kaybetmek demektir:
- `statement timeout`: Sorgu gerçekten işlemci/disk üzerinde uzun sürdü ve zaman aşımı sınırını aştı.
- `lock timeout`: Sorgu 1 milisaniyede bitecek kadar hızlı olabilir; ancak başka bir işlem tabloyu kilitlediği için beklerken lock_timeout eşiğine takıldı! Çözüm indeks değil kilit zincirini çözmektir (H-19, H-27).
- `user request`: İptal emri sunucudan değil istemciden geldi! İstemci kütüphanesi (JDBC setQueryTimeout, .NET CommandTimeout, Go context timeout) süresi dolduğu için PostgreSQL'e kasten pg_cancel_backend() gönderdi. Sunucu tarafında hiçbir ayar hatası yoktur.
- `conflict with recovery`: Sorgu bir Read Replica üzerinde çalışırken Master'dan gelen WAL replay işlemiyle çakıştı (H-11).▸Eşiğin Nereden Geldiğini Tespit Edin (`pg_settings`)
PostgreSQL'de statement_timeout ayarı beş farklı hiyerarşik katmandan gelebilir:
SELECT name, setting, unit, source, sourcefile, sourceline
FROM pg_settings
WHERE name IN ('statement_timeout', 'lock_timeout', 'idle_in_transaction_session_timeout');source sütunu teşhisi netleştirir:
- •
configuration file:postgresql.confdosyasından gelen global ayar. - •
database:ALTER DATABASE dbname SET statement_timeout = ...ile verilmiş veritabanı ayarı. - •
user:ALTER ROLE app_user SET statement_timeout = ...ile atanmış rol düzeyi kısıtlama. - •
client: Bağlantı havuzu (PgBouncer) veya uygulama kodu oturum açarkenSET statement_timeout = ...gönderdi. - •
default: Ayarlanmamış; PostgreSQL varsayılanı0(sınırsız).
▸Adım Adım Teşhis ve Çözüm Akışı
1. Yavaş Sorguyu pg_stat_statements ile Ölçün
Tahmin yürütmek yerine gerçek kaynak tüketimini sorgulayın:
CREATE EXTENSION IF NOT EXISTS pg_stat_statements;
SELECT queryid, calls,
round(mean_exec_time::numeric, 1) AS ortalama_ms,
round(total_exec_time::numeric) AS toplam_ms,
left(query, 100) AS sorgu
FROM pg_stat_statements
ORDER BY total_exec_time DESC
LIMIT 15;- •
total_exec_timeveritabanına en çok kümülatif yük getiren sorguları gösterir. - •
mean_exec_timetek başına timeout eşiğini aşan sorguları listeler.
2. Kilit Beklemesi (Lock Wait) Kontrolü
SELECT pid, now() - query_start AS suredir, wait_event_type, wait_event,
cardinality(pg_blocking_pids(pid)) AS bloklayan_sayisi,
pg_blocking_pids(pid) AS bloklayan_pidler,
left(query, 80) AS sorgu
FROM pg_stat_activity
WHERE state = 'active' AND pid <> pg_backend_pid()
ORDER BY suredir DESC;Eğer wait_event_type = 'Lock' ise sorgu CPU tüketmiyor; başka bir oturumun açtığı satır/tablo kilidini bekliyor demektir.
3. Gerçek Yürütme Planını (BUFFERS Dahil) Alın
EXPLAIN (ANALYZE, BUFFERS) SELECT ...;BUFFERS ibaresi olmadan diskten okunan blok sayısını göremezsiniz; bellek (shared hit) ile disk (read) arasındaki farkı yalnızca buffers çıktısı gösterir.
▸Kalıcı Çözüm: Timeout Yönetimi Bir Politikadır
1. Global Timeout'u Sıfırlamak Büyük Bir Hatadır!
Timeout aldığında ilk yapılan hatalı refleks statement_timeout = 0 yapmaktır. Zaman aşımı eşiği bir emniyet kemeridir; onu kaldırmak yavaş sorguyu çözmez, aksine o sorgunun bağlantı havuzunu tüketip tüm siteyi çökertmesine yol açar.
2. Rol Bazlı Kademeli Zaman Aşımı Tanımlayın
Web kullanıcıları ile analitik rapor servisleri asla aynı timeout sınırına tabi olmamalıdır:
-- Web API kullanıcıları için agresif sınır (5 saniye)
ALTER ROLE app_web SET statement_timeout = '5s';
-- Gece çalışan raporlama kullanıcısı için geniş sınır (15 dakika)
ALTER ROLE app_rapor SET statement_timeout = '15min';3. lock_timeout Değerini statement_timeout Değerinden Kısa Tutun
ALTER SYSTEM SET lock_timeout = '3s';
ALTER SYSTEM SET statement_timeout = '10s';
SELECT pg_reload_conf();Bu sayede bir sorgu kilit yüzünden takıldığında, 10 saniye boyunca havuzu meşgul etmeden 3. saniyede canceling statement due to lock timeout hatasıyla hızla başarısız olur ve hatanın kilit kaynaklı olduğu logda açıkça belgelenir.
▸İlgili Hata Rehberleri & Hub Bağlantıları
- •PostgreSQL Conflict with Recovery (H-11) — Replikasyon iptal çakışmaları
- •PostgreSQL Deadlock Detected (H-27) — Karşılıklı kilitlenme çözümü
- •SQL Server Lock Request Timeout 1222 (H-19) — SQL Server kilit zaman aşımı
- •MySQL Lock Wait Timeout Exceeded (H-09) — MySQL kilit bekleme süresi
- •PostgreSQL Hub — Performans ve sorgu planlama rehberleri
Diğer Veritabanı Hata Teşhisleri
Kriz anında başvurabileceğiniz diğer doğrulanmış hata rehberleri.
PostgreSQL Bağlantı Tükenmesi ve too many clients Teşhisi
FATAL: sorry, too many clients already ve remaining connection slots hatalarının üç temel kök nedeni, yetki sınırlarıyla salt okunur pg_stat_activity teşhisi ve kalıcı iki katmanlı havuzlama çözümü.
PostgreSQL password authentication failed Hatası: Neden ve Çözüm
psql password authentication failed hatasının dört nedeni: yanlış şifre, md5/SCRAM uyuşmazlığı, pg_hba.conf sırası ve yanlış cluster. Adım adım teşhis.
PostgreSQL connection refused: 8 Adımda Kesin Teşhis
Connection refused, timeout ve "no pg_hba.conf entry" arasındaki fark; listen_addresses, port, firewall ve Docker port yayınlama kontrolleri.