How an Application Program Initiates a Transaction
An application program initiates a transaction by:
- Connecting to MS DTC and obtaining a transaction dispenser interface that it uses to initiate transactions.
- Opening the appropriate resource managers, for example, by connecting to a relational database using ODBC.
- Initiating the MS DTC transaction by calling BeginTransaction and obtaining a transaction object that represents the transaction.
- Propagating the transaction to each resource manager by invoking the resource manager's transaction enlistment interface. For example, the application program uses the ODBC SQLSetConnectOption to propagate the MS DTC transaction object to resource managers that support ODBC. All subsequent work done on the ODBC connection is performed as part of the transaction. When the resource manager becomes aware of the MS DTC transaction, it enlists in the transaction with its local MS DTC transaction manager. This permits the resource manager to participate in the two-phase commit protocol and to receive transaction commit or abort notifications from MS DTC.
- Invoking the normal resource manager functions that update transaction-protected resource manager data.
For example, the application might insert, delete, or update records in a relational database, or it might invoke a database stored procedure that modifies the relational database.
- Calling Commit when the work of the transaction is complete. In response to the Commit call, MS DTC uses the two-phase commit protocol to coordinate commitment of the transaction with all of the resource managers enlisted in the transaction. Alternatively, the application program could call Abort to undo the effects of the transaction. The application may then go on to perform more MS DTC transactions.
- Releasing the transaction dispenser object and closing the ODBC connections when the application program completes.
In DTC, a deadlock condition can occur if you attempt to nest transactions in the same resource manager. Consider the following example. If you have two objects (A and B) that attempt to acquire a lock on the same resource manager, the following scenario would force a deadlock condition:
- Object A initiates a transaction in the resource manager. In so doing, the object acquires a lock on a specific resource.
- Object A then invokes a method on Object B.
- Object B then initiates its own transaction and attempts to acquire a lock on the same resource manager.
- Since the lock request from Object B is running on a different transaction than Object A, the resource manager blocks the attempt of Object B to block the resource, creating a deadlock condition.
The lock manager in the resource manager cannot detect the deadlock because the transactions for each object will wait indefinitely for the other to commit their associated transactions. The DTC cannot break the deadlock either because it is "unaware" of the dependency of each object on the other.