【问题标题】:SQL Server deadlock LINQ to SQLSQL Server 死锁 LINQ to SQL
【发布时间】:2014-07-09 09:34:54
【问题描述】:

我正在尝试为此找到明确的答案。如果在可序列化事务中使用 SQL Server 上的 Linq 选择然后更新,是否存在死锁风险?例如:

using (var trans = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions { IsolationLevel = IsolationLevel.Serializable, Timeout = new TimeSpan(0, 0, 10) }))
{
    using (var con = new MyContext())
    {
        var record = con.MyTable.Single(t => t.id == 1);    // share lock?

        record.field = 99;
        con.SubmitChanges();                                // upgraded to exclusive lock? possible deadlock

        trans.Complete();
    }
}

而且由于这是一种常见的模式,因此避免它的唯一方法是:

var record = con.ExecuteQuery<MyTable>("select * from MyTable with (updlock) where id = {0}", 1).Single();

【问题讨论】:

    标签: sql-server linq deadlock


    【解决方案1】:

    是的,这是典型的僵局。两个事务都读取,然后都尝试更新。两者都必须等待对方释放共享锁。

    对于乐观并发模型,这会导致写入冲突。

    UPDLOCK, HOLDLOCK, ROWLOCK 提示组合是我通常在这些情况下使用的组合。请注意,为方便起见,您可以使用ExecuteQuery 执行此锁定查询,丢弃结果,然后正常使用 LINQ。您无需将所有内容都转换为 SQL。

    L2S 和 EF 不允许您设置表格提示。这是不幸的。您必须在某种程度上求助于 SQL。手动或使用函数或包装器视图。

    【讨论】:

    • 感谢您的信息。单独使用 UPDLOCK 还不够吗?
    • 另外,有没有人写过一个扩展方法来修改表达式树来很好地做到这一点?例如允许con.MyTable.WithUpdateLock().Single(...);
    • L2S 和 EF 不允许您设置表格提示。无法将此信息应用于表达式树。 UPDLOCK 就足够了,因为您在相当于 HOLDLOCK 的 SERIALIZABLE 下运行。我仍然强制 HOLDLOCK 以便查询相对于其周围的隔离级别更稳定
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-11
    • 1970-01-01
    • 2023-03-12
    相关资源
    最近更新 更多