Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
Cada recurso usado em uma transação é gerenciado por um gerenciador de recursos (RM), cujas ações são coordenadas por um gerente de transações (TM). O tópico Recrutando recursos como participantes em uma transação discute como um recurso (ou vários recursos) pode ser inscrito em uma transação. Este tópico discute como o compromisso de transação pode ser coordenado entre os recursos alistados.
No final da transação, o aplicativo solicita que a transação seja confirmada ou revertida. O gerente de transações deve eliminar riscos, como alguns gerentes de recursos votando para se comprometer enquanto outros votam para reverter a transação.
Se sua transação envolver mais de um recurso, você deverá executar uma confirmação em duas fases (2PC). O protocolo de confirmação de duas fases (a fase de preparação e a fase de confirmação) garante que, quando a transação terminar, todas as alterações em todos os recursos sejam totalmente comprometidas ou totalmente revertidas. Todos os participantes são então informados do resultado final. Para uma discussão detalhada do protocolo de confirmação em duas fases, consulte o livro "Transaction Processing: Concepts and Techniques (Morgan Kaufmann Series in Data Management Systems) ISBN:1558601902" de Jim Gray.
Você também pode otimizar o desempenho da sua transação participando do protocolo Single Phase Commit. Para obter mais informações, consulte Otimização usando Compromisso de Fase Única e Notificação Promovível de Fase Única.
Se quiser apenas ser informado do resultado de uma transação e não quiser participar na votação, deve registar-se no TransactionCompleted evento.
Confirmação bifásica (2PC)
Na primeira fase de transação, o gerenciador de transações consulta cada recurso para determinar se uma transação deve ser confirmada ou revertida. Na segunda fase de transação, o gerenciador de transações notifica cada recurso sobre o resultado de suas consultas, permitindo que ele execute qualquer limpeza necessária.
Para participar deste tipo de transação, um gestor de recursos deve implementar a IEnlistmentNotification interface, que fornece os métodos que são invocados pelo TM como notificações durante um 2PC. O exemplo a seguir mostra um exemplo dessa implementação.
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
Fase de preparação (Fase 1)
Ao receber um Commit pedido da aplicação, o gestor de transações inicia a fase de Preparação de todos os participantes alistados, chamando o método Prepare de cada recurso alistado, para obter o voto de cada recurso na transação.
Seu gerenciador de recursos que implementa a IEnlistmentNotification interface deve primeiro implementar o método, Prepare(PreparingEnlistment) como mostra o exemplo simples a seguir.
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;
}
}
Quando o gestor de recursos duráveis recebe esta chamada, ele deve registar as informações de recuperação da transação (disponíveis ao recuperar a propriedade RecoveryInformation) e qualquer informação necessária para concluir a transação quando a transação é confirmada. Isso não precisa ser executado dentro do Prepare método porque o RM pode fazer isso em um thread de trabalho.
Quando o RM terminar o seu trabalho de preparação, deve votar para confirmar ou reverter chamando o método Prepared ou ForceRollback. Observe que a PreparingEnlistment classe herda um Done método da Enlistment classe. Se chamar este método no retorno da chamada PreparingEnlistment durante a fase Preparar, ele informará ao TM que se trata de um alistamento Read-Only (ou seja, gestores de recursos que podem ler, mas não podem atualizar dados protegidos por transações) e o RM não receberá mais notificações do gestor de transações quanto ao resultado da transação na fase 2.
O aplicativo é informado do compromisso bem-sucedido da transação depois que todos os gerentes de recursos votam Prepared.
Fase de confirmação (Fase 2)
Na segunda fase da transação, se o gerenciador de transações receber preparações bem-sucedidas de todos os gerentes de recursos (todos os gerentes de recursos invocaram Prepared no final da fase 1), ele invocará o Commit método para cada gerente de recursos. Os gerentes de recursos podem, então, tornar as alterações duráveis e concluir a confirmação.
Se algum gerente de recursos relatar uma falha na preparação na fase 1, o gerenciador de transações invocará o Rollback método para cada gerente de recursos e indicará a falha da confirmação para o aplicativo.
Assim, seu gerente de recursos deve implementar os seguintes métodos.
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();
}
O RM deve executar qualquer trabalho necessário para concluir a transação com base no tipo de notificação e informar o TM que terminou chamando o método Done no parâmetro Enlistment. Esse trabalho pode ser feito em um thread de trabalho. Observe que as notificações da fase 2 podem acontecer embutidas no mesmo thread que chamou o Prepared método na fase 1. Como tal, você não deve fazer nenhum trabalho após a Prepared chamada (por exemplo, liberar bloqueios) que você esperaria ter concluído antes de receber as notificações da fase 2.
Implementação do InDoubt
Finalmente, você deve implementar o InDoubt método para o gerenciador de recursos voláteis. Esse método é chamado se o gerente de transações perder contato com um ou mais participantes, portanto, seu status é desconhecido. Se isso ocorrer, você deve registrar esse fato para que possa investigar mais tarde se algum dos participantes da transação foi deixado em um estado inconsistente.
public void InDoubt (Enlistment enlistment)
{
// log this
enlistment.Done();
}
Otimização de commit monofásico
O protocolo de Commit de Fase Única é mais eficiente em tempo de execução porque todas as atualizações são feitas sem qualquer coordenação explícita. Para obter mais informações sobre este protocolo, consulte Otimização usando Compromisso Monofásico e Notificação Monofásica Promovível.