【问题标题】:DeadLock DbContext Concurrent Transactions死锁 DbContext 并发事务
【发布时间】:2012-06-05 11:44:24
【问题描述】:

嗨,请看上图中的死锁图部分。我有两个事务更新同一个表,其中一个是长事务,更新该表(同一行)5 次,但另一个事务只更新该表一次,并且是两个 DB 命中的小事务。从死锁图中,这两个事务在不同行上都有 X 锁并试图获得 U 锁,这在逻辑上是正确的。我不明白为什么较短的事务虽然还没有触发更新查询但会获得 X 锁(因为它是导致死锁的更新查询,这意味着它还没有被触发)。任何帮助都会非常明显。 1)我正在使用隔离级别读取提交 2)我无法理解第二个/第一个事务如何获得 X 锁,而另一个事务已经在某个行上获得它。我在更新查询中读到第一个 U 锁被应用,然后升级到该特定更新行的 X 锁。现在,当一个事务具有 X 锁时,另一个事务如何在表扫描期间具有 U 锁(以确定要更新的行)它无法读取其他事务具有 X 锁的行。3)两个事务都更新一个不同的同一表的行。在不更改隔离级别的情况下,可以在数据库级别进行任何可能的解决方案。

【问题讨论】:

  • 这里的经典答案是:按顺序取锁;这可能涉及发出选择,可能使用 UPDLOCK。不过不确定是否可以使用 EF。
  • 使用 SQL 分析器查看事务期间执行了哪些命令。
  • 是的,我正在使用 EF,除非我们通过 ExecuteStoreCommand @Marc 发送查询,否则无法使用锁定提示。
  • 它唯一的更新命令@Ladislav。如果另一个事务在同一张表上获得了 X 锁,那么一个事务是否可以放置 U 锁?
  • 更新命令导致 X 锁,并且在持有 X 锁的事务完成之前,没有其他事务(具有您的隔离级别)可以使用该记录。

标签: c# sql-server-2008 entity-framework-4.1


【解决方案1】:

我无法理解第二个/第一个事务如何获得 X 锁 而另一笔交易已经在某行获得了它。

这就是数据库及其性能背后的魔力。锁可以在不同的级别上发布,如果第二个事务不使用表扫描,它可以发布 X 锁而不会与第一个事务冲突。可能没有发生使用索引和表扫描搜索的更新记录,因此您的表中可能存在多个并发 X 锁。

我在更新查询中读到,首先应用 U 锁,然后是 为该特定更新行升级到 X 锁。

没有。更新应该直接在记录上使用 X 锁。读取要更新的数据的读取查询必须强制 U 锁定(这就是 @Marc 在他的评论中提到的)。如您所知,EF 不支持这一点,因为它不能使用提示。

【讨论】:

  • 非常感谢这些非常有用的建议。是的,我没有使用任何 UPDLOCK 提示。当我通过使用 Select * from sys.dm_tran_Locks 查看锁列表时,应用的锁仅在键级别为 X,在页面级别为 IX,但为什么在死锁图中它显示两个事务都在等待放U型锁。
  • 这是你必须在执行的命令中找到的东西。死锁图也应该显示。
  • 在 IX 锁应用于更新表 X 后 KeyLocks 应用于 sys.sysconvgroup、sys.sysdesend
猜你喜欢
  • 2020-07-08
  • 1970-01-01
  • 1970-01-01
  • 2018-08-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-26
  • 1970-01-01
相关资源
最近更新 更多