PostgreSQL advisory kilitleri ile eşzamanlılığa güvenli iş akışları
Onaylarda, faturalamada ve zamanlayıcılarda çift işlemeyi durdurmak için PostgreSQL advisory kilitlerini öğrenin: pratik desenler, SQL örnekleri ve basit kontroller.

Gerçek sorun: iki süreç aynı işi yapıyor
Çift işlem, aynı öğenin iki farklı aktör tarafından iki kez işlenmesidir çünkü her biri kendisinin sorumlu olduğunu düşünüyor. Gerçek uygulamalarda bu, müşterinin iki kez ücretlendirilmesi, bir onayın iki kez uygulanması veya "fatura hazır" e-postasının iki kez gönderilmesi şeklinde ortaya çıkar. Testlerde her şey düzgün görünür, sonra gerçek trafiğin altında bozulur.
Genellikle zamanlama sıkıştığında ve birden fazla şey harekete geçebildiğinde olur:
İki worker aynı işi aynı anda alır. Ağ çağrısı yavaş olduğundan bir retry tetiklenir ama ilk deneme hâlâ çalışıyordur. Kullanıcı UI takıldığı için Onay'a çift tıklar. Deploy sonrası iki scheduler örtüşür veya saat kayması olur. Bir mobil uygulama zaman aşımından sonra yeniden gönderirse tek bir dokunuş iki isteğe dönüşebilir.
Sorunun acı tarafı, her aktörün tek başına "makul" davranmasıdır. Hata, aralarındaki boşluktur: hiçbiri diğerinin aynı kaydı zaten işlediğini bilmez.
Amaç basit: belirli bir öğe (bir sipariş, bir onay isteği, bir fatura) için kritik işi aynı anda yalnızca bir aktör yapabilmeli. Diğerleri ya kısa süre beklemeli ya da geri çekilip tekrar denemeli.
PostgreSQL advisory kilitleri yardımcı olabilir. Bunlar size, zaten güven duyduğunuz veritabanını kullanarak "Öğeyle X üzerinde çalışıyorum" demenin hafif bir yolunu verir.
Beklentileri belirleyin: bir kilit tam bir sıra sistemi değildir. İşleri sizin için zamanlamaz, sıralamayı garanti etmez veya mesajları saklamaz. Tekrar çalıştırılmaması gereken iş akışının etrafında bir güvenlik kapısıdır.
PostgreSQL advisory kilitleri nedir (ve ne değildir)
PostgreSQL advisory kilitleri, yalnızca bir worker'ın aynı anda bir işi yapmasını sağlama yöntemidir. Bir kilit anahtarı seçersiniz (ör. "fatura 123"), veritabanından onu kilitlemesini istersiniz, işi yapar ve sonra kilidi serbest bırakırsınız.
"Advisory" kelimesi önemlidir. Postgres anahtarınızın ne anlama geldiğini bilmez ve otomatik olarak hiçbir şeyi korumaz. Sadece bir gerçeği izler: bu anahtar kilitli mi değil mi. Kodunuz anahtar formatında anlaşmalı ve riskli kısmı çalıştırmadan önce kilidi almalıdır.
Ayrıca advisory kilitleri satır kilitleriyle karşılaştırmak faydalıdır. Satır kilitleri (SELECT ... FOR UPDATE gibi) gerçek tablo satırlarını korur. İş doğrudan bir satıra uyuyorsa bunlar harikadır. Advisory kilitler ise sizin seçtiğiniz bir anahtarı korur; iş akışı birçok tabloyu etkiliyorsa, harici servisleri çağırıyorsa veya satır daha oluşmadan önce başlıyorsa bu işe yarar.
Advisory kilitleri şu durumlarda kullanışlıdır:
- Bir varlık için birer birer yapılması gereken işlemler (bir isteğe bir onay, bir faturaya bir tahsilat)
- Ayrı bir kilitleme servisi eklemeden çoklu uygulama sunucuları arasında koordinasyon
- Tek bir satır güncellemesinden daha geniş bir iş akışı adımının korunması
Bunlar diğer güvenlik araçlarının yerine geçmez. İşlemleri idempotent yapmazlar, iş kurallarını uygulamazlar ve bir kod yolu kilidi almayı unutursa çoğaltmaları durdurmazlar.
Genelde "hafif" olarak anılırlar çünkü şema değişikliği veya ek altyapı gerektirmeden kullanılabilirler. Birçok durumda, kritik bir bölüm etrafına tek bir kilit çağrısı ekleyerek çift işlemeyi çözebilirsiniz.
Gerçekte kullanacağınız kilit tipleri
İnsanlar "PostgreSQL advisory kilitleri" derken genellikle birkaç işlevi kastederler. Doğru olanı seçmek hata, zaman aşımı ve retry durumlarında ne olacağını değiştirir.
Oturum (session) vs işlem (transaction) kilitleri
Oturum seviyesindeki bir kilit (pg_advisory_lock) veritabanı bağlantısı kadar sürer. Uzun süre çalışan worker'lar için kullanışlı olabilir, ama uygulamanız çöküp bağlantı havuzunda takılı bir bağlantı kalırsa kilit uzun süre kalabilir.
İşlem seviyesindeki bir kilit (pg_advisory_xact_lock) mevcut transaction'a bağlıdır. Commit veya rollback yaptığınızda PostgreSQL onu otomatik olarak serbest bırakır. Çoğu istek-yanıt iş akışı (onaylar, ödeme tıklamaları, admin işlemleri) için bu daha güvenli varsayımdır çünkü serbest bırakmayı unutmak daha zordur.
Bloklayıcı vs try-lock
Bloklayan çağrılar kilit serbest olana kadar bekler. Basit ama başka bir oturum kilidi tutuyorsa web isteğinin takılmış hissetmesine neden olabilir.
Try-lock çağrıları hemen döner:
pg_try_advisory_lock(session-level)pg_try_advisory_xact_lock(transaction-level)
Try-lock genelde UI aksiyonları için daha iyidir. Kilit alınamazsa kullanıcıya "Zaten işleniyor" gibi net bir mesaj dönebilirsiniz.
Paylaşılan vs münhasır
Münhasır kilitler "birer birer" çalışır. Paylaşılan kilit birden fazla tutana izin verir ama münhasır bir kilidin alınmasını engeller. Çoğu çift işlem problemi için münhasır kilitler kullanılır. Çok okuyucunun ilerleyebildiği ama nadir bir yazarın tek başına çalışması gereken senaryolarda paylaşılan kilitler faydalıdır.
Kilitler nasıl serbest bırakılır
Serbest bırakma tipi şu anlama gelir:
- Oturum kilitleri: bağlantı kesildiğinde veya
pg_advisory_unlockile açıkça çağrıldığında serbest bırakılır - İşlem kilitleri: transaction sona erdiğinde otomatik serbest bırakılır
Doğru kilit anahtarını seçmek
Bir advisory kilit işe yarar yalnızca her worker tam olarak aynı anahtarı kilitlemeye çalışırsa. Bir kod yolu "invoice 123" kilitlerken başka bir yol "customer 45" kilitlermiş gibi davranırsa yine çoğaltma olur.
Korumak istediğiniz "şeyi" isimlendirerek başlayın. Somut olun: bir fatura, bir onay isteği, bir zamanlanmış görev çalışması veya bir müşterinin aylık faturalama döngüsü. Bu seçim kaç paralelliğe izin vereceğinizi belirler.
Riski eşleştiren bir kapsam seçin
Çoğu takım şu seçeneklerden biriyle sonuçlanır:
- Kayıt başına: onaylar ve faturalar için en güvenli (invoice_id veya request_id ile kilitleme)
- Müşteri/hesap başına: eğer işlemler müşteri bazında sıraya alınmalıysa kullanışlı (faturalama, kredi değişiklikleri)
- İş akışı adımı başına: farklı adımlar paralel çalışabilir ama her adım birer birer çalışmalıysa
Kapsamı bir veritabanı detayı değil, ürün kararı olarak ele alın. "Kayıt başına" çift tıklamaların iki kez ücretlendirmesini önler. "Müşteri başına" iki background jobun örtüşen bildirimler üretmesini engeller.
Stabil bir anahtar stratejisi seçin
Genelde iki seçenek vardır: iki 32-bit tamsayı (genellikle namespace + id) veya tek bir 64-bit tamsayı (bigint), bazen bir string ID hash'lenerek oluşturulur.
İki-int anahtarlar standartlaştırması kolaydır: her iş akışı için sabit bir namespace numarası seçip (ör. onaylar vs faturalama) record ID'yi ikinci değer olarak kullanın.
UUID gibi bir tanımlayıcınız varsa hashleme işe yarayabilir, ama küçük bir çakışma riski olduğunu kabul etmelisiniz ve her yerde tutarlı olmalısınız.
Ne seçerseniz seçin, formatı yazılı hale getirin ve merkezileştirin. İki yerde "neredeyse aynı" anahtar kullanmak çoğaltmaları yeniden getiren yaygın bir yoldur.
Adım adım: tek seferlik güvenli bir işleme deseni
İyi bir advisory-lock iş akışı basittir: kilitle, yeniden kontrol et, uygula, kaydet, commit et. Kilit tek başına iş kuralı değildir. Aynı kaydı aynı anda iki worker vurursa kuralı güvenilir kılan bir korumadır.
Pratik bir desen:
- Sonucun atomik olması gerekiyorsa bir transaction açın.
- Spesifik iş birimi için kilidi alın. Transaction seviyesinde kilit (
pg_advisory_xact_lock) tercih edin ki otomatik bırakılsın. - Veritabanında durumu tekrar kontrol edin. İlk sizmişsiniz gibi varsaymayın. Kaydın hâlâ uygun olduğundan emin olun.
- İşi yapın ve veritabanında kalıcı bir "tamamlandı" işareti yazın (durum güncellemesi, defter kaydı, denetim satırı).
- Commit edin ve kilidin bırakılmasına izin verin. Oturum seviyesinde kilit kullandıysanız, bağlantıyı havuza geri vermeden önce unlock edin.
Örnek: iki app sunucusu aynı saniye içinde "Invoice #123'i onayla" alır. İkisi başlar ama sadece biri 123 için kilidi alır. Kazanan, invoice #123'ün hâlâ pending olduğunu kontrol eder, approved yapar, audit/ödeme kaydını yazar ve commit eder. İkinci sunucu ya hızlıca başarısız olur (try-lock) ya da ilk bittikten sonra kilidi alır, durumun zaten onaylı olduğunu görür ve hiçbir şeyi değiştirmeden çıkar. Her iki durumda da çift işlemeyi önlemiş olursunuz ve UI duyarlı kalır.
Hata ayıklama için yeterince log tutun: istek id'si, approval id ve hesaplanan kilit anahtarı, aktör id'si, sonuç (lock_busy, already_approved, approved_ok) ve zamanlama.
Advisory kilitlerin uygun olduğu yerler: onaylar, faturalama, zamanlayıcılar
Advisory kilitler en iyi şu durumda uyar: belirli bir şey için yalnızca bir süreç "kazanan" işi aynı anda yapabilmeli. Mevcut veritabanınızı ve uygulama kodunuzu korursunuz, ama yarış durumlarını tetiklemeyi zorlaştıran küçük bir kapı eklersiniz.
Onaylar
Onaylar klasik yarış tuzaklarıdır. İki inceleyen (veya aynı kişi çift tıkladığında) Onay'a milisaniyeler içinde basabilir. İstek ID'sine kilit koyarak yalnızca bir transaction durum değişikliğini yapar. Diğerleri sonucu hızlıca öğrenir ve "zaten onaylandı" veya "zaten reddedildi" gibi net bir mesaj gösterebilir.
Bu, birçok kişinin aynı kuyruğu izlediği müşteri portalları ve admin panellerinde yaygındır.
Faturalama
Faturalama genelde daha sıkı bir kural ister: bir fatura için bir ödeme denemesi, retry olsa bile tek seferlik. Ağ zaman aşımı kullanıcının tekrar Pay'e tıklamasına neden olabilir veya arka plan retry ilk deneme devam ederken çalışabilir.
Fatura ID'sine kilit koymak, ödeme sağlayıcıyla aynı anda yalnızca bir yolun konuşmasını sağlar. İkinci deneme "ödeme işleniyor" dönebilir veya en son ödeme durumunu okuyabilir. Bu, çift iş yapılmasını önler ve çift ücretlendirme riskini azaltır.
Zamanlayıcılar ve arka plan çalışanları
Çok örnekli kurulumlarda zamanlayıcılar aynı pencereyi yanlışlıkla paralel çalıştırabilir. İş adı artı zaman penceresi üzerine kilit atmak (ör. "daily-settlement:2026-01-29") sadece bir örneğin çalışmasını sağlar.
Tablodan öğe çeken worker'lar için de aynı yaklaşım çalışır: yalnızca bir worker'ın işleyebilmesi için öğe ID'si üzerinde kilit alın.
İnsanların genelde kilitlediği ortak anahtarlar: tek bir onay isteği ID'si, tek bir fatura ID'si, iş adı + zaman penceresi, "bir seferde bir dışa aktarma" için müşteri ID'si veya retry'ler için benzersiz idempotency anahtarı.
Gerçekçi bir örnek: portalde çift-onayı durdurmak
Bir portalde bir onay isteğini düşünün: bir satın alma siparişi bekliyor ve iki yönetici aynı saniye içinde Onay'a tıklıyor. Koruma yoksa her iki istek de "pending" okur ve her ikisi de "approved" yazabilir; bu çift denetim girdileri, çift bildirimler veya aşağı doğru tetiklenen işlerin iki kez çalışmasına yol açar.
PostgreSQL advisory kilitleri bu işlemi onay başına birer birer yapmanın basit bir yolunu sunar.
Akış
API onay aksiyonunu aldığında önce onay id'sine dayalı bir kilit alır (farklı onayların paralel işlenmesine izin vermek için).
Yaygın bir desen: approval_id üzerinde kilit al, mevcut durumu oku, durumu güncelle, bir denetim kaydı yaz; hepsi tek bir transaction içinde.
BEGIN;
-- One-at-a-time per approval_id
SELECT pg_try_advisory_xact_lock($1) AS got_lock; -- $1 = approval_id
-- If got_lock = false, return "someone else is approving, try again".
SELECT status FROM approvals WHERE id = $1 FOR UPDATE;
-- If status != 'pending', return "already processed".
UPDATE approvals
SET status = 'approved', approved_by = $2, approved_at = now()
WHERE id = $1;
INSERT INTO approval_audit(approval_id, actor_id, action, created_at)
VALUES ($1, $2, 'approved', now());
COMMIT;
İkinci tıklamanın deneyimi
İkinci istek ya kilidi alamaz (böylece hızlıca "Zaten işleniyor" döner) ya da ilk işlem bitince kilidi alır, sonra durumun zaten onaylı olduğunu görür ve çıkış yapar. Her iki durumda da çift işlenmenin önüne geçilir ve UI duyarlılığı korunur.
Hata ayıklama için her denemeyi izleyin: istek id'si, onay id'si ve hesaplanan kilit anahtarı, aktör id'si, sonuç (lock_busy, already_approved, approved_ok) ve zamanlama.
Uygulamayı donuklaştırmadan bekleme, zaman aşımı ve retryleri ele alma
Kilidi beklemek zararsız görünür ama bir süre sonra dönen düğme, takılmış bir worker veya asla temizlenmeyen bir iş kuyruğu haline gelebilir. Kilidi alamadığınızda insan bekliyorsa hızlıca başarısız olun; yalnızca beklemenin güvenli olduğu durumlarda bekleyin.
Kullanıcı aksiyonları için: try-lock ve net cevap
Biri Onay veya Öde'ye tıklıyorsa isteği saniyelerce bloklamayın. Try-lock kullanın ki uygulama hemen yanıt verebilsin.
Pratik yaklaşım: kilidi dene; eğer alınamazsa net bir "meşgul, tekrar deneyin" yanıtı verin (veya öğe durumunu yenileyin). Bu zaman aşımını azaltır ve tekrar tıklamaları caydırır.
Kilitleme bölümünü kısa tutun: durumu doğrula, durumu uygula, commit et.
Arka plan işleri için: bloklamak kabul edilebilir ama sınır koyun
Zamanlayıcılar ve worker'lar için bloklamak uygundur çünkü insan beklemiyor. Ama yine de sınırlar koyun; aksi takdirde bir yavaş iş tüm filoyu bekletebilir.
Bir worker'ın vazgeçebilmesi için zaman aşımı kullanın:
SET lock_timeout = '2s';
SET statement_timeout = '30s';
SELECT pg_advisory_lock(123456);
Ayrıca işin beklenen maksimum süresini belirleyin. Eğer faturalama genelde 10 saniyeden kısa sürüyorsa 2 dakika bir olay sayılmalı. Başlangıç zamanı, iş id'si ve kilidin ne kadar süre tutulduğunu izleyin. Eğer işçi zaman aşımını destekliyorsa, üst sınırı aşan görevleri iptal edin ki oturum sona ersin ve kilit bırakılabilsin.
Retryleri amaca uygun planlayın. Kilit alınamazsa ne olacağına karar verin: hemen küçük bir gecikme ve rastgelelik ile yeniden planla, bu döngü için en iyi çabayı atla veya tekrarlayan hatalarda öğeyi içerme olarak işaretleyin.
Takılmış kilitler veya çoğaltmalarla sonuçlanan yaygın hatalar
En yaygın sürpriz, asla serbest bırakılmayan session-level kilitlerdir. Bağlantı havuzları bağlantıları açık tutar, bu yüzden bir oturum kilidi alıp unlock etmeyi unutursanız kilit, bağlantı geri dönene kadar tutulabilir. Diğer worker'lar bekler (veya başarısız olur) ve nedenini bulmak zor olabilir.
Bir diğer çoğaltma kaynağı, kilitleyip durumu kontrol etmemektir. Kilit sadece kritik bölümün aynı anda birden fazla kere çalışmasını engeller. Kaydın hâlâ uygun olduğundan emin olmak için ayni transaction içinde yeniden kontrol edin (ör. pending mi diye doğrulayın) .
Kilit anahtarları da takımların işini zorlaştırır. Bir servis order_id üzerinde kilitlerken başka bir servis aynı gerçek dünya kaynağı için farklı hesaplanmış bir anahtar kullanıyorsa iki farklı kilit oluşur. Her iki yol da aynı anda çalışabilir ve bu yanlış bir güven hissi yaratır.
Uzun kilit tutulması genelde kendinizin sebep olduğu bir durumdur. Kilitliyken yavaş ağ çağrıları yaparsanız (ödeme sağlayıcı, e-posta/SMS, webhooklar) kısa bir koruma darboğaza dönüşür. Kilitli kısmı hızlı veritabanı işine odaklayın: durumu doğrulayın, yeni durumu yazın, sonra tetiklenecek yan etkileri transaction commit'ten sonra çalıştırın.
Son olarak, advisory kilitler idempotency veya veritabanı kısıtlarının yerini almaz. Bunları bir trafik ışığı olarak görün, kanıt sistemi olarak değil. Uygun yerlerde unique constraint kullanın ve harici çağrılar için idempotency anahtarları kullanın.
Yayına almadan önce kısa kontrol listesi
Advisory kilitlerini küçük bir sözleşme olarak ele alın: takımda herkes kilidin ne anlama geldiğini, neyi koruduğunu ve kilit tutulurken ne yapılabileceğini bilmelidir.
Çoğu problemi yakalayan kısa kontrol listesi:
- Her kaynak için tek bir net kilit anahtarı, yazılı ve her yerde yeniden kullanılan
- Geri dönüşü olmayan şeylerden önce kilidi alın (ödemeler, e-postalar, harici API çağrıları)
- Kilidi aldıktan sonra durumu tekrar kontrol edin ve yazmadan önce uygunluğu doğrulayın
- Kilitli bölümü kısa ve ölçülebilir tutun (kilit bekleme ve yürütme sürelerini loglayın)
lock busydurumunun her yol için ne anlama geldiğini kararlaştırın (UI mesajı, geri çekilmeli retry, atla)
Sonraki adımlar: deseni uygulayın ve sürdürülebilir tutun
En çok zarar veren bir yeri seçin ve oradan başlayın. İyi ilk hedefler para maliyeti olan veya durumu kalıcı değiştiren aksiyonlardır: "faturayı tahsil et" veya "isteği onayla" gibi. Sadece o kritik bölümü advisory lock ile sarın, sonra davranışa güvendikçe yakındaki adımları genişletin.
Erken temel gözlemlenebilirlik (observability) ekleyin. Bir worker kilidi alamadığında ve kilitli işin ne kadar sürdüğünde log tutun. Eğer kilit beklemeleri artarsa genelde kilitli bölüm çok büyük demektir veya içinde yavaş bir sorgu gizlidir.
Kilitler verinin güvenliği üzerine kurulu olduğunda en iyi şekilde çalışır, onun yerine değil. Açık durum alanları (pending, processing, done, failed) tutun ve mümkünse bunları constraint'lerle destekleyin. En kötü anda bir retry olursa, unique constraint veya idempotency anahtarı ikinci savunma hattı olabilir.
Eğer AppMaster'da (appmaster.io) iş akışları inşa ediyorsanız, aynı deseni uygulayabilirsiniz: kritik durum değişikliğini tek bir transaction içinde tutun ve "finalize" adımından önce transaction-level advisory lock almak için küçük bir SQL adımı ekleyin.
Advisory kilitler, gerçekten kuyruk özelliklerine (öncelikler, gecikmeli işler, dead-letter handling) ihtiyaç duyana, yoğun içerme yaşayıncaya veya paylaşılan bir Postgres olmadan veritabanları arasında koordinasyon gerektiğinde kadar iyi bir çözümdür. Hedef sıkıcı güvenilirliktir: deseni küçük, tutarlı, loglarda görünür ve constraint'lerle desteklenmiş tutun.
SSS
Bir öğe üzerinde aynı anda yalnızca bir aktörün çalışmasını istediğinizde advisory lock kullanın; örneğin bir isteği onaylama, bir faturayı tahsil etme veya zamanlanmış bir pencereyi çalıştırma gibi. Çoklu uygulama örneklerinin aynı öğeye dokunabildiği ve ayrı bir kilitleme servisi eklemek istemediğiniz durumlarda özellikle faydalıdır.
Satırlara yönelik kilitler (ör. SELECT ... FOR UPDATE) seçtiğiniz gerçek tablo satırlarını korur ve tüm işlem tek bir satır güncellemesine denk geliyorsa mükemmeldir. Advisory kilitler ise sizin seçtiğiniz bir anahtarı korur, bu yüzden iş akışı birden fazla tabloyu etkiliyorsa, harici servis çağrıları yapıyorsa veya nihai satır henüz yokken başlaması gerekiyorsa işe yarar.
İstek/yanıt aksiyonları için varsayılan olarak pg_advisory_xact_lock (transaction-level) kullanın; çünkü commit veya rollback olduğunda kilidi otomatik bırakır. pg_advisory_lock (session-level) yalnızca kilidin gerçekten bir işlemin ömründen daha uzun yaşaması gerektiğinde ve bağlantı havuzuna kilidi geri vermeden önce her zaman unlock yapacağınızdan emin olduğunuzda kullanılmalıdır.
Kullanıcı arayüzü kaynaklı işlemler için pg_try_advisory_xact_lock (try-lock) tercih edin; böylece istek hızlıca başarısız olur ve net bir “zaten işleniyor” mesajı döndürebilirsiniz. Arka plan çalışanları için bloklayan kilit kabul edilebilir, ancak lock_timeout ile sınır koyun ki tek bir takılmış görev tüm havuzu tıkamasın.
Genelde kilitlemeniz gereken en küçük şeyi kilitleyin: çoğunlukla “tek bir fatura” veya “tek bir onay isteği”. Çok geniş (ör. müşteri bazında) kilitlerseniz verimi düşürebilirsiniz; çok dar kilitlerseniz (örn. adım bazlı ama ortak anahtar yoksa) yine çoğaltmalarla karşılaşabilirsiniz.
Tüm hizmetlerin aynı kilidi kullandığından emin olmak için tek ve stabil bir anahtar formatı seçin ve her yerde onu kullanın. Yaygın yöntem iki tamsayıdır: bir namespace sabit sayısı (iş akışı için) ve varlık ID'si; böylece farklı iş akışları yanlışlıkla birbirini engellemez ama aynı kaynak doğru şekilde koordine edilir.
Hayır. Kilit sadece eşzamanlı yürütmeyi engeller; işlemin tekrarlanmasının güvenli olduğunu kanıtlamaz. Kilidi aldıktan sonra işlem içinde durumu yeniden kontrol etmelisiniz (ör. öğenin hâlâ pending olduğunu doğrulayın) ve uygun yerlerde unique constraint veya idempotency anahtarlarına güvenin.
Kilidi kısa ve veritabanı odaklı tutun: kilidi al, uygunluğu yeniden kontrol et, yeni durumu yaz ve commit et. Ağ gecikmesi olan yavaş ödeme sağlayıcıları, e-posta veya webhooks gibi işlemleri commit'ten sonra veya outbox tarzı bir yaklaşımla tetikleyin ki kilit süresini uzatmayın.
En yaygın neden, bağlantı havuzunda geri verilen bir oturum tarafından tutulan session-level kilittir; unlock çağrısı unutulduğunda kilit açık kalır. Transaction-level kilitleri tercih edin; eğer session kilidi kullanmanız gerekliyse, pg_advisory_unlock'un bağlantı havuzuna dönmeden önce güvenle çalıştığından emin olun.
Entity ID ve hesaplanan kilit anahtarını, kilidin alınıp alınmadığını, kilidi almak için geçen süreyi ve işlemin toplam çalışmasını loglayın. Ayrıca lock_busy, already_processed veya processed_ok gibi sonuçları da kaydedin ki içerme (contention) ile gerçek çoğaltmalar ayrıştırılabilsin.


