事务范围和连接池技术

10

我正在调查我们的应用程序是否存在使用不正确的隔离级别进行数据库连接的问题。我们的应用程序是一个使用SQL Server 2005的.Net 3.5数据库应用程序。

我发现当连接返回到连接池时,连接的隔离级别没有被重置(请参见这里),我也很惊讶地在这篇博客文章中读到,每个新创建的TransactionScope都会分配自己的连接池。

我们的数据库更新(通过业务对象)在TransactionScope内完成(为每个业务对象图更新创建一个新的TransactionScope)。但是我们的获取操作不使用明确的事务。因此,我想知道我们是否可能遇到这样一种情况,即我们的获取操作(应该使用默认的隔离级别 - Read Committed)将重用从池中用于更新的连接,并继承更新隔离级别(RepeatableRead)?或者我们的更新是否保证使用不同的连接池,因为它们被包装在TransactionScope中?

谢谢您提前的帮助,

Graham

2个回答

8

这很令人担忧!

你链接的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文章中包含的信息是不正确的。 - Graham
“强制”问题的部分只是TransactionOptionsTransactionScope的创建,对吗?例如(通过链接更易读:http://pastie.org/10314190):`TransactionOptions op = new TransactionOptions(); op.IsolationLevel = IsolationLevel.ReadCommitted; using (TransactionScope tx = new TransactionScope(TransactionScopeOption.RequiresNew, op)) { /* ...在此处完成您的工作... */ tx.Complete(); }` - T.J. Crowder

4
在SQL Server 2014中,当连接返回到池中时,池化连接的隔离级别会被重置。而在早期版本中则不会发生此情况。
请参阅此论坛帖子:
“在SQL 2014中,对于使用TDS版本7.3或更高版本的客户端驱动程序,SQL服务器将重置池化连接的事务隔离级别为默认值(读取提交)。对于使用低于7.3版本的客户端,则在运行SQL 2014时仍将保留旧行为。”
更新:
在SQL 2014 CU6和SQL 2014 SP1 CU1中,此问题已通过以下修复恢复到以前的行为。

FIX: 当SQL Server连接在SQL Server 2014中被释放时,事务隔离级别会被错误重置

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


这在我们的系统上看不到 - 2014年与.NET 4.5.1仍共享池。或者TDS与.NET版本不同吗? - user2864740
同意,这在 SQL Server 2014 SP2 中似乎又出问题了。 - Thomas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接