9

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

我发现连接的 IsolationLevel 在返回到连接池时不会重置(请参见此处),并且在此博客文章中读到每个新创建的 TransactionScope 都分配给它自己的连接池,这让我感到非常惊讶。

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

提前致谢,

格雷厄姆

4

2 回答 2

7

这令人担忧!

您链接到的 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"到您的连接字符串。

于 2010-03-15T09:02:53.773 回答
3

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

请参阅此论坛帖子:

“在 SQL 2014 中,对于 TDS 版本 7.3 或更高版本的客户端驱动程序,SQL Server 会将池连接的事务隔离级别重置为默认(读取已提交)。对于 TDS 版本低于 7.3 的客户端,它们在针对 SQL 运行时将具有旧行为2014 年。”

更新

通过此修复,这再次变回 SQL 2014 CU6 和 SQL 2014 SP1 CU1 中的先前行为:

FIX:在 SQL Server 2014 中释放 SQL Server 连接时,事务隔离级别重置不正确

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

于 2014-09-04T13:45:38.937 回答