DBAtlas · Veritabanı operasyon atlası

DDL'i lock_timeout ve yeniden deneme ile güvenli uygula (lock kuyruğunu önle)

PostgreSQLOturum

Komut

-- 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.

DBAtlas'ta aç →

İlgili