TansactionScope和MSDTC争用问题

时间:2014-03-13 11:04:45

标签: c# sql sql-server sql-server-2008 msdtc

我一直在研究我们面临的问题的解决方案。我使用transacitonscope将一些循环代码保存到SQL 2005中。我们不得不恢复使用字符串并在proc中拆分,所以当字符串是长度> 8000我把它分开了,这在我们的测试环境中运行得很好,这是SQL 2008R2。问题是当我们将测试移到SQL 2005环境时,事务会自动登记到msdtc。由于2005年的环境不同,例如不同的域和防火墙后面等我希望SQL服务器处理事务而不是msdtc。我们已经跟踪了SQL 2005 db并且可以在跟踪中看到DTC事务,当跟踪SQL2008时它只在跟踪中使用SQL事务。

代码本身很简单 - 使用语句(TransactionScope ...),在using块中有一个循环,它最多只能在1到4次迭代之间循环,并且在循环中有代码新建了一个sql连接到同一个数据库,并且在此连接上创建了一个隐式SQltransaction(用于解析单个更新)。我无法将相同的新连接传递回自身,因为代码在数据访问层中,但测试SQL2008它必须可以与同一个数据库的新连接(我认为新的汇集)。每个循环都会对DB进行实际的更新调用。如果是,如果字符串是1200 char长度,将有2次调用来更新db ...

基于一些SO帖子,例如SqlConnection and avoiding promotion to MSDTC

有一个设置可以传递给连接字符串Enlist = false,根据我的理解,这将保持事务管理到sql server并且只要你使用相同的数据库资源就会工作 - 在我的情况下是相同的sql 2005,每个循环中包含一个connection.begintransaction的新连接 - 任何人都可以确认这个吗?或者在我的情况下使用连接设置Enlist = false dangerous?

更新 重新定义,使用transcationscope,sql 2005和看起来有点像这样的代码(伪代码)时,在连接字符串中使用Enlist = false是否有任何警告:

using (var ts = new transactionscope)    
{ 
    loop (twice) 
    {      
         using (var conn = new SqlConnection)
         using (var tran = conn.BeginTransaction)
         {
             //do update to the db code here; 
             tran.Commit();
         }
    }

    ts.Complete();
}

1 个答案:

答案 0 :(得分:1)

如果您未登记连接(可能),则TransactionScope无效。你不想要那个。

如果您登记多个SqlConnections,则可以按设计获得分布式事务。这基本上是这样的。如果幸运的话,两者都将使用相同的内部池连接并避免使用MSDTC(而是使用SQL Server轻量级分布式事务)。但是,这永远保证并且不受时间问题的影响。这是一种性能优化。我讨厌这种优化,因为在测试过程中它总会发生并掩盖潜在的问题。

不要打开多个连接。重用相同的连接。