postgres trigger constraints - ghdrako/doc_snipets GitHub Wiki
Problem jest ze trigger nie widzi zmian nieskomitowanych w innej sesji przez MVCC wiec nie może wykryć race condition.
Systemowe constrainty nie maja tego problemu. constrainty systemowe
NIE używają zwykłego MVCC.PostgreSQL ma specjalny kod w C dla:UNIQUE,PRIMARY KEY,FOREIGN KEY który potrafi:
- zaglądać do uncommitted tuples
- robić specjalne locki
- sprawdzać pending rows PostgreSQL also checks rows that would normally not be visible
Unikalnosc z uzyciem tabeli unikalnosci i trigera dla tabel partycjonowanych jest bezpiieczny : trigger + registry table + UNIQUE bo unikalnosci plinuje PRIMARY KEY na registry table wiec uzywane sa specjalne mechanizmy postgresa zapobiegajace race condition co opisano wyzej.
Czyli niebezpieczne sa triggery w ktorych wykonujemy sql-a i na tej podstawie cos robimy bo podlegaja MVCC.
Przeciwdzialanie:
- explicit locking - czyli ręczne blokowanie wierszy (SELECT ... FOR UPDATE) tak, żeby konkurencyjne transakcje nie mogły równocześnie przejść walidacji constraintu.
Lockowanie rekordów
Zamiast:
SELECT count(*)
robi:
SELECT *
FROM on_duty
WHERE prison_id = OLD.prison_id
FOR UPDATE;
Jeśli robisz constraint triggerem:
musisz samodzielnie zapewnić serializację
bo PostgreSQL:
- nie zrobi tego za Ciebie
- trigger działa normalnie pod MVCC
Trzeba lockować w ustalonej kolejności
W artykule jest:
ORDER BY guard_id
FOR KEY SHARE
Dlaczego ORDER BY Żeby uniknąć deadlock
FOR KEY SHARE
- to słabszy lock niż FOR UPDATE
- wystarcza do ochrony przed DELETE
- daje lepszą concurrency