已提交读隔离级别是否会导致死锁(Sql Server)?

问题描述 投票:0回答:2

我对死锁的理解是——两个进程试图争夺同一资源——通常是两个进程试图“写入”同一行数据。如果一个进程所做的只是读取数据,而另一个进程正在更新数据,那么这怎么会是资源争用呢?然而,在我们设置为默认事务级别“ReadCommited”的数据库中,我们看到了几个死锁异常。 ReadCommited 定义 - 无法读取已修改(但尚未提交)的数据。这很好,但是如果 SQL Server 遇到这种“脏读”发生,它是否应该抛出死锁异常? 有人对这种情况有实际经验吗?我发现了一篇博客文章(由 stackoverflow 开发人员撰写,同样如此:)声称这可能是真的。

sql sql-server deadlock
2个回答
11
投票

ReadCommited 事务隔离级别最初在资源上获得

Shared Lock
,即在读取行时,但是当我们尝试更新该行时,它在资源上获得
Exclusive lock
。多个用户可以在同一行上拥有共享锁,这不会产生影响,但是一旦一个用户尝试更新一行,它就会在该行上获得独占锁,当用户最初可以看到该记录时,这可能会导致 A
dead lock
,因为该行上的共享锁的数量,但现在当用户尝试更新它时,第一个用户已经拥有了独占锁。想象这样一个场景,用户 1 和用户 2 都有共享锁,当他们尝试更新某些记录时,他们都会在其他用户提交事务所需的行上获得独占锁。这将导致死锁。
如果发生死锁,如果
Priority Level is not set
SQL Server 会等待一段时间,然后它会
RollBack
需要回滚的事务
cheaper

编辑
是的,如果用户 1 仅读取数据并且用户 2 尝试更新某些数据并且该表上有非聚集索引,则这是可能的。

  1. User1 正在读取一些数据并获取非聚集索引上的共享锁以执行查找,然后尝试获取包含数据的页面上的共享锁以返回数据本身。

  2. 正在写入/更新的用户2首先在包含数据的数据库页上获取排它锁,然后尝试获取索引上的排它锁以更新索引。


5
投票

是的,这有可能发生。想象一下您有两个进程,每个进程都有自己的事务。首先更新表 A,然后尝试更新表 B。第二个更新表 B,然后尝试更新表 A。如果你不幸运,两个进程都会设法完成第一步,然后无限期地等待另一个进程才能完成第二步。

顺便说一句,这是避免死锁的最常见方法之一:更新表的顺序保持一致。如果两个进程先更新 TableA 然后更新 TableB,就不会发生死锁。

© www.soinside.com 2019 - 2024. All rights reserved.