Optimization using Single Phase Commit and Promotable Single Phase Notification
This topic describes the mechanisms provided by the System.Transactions infrastructure to optimize performance.
Promotable Single Phase Enlistment
The System.Transactions infrastructure administrates a transaction inside a single application domain that involves at most a single durable resource or multiple volatile resources. Since the System.Transactions infrastructure uses only intra-application domain calls, it yields the best throughput and performance.
However, if the transaction is provided to another object in another application domain (including across process and machine boundaries) on the same computer, or if you were to enlist another durable resource manager, the System.Transactions infrastructure automatically escalates the transaction to be managed by the MSDTC. A transaction managed by MSDTC is not as performance-wise as one managed by the System.Transactions infrastructure.
To optimize performance, the System.Transactions infrastructure provides the Promotable Single Phase Enlistment (PSPE) that allows a single remote durable resource, located in a different application domain, process or machine, to participate in a System.Transactions transaction without causing it to be escalated to an MSDTC transaction. This resource manager (RM) can host and "own" a transaction that can later be escalated to a distributed transaction (or MSDTC transaction) if necessary. This reduces the chance of using the MSDTC.
This specific resource manager usually has its own internal non distributed transactions and it needs to support converting those transactions to distributed transactions at runtime. For example, SQL Server 2005 is such a resource manager. In such case, the System.Transactions infrastructure takes a passive management role by just monitoring the transaction for a need for escalation. To support the interaction between the System.Transactions infrastructure and resource manager, the latter needs to implement the interface IPromotableSinglePhaseNotification.
The EnlistPromotableSinglePhase method is used to enlist a single durable resource that can be escalated later. This method ensures that the enlistment can be escalated as needed. If the enlistment succeeds, the RM creates its internal transaction and associates it with the System.Transactions transaction. If the PSPE enlistment fails, the RM should instead enlist using the EnlistDurable method. Failures to enlist in PSPE might happen when the transaction is already a distributed transaction, or when another RM has already performed a PSPE enlistment
Once enlisted, calls by clients to commit or abort the System.Transactions transaction are converted to calls on the Resource Manager by invoking the SinglePhaseCommit method, or the Rollback respectively.
If the System.Transactions transaction never requires escalation, when the transaction is committed, the RM receives a SinglePhaseCommit notification. It can then commit the internal transaction that was initially created.
If the System.Transactions transaction needs to be escalated (e.g., to support multiple RMs), System.Transactions informs the resource manager by calling the Promote method on the ITransactionPromoter interface, from which the IPromotableSinglePhaseNotification interface derives. The resource manager then converts the transaction internally from a local transaction (which does not require logging) to a transaction object that is capable of participating in a DTC transaction, and associates it with the work already done. When the transaction is asked to commit, the transaction manager still sends the SinglePhaseCommit notification to the resource manager, which commits the distributed transaction that it created during escalation.
The TransactionCommitted traces (that are generated when a Commit is invoked on the escalated transaction) contain the activity ID of the DTC transaction.
For more information on management escalation, see Transaction Management Escalation.
Transaction Management Escalation Scenario
The following scenario demonstrates an escalation to a distributed transaction using the System.Data namespace as the ‘proxy’ for the resource manager. This scenario assumes that there is already one System.Data connection to the database, CN1, involved in the transaction, and the application wants to involve another System.Data connection, CN2. The transaction must be escalated to DTC, as a full distributed two-phase commit transaction.
In this scenario,
CN1 calls the EnlistPromotableSinglePhase method to enlist in the transaction. Then, the transaction is still local and there are no other promotable enlistments on the transaction, so the EnlistPromotableSinglePhase call succeeds.
When the second connection, CN2 calls EnlistPromotableSinglePhase, the call fails because there is another promotable enlistment involved. Because of this, CN2 must get a DTC transaction in order to pass it to SQL. To do this, it uses one of the methods provided by the TransactionInterop class to produce a format of the transaction that can be given to SQL.
System.Transactions calls the Promote method on the ITransactionPromoter interface implemented by CN1.
At this point, CN1 escalates the transaction, using some mechanism specific to SQL 2005 and System.Data.
The return value from the Promote method is a byte array that contains a propagation token for the transaction. System.Transactions uses this propagaition token to create a DTC transaction that it can incorporate into the local transaction.
At this point, CN2 can use the data received from calling one of the methods by TransactionInterop to pass the transaction to SQL.
Now, both are enlisted in a DTC distributed transaction.
Single Phase Commit Optimization
The Single Phase Commit protocol is more efficient at runtime as all updates are done without any explicit coordination. To take advantage of this optimization, you should implement a resource manager using ISinglePhaseNotification interface for the resource and enlist in a transaction using the EnlistDurable or EnlistVolatile method. Specifically, the EnlistmentOptions parameter should equal to None to ensure that a single phase commit would be performed.
Since the ISinglePhaseNotification interface derives from the IEnlistmentNotification interface, if your RM is not eligible for single phase commit, it can still receive the two phase commit notifications. If your RM receives a SinglePhaseCommit notification from the TM, it should try to do the work necessary for it to commit and correspondingly inform the transaction manager if the transaction is to be committed or rolled back by calling the Committed, Aborted, or InDoubt method on the SinglePhaseEnlistment parameter. A response of Done on the enlistment at this stage implies ReadOnly semantics. Therefore, you should not reply Done in addition to any of the other methods.
If there is only one volatile enlistment and no durable enlistment, the volatile enlistment receives SPC notification. If there are any volatile enlistments and only one durable enlistment, the volatile enlistments receive 2PC. When it is completed, the durable enlistment receives SPC.