Jeg tror, du har misforstået PREPARE TRANSACTION
.
Denne erklæring afslutter arbejdet med transaktionen, det vil sige, den skal udstedes efter alt arbejdet er udført. Tanken er, at PREPARE TRANSACTION
gør alt, hvad der potentielt kan fejle under en commit, bortset fra selve commit. Det er for at garantere, at en efterfølgende COMMIT PREPARED
kan ikke fejle.
Tanken er, at behandlingen er som følger:
-
Kør
START TRANSACTION
på alle databaser, der er involveret i den distribuerede transaktion. -
Gør alt arbejdet. Hvis der er fejl,
ROLLBACK
alle transaktioner. -
Kør
PREPARE TRANSACTION
på alle databaser. Hvis det mislykkes nogen steder, skal du køreROLLBACK PREPARED
på de databaser, hvor transaktionen allerede var forberedt ogROLLBACK
på de andre. -
En gang
PREPARE TRANSACTION
er lykkedes overalt, kørCOMMIT PREPARED
på alle involverede databaser.
På den måde kan du garantere "alt eller intet" på tværs af flere databaser.
En vigtig komponent her, som jeg ikke har nævnt, er den distribuerede transaktionsmanager . Det er et stykke software, der vedvarende husker, hvor i ovenstående algoritme behandlingen i øjeblikket er, så den kan rydde op eller fortsætte med at begå efter et nedbrud.
Uden en distribueret transaktionsmanager er to-fase commit ikke meget værd, og det er faktisk farligt:Hvis transaktioner sætter sig fast i den "forberedte" fase, men ikke er commitet endnu, vil de fortsætte med at holde låse og (i tilfælde af PostgreSQL) blokerer autovakuumarbejde selv gennem servergenstarter , da sådanne transaktioner skal være vedvarende.
Det er svært at få det rigtige.