単一フェースおよび複数フェーズでのトランザクションのコミットCommitting a Transaction in Single-Phase and Multi-Phase

トランザクションで使用される各リソースは、リソース マネージャー (RM) によって管理され、その動作はトランザクション マネージャー (TM) によって調整されます。Each resource used in a transaction is managed by a resource manager (RM), whose actions are coordinated by a transaction manager (TM). トランザクションの参加要素としてのリソースの参加」トピックでは、単一 (または複数) のリソースがトランザクションに参加する方法が説明されています。The Enlisting Resources as Participants in a Transaction topic discusses how a resource (or multiple resources) can be enlisted in a transaction. ここでは、参加リソース間でトランザクションのコミットメントを調整する方法について説明します。This topic discusses how transaction commitment can be coordinated among enlisted resources.

トランザクションの最後に、アプリケーションはトランザクションのコミットまたはロールバックを要求します。At the end of the transaction, the application requests the transaction to be either committed or rolled back. トランザクション マネージャーは、一部のリソース マネージャーがトランザクションのコミットを選択し、他のリソース マネージャーがトランザクションのロールバックを選択するというようなリスクを回避する必要があります。The transaction manager must eliminate risks like some resource managers voting to commit while others voting to roll back the transaction.

トランザクションに複数のリソースが含まれる場合は、2 フェーズ コミット (2PC) を実行する必要があります。If your transaction involves more than one resource, you must perform a two-phase commit (2PC). 2 フェーズ コミット プロトコル (準備フェーズとコミット フェーズ) により、すべてのリソースに対する変更がトランザクションの終了時に完全にコミットされるか、または完全にロールバックされることが保証されます。The two-phase commit protocol (the prepare phase and the commit phase) ensures that when the transaction ends, all changes to all resources are either totally committed or fully rolled back. その後、すべての参加要素に最終結果が通知されます。All the participants are then informed of the final result. 2 フェーズ コミット プロトコルの詳細については、『トランザクション処理: 概念と手法』(Morgan Kaufmann Series in Data Management Systems、ISBN: 1558601902、Jim Gray 著) をお読みください。For a detailed discussion of the two-phase commit protocol, please consult the book "Transaction Processing : Concepts and Techniques (Morgan Kaufmann Series in Data Management Systems) ISBN:1558601902" by Jim Gray.

単一フェーズ コミット プロトコルに参加することで、トランザクションのパフォーマンスを最適化することもできます。You can also optimize your transaction's performance by taking part in the Single Phase Commit protocol. 詳しくは、「単一フェーズ コミットおよび昇格可能単一フェーズ通知を使用した最適化」をご覧ください。For more information, see Optimization using Single Phase Commit and Promotable Single Phase Notification.

トランザクション結果の通知を受信するだけで、コミットまたはロールバックの選択には参加しない場合は、TransactionCompleted イベントに登録する必要があります。If you just want to be informed of a transaction's outcome, and do not want to participate in voting, you should register for the TransactionCompleted event.

2 フェーズ コミット (2PC)Two-phase Commit (2PC)

最初のトランザクション フェーズで、トランザクション マネージャーは、トランザクションをコミットするかロールバックするかを決定するため、各リソースに照会します。In the first transaction phase, the transaction manager queries each resource to determine whether a transaction should be committed or rolled back. 2 番目のトランザクション フェーズでは、トランザクション マネージャーは照会結果を各リソースに通知し、必要なクリーンアップを実行できるようにします。In the second transaction phase, the transaction manager notifies each resource of the outcome of its queries, allowing it to perform any necessary cleanup.

この種のトランザクションに参加するために、リソース マネージャーは IEnlistmentNotification インターフェイスを実装する必要があります。このインターフェイスは、2PC 中に通知として TM が呼び出すメソッドを提供します。To participate in this kind of transaction, a resource manager must implement the IEnlistmentNotification interface, which provides methods that are called by the TM as notifications during a 2PC. このような実装の例を次に示します。The following sample shows an example of such implementation.

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 indout 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 indout notification is received

        'Declare done on the enlistment
        myEnlistment.Done()
    End Sub
End Class

準備フェーズ (フェーズ 1)Prepare phase (Phase 1)

アプリケーションから Commit 要求を受信すると、トランザクション マネージャーは、各リソースのトランザクションに対する選択を取得するため、各参加リソースに対して Prepare メソッドを呼び出し、参加しているすべての参加要素の準備フェーズを開始します。Upon receiving a Commit request from the application, the transaction manager begins the Prepare phase of all the enlisted participants by calling the Prepare method on each enlisted resource, in order to obtain each resource's vote on the transaction.

