Udostępnij za pośrednictwem


Zatwierdzanie transakcji w Single-Phase i wielofazowych

Każdy zasób używany w transakcji jest zarządzany przez menedżera zasobów (RM), którego akcje są koordynowane przez menedżera transakcji (TM). W temacie Rejestrowanie zasobów jako uczestnicy transakcji omówiono sposób, w jaki zasób (lub wiele zasobów) można zarejestrować w transakcji. W tym temacie omówiono sposób koordynowania zobowiązania transakcji między zasobami wymienionymi na liście.

Na końcu transakcji aplikacja żąda zatwierdzenia lub wycofania transakcji. Menedżer transakcji musi wyeliminować ryzyko, takie jak sytuacja, w której niektórzy menedżerowie zasobów głosują za zatwierdzeniem transakcji, podczas gdy inni głosują za jej wycofaniem.

Jeśli twoja transakcja obejmuje więcej niż jeden zasób, musisz przeprowadzić dwufazowe zatwierdzenie (2PC). Dwufazowy protokół zatwierdzania (faza przygotowania i faza zatwierdzania) gwarantuje, że po zakończeniu transakcji wszystkie zmiany wszystkich zasobów zostaną całkowicie zatwierdzone lub całkowicie wycofane. Wszyscy uczestnicy są następnie informowani o końcowym wyniku. Aby zapoznać się ze szczegółowym omówieniem dwufazowego protokołu zatwierdzania, zapoznaj się z książką "Przetwarzanie transakcji : Pojęcia i techniki (Morgan Kaufmann Series in Data Management Systems) ISBN:1558601902" Autorstwa Jima Graya.

Możesz również zoptymalizować wydajność transakcji, biorąc udział w protokole zatwierdzania jednofazowego. Aby uzyskać więcej informacji, zobacz Optymalizacja przy użyciu zatwierdzania jednofazowego i promowalnego powiadomienia jednofazowego.

Jeśli chcesz po prostu poinformować o wyniku transakcji i nie chcesz uczestniczyć w głosowaniu, należy zarejestrować się na imprezie TransactionCompleted .

Zatwierdzenie dwufazowe (2PC)

W pierwszej fazie transakcji menedżer transakcji wysyła zapytanie do każdego zasobu, aby określić, czy transakcja powinna zostać zatwierdzona, czy wycofana. W drugiej fazie transakcji menedżer transakcji powiadamia każdy z zasobów o wyniku zapytań, umożliwiając mu przeprowadzenie wszelkich niezbędnych czynności porządkowych.

Aby uczestniczyć w tego rodzaju transakcji, menedżer zasobów musi zaimplementować interfejs IEnlistmentNotification, który udostępnia metody wywoływane przez TM jako powiadomienia podczas protokołu dwóch faz (2PC). Poniższy przykład przedstawia przykład takiej implementacji.

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

Faza przygotowania (faza 1)

Po otrzymaniu Commit żądania od aplikacji menedżer transakcji rozpoczyna fazę Przygotowania wszystkich zarejestrowanych uczestników, wywołując metodę Prepare dla każdego zarejestrowanego zasobu, aby uzyskać głos każdego zasobu w sprawie transakcji.

Menedżer zasobów, który implementuje IEnlistmentNotification interfejs, powinien najpierw zaimplementować metodę Prepare(PreparingEnlistment) , jak pokazano w poniższym prostym przykładzie.

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

Kiedy trwały menedżer zasobów odbiera to wywołanie, powinien zarejestrować informacje dotyczące odzyskiwania transakcji (dostępne poprzez pobranie właściwości RecoveryInformation) oraz wszelkie inne informacje niezbędne do ukończenia transakcji po jej zatwierdzeniu. Nie trzeba tego wykonywać w ramach Prepare metody, ponieważ narzędzie RM może to zrobić w wątku procesu roboczego.

Po tym jak menedżer zasobów zakończy przygotowania, powinien przystąpić do głosowania nad zatwierdzeniem lub wycofaniem, wywołując metodę Prepared lub ForceRollback. Zwróć uwagę, że PreparingEnlistment klasa dziedziczy metodę Done z Enlistment klasy . Jeśli wywołasz tę metodę na zwrotnym wywołaniu PreparingEnlistment w fazie Przygotowywania, informuje to TM, że jest to zarejestrowanie się Read-Only (czyli menedżerów zasobów, którzy mogą odczytywać, choć nie mogą aktualizować chronionych transakcją danych), a menedżer zasobów nie otrzymuje dalszych powiadomień od menedżera transakcji co do wyniku transakcji w drugiej fazie.

Aplikacja zostaje poinformowana o pomyślnym zatwierdzeniu transakcji, gdy wszyscy menedżerowie zasobów zakończą głosowanie Prepared.

Faza zatwierdzania (faza 2)

W drugiej fazie transakcji, jeśli menedżer transakcji otrzyma pomyślne przygotowania od wszystkich menedżerów zasobów (wszyscy menedżerowie zasobów wywołali Prepared na końcu fazy 1), wywołuje metodę Commit dla każdego menedżera zasobów. Menedżerowie zasobów mogą następnie wprowadzić zmiany trwałe i zakończyć zatwierdzenie.

Jeśli którykolwiek menedżer zasobów zgłosi problem z przygotowaniem w fazie 1, menedżer transakcji wywołuje metodę Rollback dla każdego menedżera zasobów i zgłasza problem zatwierdzenia aplikacji.

W związku z tym menedżer zasobów powinien zaimplementować następujące metody.

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

Menedżer zasobów powinien wykonać każdą pracę niezbędną do zakończenia transakcji na podstawie typu powiadomienia i poinformować TM, że zakończył pracę, wywołując metodę Done za pomocą parametru Enlistment. Tę pracę można wykonać w wątku procesu roboczego. Należy pamiętać, że powiadomienia fazy 2 mogą występować bezpośrednio w tym samym wątku, który wywołał metodę Prepared w fazie 1. W związku z tym nie należy wykonywać żadnej pracy po Prepared wywołaniu (na przykład zwalniając blokady), które powinny zostać ukończone przed otrzymaniem powiadomień fazy 2.

Implementowanie rozwiązania InDoubt

Na koniec należy zaimplementować metodę InDoubt dla menedżera zasobów volatile. Ta metoda jest wywoływana, jeśli menedżer transakcji utraci kontakt z co najmniej jednym uczestnikiem, więc ich stan jest nieznany. W takim przypadku należy zarejestrować ten fakt, aby można było później zbadać, czy którykolwiek z uczestników transakcji został pozostawiony w stanie niespójnym.

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

Optymalizacja zatwierdzania jednofazowego

Protokół zatwierdzania jednofazowego jest bardziej wydajny w czasie wykonywania, ponieważ wszystkie aktualizacje są wykonywane bez wyraźnej koordynacji. Aby uzyskać więcej informacji na temat tego protokołu, zobacz Optymalizacja przy użyciu jednofazowego zatwierdzenia oraz powiadomienia o możliwości promocji jednofazowej.

Zobacz także