What are the goals for System.Transactions?

When we started working on System.Transactions in .Net 2.0, we had a simple goal: to decompose transaction services down to a simple common set of interfaces; and in doing so to reduce the complexity associated with using transactions and extend their reach.

This gave us two basic goals to aim at: a very simple object model with few ties to any larger environment, and sufficiently high performance for simple transactions to remove the need for any custom environment.

The first goal led to a simple set of services that were available as a core feature of .Net 2.0.  The application programmer typically only has to bracket the activities that are to be part of a transaction, so with .Net 2.0 their primary, and possibly sole, exposure to System.Transactions will be with TransactionScope.  That class has a number of constructors that provide for various settings from timeout to COM+ styles of transaction inheritance.  The typical pattern is likely to be (in C#):

    using (TransactionScope ts = new TransactionScope ())
    {
        // the transaction is active within here
        // ...
        ts.Complete ();
    }

There is no further exposure until the application needs to handle distribution.  It does not require a special type of class, or custom attributes, or a specific run time.  In fact, the expectation is that application environments, such as System.EnterpriseServices, will make use of it for their underlying transaction feature.

The second goal required that we achieve very high performance for transactions that had simple topologies and one resource.  This was to avoid the pattern where components are built differently if the author expects that a single SQL connection will suffice.  This is typically done for performance, and our goal was to remove the performance argument and reduce the design pattern choices to a common set.

Our approach was to build a transaction stack that, behind the scenes, staged a series of fallbacks to more and more capable transaction management engines.  With this sort of structure, initial transaction creation is extremely cheap.  Furthermore, there are features, known as promotable single phase enlistment, in System.Transactions that allow a database to assume control of a simple transaction topology, yet have that control revoked if the topology increases sufficiently.  With this structure in place, our tests have shown very little difference between using System.Transactions and using ADO's single database transaction interfaces.

Between these two, we have a very simple object model, with a performance profile that means that you shouldn't have to code around it.


Posted Feb 07 2005, 06:24 AM by jim-johnson

Comments

Erik Johnson wrote re: What are the goals for System.Transactions?
on 02-07-2005 8:21 AM
Good stuff, Jim! Perhaps when you get a chance, you could more fully describe the fallback process?

In our situation, whatever component gets the first call starts the transaction (using sytax identical to the TransactionScope example). But obviously other components get called, each with their own transactions similarly fenced. I think this is a very common practice and it would be great to know more about what triggers a "fallback" and how is affects the overall transaction process.

Also, our apps have an asynchronous bit that we feed using MSMQ. Does MSMQ get promotable single-phase enlistment as well?

One side note: COM+ 1.5 acts differently on XP vs. Server 2003 when the app attempts to enlist an existing transation but with a different isolation level. As I recall, XP will start a nested transaction while Server 2003 will throw an exception (it depends on which way the isolation level is changing).

It would be great to (a) have this discrepancy fixed and (b) understand how isolation level settings affect the fallback/enlistment process.

Thanks again for the info. These look like great additions for .Net development.

- Erik
Patrick Foley wrote re: What are the goals for System.Transactions?
on 02-07-2005 9:15 AM
Is there any additional support for making transaction timeouts less annoying while debugging? I usually just create a configuration setting and disable transactions while debugging, but since you are building a whole new stack, maybe there is a better way to deal it.
Jim Johnson wrote re: What are the goals for System.Transactions?
on 02-09-2005 4:43 PM
Erik,

Thanks for the comments and the questions. I'll go deeper into how the fallback logic works in one or more upcoming entries.

MSMQ does not yet support promotable single phase enlistments, but I would expect that it will at some point.

Re Isolation levels: We try very hard to not do anything at this point to change existing behavior. As for System.Transactions, we insist on an exact match for isolation levels, although the default is 'unspecified', which matches anything and is interpreted as 'serializable' if it is creating the transaction.

Patrick,

We didn't do anything to make handling timeouts during debugging easier. In fact, in the current version it is probably harder. This is because there's a machine wide maximum that the transaction timeout is minimized against. For now, you should be able to set the machine wide maximum and not specify a timeout yourself. However, this is good input that I'll bring up here. I don't know what we can do about it, but we can at least explore it.

Jim.
Tim Fischer wrote re: What are the goals for System.Transactions?
on 03-20-2005 6:40 AM
Hello Patrick,

i am pretty interested in your work.

I do have one novice question: Has someone from microsoft research or your team thought about a tranactional heap and stack feature for the CLR 2.0?

As we all know application state is hard thing to manage. Therefore it might be useful to have transactional support on c# objects themselves. (Like O/R Mappers do).
If this feature was deeply integrated into the CLR (stack and heap manager, garbage collector) there might be some new possiblities to implement nested transactions and advanced caching strategies. (This might also be interesting for the MBF and Nautilus team)

Please send email to tfischer@tangible.de

Kind Regards

Tim
Jim Johnson wrote re: What are the goals for System.Transactions?
on 03-20-2005 1:41 PM
Tim,

Thanks for your question, and for your interest.

It's certainly my view that transactions represent a technology that should be usable from today's database applications down to very simple operations.

I also believe that for transactions to be usable it needs to be based on a structure that provides a single, consistent, and simple set of structures that work across this entire range of possible operations. In other words, I do believe that transactions are useful from individual objects up through databases, and that the application must not need to change its code in order to grow from one extreme into the other.

It's also true that there's been active research into software transacted memory (STM) support and lighter weight transacted objects for a very long time. Some of that research has looked at transactions that span from the very lightweight up through more traditional transaction systems. I can't say that I've done an exhaustive research, but I have read some number of these papers over the years.

I also believe that System.Transactions forms a solid basis for transaction management that is in line with these views. I know that we've described how these could be used with, for instance, transacted collection classes. While I can't say how far we'll be able to take this, or in what timeframe, we have been looking into doing something in this space post .Net 2.0.

Jim.
Jim Johnson's Blog wrote A peek at Longhorn: how TxF integrates
on 04-28-2005 12:41 AM
Jim Johnson's Blog wrote A peek at Longhorn: how TxF integrates
on 04-28-2005 12:42 AM
KjellSJ wrote re: What are the goals for System.Transactions?
on 11-16-2005 1:45 AM
We are have several components that we want to use "COM+ style" by using TransactionScope(.Required) so that the the transaction context is passed on between the components to share an implicit, common transaction, but alas without incuring the DTC. Our database system is SQL Server 2005.

The "problem" is that we are using TableAdapters that each internally opens their own connection, all to the same SS2K5 database using the same connect string, and this causes the transaction to be promoted from lightweight to DTC. This surprised me alot, is there a way to avoid this ? Do we need to pass the SqlConnection around ?

From MSDN Mag 'Data Points':
When the first connection is created against the SQL Server 2005 database, the transaction stays lightweight. But when it connects to the second database, regardless of the type, the transaction is promoted to a distributed transaction.
Jim Johnson wrote re: What are the goals for System.Transactions?
on 12-14-2005 7:05 AM
KjellSJ:

I apologize for the delay in getting back to you. TableAdapter isn't a mechanism that I'm familiar with, so I had to do ask around a bit here.

What I've been told is that to avoid promotion you should supply the SqlConnection to the TableAdapter to make sure that they use the same one.

Let me know if this does, or doesn't, help.

Thanks,
Jim.

Add a Comment

(required)  
(optional)
(required)  
Remember Me?