This article may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist. To maintain the flow of the article, we've left these URLs in the text, but disabled the links.


July 1998

Microsoft Systems Journal Homepage

Transactions in Distributed Applications

A distributed environment requires more interaction between components that do the work. In a simple client/server application, a series of actions can be completed within a transaction. A transaction guarantees atomicity, consistency, isolation, and durability. Together, the Se properties are known by the acronym ACID.
Atomicity All of the work specified within a transaction is either committed, or it is aborted and rolled back to the application state before the transaction.
Consistency A transaction is a correct transformation of the system state, preserving the state invariants. The application is usually responsible for maintaining consistency.
Isolation Concurrent transactions are protected from seeing each other's uncommitted results. Transactions are serialized to behave as if one transaction waits until no other transaction is running before attempting to commit its work.
Durability Once a transaction commits, its effects will persist even if there are system failures.
In the client/server scenario, the server guarantees ACID properties by keeping track of the state of the transaction and doing whatever's necessary to successfully commit or abort in the event of failure.
A transaction essentially guarantees that work done by your components either happens or it doesn't. There is no messy cleanup if the transaction fails—MTS returns your application to its state prior to starting the transaction. Even better, you don't have to provide any special code in your application components to handle transactions. You use the MTS Explorer to mark your components as transactional.
 


Scalable Servers with MTS

MTS is primarily about making it easier to build scalable servers. An application component executing within the MTS runtime environment does not require code to handle concurrent access by multiple clients. MTS shields a component's objects from concurrency issues by creating an activity. An activity is a set of objects executing on behalf of a client application. Every MTS object belongs to one activity. An activity includes the MTS object created by the base client, as well as any MTS objects created by that object and its descendants. the Se objects can be distributed across one or more processes, executing on one or more computers.
Server scalability is enhanced through just-in-time activation and database connection pooling. MTS objects are initially created in the deactivated state. When a client calls a method on an object that is in a deactivated state, MTS automatically activates the Object. During activation, the Object is put into its initial state. When an object has completed its work, either by committing a transaction or explicitly notifying MTS, MTS deactivates the Object, freeing up any resources used by the Object such as a database connection. MTS works with the ODBC Driver Manager to automatically pool connec-tions. A component that works with a database using ActiveX® Data Objects (ADO) or Remote Data Objects (RDO) can also benefit from database connection pooling because the Se data-access APIs use the ODBC Driver Manager.
Using MSMQ with MTS is a natural integration of two valuable technologies. With MTS, you get automatic scaling and transactions for your application. Extending that application with MSMQ enables you to work in an environment where real-time application processing won't fit the bill. Making method calls on an object and waiting for the M to return would result in server timeouts when there's no server available. By using MSMQ, you can send a request for work in the form of a message to a queue, where it will stay until the server becomes available. Transactional MSMQ guarantees that queued messages are only sent once and will accurately confirm that a message has been dispatched or received.
By not locking your server up in synchronous operations unnecessarily, MSMQ is a better way of managing your server resources. This means that even with a readily available server connection, queuing may still be good for your application. A typical object-oriented design decomposes work into discrete method calls. This often results in a lot of chatter between a client and server object. Furthermore, each of the Se method calls requires the channel between client and server to be maintained until the call returns from the server. With a queued approach, work requests can be packaged into a single message, reducing the number of server calls. And with messaging, results are sent in separate messages any time after the Originating message, without tying up a connection. Servers reading queued messages are free to dedicate resources to servicing messages when convenient, thus establishing a form of load balancing.