DBAtlas · Atlas für Datenbankbetrieb

DDL sicher mit lock_timeout und Wiederholungen anwenden (Lock Queues vermeiden)

PostgreSQLSessions

Befehl

-- Single attempt: give up if the lock is not acquired within 3 s instead of queueing and blocking traffic
SET lock_timeout = '3s';
ALTER TABLE customer ADD COLUMN IF NOT EXISTS segment text;
RESET lock_timeout;

-- Automatic retry: up to 5 attempts, 3 s apart
DO $$
DECLARE
  attempt int := 0;
BEGIN
  LOOP
    attempt := attempt + 1;
    BEGIN
      SET LOCAL lock_timeout = '2s';
      ALTER TABLE customer 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 $$;

Was es tut

Verhindert, dass eine DDL, die ACCESS EXCLUSIVE braucht, endlos wartet, wenn sie die Sperre nicht bekommt, und dabei jede dahinter eingereihte Abfrage blockiert (Lock Queue); wiederholt den Versuch in kurzen Abständen.

Wann einsetzen

Beim Anwenden schneller, aber stark sperrender Änderungen wie ALTER TABLE, CREATE/DROP TRIGGER, ATTACH PARTITION oder RENAME auf stark genutzten Tabellen in der Produktion.

Vorsicht

Ohne lock_timeout lässt ein ALTER TABLE, das hinter einem einzigen langen SELECT wartet, auch jeden folgenden Lese-/Schreibzugriff warten und kann binnen Minuten den Connection Pool erschöpfen. lock_timeout begrenzt nur das Warten auf die Sperre, nicht die Laufzeit einer DDL, die die Tabelle neu schreibt (z. B. Änderung eines Spaltentyps). Der DO-Block ist eine einzige Transaktion und hält über alle Versuche hinweg einen Snapshot; für lange Wiederholungsszenarien besser eine externe Shell-Schleife verwenden.

In DBAtlas öffnen →

Verwandte Einträge