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

Autorollback dans postgres en utilisant PDO

Ce n'est pas la faute de PDO, c'est inhérent à la gestion des transactions de PostgreSQL. Voir :

PostgreSQL n'annule pas la transaction, mais la définit dans un état abandonné où elle ne peut qu'être annulée et où toutes les instructions sauf ROLLBACK signaler une erreur :

(Je suis surpris de ne pas trouver cela mentionné dans la documentation officielle ; je pense que je vais devoir écrire un correctif pour améliorer cela.)

Alors. Lorsque vous essayez/attrapez et avalez l'exception dans PDO, vous interceptez une exception côté PHP, mais vous ne changez pas le fait que la transaction PostgreSQL est dans un état abandonné.

Si vous vouliez pouvoir avaler des exceptions et continuer à utiliser la transaction, vous devez créer un SAVEPOINT avant chaque instruction susceptible d'échouer. Si cela échoue, vous devez ROLLBACK TO SAVEPOINT ...; . Si cela réussit, vous pouvez RELEASE SAVEPOINT ...; . Cela impose une charge supplémentaire à la base de données pour la gestion des transactions, ajoute des allers-retours et brûle les ID de transaction plus rapidement (ce qui signifie que PostgreSQL doit effectuer plus de travail de nettoyage en arrière-plan).

Il est généralement préférable de concevoir à la place votre SQL afin qu'il n'échoue pas dans des circonstances normales. Par exemple, vous pouvez valider la plupart des contraintes côté client, en traitant les contraintes côté serveur comme un deuxième niveau d'assurance tout en interceptant la plupart des erreurs côté client.

Lorsque cela n'est pas pratique, rendez votre application tolérante aux pannes, afin qu'elle puisse réessayer une transaction ayant échoué. Parfois, cela est nécessaire de toute façon - par exemple, vous ne pouvez généralement pas utiliser de points de sauvegarde pour récupérer des blocages, des abandons de transaction ou des échecs de sérialisation. Il peut également être utile de raccourcir au maximum les transactions sujettes aux échecs, en ne faisant que le minimum de travail requis, de sorte que vous ayez moins à suivre et à répéter.

Donc :dans la mesure du possible, au lieu d'avaler une exception, exécutez le code de base de données sujet aux échecs dans une boucle de nouvelle tentative. Assurez-vous que votre code conserve un enregistrement des informations dont il a besoin pour réessayer toute la transaction en cas d'erreur, et pas seulement la déclaration la plus récente.

N'oubliez pas, tout la transaction peut échouer :le DBA peut redémarrer la base de données pour appliquer un correctif, le système peut manquer de RAM en raison d'un travail cron incontrôlable, etc. Les applications tolérantes aux pannes sont donc de toute façon une bonne conception.

Bravo pour au moins l'utilisation des exceptions PDO et la gestion des exceptions - vous avez déjà une longueur d'avance sur la plupart des développeurs.