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 TRANSACTIONpå alle databaser, der er involveret i den distribuerede transaktion. -
Gør alt arbejdet. Hvis der er fejl,
ROLLBACKalle transaktioner. -
Kør
PREPARE TRANSACTIONpå alle databaser. Hvis det mislykkes nogen steder, skal du køreROLLBACK PREPAREDpå de databaser, hvor transaktionen allerede var forberedt ogROLLBACKpå de andre. -
En gang
PREPARE TRANSACTIONer lykkedes overalt, kørCOMMIT PREPAREDpå 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.