Le mythe du Commit à deux phases…

Beaucoup d’article pseudo techniques présentent le COMMIT à deux phases (Two Phase Commit ou 2PC) comme étant ACID, c’est à dire respectant les propriétés des transactions (ACID signifiant Atomicité, Cohérence, Isolation, Durabilité). Or il n’en est rien et la COMMIT à deux phases peu parfaitement rendre votre base non intègre… Il faut comprendre que le COMMIT à deux phases n’est qu’un vulgaire moyen de coordonner des transactions distribuées sur différents SGBDR, mais est incapable de garantir la bonne finalité des différentes transactions unitaires.

1 – Principe du COMMIT à deux phases
Lorsqu’une transaction concerne la mise à jour de données sur plusieurs serveurs indépendants, et comme chaque base de données possède son propre journal de transaction, il est nécessaire d’ajouter une couche de coordination des transactions distribuées.
Le principe du COMMIT à deux phases passe donc par un superviseur (ou coordinateur de transactions distribuées) qui scrute l’état des serveurs et ordonne la finalité globale de la transaction.

La méthode consiste à envoyer les différents ordres SQL à tous les serveurs puis demander à chacun s’il peut valider la transaction (par exemple si aucune erreur n’est survenue sur aucun serveur).
C’est la première phase dite de scrutation ou de vote.

Si tous les serveurs participant à la transaction distribuée sont dans la capacité de valider chacun leur propre transaction, alors le coordinateur intime à chaque serveur d’appliquer la commande COMMIT. Dans le cas ou un seul des serveurs est dans l’incapacité de valider, alors le coordinateur prend la décision de demander l’annulation et force chacun à appliquer un ROLLBACK. C’est un vote à l’unanimité.
C’est la seconde phase dite d’application ou de décision.

Commit à deux phases

2 – le problème

Entre le moment ou chaque serveur envoi un message indiquant s’il peut valider et le moment ou le coordinateur renvoie à tous les serveurs la confirmation ou l’invalidation, il se peut qu’un serveur tombe en panne.
Il est alors trop tard et les transactions sont appliquées sur les serveurs vivant, tandis que le serveur en panne ne peut pas finaliser la mise à jour.
Si le serveur en panne retrouve sa marche normale, il ne trouvera pas dans son journal de transaction l’ordre de finalisation de la transaction, ce qui se traduit par l’application d’un ROLLBACK implicite.
Le système de données distribué est devenu incohérent !

3 – des moyens de contournement ?

On pourrait bloquer les serveurs vivant jusqu’à ce que l’on ait confirmation que chaque serveur ait appliqué la finalisation de la transaction. Mais cette façon de faire entrainerait déjà un allongement des temps de réponse significatif, lié au serveur répondant le plus tardivement… Et dans le cas ou le serveur en panne a recouvré la santé, il faudrait qu’on lui force l’application de cette dernière partie de la transaction distribuée.
On voit immédiatement l’inconvénient de cette solution : un ralentissement significatif de toutes les transactions et un blocage complet du système en cas de panne d’un des leurs (tous les serveurs attendent) alors que l’intérêt de distribuer les données est de pouvoir répartir la charge…
Ce n’est donc généralement pas cette solution qui est majoritairement appliqué dans les mécanismes de distribution des transactions.

4 – comment savoir ce qui s’est passé ?

Si l’on accepte donc la survenance d’une telle problématique encore est-il intéressant de savoir ce qui s’est passé, lorsque cela se passe mal !
En général les superviseurs de transactions distribuées ou coordinateur ou encore moniteurs transactionnels incorporent un journal d’événement (et non un journal de transactions) permettant de savoir l’état final des transactions distribuées.
En cas de panne, le système indique quel serveur a été défaillant et montre la requête distribuée qui a été en échec. A vous de remettre manuellement les choses en place… lorsque c’est possible !

Dans l’univers Microsoft, le système est un service intitulé MSDTC, pour « Microsoft Data Transaction Coordinator ». Il est capable de gérer des transactions distribuées au protocole standard XA, donc avec n’importe quel SGBDR transactionnel supportant ce protocole, comme SQL Server, Oracle, DB2 UDB… A lire : http://blog.jonathanoliver.com/2011/04/my-beef-with-msdtc-and-two-phase-commits/

5 – Faire autrement ?

Le risque de panne rendant incohérent un système de bases distribuées peut être un frein à l’utilisation d’une telle technique. Mais il y en a un autre : le temps de réponse… loin d’être négligeable ! En effet scruter plusieurs serveur via le réseau dilapide un temps qui, à l’échelle de la plupart des transactions, peut s’avérer fortement pénalisant.
Dès lors, on peut choisir un autre mode de gestion des bases de données réparties. Certains SGBDR comme Oracle ou MS SQL Server proposent des outils pour gérer les communications de données à données entre les serveurs de bases de données (MOM : Middleware Oriented Message) en mode asynchrone, transactionné et distribué. C’est le principe de SODA (Service Oriented Database Architecture). Par exemple dans le cas de MS SQL Server, c’est Service Broker qui assure cette couche.

Références :

Problématique du COMMIT à deux phases :

Two Phase Commit Need Have Nothing To Do With ACID or Any Other Kind of Transaction!
Distributed Transactions and Two-Phase Commit (page 15 en particulier)
Le processus de commit (validation) des transactions distribuées. (diapo 19 en particulier)

Service Broker :
Introducing Distributed Messaging using Service Broker in SQL Server 2005
A quoi sert Service Broker ?


--------
Frédéric Brouard, SQLpro - ARCHITECTE DE DONNÉES, http://sqlpro.developpez.com/
Expert bases de données relationnelles et langage SQL. MVP Microsoft SQL Server
www.sqlspot.com : modélisation, conseil, audit, optimisation, tuning, formation
* * * * *  Enseignant CNAM PACA - ISEN Toulon - CESI Aix en Provence  * * * * *

MVP Microsoft SQL Server

Une réflexion au sujet de « Le mythe du Commit à deux phases… »

  1. Avatar de asenaiciasenaici

    Bonjour

    Article très intéressant : je suis en plein développement
    et j’utilise du two-phase commit sur 2 bases firebird installées sur 2 serveurs différents (donc 2 moteurs qui tournent)

    Que proposez-vous comme alternative pour éviter les problèmes que vous avez cités ?
    NB: j’utilise Firebird 2.5

    Cordialement

Laisser un commentaire