【问题标题】:Deadlock in transaction of Entity FrameworkEntity Framework 事务死锁
【发布时间】:2016-04-15 07:51:21
【问题描述】:

我有一个使用实体框架的小程序。我以下列方式使用它们。

  1. 在数据库中创建过程。
  2. 在实体框架中进行交易。
  3. 调用该事务中的过程。

这再简单不过了。但是,我怀疑是否可能出现死锁?我的代码如下。

void AddA()
{
    using (var db = new Entities())
    {
        using (var tran = db.Database.BeginTransaction())
        {
            db.Add_A("helloA");
            Thread.Sleep(5000);
            db.Add_B("helloB");
            tran.Commit();
        }
    } 
}

void AddB()
{
    using (var db = new Entities())
    {
        using (var tran = db.Database.BeginTransaction())
        {
            db.Add_B("helloB");
            Thread.Sleep(5000);
            db.Add_A("helloA");
            tran.Commit();
        }
    } 
}

Add_AAdd_B 是这里的过程。

在我看来,这两个方法同时调用会导致死锁,因为它们占用表的顺序不同。

但是,当我做一些测试时,死锁并没有发生。这里有什么问题?是我做错了什么还是没有死锁的风险?

欢迎任何反馈。提前致谢。

PS:我使用的是 SQL Server 2014 和 Entity Framework 6.0。

【问题讨论】:

  • 怎么称呼AddA和AddB?因为如果它只是顺序的,你永远不会冲突
  • 你为什么要使用事务? SaveChanges 已经使用了一个事务。如果您在每个Add 方法中保存,那么您做错了。您应该将所需的所有实体添加到上下文中,然后调用 SaveChanges 一次
  • @AllanS.Hansen 嗯,我同时调用了 AddA 和 AddB,据我所知,可能有问题,因为 AddA 先占表 A,而 AddB 先占表 B,他们很想占另一张桌子已经被对方占用了。
  • @AllanS.Hansen 嗯,我同时调用了 AddA 和 AddB,据我所知,可能有问题,因为 AddA 先占表 A,而 AddB 先占表 B,他们很想占另一张桌子已经被对方占用了。
  • @PanagiotisKanavos 感谢您的帮助。但是为什么我在这里使用程序是程序中有一些逻辑。所以,毕竟我想要实现的是创建一个包含多个过程并且不会发生任何死锁的事务。我对数据库的东西有点傻,所以我知道这不是一个好方法。你有更好的方法吗?

标签: sql-server entity-framework deadlock sql-server-2014


【解决方案1】:

从问题中不清楚程序在做什么。只有当 Add_A 和 Add_B 都包含放置一个如果多次调用时不兼容的锁的语句时,才会发生死锁。

例如,如果 Add_A 和 Add_B 都简单地运行一条 select 语句(在默认隔离级别下读取已提交),那么不会发生死锁,因为 select 语句只放置了一个与其他线程放置的另一个共享锁兼容的共享锁。如果 Add_A 和 Add_B 包含 update 语句,则会发生死锁(当您同时或不同时间运行但小于延迟时),因为 update 语句会将排他锁放在与另一个排他锁不兼容的对象上。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-28
    相关资源
    最近更新 更多