Partager via


Validation d'une transaction en une phase unique et en plusieurs phases

Chaque ressource utilisée dans une transaction est gérée par un gestionnaire de ressources (RM), dont les actions sont coordonnées par un gestionnaire de transactions (TM). L’inscription de ressources en tant que participants dans une rubrique Transaction explique comment une ressource (ou plusieurs ressources) peut être inscrite dans une transaction. Cette rubrique explique comment l’engagement transactionnel peut être coordonné entre les ressources inscrites.

À la fin de la transaction, l'application requiert que la transaction soit validée ou restaurée. Le gestionnaire de transactions doit éliminer les risques tels que certains gestionnaires de ressources qui votent pour valider, tandis que d’autres votent pour annuler la transaction.

Si votre transaction implique plusieurs ressources, vous devez effectuer une validation en deux phases (2PC). Le protocole de validation en deux phases (la phase de préparation et la phase de validation) garantit que lorsque la transaction se termine, toutes les modifications apportées à toutes les ressources sont totalement validées ou entièrement restaurées. Tous les participants sont ensuite informés du résultat final. Pour une discussion détaillée sur le protocole de validation en deux phases, consultez le livre « Transaction Processing : Concepts and Techniques (Morgan Kaufmann Series in Data Management Systems) ISBN :1558601902 » de Jim Gray.

Vous pouvez également optimiser les performances de votre transaction en prenant part au protocole de validation à phase unique. Pour plus d’informations, consultez Optimisation à l’aide de la validation à phase unique et de la notification de phase unique pouvant être promue.

Si vous souhaitez simplement être informé du résultat d’une transaction et ne souhaitez pas participer au vote, vous devez vous inscrire à l’événement TransactionCompleted .

Validation en deux phases (2PC)

Dans la première phase de transaction, le gestionnaire de transactions interroge chaque ressource pour déterminer si une transaction doit être validée ou restaurée. Dans la deuxième phase de transaction, le gestionnaire de transactions notifie chaque ressource du résultat de ses requêtes, ce qui lui permet d’effectuer tout nettoyage nécessaire.

Pour participer à ce type de transaction, un gestionnaire de ressources doit implémenter l’interface IEnlistmentNotification , qui fournit des méthodes appelées par le TM en tant que notifications pendant un 2PC. L’exemple suivant montre un exemple d’implémentation de ce type.

class myEnlistmentClass : IEnlistmentNotification
{
    public void Prepare(PreparingEnlistment preparingEnlistment)
    {
        Console.WriteLine("Prepare notification received");

        //Perform transactional work

        //If work finished correctly, reply prepared
        preparingEnlistment.Prepared();

        // otherwise, do a ForceRollback
        preparingEnlistment.ForceRollback();
    }

    public void Commit(Enlistment enlistment)
    {
        Console.WriteLine("Commit notification received");

        //Do any work necessary when commit notification is received

        //Declare done on the enlistment
        enlistment.Done();
    }

    public void Rollback(Enlistment enlistment)
    {
        Console.WriteLine("Rollback notification received");

        //Do any work necessary when rollback notification is received

        //Declare done on the enlistment
        enlistment.Done();
    }

    public void InDoubt(Enlistment enlistment)
    {
        Console.WriteLine("In doubt notification received");

        //Do any work necessary when in doubt notification is received

        //Declare done on the enlistment
        enlistment.Done();
    }
}
Public Class EnlistmentClass
    Implements IEnlistmentNotification

    Public Sub Prepare(ByVal myPreparingEnlistment As PreparingEnlistment) Implements System.Transactions.IEnlistmentNotification.Prepare
        Console.WriteLine("Prepare notification received")

        'Perform transactional work

        'If work finished correctly, reply with prepared
        myPreparingEnlistment.Prepared()
    End Sub

    Public Sub Commit(ByVal myEnlistment As Enlistment) Implements System.Transactions.IEnlistmentNotification.Commit
        Console.WriteLine("Commit notification received")

        'Do any work necessary when commit notification is received

        'Declare done on the enlistment
        myEnlistment.Done()
    End Sub

    Public Sub Rollback(ByVal myEnlistment As Enlistment) Implements System.Transactions.IEnlistmentNotification.Rollback
        Console.WriteLine("Rollback notification received")

        'Do any work necessary when rollback notification is received

        'Declare done on the enlistment
        myEnlistment.Done()
    End Sub

    Public Sub InDoubt(ByVal myEnlistment As Enlistment) Implements System.Transactions.IEnlistmentNotification.InDoubt
        Console.WriteLine("In doubt notification received")

        'Do any work necessary when in doubt notification is received

        'Declare done on the enlistment
        myEnlistment.Done()
    End Sub
End Class

Phase de préparation (phase 1)

