Jednofazowe i wielofazowe zatwierdzanie transakcji
Poszczególne zasoby używane w transakcji jest zarządzane przez Menedżera zasobów (MB), w których działania są koordynowany 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 opisano, jak można skoordynowanego między wyświetlone zasoby zobowiązaniom transakcji.
Na końcu transakcji aplikacja żąda zatwierdzenia lub wycofania transakcji. Menedżer transakcji musi wyeliminowania zagrożeń, takich jak niektórych menedżerów zasobów głosowanie zatwierdzić, podczas gdy inne głosowania można wycofać transakcji.
Transakcja wiąże się z więcej niż jeden zasób, należy wykonać dwufazowego (2PC). Protokół dwufazowego (fazy przygotowania i fazy rezerwacji) zapewnia, że po zakończeniu transakcji, wszystkie zmiany do wszystkich zasobów są całkowicie zadeklarowanej lub w pełni przywrócona. Wszyscy uczestnicy są następnie poinformowany o wyniku końcowego. Aby zapoznać się ze szczegółowym omówieniem protokołu zatwierdzania dwufazowego, zapoznaj się z książką "Przetwarzanie transakcji: Pojęcia i techniki (Morgan Kaufmann Series in Zarządzanie danymi Systems) ISBN:1558601902" Jim Gray.
Można także zoptymalizować wydajność Twojej transakcji przez biorących udział w protokole zatwierdzania jednego etapu. Aby uzyskać więcej informacji, zobacz Optymalizacja przy użyciu zatwierdzania jednofazowego i promotable jednofazowego powiadomienia.
Jeśli po prostu chcesz informujące o wyniku transakcji i zrezygnować z uczestnictwa w głosowaniu, należy zarejestrować dla TransactionCompleted zdarzenia.
Dwufazowego (2PC)
W pierwszej fazy transakcji Menedżer transakcji pyta każdy zasób, aby ustalić, czy zatwierdzeniu lub wycofać transakcji. Drugi etap transakcji Menedżer transakcji powiadamia każdego zasobu wynik jego zapytań, dzięki któremu można wykonać wszelkie niezbędne czyszczenia.
Aby uczestniczyć w tego rodzaju transakcji, menedżer zasobów musi zaimplementować IEnlistmentNotification interfejs, który udostępnia metody wywoływane przez TM jako powiadomienia podczas 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
Przygotuj faza (fazy 1)
Po otrzymaniu Commit żądania od aplikacji menedżer transakcji rozpoczyna fazę Przygotowywania wszystkich uczestników na liście, wywołując Prepare metodę dla każdego zasobu enlisted, 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;
}
}
Gdy trwały menedżer zasobów odbiera to wywołanie, powinien rejestrować informacje odzyskiwania transakcji (dostępne przez pobranie RecoveryInformation właściwości) i wszelkie informacje niezbędne do ukończenia transakcji po zatwierdzeniu. To nie jest konieczne jest wykonywana w ramach Prepare metoda, ponieważ Menedżer zasobów można to zrobić w wątku roboczego.
Po zakończeniu Menedżera zasobów jego przygotowania pracy, należy głosowania przekazać ani wycofać przez wywołanie metody Prepared lub ForceRollback metody. Należy zauważyć, że PreparingEnlistment klasa dziedziczy Done metodę z Enlistment klasy. Wywołanie tej metody na PreparingEnlistment wywołania zwrotnego w fazie przygotowania, informuje Menedżer transakcji czy jest tylko do odczytu rejestracji (czyli menedżerów zasobów, które może być odczytany, ale nie można zaktualizować dane chronione przed transakcjami) i Menedżera zasobów odbiera żadne dalsze powiadomienia z menedżerem transakcji wyniku transakcji w fazie 2.
Aplikacja jest poinformowana o pomyślnym zobowiązaniu transakcji po tym, jak wszyscy menedżerowie zasobów głosują Prepared.
Zatwierdź fazy (faza 2)
W drugiej fazy transakcji, gdy Menedżer transakcji odbiera pomyślne przygotowuje z wszystkich menedżerów zasobów (wywoływane ma wszystkich menedżerów zasobów Prepared na końcu fazy 1), wywołuje ono Commit metody dla każdego Menedżera zasobów. Menedżerowie zasobów mogą następnie wprowadzić zmiany trwałe i zakończyć zatwierdzenie.
Jeśli jakikolwiek menedżer zasobów zgłosił błąd przygotowania w fazie 1, menedżer transakcji wywołuje Rollback metodę dla każdego menedżera zasobów i wskazuje niepowodzenie zatwierdzenia w 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ć wszelkie prace niezbędne do zakończenia transakcji na podstawie typu powiadomień i informuje Menedżer transakcji, który zakończył się przez wywołanie metody Done metody w Enlistment parametru. Tej pracy można wykonać na wątku roboczego. Należy pamiętać, że powiadomieniami 2 może się tak zdarzyć tekście w tym samym wątku, który wywołał Prepared metody 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, gdy Menedżer transakcji traci kontaktu z jednego lub więcej uczestników, więc ich stan jest nieznany. W takim przypadku powinni wylogować się ten fakt tak, aby można było zbadać później czy wszystkich uczestników transakcji pozostały w niespójnym stanie.
public void InDoubt (Enlistment enlistment)
{
// log this
enlistment.Done();
}
Jedna faza zatwierdzania optymalizacji
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 zatwierdzania jednofazowego i promotable jednofazowego powiadomienia.