DDL'i lock_timeout ve yeniden deneme ile güvenli uygula (lock kuyruğunu önle)
PostgreSQLOturumKomut
-- Tek deneme: kilit 3 sn içinde alınamazsa vazgeç, kuyrukta bekleyip trafiği bloklama
SET lock_timeout = '3s';
ALTER TABLE musteri ADD COLUMN IF NOT EXISTS segment text;
RESET lock_timeout;
-- Otomatik yeniden deneme: en fazla 5 deneme, aralarda 3 sn
DO $$
DECLARE
attempt int := 0;
BEGIN
LOOP
attempt := attempt + 1;
BEGIN
SET LOCAL lock_timeout = '2s';
ALTER TABLE musteri ADD COLUMN IF NOT EXISTS segment text;
RAISE NOTICE 'OK, attempt %', attempt;
EXIT;
EXCEPTION WHEN lock_not_available THEN
RAISE NOTICE 'lock not acquired, attempt %', attempt;
IF attempt >= 5 THEN RAISE; END IF;
PERFORM pg_sleep(3);
END;
END LOOP;
END $$;Ne yapar?
ACCESS EXCLUSIVE gerektiren DDL'in lock'u alamadığında süresiz beklemesini ve beklerken arkasında biriken tüm sorguları (lock kuyruğu) bloklamasını önler; kısa aralıklarla yeniden dener.
Ne zaman kullanılır?
Yoğun tablolarda ALTER TABLE, CREATE/DROP TRIGGER, ATTACH PARTITION, RENAME gibi kısa süren ama ağır lock isteyen değişiklikleri canlıda uygularken.
Dikkat
lock_timeout olmadan, uzun süren tek bir SELECT'in arkasında bekleyen ALTER TABLE, sonradan gelen tüm okuma/yazmaları da bekletir ve dakikalar içinde bağlantı havuzunu tüketebilir. lock_timeout yalnızca lock bekleme süresini sınırlar; tabloyu yeniden yazan DDL'lerin (örn. kolon tipi değişikliği) çalışma süresini sınırlamaz. DO bloğu tek transaction'dır ve denemeler boyunca snapshot tutar; uzun yeniden deneme senaryolarında dışarıdan bir shell döngüsü tercih et.
İlgili
- Backend'i sonlandır (pg_terminate_backend)
- Çalışan sorguyu iptal et (pg_cancel_backend)
- Aktif ve bloklayan sorguları gör
- Blocking ağacını çıkar (kök bloklayan oturumu bul)
- Bekleyen lock'ları nesne ve lock modu düzeyinde ayrıntılı gör (pg_locks)
- Uzun süren ve 'idle in transaction' kalan transaction'ları bul