SQL /代码阻塞读取中的快照隔离

时间:2014-01-24 10:49:36

标签: c# sql-server entity-framework transactionscope isolation-level

我怀疑我并不完全理解发生了什么或者发生了什么奇怪的事情。 (我猜的第一种情况更有可能。)

大局:

  • 我正在尝试让Web服务异步执行某些操作,因为它们非常耗时,我不希望客户端等待操作完成(只是不时地查询结果以查看操作完成了。)
  • 异步代码包含在事务中 - 如果出现问题,我希望能够回滚任何更改。
  • 不幸的是,异步代码的最后一步是调用查询同一数据库的DIFFERENT服务。
  • 尽管将整个内容包装在Snapshot事务中,但最后一步失败,因为服务无法从数据库中读取。
  • 就此而言,当异步操作正在进行时,我也无法从数据库中执行简单的SELECT语句。

以下是我目前用于测试交易的代码示例(首先使用Entity Framework 5模型):

        using (var transaction = new System.Transactions.TransactionScope(System.Transactions.TransactionScopeOption.RequiresNew, new System.Transactions.TransactionOptions() { IsolationLevel = System.Transactions.IsolationLevel.Snapshot }))
        {
            var db = new DataModelContainer();
            Log test = new Log();
            test.Message = "TEST";
            test.Date = DateTime.UtcNow;
            test.Details = "asd";
            test.Type = "test";
            test.StackTrace = "asd";
            db.LogSet.Add(test);
            db.SaveChanges();
            using (var suppressed = new System.Transactions.TransactionScope(System.Transactions.TransactionScopeOption.Suppress))
            {
                var newDb = new DataModelContainer();
                var log = newDb.LogSet.ToArray();  //deadlock here... WHY?
            }
            test = db.LogSet.Where(l => l.Message == "TEST").Single();
            db.LogSet.Remove(test);
            db.SaveChanges();
            transaction.Complete();
        }

代码在数据库中创建一个简单的日志条目(是的,我现在正在玩这个值,所以值是垃圾)。我已经设置了SQL数据库以允许快照隔离,据我所知,仍然应该允许读取(这些正在使用新的,被抑制的事务和新的DataModelContainer在此代码中进行测试)。但是,我无法在被抑制的事务或SQL Management Studio中查询LogSet - 整个表都被锁定了!

那么......为什么?如果事务范围被定义为什么它被锁定?我也尝试过其他隔离级别(比如ReadUncommited),我仍然无法查询表格。

有人可以就此行为提供解释吗?

1 个答案:

答案 0 :(得分:1)

在SSMS中,将当前的隔离级别设置为SNAPSHOT并查看是否可以纠正您的问题 - 它可能设置为READ COMMITTED,因此会因挂起的更新而阻止。

更新

您可以通过更改以下选项(并避免不断将当前隔离级别设置为READ COMMITTED)来允许SNAPSHOT访问数据库范围内的版本行:

ALTER DATABASE MyDatabase
SET READ_COMMITTED_SNAPSHOT ON