Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Каждый ресурс, используемый в транзакции, управляется диспетчером ресурсов (RM), действия которого координируются диспетчером транзакций (TM). Тема "Включение ресурсов в качестве участников транзакции" обсуждает, как ресурс (или несколько ресурсов) можно включить в транзакцию. В этом разделе описывается, как можно координировать обязательства по транзакциям между зачисленными ресурсами.
В конце транзакции приложение запрашивает ее фиксацию или откат. Диспетчер транзакций должен устранять риски, такие как ситуация, когда некоторые менеджеры ресурсов голосуют за фиксацию, в то время как другие голосуют за откат транзакции.
Если транзакция включает несколько ресурсов, необходимо выполнить двухфазную фиксацию (2PC). Протокол двухфазного подтверждения (фаза подготовки и фаза подтверждения) гарантирует, что при завершении транзакции все изменения всех ресурсов либо полностью подтверждены, либо полностью отменены. Затем все участники получают информацию о окончательном результатах. Для подробного обсуждения протокола двухфазной фиксации см. книгу "Обработка транзакций: концепции и методы (серия Morgan Kaufmann по системам управления данными) ISBN:1558601902" Джима Грея.
Вы также можете оптимизировать производительность транзакции, приняв участие в протоколе однофазной фиксации. Дополнительные сведения см. в статье "Оптимизация с помощью однофазной фиксации и уведомления о промотабельной однофазной фазе".
Если вы просто хотите быть проинформированы о результатах транзакции, и не хотите участвовать в голосовании, необходимо зарегистрироваться для TransactionCompleted мероприятия.
Двухфазная фиксация (2PC)
На первом этапе транзакции диспетчер транзакций запрашивает каждый ресурс, чтобы определить, должна ли транзакция быть зафиксирована или откатена. На втором этапе транзакции диспетчер транзакций уведомляет каждый ресурс о результатах запросов, позволяя ему выполнять любую необходимую очистку.
Для участия в этой транзакции диспетчер ресурсов должен реализовать IEnlistmentNotification интерфейс, который предоставляет методы, вызываемые TM в качестве уведомлений во время 2PC. В следующем примере показан пример такой реализации.
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
Этап подготовки (этап 1)
После получения Commit запроса от приложения менеджер транзакций начинает фазу подготовки всех участвующих участников, вызывая метод Prepare для каждого задействованного ресурса, чтобы получить решение каждого ресурса по транзакции.
Диспетчер ресурсов, реализующий IEnlistmentNotification интерфейс, сначала должен реализовать Prepare(PreparingEnlistment) метод, как показано в следующем простом примере.
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;
}
}
Когда диспетчер устойчивых ресурсов получает этот вызов, он должен регистрировать информацию о восстановлении транзакции (доступную путем извлечения свойства RecoveryInformation), а также всю информацию, необходимую для завершения транзакции при её фиксации. Это не требуется выполнять в методе Prepare , так как RM может сделать это в рабочем потоке.
Когда RM завершит подготовку, он должен проголосовать за подтверждение или отмену, вызвав метод Prepared или ForceRollback. Обратите внимание, что PreparingEnlistment класс наследует Done метод из Enlistment класса. Если этот метод вызывается на PreparingEnlistment обратном вызове во время этапа подготовки, он сообщает менеджеру транзакций, что это участие в Read-Only (то есть управляющие ресурсами, которые могут считывать, но не могут обновлять данные, защищенные транзакциями), и RM не получает никаких дополнительных уведомлений от менеджера транзакций о результате транзакции на втором этапе.
Приложение получает уведомление о успешном подтверждении транзакции после того, как все руководители ресурсов проголосовали Prepared.
Этап фиксации (Этап 2)
На втором этапе транзакции, если менеджер транзакций получает подтверждение об успешной подготовке от всех менеджеров ресурсов (все менеджеры ресурсов вызвали Prepared в конце этапа 1), он вызывает метод Commit для каждого менеджера ресурсов. Затем диспетчеры ресурсов могут сделать изменения постоянными и завершить фиксацию изменений.
Если любой диспетчер ресурсов сообщил о сбое подготовки на этапе 1, диспетчер транзакций вызывает Rollback метод для каждого диспетчера ресурсов и указывает на сбой фиксации в приложении.
Таким образом, диспетчер ресурсов должен реализовать следующие методы.
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();
}
RM должен выполнить любую работу, необходимую для завершения транзакции в зависимости от типа уведомления, и сообщить TM о завершении путем вызова метода Done на параметре Enlistment. Эту работу можно выполнить в рабочем потоке. Обратите внимание, что уведомления этапа 2 могут происходить внутри того же потока, где был вызван метод на Prepared этапе 1. Таким образом, вы не должны выполнять никаких действий после Prepared вызова (например, освобождение блокировок), которые вы ожидаете завершить до получения уведомлений этапа 2.
Внедрение InDoubt
Наконец, следует реализовать InDoubt метод для диспетчера переменных ресурсов. Этот метод вызывается, если диспетчер транзакций теряет контакт с одним или несколькими участниками, поэтому их состояние неизвестно. Если это происходит, необходимо записать этот факт, чтобы можно было позже изучить, остался ли любой из участников транзакции в несогласованном состоянии.
public void InDoubt (Enlistment enlistment)
{
// log this
enlistment.Done();
}
Оптимизация однофазной фиксации
Протокол однофазной фиксации более эффективен в процессе выполнения, так как все обновления выполняются без явной координации. Дополнительные сведения об этом протоколе см. в разделе "Оптимизация с помощью однофазной фиксации" и уведомления о промотабельном однофазном уведомлении.