Search code examples
sql-server-2005transactionstransactionscope

.NET TransactionScopes and SQL 2005 Lightweight Transaction Manager - Multiple Connections same SPID?


Can someone shed light on what is happening behind the scenes with the SQL Lightweight transaction manager when multiple connections are opened to the same DB, using the Microsoft Data Access Application Block (DAAB)?

With the below code, we verified that MSDTC is indeed not required when opening 'multiple connections' to the same database.

This was the first scenario I tested: (where Txn1 and Txn2 use EntLib 4.1 to open a connection to the same DB and call different SPROCS)

using (var ts = new TransactionScope(TransactionScopeOption.Required))
{
    DAL1.Txn1();
    DAL2.Txn2();
    ts.Complete();
}

Tracing this from profiler revealed that the same connection SPID was used for Txn1 and Txn2. After Txn1() was called, the Sql SPID would have been released back into the pool and Txn2() was able to re-use it.

However, when repeating this experiment and this time holding the connections open:

using (var ts = new TransactionScope(TransactionScopeOption.Required))
{
    Database db1 = DatabaseFactory.CreateDatabase("db1");
    DAL1.Txn1OnCon(db1);
    Database db2 = DatabaseFactory.CreateDatabase("db1");
    DAL2.Txn2OnCon(db2);
    ts.Complete();
}

Viewing this from Profiler indicated that the 2 transactions were STILL using the same SPID. I was expecting the TransactionScope to have escalated to DTC as a distributed transaction should be required to control 2 concurrent connections. What have I missed?


Solution

  • Quoting from MSDN http://msdn.microsoft.com/en-us/library/8xx3tyca(VS.80).aspx

    Connection pooling reduces the number of times that new connections need to be opened. The pooler maintains ownership of the physical connection. It manages connections by keeping alive a set of active connections for each given connection configuration. Whenever a user calls Open on a connection, the pooler looks to see if there is an available connection in the pool. If a pooled connection is available, it returns it to the caller instead of opening a new connection. When the application calls Close on the connection, the pooler returns it to the pooled set of active connections instead of actually closing it. Once the connection is returned to the pool, it is ready to be reused on the next Open call.

    Just because a connection was used in a transaction doesn't mean it cannot be available for the next call. I found that If the connection string varied by the slightest thing, such as capitalization of a hostname, then you'd get a new physical connection to the db.