TransactionScope 和连接池

Posted

技术标签:

【中文标题】TransactionScope 和连接池【英文标题】:TransactionScope and Connection Pooling 【发布时间】:2011-01-26 09:38:33 【问题描述】:

我正在尝试了解我们的应用程序中是否存在使用不正确 IsolationLevels 进行数据库连接的问题。我们的应用程序是使用 SQL Server 2005 的 .Net 3.5 数据库应用程序。

我发现连接的 IsolationLevel 在返回到连接池时不会重置(请参阅here),并且在此blog post 中读到每个新创建的 TransactionScope 都有自己的连接也很惊讶分配给它的池。

我们的数据库更新(通过我们的业务对象)发生在 TransactionScope 内(为每个业务对象图更新创建一个新的)。但是我们的提取不使用显式事务。所以我想知道的是,我们是否会遇到这样的情况:我们的 fetch 操作(应该使用默认的 IsolationLevel - Read Committed)会重用池中已用于更新的连接,并继承更新 IsolationLevel (可重复读取)?或者我们的更新是否可以保证使用不同的连接池,因为它们被包装在 TransactionScope 中?

提前致谢,

格雷厄姆

【问题讨论】:

【参考方案1】:

这令人担忧!

您链接到的 Bill Vaughan 的文章指出“...每个 TransactionScope 都有自己的池”,但您链接到的支持文章中的代码表明这是不正确的,因为 NoTxScope() 的第二次运行获得了来自使用提升隔离级别的池的连接。

您可以通过 [我正在使用第一个链接中的代码] 来“强制”解决问题:

static void ForceReadCommitedScope()

    TransactionOptions op = new TransactionOptions();
    op.IsolationLevel = IsolationLevel.ReadCommitted;
    using (TransactionScope tx = new TransactionScope(TransactionScopeOption.RequiresNew, op))
    
        SqlConnection con = new SqlConnection("Data Source=.;Initial Catalog=master;Integrated Security=True;");
        SqlCommand com = new SqlCommand("select transaction_isolation_level from sys.dm_exec_sessions where (session_id = @@SPID)", con);
        con.Open();
        short level = (short)com.ExecuteScalar();
        Console.WriteLine("transaction_isolation_level : " + level.ToString());
        con.Close();
        tx.Complete();
    

或通过将"..;Pooling=False" 添加到您的连接字符串。

【讨论】:

这是一个非常好的观点!似乎 TransactionScope 没有获得自己的专用连接池,这表明 Bill Vaughan 的文章中包含的信息不正确。 “强迫”问题的部分只是TransactionOptionsTransactionScope 的创建,对吧?例如。 (通过链接阅读更多内容:pastie.org/10314190):TransactionOptions op = new TransactionOptions(); op.IsolationLevel = IsolationLevel.ReadCommitted; using (TransactionScope tx = new TransactionScope(TransactionScopeOption.RequiresNew, op)) /* ...do your work here... */ tx.Complete(); 【参考方案2】:

SQL Server 2014 中,当连接返回池时,池连接的隔离级别会重置。在早期版本中不是。

查看此论坛帖子:

"in SQL 2014, for client drivers with TDS version 7.3 or higher, SQL server will reset transaction isolation level to default (read committed) for pooled connections. for clients with TDS version lower than 7.3 they will have the old behavior when running against SQL 2014."

更新

这又变回了 SQL 2014 CU6 和 SQL 2014 SP1 CU1 中的先前行为,此修复:

FIX: The transaction isolation level is reset incorrectly when the SQL Server connection is released in SQL Server 2014

"假设您在SQL Server客户端源代码中使用TransactionScope类,并且您没有在事务中显式打开SQL Server连接。当释放SQL Server连接时,事务隔离级别被错误重置。 "

【讨论】:

这不会出现在我们的系统上 - 2014 年,.NET 4.5.1 仍然共享池。还是 TDS 与 .NET 版本不同? 同意,这在 SQL Server 2014 SP2 中似乎又被破坏了

以上是关于TransactionScope 和连接池的主要内容,如果未能解决你的问题,请参考以下文章

TransactionScope 打破 SqlConnection 池?

忽略特定查询的 TransactionScope

如何在多实例应用程序上处理 TransactionScope?

TransactionScope:具有不同数据库连接的嵌套事务(SQL Server 和 Postgresql)

TransactionScope 的基本原理简介

错误 - 具有多个数据库连接的 LINQ/TransactionScope