Microsoft KB Archive/939756

= What a database resource manager in Microsoft COM+ should do during database failure when a transaction is committed =

Article ID: 939756

Article Last Modified on 7/17/2007

-

APPLIES TO


 * Microsoft COM+ 2.0 Standard Edition

-



INTRODUCTION
A database may go into an abnormal state when a transaction is committed. For example, a database may fail during the commitment process.

This article describes what a database resource manager in Microsoft COM+ should do in this situation.



MORE INFORMATION
Consider the following scenario:
 * A client program starts a transaction.
 * Microsoft Distributed Transaction Coordinator (MSDTC) tells the resource manager to commit the transaction.
 * The resource manager successfully commits the transaction.
 * The database fails while the transaction is being committed.
 * The resource manager calls the ITransactionEnlistmentAsync::PrepareRequestDone method by using a value of E_FAIL for the hr parameter.

Note The ITransactionEnlistmentAsync::PrepareRequestDone method may also use any other value for the hr parameter except the following values:
 * S_OK
 * XACT_S_READONLY
 * XACT_S_SINGLEPHASE
 * MSDTC passes a message to the client program that the transaction has been aborted.

The problem in this situation is that the database actually committed the transaction. To deal with this problem, use one of the following methods:
 * Call the PrepareRequestDone method together with an hr parameter value of XACT_S_SINGLEPHASE.
 * Release the ITransactionEnlistmentAsync interface.

The &quot;PrepareRequestDone&quot; method
If the database confirms that it committed the transaction successfully, the resource manager should return the ITransactionEnlistmentAsync::PrepareRequestDone method together with an hr parameter value of XACT_S_SINGLEPHASE. This tells the transaction manager that the transaction was committed successfully.

The release method
If the database does not confirm that it committed the transaction successfully, the resource manager should call the ITransactionEnlistmentAsync::Release method if the single-phase commit protocol is used. This call results in the TransactionStatus.InDoubt enumeration. This enumeration indicates that the transaction manager has received no confirmation that the database committed the transaction.

The ITransactionEnlistmentAsync interface derives from the IUnknown interface. The client program obtains a reference to the ITransactionEnlistmentAsync interface by calling the IResourceManager.Enlist method. If no other calls are made to the IUnknown.QueryInterface method, the only reference to the enlistment is released when the program calls the ITransactionEnlistmentAsync::Release method. However, later calls to the QueryInterface method on the IUnknown interface increment the reference count.

If the commitment protocol is incomplete when the last reference is released, the transaction goes into one of the following three states:  Abort - The transaction aborts if the following conditions are true:  The last reference is released before the resource manager calls the ITransactionEnlistmentAsync::PrepareRequestDone method. The fSinglePhase parameter was not set to TRUE in the ITransactionResourceAsync::PrepareRequest method  InDoubt - The transaction status is in doubt if the following conditions are true:  The ITransactionResourceAsync::PrepareRequest call was made, and the fSinglePhase parameter was set to TRUE. The resource manager releases the last reference to the ITransactionEnlistmentAsync interface.</li></ul>

This issue occurs because the transaction manager asked the resource manager to perform a single-phase commit. However, the transaction manager lost the connection to the resource manager. Therefore, the transaction manager could not determine whether the transaction was committed.</li> Failed to notify - The transaction status is &quot;failed to notify&quot; if the last reference is released after the resource manager calls the ITransactionEnlistmentAsync::PrepareRequestDone method and before the resource manager calls the ITransactionEnlistmentAsync::CommitRequestDone method. In this case, the transaction manager maintains &quot;failed to notify&quot; status for the enlistment if all the other transaction enlistments respond positively.</li></ul>

<div class="references_section">