【问题标题】:Implement SQL Server 2016 Snapshot Isolation in C#/ADO.NET for SELECT queries在 C#/ADO.NET 中为 SELECT 查询实现 SQL Server 2016 快照隔离
【发布时间】:2020-03-23 05:43:08
【问题描述】:

为了防止长读取操作阻塞我现有的由 SQL Server 2016 支持的混合 OLTP/报告 Web 应用程序中的短而频繁的写入操作,我想对一些长时间运行的查询使用快照隔离。查询已经被很好地索引了,由于数据量很大,运行时间很长,虽然我以后可能会使用 RCSI,但我想先使用侵入性较小的 Snapshot Isolation。

我的问题是:如何在 C# 中对我的 SELECT 查询启用快照隔离?看来我必须将我的选择查询包装在一个事务中,这感觉完全不对。

            List<Cat> cats = new List<Cat>();
            TransactionOptions transactionOption = new TransactionOptions
            {
                IsolationLevel = IsolationLevel.Snapshot
            };
            using (TransactionScope transactionScope = new TransactionScope(TransactionScopeOption.Required, transactionOption))
            {
                using (SqlConnection sqlConnection = new SqlConnection(databaseConnectionString))
                {
                    using (SqlCommand sqlCommand = sqlConnection.CreateCommand())
                    {
                        sqlCommand.CommandText = "proc_Select_A_Billion_Cats";
                        sqlCommand.CommandType = CommandType.StoredProcedure;

                        sqlConnection.Open();

                        using (SqlDataReader sqlDataReader = sqlCommand.ExecuteReader())
                        {
                            while (sqlDataReader.Read())
                            {
                                // SOME CODE HERE can read the Cat object in from data reader

                                // Add this cat to the collection
                                cats.Add(cat);
                            }
                        }
                    }
                }
            }

http://www.levibotelho.com/development/plugging-isolation-leaks-in-sql-server/ 可以看出,在SQL Server 2014 及以后的版本中,当连接返回池时,隔离级别将被重置,这很好。

但是在 ADO.NET 事务中包装只执行 SELECT 的存储过程是否正确?在 C# 中实现快照隔离没有比这更好的方法吗?

【问题讨论】:

  • 您可以通过在 sql 语句中使用 with (nolock) 提示来实现相同的行为。

标签: c# sql-server ado.net transactionscope isolation-level


【解决方案1】:

不,你需要在BeginTransaction方法中set the isolation level

如果数据库已启用快照隔离但未启用 配置为 READ_COMMITTED_SNAPSHOT ON,您必须启动一个 SqlTransaction 使用 IsolationLevel.Snapshot 枚举值 调用 BeginTransaction 方法时。

否则,使用默认的Read Committed 模式,READ 将被修改表的事务阻塞(可能)。

【讨论】:

  • 我想 100% 确定我理解您的回答。这意味着我调用的每个读取数据的存储过程都将包装在显式 ADO.NET 事务中,就像上面的代码示例一样?
  • @J.T.Taylor 大声笑,不 :-) 这仅用于临时查询 - 您可以使用 SET TRANSACTION ISOLATION LEVEL 在存储过程中设置隔离级别。
猜你喜欢
  • 1970-01-01
  • 2010-11-10
  • 2014-02-20
  • 1970-01-01
  • 1970-01-01
  • 2014-09-27
  • 2020-03-13
  • 2012-12-05
  • 1970-01-01
相关资源
最近更新 更多