Je pense que vous avez mal compris PREPARE TRANSACTION
.
Cette instruction met fin au travail sur la transaction, c'est-à-dire qu'elle doit être émise après Tout le travail est fait. L'idée est que PREPARE TRANSACTION
fait tout ce qui pourrait potentiellement échouer lors d'un commit, à l'exception du commit lui-même. C'est pour garantir qu'un COMMIT PREPARED
ultérieur ne peut pas échouer.
L'idée est que le traitement est le suivant :
-
Exécutez
START TRANSACTION
sur toutes les bases de données impliquées dans la transaction distribuée. -
Faites tout le travail. S'il y a des erreurs,
ROLLBACK
toutes les transactions. -
Exécutez
PREPARE TRANSACTION
sur toutes les bases de données. Si cela échoue n'importe où, exécutezROLLBACK PREPARED
sur les bases de données où la transaction a déjà été préparée etROLLBACK
sur les autres. -
Une fois
PREPARE TRANSACTION
a réussi partout, exécutezCOMMIT PREPARED
sur toutes les bases de données impliquées.
De cette façon, vous pouvez garantir "tout ou rien" sur plusieurs bases de données.
Un composant important ici que je n'ai pas mentionné est le gestionnaire de transactions distribuées . Il s'agit d'un logiciel qui mémorise de manière persistante où se trouve actuellement le traitement de l'algorithme ci-dessus afin qu'il puisse nettoyer ou continuer à s'engager après un crash.
Sans gestionnaire de transactions distribué, la validation en deux phases ne vaut pas grand-chose, et elle est en fait dangereuse :si les transactions restent bloquées dans la phase "préparée" mais ne sont pas encore validées, elles continueront à détenir des verrous et (dans le cas de PostgreSQL) bloquent le travail de vide automatique même lors des redémarrages du serveur , car ces transactions doivent nécessairement être persistantes.
C'est difficile à faire correctement.