Lors de la réception d’une Commit demande de l’application, le gestionnaire de transactions commence la phase de préparation de tous les participants inscrits en appelant la méthode Prepare sur chaque ressource inscrite, afin d’obtenir le vote de chaque ressource concernant la transaction.

Votre gestionnaire de ressources qui implémente l’interface IEnlistmentNotification doit d’abord implémenter la Prepare(PreparingEnlistment) méthode, comme l’illustre l’exemple simple suivant.

public void Prepare(PreparingEnlistment preparingEnlistment)
{
     Console.WriteLine("Prepare notification received");
     //Perform work

     Console.Write("reply with prepared? [Y|N] ");
     c = Console.ReadKey();
     Console.WriteLine();

     //If work finished correctly, reply with prepared
     if ((c.KeyChar == 'Y') || (c.KeyChar == 'y'))
     {
          preparingEnlistment.Prepared();
          break;
     }

     // otherwise, do a ForceRollback
     else if ((c.KeyChar == 'N') || (c.KeyChar == 'n'))
     {
          preparingEnlistment.ForceRollback();
          break;
     }
}

Lorsque le gestionnaire de ressources durable reçoit cet appel, il doit consigner les informations de récupération de la transaction (qui deviennent disponibles en récupérant la propriété RecoveryInformation) ainsi que toutes les informations nécessaires pour terminer la transaction à la validation. Il n'est pas nécessaire d'effectuer cette opération au sein de la méthode Prepare car le gestionnaire de ressources peut le faire sur un thread de travail.

Lorsque le RM a terminé son travail de préparation, il doit voter pour valider ou annuler en appelant la méthode Prepared ou ForceRollback. Notez que la PreparingEnlistment classe hérite d’une Done méthode de la Enlistment classe. L'appel à cette méthode sur le rappel PreparingEnlistment au cours de la phase de préparation indique au gestionnaire de transactions qu'il s'agit d'une inscription en lecture seule (des gestionnaires de ressources qui peuvent être lus mais qui ne peuvent pas mettre à jour les données protégées par la transaction) et le gestionnaire de ressources ne reçoit plus de notification du gestionnaire de transaction jusqu'au résultat de la transaction en phase 2.

L'application est informée de la confirmation de la transaction après que tous les gestionnaires de ressources aient voté Prepared.

Phase de validation (Phase 2)

Dans la deuxième phase de la transaction, si le gestionnaire de transactions reçoit des préparations réussies de tous les gestionnaires de ressources (tous les gestionnaires de ressources ont appelé Prepared à la fin de la phase 1), il appelle la Commit méthode pour chaque gestionnaire de ressources. Les gestionnaires de ressources peuvent ensuite apporter les modifications durables et terminer la validation.

Si un gestionnaire de ressources a signalé un échec de préparation à la phase 1, le gestionnaire de transactions appelle la Rollback méthode pour chaque gestionnaire de ressources et indique l’échec de la validation sur l’application.

Par conséquent, votre gestionnaire de ressources doit implémenter les méthodes suivantes.

public void Commit (Enlistment enlistment)
{
     // Do any work necessary when commit notification is received

     // Declare done on the enlistment
     enlistment.Done();
}

public void Rollback (Enlistment enlistment)
{
     // Do any work necessary when rollback notification is received

     // Declare done on the enlistment
     enlistment.Done();
}

Le RM doit effectuer tout travail nécessaire pour terminer la transaction en fonction du type de notification et informer le TM qu'elle est terminée en appelant la méthode Done sur le paramètre Enlistment. Cela peut s'effectuer sur un thread de travail. Notez que les notifications de phase 2 peuvent se produire inline sur le même thread que celui qui a appelé la méthode dans la Prepared phase 1. Par conséquent, vous ne devez pas effectuer de travail après l’appel Prepared (par exemple, libérer des verrous) que vous prévoyez d’avoir terminé avant de recevoir les notifications de la phase 2.

Implémentation d’InDoubt

Enfin, vous devez implémenter la InDoubt méthode pour le gestionnaire de ressources volatile. Cette méthode est appelée si le gestionnaire de transactions perd le contact avec un ou plusieurs participants, de sorte que son état est inconnu. Si cela se produit, vous devez consigner ce fait afin que vous puissiez examiner ultérieurement si l’un des participants à la transaction a été laissé dans un état incohérent.

public void InDoubt (Enlistment enlistment)
{
     // log this
     enlistment.Done();
}

Optimisation de la validation en une phase

Le protocole de validation à phase unique est plus efficace au moment de l’exécution, car toutes les mises à jour sont effectuées sans coordination explicite. Pour plus d’informations sur ce protocole, consultez Optimisation à l’aide de la validation à phase unique et de la notification de phase unique pouvant être promue.

Voir aussi