我对死锁的理解是——两个进程试图争夺相同的资源——通常是两个进程试图“写入”同一行数据。如果所有一个进程都在读取数据 - 而另一个进程正在更新数据,那么资源争用如何?然而,在我们设置为默认事务级别“ReadCommitted”的数据库中,我们看到了几个死锁异常。ReadComitted definitin - 无法读取已修改(但尚未提交)的数据。这很好——但是如果 SQL Server 遇到这种“脏读”发生,它应该抛出死锁异常吗?有人对这种情况有实际经验吗?我发现一篇博文(由 stackoverflow 开发人员撰写,不少于 :) 声称这可能是真的。
2 回答
ReadCommitted Transaction Isolation Level 最初Shared Lock
在资源上获得 a,即在读取行时,但当我们尝试更新行时,它Exclusive lock
在资源上获得 a。多个用户可以在同一行上拥有共享锁并且它不会生效,但是一旦一个用户尝试更新一行它就会在该行上获得一个排他锁,这可能导致 Adead lock
当用户最初可以看到由于共享的记录时锁定该行,但现在当用户尝试更新它时,它已经被第一个用户锁定了。想象一个场景,其中 User1 和 User2 都有共享锁,当他们尝试更新一些记录时,他们都在其他用户需要提交事务的行上获得了独占锁。这将导致死锁。
在死锁的情况下,如果Priority Level is not set
SQL Server 将等待一段时间,然后它将回滚RollBack
的事务。编辑
是,如果 User1 只读取数据并且 User2 尝试更新一些数据并且该表上有一个非聚集索引,这是可能的。cheaper
User1 正在读取 Some Data 并在非聚集索引上获取共享锁以执行查找,然后尝试在包含数据的页面上获取共享锁以返回数据本身。
正在写入/更新的用户2首先在包含数据的数据库页面上获得排他锁,然后尝试在索引上获得排他锁以更新索引。
是的,它可能发生。想象一下,您有两个进程,每个进程都有自己的事务。第一个更新 TableA,然后尝试更新 TableB。第二个更新 TableB 然后尝试更新 TableA。如果你不走运,两个进程都会设法完成它们的第一步,然后无限期地等待另一个以完成第二步。
顺便说一句,这是避免死锁的最常见方法之一:更新表的顺序保持一致。如果两个进程先更新 TableA 然后更新 TableB,就不会发生死锁。