PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Utiliser des commits en deux phases sur postgres

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écutez ROLLBACK PREPARED sur les bases de données où la transaction a déjà été préparée et ROLLBACK sur les autres.

  • Une fois PREPARE TRANSACTION a réussi partout, exécutez COMMIT 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.