Freigeben über


Ausführen eines Einphasen- oder Mehrphasencommits für eine Transaktion

Jede ressource, die in einer Transaktion verwendet wird, wird von einem Ressourcen-Manager (RM) verwaltet, dessen Aktionen von einem Transaktionsmanager (TM) koordiniert werden. Im Thema "Enlisting Resources as Participants in a Transaction" wird erläutert, wie eine Ressource (oder mehrere Ressourcen) in eine Transaktion eingebunden werden kann. In diesem Thema wird erläutert, wie die Transaktionsbindung zwischen den aufgelisteten Ressourcen koordiniert werden kann.

Am Ende der Transaktion fordert die Anwendung die Transaktion auf, entweder einen Commit oder Rollback auszuführen. Der Transaktionsmanager muss Risiken vermeiden, wie z.B. dass einige Ressourcenmanager für die Bestätigung stimmen, während andere für das Zurücksetzen der Transaktion stimmen.

Wenn Ihre Transaktion mehrere Ressourcen umfasst, müssen Sie einen zweistufigen Commit (2PC) ausführen. Mit dem Zweiphasencommit-Protokoll (Vorbereitungs- und Commitphase) wird sichergestellt, dass am Ende der Transaktion für alle Änderungen an allen Ressourcen entweder ein vollständiges Commit ausgeführt wurde oder sie vollständig zurückgesetzt wurden. Alle Teilnehmer werden dann über das Endergebnis informiert. Eine ausführliche Erläuterung des zweistufigen Commitprotokolls finden Sie im Buch "Transaction Processing : Concepts and Techniques (Morgan Kaufmann Series in Data Management Systems) ISBN:1558601902" von Jim Gray.

Sie können die Leistung Ihrer Transaktion auch optimieren, indem Sie am Single Phase Commit-Protokoll teilnehmen. Weitere Informationen finden Sie unter Optimierung mithilfe von Single Phase Commit und Promotable Single Phase Notification.

Wenn Sie nur über das Ergebnis einer Transaktion informiert werden möchten und nicht an der Abstimmung teilnehmen möchten, sollten Sie sich für das TransactionCompleted Ereignis registrieren.

Zweiphasencommit (2PC)

In der ersten Transaktionsphase fragt der Transaktions-Manager jede Ressource ab, um festzustellen, ob eine Transaktion zugesichert oder zurückgesetzt werden soll. In der zweiten Transaktionsphase benachrichtigt der Transaktionsmanager jede Ressource des Ergebnisses seiner Abfragen, sodass sie alle erforderlichen Bereinigungen durchführen kann.

Um an dieser Art von Transaktion teilzunehmen, muss ein Ressourcenmanager die IEnlistmentNotification Schnittstelle implementieren, die Methoden bereitstellt, die von der TM als Benachrichtigungen während eines 2PC aufgerufen werden. Das folgende Beispiel zeigt ein Beispiel für eine solche Implementierung.

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

Vorbereitungsphase (Phase 1)

Nach Erhalt einer Commit Anforderung von der Anwendung beginnt der Transaktionsmanager mit der Vorbereitungsphase aller aufgelisteten Teilnehmer, indem die Prepare Methode für jede aufgelistete Ressource aufgerufen wird, um die Abstimmung der einzelnen Ressourcen für die Transaktion zu erhalten.

Der Ressourcenmanager, der die IEnlistmentNotification Schnittstelle implementiert, sollte zunächst die Prepare(PreparingEnlistment) Methode implementieren, wie im folgenden einfachen Beispiel gezeigt.

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;  
     }  
}  

Wenn der Manager für dauerhafte Ressourcen diesen Aufruf erhält, muss er die Wiederherstellungsinformationen der Transaktion (die nach Abruf der RecoveryInformation-Eigenschaft verfügbar sind) sowie eventuelle weitere Informationen protokollieren, die zur Ausführung der vom Commit betroffenen Transaktion erforderlich sind. Dies muss nicht innerhalb der Prepare Methode ausgeführt werden, da der RM dies in einem Arbeitsthread ausführen kann.

Wenn der RM seine Vorbereitung abgeschlossen hat, muss er entscheiden, ob ein Commit oder ein Rollback ausgeführt wird, indem er die Prepared-Methode oder die ForceRollback-Methode aufruft. Beachten Sie, dass die PreparingEnlistment Klasse eine Done Methode von der Enlistment Klasse erbt. Wenn Sie diese Methode während der Vorbereitungsphase für den PreparingEnlistment Rückruf aufrufen, informiert sie die TM darüber, dass es sich um eine Read-Only Einlistung handelt (d. h. Ressourcenmanager, die transaktionsgeschützte Daten lesen, aber keine transaktionsgeschützten Daten aktualisieren können), und die RM erhält keine weiteren Benachrichtigungen vom Transaktionsmanager hinsichtlich des Ergebnisses der Transaktion in Phase 2.

Nachdem alle Ressourcen-Manager Prepared gestimmt haben, wird der Anwendung mitgeteilt, dass das Commit der Transaktion erfolgreich war.

Commitphase (Phase 2)

Wenn der Transaktionsmanager in der zweiten Phase der Transaktion erfolgreiche Prepare-Bestätigungen von allen Ressourcenmanagern empfängt (alle Ressourcenmanager haben Prepared am Ende der Phase 1 aufgerufen), ruft er die Commit-Methode für jeden Ressourcenmanager auf. Anschließend können die Ressourcenmanager die Änderungen dauerhaft vornehmen und den Commit abschließen.

Wenn ein Ressourcenmanager einen Fehler bei der Vorbereitung in Phase 1 gemeldet hat, ruft der Transaktionsmanager die Rollback-Methode für jeden Ressourcenmanager auf und teilt der Anwendung den Fehler des Commits mit.

Daher sollte Ihr Ressourcenmanager die folgenden Methoden implementieren.

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();
}  

Der RM sollte alle erforderlichen Schritte ausführen, um die Transaktion basierend auf dem Benachrichtigungstyp abzuschließen, und die TM darüber informieren, dass sie mit dem Aufrufen Done der Methode für den Enlistment Parameter abgeschlossen wurde. Diese Aufgabe kann als Arbeitsthread ausgeführt werden. Beachten Sie, dass die Phase 2-Benachrichtigungen inline im selben Thread auftreten können, der die Prepared Methode in Phase 1 aufgerufen hat. Daher sollten Sie nach dem Prepared Aufruf keine Arbeiten ausführen (z.B. das Freigeben von Sperren), die Sie vor dem Empfang der Phase 2-Benachrichtigungen abgeschlossen haben möchten.

Implementieren von InDoubt

Schließlich sollten Sie die InDoubt Methode für den veränderliche Ressourcen-Manager implementieren. Diese Methode wird aufgerufen, wenn der Transaktionsmanager den Kontakt mit einem oder mehreren Teilnehmern verliert, sodass ihr Status unbekannt ist. Wenn dies geschieht, sollten Sie diese Tatsache protokollieren, damit Sie später untersuchen können, ob einer der Transaktionsteilnehmer in einem inkonsistenten Zustand verblieben ist.

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

Optimierung des Einphasencommit

Das "Single Phase Commit"-Protokoll ist während der Ausführung effizienter, da alle Updates ohne explizite Koordination durchgeführt werden. Weitere Informationen zu diesem Protokoll finden Sie unter Optimierung mit Single Phase Commit und Promotable Single Phase Notification.

Siehe auch