What is the Lighweight Transaction Manager and why do you need to know about it

A "hidden" feature available in System.Transactions is the Lightweight Transaction Manager (LTM). It provides support for light weight transactions that live in the current appdomain. The LTM acts as a façade layer for all the transactions started in System.Transactions and based on a set of rules, it will "fallback" to an MSDTC distributed transaction when it is necessary. I call it "fallback" because there is some performance penalty that you need to pay when this happens: the transaction will span beyond the appdomain and there will be cross-process messages that will be sent, since MSDTC resides in a different process. (Note that from the TM functionality point of view, you can also call this a "promotion", since the MSDTC is a more general purpose and more complete TM). The fallback/promotion happens behind the scenes without any action required from the application developer.

As long as the LTM deals with volatile resources (that enlist using Transaction.EnlistVolatile) and with at most one durable resource that supports single phase notifications (this resource enlists with Transaction.EnlistDurable and implements ISinglePhaseNotification) then the transaction remains in the ownership of LTM. The LTM restricts itself only to those resources that live in the same appdomain and for which "logging" (writing the transaction outcome to the disk) is not required.

The fallback will take place and the LTM will transfer the ownership of the transaction to MSDTC if any of the following is true:
- at least one durable resource that doesn't support single phase notifications is enlisted in the transaction
- at least two durable resources that support single phase notifications are enlisted in the transaction
- a request to "marshal" the transaction to a different appdomain or different process is done.

In between the LTM transaction and MSDTC transaction there is one intermediary type of transaction that we sometimes call it "database transaction" that is made available through the Promotable Single Phase Enlistment. PSPE is another important mechanism in System.Transactions for performance optimization. It allows a remote durable resource, located in a different appdomain/process/machine, to participate in the LTM transaction without causing it to "fallback" to an MSDTC transaction.

Since the LTM is a "hidden" feature, the only reason for which you need to know about its existence is when you care a lot about performance. You will want to delay or avoid the fallback to MSDTC as much as possible to gain performance and for that you need to know how and when the fallback is triggered.

Comments (14)

  1. arnold says:

    Would you explain the single phase/ Multi phase Transaction plz?

  2. arnold says:

    As I understand it,

    LTM == Single Phase Transaction and

    DTC == Multi Phase Transaction..

    Is this right?

  3. florinlazar says:

    To: arnold

    In general, transactions are done in 2 Phase Commit or 2PC. In phase 1, the transaction manager sends "prepare" messages to the resource managers participating in transaction. Once the TM receives the answers from all the RMs, it will start phase 2. In phase 2, if all the RM answers were positive in phase 1, then a "commit" message is broadcasted, otherwise, the TM will "abort" the transaction.

    In some cases, the TM can optimize the 2-PC to a single phase commit, and instead of sending a "prepare" followed by "commit"/"abort", it will only send a SinglePhaseCommit. This optimization happens when only one durable resource manager is involved in the transaction.

  4. arnoldpark says:

    Thanks a lot. It was very helpful.

  5. Hi Florin

    I’m back again 🙂

    From what I understood, a connection to a SQLSvr2005 DB is considered as a durable RM which supports single phase notifications. Consequently, a tx which deals with one such cnx and several RM volatiles is managed by the LTM.

    On the other side, a connection to any other RDBMS than SqlSvr2005 (say SQLSvr2000) is considered as a durable RM which doesn’t support single phase notifications. Consequently, LTM can’t work with any SQLSvr2000 cnx. As soon as a SQLSvr2000 cnx is being enrolled in a tx, the DTC comes in the ring. This particular behavior is less efficient than using SQLSvr2000 with ADO.NET 1.

    Am I right?



  6. florinlazar says:

    To: Patrick

    In your second scenario "SQLSvr2000 with ADO.NET 1" do you involve any transaction (like a transaction started by a ServicedComponent)? If you don’t, then yes, you will get a small payload when you add transactions. But this payload may payback in the future, if you expect to add another database connection to your app. Or maybe SQL Server 2000 will support PSPE in the future.

  7. kmw says:

    Is there a suggested way to keep the LTM in charge of the tranasction when only writing against a SQL2k5 database but factoring your code into multiple objects (or methods) that each connect to the same SQL2k5 database? For example, an order object and a line item object (or individual methods of the same object) where you call the order object to insert the order followed by calling the line item object multiple times to insert line items. As soon as you open the second connection to the same database on SQL2k5, it seems the transaction is propogated. It looks like you have to maintain the same connection to keep the transaction under the control of the LTM. Would it be best to stick with SqlTransactions for this?

  8. florinlazar says:

    To: kmv

    This is an optimization that System.Data should investigate if it is possible, but from what I remember they don’t support sharing a transaction across multiple connections. From System.Transactions point of you, when you open the second connection, there is second call from System.Data to EnlistPromotableSinglePhase, to which we need to return false, because only one PSPE enlistment should be allowed per transaction. (See also http://blogs.msdn.com/florinlazar/archive/2005/05/17/418595.aspx)

  9. Vince says:

    hello,florinlazar. I have one question about Transaction.

    using (TransactionScope transScope = new TransactionScope())
    //do something on database

    above code is the standard usage. my question is the lifecycle about dbconnection. we add some code nearby “//do something on database”, meanwhile before transScope.Complete(), such as — open a db connection , and insert one row, then close db connection. my question is — is db connection really closed before transScope.Complete() ? let’s don’t consider the connection pool on the client.

    Thanks in advance.

  10. Estos últimos días he estado investigando sobre el funcionamiento de System.Transactions y su relación

  11. florinlazar says:

    To: Vince

    That is a question for the System.Data folks. It also depends on what you mean by "really closed".

  12. A key feature that targets performance in System.Transactions is the Promotable Single Phase Enlistment.

Skip to main content