· kaynak dev.to (home feed)
PostgreSQL NOTIFY kuyruk hatası tek bir boşta bekleyen transaction ile yeniden üretildi
dev.to üzerindeki bir yeniden üretim çalışması, açık bir transaction içinde boşta bırakılan bir dinleyicinin PostgreSQL'in NOTIFY kuyruğunu nasıl doldurduğunu ve max_notify_queue_pages değerinin artırılmasının bunu neden çözmediğini gösteriyor.

Bir geliştirici, PostgreSQL'in daha sessiz hata modlarından biri olan too many notifications in the NOTIFY queue hatası hakkında kompakt ve yeniden üretilebilir bir anlatı yayımladı. dev.to'da yazan yazar, bu durumu Docker içinde çalışan PostgreSQL 17 üzerinde iki psql oturumuyla yeniden oluşturdu ve belirleyici faktörün kuyruk kapasitesi değil, dinleme tarafında açık bırakılan bir transaction olduğunu gösterdi.
Kuyruk 512 KiB'ye düşürüldü
PostgreSQL'in bildirim kuyruğu varsayılan olarak çok gigabayt büyüklüğündedir; bu yüzden normal ayarlarla doldurmak aşırı bir iş yükü gerektirirdi. Deneyi pratik kılmak için yazar, sunucuyu max_notify_queue_pages=64 ile başlattı. Her sayfa 8 KiB olduğundan, toplam kuyruk kapasitesi yalnızca 512 KiB oldu.
Test iki bağlantı kullandı. İlkinde dinleyici LISTEN demo; çalıştırdı, ardından BEGIN; ile transaction başlatıp o transaction açık kalacak şekilde boşta bekledi. İkinci bağlantıdan yazar, 100 büyük pg_notify() çağrısı gerçekleştirdi.
Gönderiye göre sonuçlar kolayca gözlemlenebilirdi: 64 gönderme başarılı oldu, 36'sı başarısız oldu ve pg_notification_queue_usage() kuyruğun yüzde 100 kapasitede olduğunu bildirdi. Başarısız olan her gönderme yukarıdaki hatayı döndürdü.
Asıl suçlu açık transaction
İlginç olan kısım, kuyruğun hiç neden dolduğudur. Dinleyici hiçbir şey göndermedi; yalnızca bildirimler gelirken açık bir transaction içinde kaldı. Yazarın vurguladığı çıkarım şudur: daha büyük bir max_notify_queue_pages yalnızca nefes alma alanı ekler. Bildirim temizliğini engelleyen transaction konusunda hiçbir şey yapmaz. Temizlik engellendiği için, gelen bildirimler birikti ve kapasite tükenene kadar; sonunda göndericiler başarısız olmaya başladı.
Bu ayrım operasyonel olarak önemli. Hata bir kapasite sorunu gibi görünür ve bariz tepki limiti yükseltmektir. Bu yeniden üretim, bunun ancak zaman kazandırdığını gösteriyor: bir transaction kuyruğu kilitlemeye devam ettiği sürece bildirimler birikmeye devam eder ve limite — yalnızca daha sonra — tekrar ulaşılır.
Kurtarma tek bir COMMIT
Hata tamamen geri alınabilir olduğunu da kanıtladı. Dinleyici oturumuna dönüp COMMIT; çalıştırmak bekleyen bildirimleri iletti ve ardından yapılan SELECT pg_notification_queue_usage(); kontrolü kullanımın tekrar 0 olduğunu gösterdi. Yeniden başlatma veya manuel müdahale gerekmedi; transaction'ı sonlandırmak kuyruğun boşalmasını sağladı.
Yazar, Docker Compose kurulumunu, SQL komutlarını, her adımdaki kuyruk ölçümlerini, notify uygulamasına bir bakışı ve kurtarmanın doğrulanmasını kapsayan daha uzun bir eşlik eden yazıya işaret ediyor.
Neden önemli
LISTEN/NOTIFY, ayrı bir mesaj broker kurmadan hafif olay kanalları ve iş tetikleyicileri oluşturmanın yaygın bir yoludur. Bu yeniden üretim, mekanizmanın ne kadar kolaylıkla kazara kilitlenebileceğini gösteriyor: transaction başlatıp sonra boşta bekleyen bir dinleyici kuyruğu sabitlerken, ortaya çıkan hatalar gerçek nedenden uzakta, gönderici tarafında görünür.
Bundan çıkan pratik öneriler net. LISTEN kullanan bağlantılarda transaction'ları kısa tutun, pg_notification_queue_usage() fonksiyonunu izlemeye değer erken uyarı metriği olarak görün ve çok fazla bildirim hatası göründüğünde daha büyük bir max_notify_queue_pages değerine başvurmadan önce sıkışmış bir transaction arayın.
- #postgresql
- #listen-notify
- #databases
- #queues
- #debugging