IEnlistmentNotification インターフェイスを実装するリソース マネージャーは、次の簡単な例に示すように、最初に Prepare(PreparingEnlistment) メソッドを実装する必要があります。Your resource manager that implements the IEnlistmentNotification interface should first implement the Prepare(PreparingEnlistment) method as the following simple example shows.

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 プロパティの取得により利用可) と、コミット時にトランザクションを完了させるのに必要な情報をすべてログに記録する必要があります。When the durable resource manager receives this call, it should log the transaction's recovery information (available by retrieving the RecoveryInformation property) and whatever information is necessary to complete the transaction on commit. RM はワーカー スレッドでこれを実行できるため、Prepare メソッド内で実行する必要はありません。This does not need to be performed within the Prepare method because the RM can do this on a worker thread.

この準備操作が完了したら、RM は Prepared メソッドまたは ForceRollback メソッドを呼び出して、コミットまたはロールバックを選択する必要があります。When the RM has finished its prepare work, it should vote to commit or roll back by calling the Prepared or ForceRollback method. PreparingEnlistment クラスは、Done クラスから Enlistment メソッドを継承することに注意してください。Notice that the PreparingEnlistment class inherits a Done method from the Enlistment class. 準備フェーズ中に PreparingEnlistment コールバックでこのメソッドを呼び出すと、読み取り専用の参加 (トランザクション保護されたデータを読み取れるが更新できないリソース マネージャー) であることが TM に通知され、RM はフェーズ 2 でのトランザクションの結果として、トランザクション マネージャーからの通知を受信しなくなります。If you call this method on the PreparingEnlistment callback during the Prepare phase, it informs the TM that it is a Read-Only enlistment (that is, resource managers that can read but cannot update transaction-protected data) and the RM receives no further notifications from the transaction manager as to the outcome of the transaction in phase 2.

すべてのリソース マネージャーが Prepared を選択すると、トランザクションのコミットメントが成功したことがアプリケーションに通知されます。The application is told of the successful commitment of the transaction after all the resource managers vote Prepared.

コミット フェーズ (フェーズ 2)Commit phase (Phase 2)

トランザクションの 2 番目のフェーズで、トランザクション マネージャーがすべてのリソース マネージャーから準備の成功を受信すると (すべてのリソース マネージャーがフェーズ 1 の終わりで Prepared を呼び出した場合)、各リソース マネージャーに対して Commit メソッドを呼び出します。In the second phase of the transaction, if the transaction manager receives successful prepares from all the resource managers (all the resource managers have invoked Prepared at the end of phase 1), it invokes the Commit method for each resource manager. これにより、リソース マネージャーは、変更を永続的なものとして、コミットを完了できます。The resource managers can then make the changes durable and complete the commit.

いずれかのリソース マネージャーがフェーズ 1 での準備の失敗を報告すると、トランザクション マネージャーは、各リソース マネージャーに対して Rollback メソッドを呼び出し、アプリケーションにコミットの失敗を通知します。If any resource manager reported a failure to prepare in phase 1, the transaction manager invokes the Rollback method for each resource manager and indicates the failure of the commit to the application.

したがって、リソース マネージャーは次のメソッドを実装する必要があります。Thus, your resource manager should implement the following methods.

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 は、通知の種類に基づいてトランザクションを終了するために必要な作業を実行し、Done パラメーターで Enlistment メソッドを呼び出すことにより、TM に作業の完了を通知する必要があります。The RM should perform any work necessary to finish the transaction based on the notification type, and inform the TM that it has finished by calling Done method on the Enlistment parameter. これはワーカー スレッドで実行できます。This work can be done on a worker thread. フェーズ 2 の通知は、フェーズ 1 で Prepared メソッドを呼び出した同じスレッドで、インラインで発生する可能性があることに注意してください。Note that the phase 2 notifications can happen inline on the same thread that called the Prepared method in phase 1. このため、フェーズ 2 の通知を受け取る前に既に完了したと考えられる作業 (ロックの解除など) は、Prepared 呼び出しの後には実行できません。As such, you should not do any work after the Prepared call (for example, releasing locks) that you would expect to have completed before receiving the phase 2 notifications.

InDoubt の実装Implementing InDoubt

最後に、揮発性リソース マネージャーに InDoubt メソッドを実装する必要があります。Finally, you should implement the InDoubt method for the volatile resource manager. このメソッドは、トランザクション マネージャーが 1 つ以上の参加要素と接続できなくなり、そのステータスが不明になった場合に呼び出されます。This method is called if the transaction manager loses contact with one or more participants, so their status is unknown. この場合は、トランザクションのいずれかの参加要素が矛盾した状態のままになっていないかどうかを後で調べることができるよう、この事実を記録しておく必要があります。If this occurs, you should log this fact so that you can investigate later whether any of the transaction participants has been left in an inconsistent state.

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

単一フェーズ コミットの最適化Single Phase Commit Optimization

単一フェーズ コミット プロトコルは、すべての更新が明示的な調整なしに行われるため、実行時に、より効率的です。The Single Phase Commit protocol is more efficient at run time because all updates are done without any explicit coordination. このプロトコルについて詳しくは、「単一フェーズ コミットおよび昇格可能単一フェーズ通知を使用した最適化」をご覧ください。For more information on this protocol, see Optimization using Single Phase Commit and Promotable Single Phase Notification.

関連項目See also