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 TRANSACTIONsur toutes les bases de données impliquées dans la transaction distribuée. -
Faites tout le travail. S'il y a des erreurs,
ROLLBACKtoutes les transactions. -
Exécutez
PREPARE TRANSACTIONsur toutes les bases de données. Si cela échoue n'importe où, exécutezROLLBACK PREPAREDsur les bases de données où la transaction a déjà été préparée etROLLBACKsur les autres. -
Une fois
PREPARE TRANSACTIONa réussi partout, exécutezCOMMIT PREPAREDsur 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.