【问题标题】:Can a readcommitted isolation level ever result in a deadlock (Sql Server)?readcommitted 隔离级别会导致死锁(Sql Server)吗?
【发布时间】:2013-10-25 16:34:25
【问题描述】:

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

【问题讨论】:

    标签: sql sql-server deadlock


    【解决方案1】:

    ReadCommitted 事务隔离级别最初在资源上获得Shared Lock,即在读取行时,但当我们尝试更新行时,它在资源上获得Exclusive lock。多个用户可以在同一行上共享锁并且它不会生效,但是一旦一个用户尝试更新一行它会在该行上获得一个排他锁,这可能导致 A dead lock 当用户最初可以看到记录时,因为行上的共享锁,但现在当用户尝试更新它时,它已经拥有第一个用户的排他锁。想象一个场景,其中 User1 和 User2 都有共享锁,当他们尝试更新一些记录时,他们都在其他用户需要提交事务的行上获得排他锁。这将导致死锁。
    在死锁的情况下,如果Priority Level is not set SQL Server 将等待某个时间,然后它将RollBackcheaper 的事务回滚。
    编辑
    是的,如果 User1 只读取数据并且 User2 尝试更新一些数据并且该表上有一个非聚集索引,这是可能的。

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

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

    【讨论】:

    • 您也在谈论 user1 和 user2 都试图更新相同的记录。这种情况下的死锁是可以接受的。但是,我想知道是否有人看到两个事务的死锁结果 - 其中一个是 WRITE,另一个是读取(当然是在相同的数据上)。
    • 看看我已经更新了答案并解释了。
    【解决方案2】:

    是的,它可能会发生。想象一下,您有两个进程,每个进程都有自己的事务。第一个更新 TableA,然后尝试更新 TableB。第二个更新 TableB 然后尝试更新 TableA。如果你不走运,两个进程都会设法完成它们的第一步,然后无限期地等待另一个进程来完成第二步。

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

    【讨论】:

    • 嗯 - 您正在描述两个更新事务。在这种情况下,陷入僵局是有意义的。我的问题是 - 其中一项交易只是 READ - 没有更新。另一个正在写入正在读取的同一条记录。这怎么可能导致死锁?
    • 在我的脑海中,这不应该陷​​入僵局,但如果您编辑问题并提供有关交易尝试执行的更多详细信息,我们也许能够深入了解它。
    猜你喜欢
    • 1970-01-01
    • 2016-03-27
    • 2018-06-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-16
    相关资源
    最近更新 更多