【问题标题】:What is a deadlock in a database?什么是数据库中的死锁?
【发布时间】:2010-05-05 16:12:16
【问题描述】:

什么是 SQL Server 中的死锁以及何时出现?

死锁有哪些问题以及如何解决?

【问题讨论】:

    标签: database sql-server-2005 deadlock database-deadlocks


    【解决方案1】:

    一般来说,死锁意味着两个或多个实体正在阻塞某些源,并且它们都无法完成,因为它们以循环方式阻塞源。

    一个例子:假设我有表 A 和表 B,我需要在 A 和 B 中进行一些更新,然后我决定在使用时锁定它们(这确实是愚蠢的行为,但它可以现在是目的)。同时,其他人以相反的顺序做同样的事情——先锁定 B,然后锁定 A。

    按时间顺序,会发生这种情况:

    proc1: 锁定​​ A

    proc2: 锁 B

    proc1: Lock B - 开始等待直到 proc2 释放 B

    proc2: Lock A - 开始等待直到 proc1 释放 A

    他们都不会完成。那是一个僵局。在实践中,这通常会导致超时错误,因为不希望任何查询永远挂起,并且底层系统(例如数据库)将终止未及时完成的​​查询。

    现实世界中的一个死锁示例是,当您将房钥匙锁在车内,车钥匙锁在房内时。

    【讨论】:

    • @Pz,我怀疑NOLOCK提示写入数据磁盘?我的意思是它会提交交易还是强制放弃交易以允许访问 anathor?
    • Nolock 正是这样做的——它确保查询不会生成锁。观点。它不会影响除此之外的任何事情。
    • 这很有趣,因为我用谷歌搜索了这个,这是第一个结果:)
    • 一个真实的死锁例子是当你把你的房钥匙锁在你的车里,你的车钥匙锁在你的房子里。这个例子令人困惑,暗示只有一个参与者参与了僵局,而实际上至少有两个参与者。
    【解决方案2】:

    什么是死锁

    当两个并发事务无法进行时,就会发生死锁,因为每个事务都在等待另一个释放锁,如下图所示。

    因为两个事务都处于锁获取阶段,所以没有一个事务在获取下一个之前释放锁。

    从死锁情况中恢复

    如果您使用依赖于锁的并发控制算法,那么总是存在在死锁情况下运行的风险。死锁可能发生在任何并发环境中,而不仅仅是在数据库系统中。

    例如,如果两个或多个线程正在等待先前获得的锁,则多线程程序可能会死锁,因此没有线程可以取得任何进展。如果这发生在 Java 应用程序中,JVM 不能仅仅强制线程停止执行并释放其锁。

    即使Thread 类公开了stop 方法,该方法自Java 1.1 以来已被弃用,因为它可能导致对象在线程停止后处于不一致状态。相反,Java 定义了一个interrupt 方法,它作为一个提示,因为被中断的线程可以简单地忽略中断并继续执行。

    因此,Java 应用程序无法从死锁情况中恢复,应用程序开发人员有责任以不会发生死锁的方式对锁获取请求进行排序。

    但是,数据库系统无法强制执行给定的锁获取顺序,因为无法预见某个事务将进一步获取哪些其他锁。保持锁定顺序成为数据访问层的职责,数据库只能协助从死锁情况中恢复。

    数据库引擎运行一个单独的进程,该进程扫描当前冲突图的锁定等待周期(由死锁引起)。 当检测到一个循环时,数据库引擎会选择一个事务并中止它,从而释放它的锁,以便另一个事务可以进行。

    与 JVM 不同,数据库事务被设计为一个原子工作单元。因此,回滚会使数据库保持一致状态。

    死锁优先级

    虽然数据库选择回滚两个被卡住的事务之一,但并不总是可以预测哪一个会被回滚。根据经验,数据库可能会选择以较低的回滚成本回滚事务。

    甲骨文

    根据Oracle documentation,检测到死锁的事务是其语句将被回滚的事务。

    SQL 服务器

    SQL Server 允许您通过DEADLOCK_PRIORITY 会话变量控制在死锁情况下哪个事务更有可能回滚。

    DEADLOCK_PRIORITY 会话可以接受介于 -10 和 10 之间的任何整数,或预定义值,例如 LOW (-5)NORMAL (0)HIGH (5)

    如果发生死锁,当前事务将回滚,除非其他事务具有较低的死锁优先级值。如果两个事务具有相同的优先级值,则 SQL Server 以最低的回滚成本回滚事务。

    PostgreSQL

    正如documentation 中所述,PostgreSQL 不保证回滚哪个事务。

    MySQL

    MySQL 尝试roll back the transaction that modified the least number of records,因为释放更少的锁成本更低。

    【讨论】:

    • 这个答案比接受的答案更具体。我宁愿在上面看到这个。
    【解决方案3】:

    当两个人需要多个资源来执行,并且其中一些资源被每个人锁定时,就会发生死锁。这导致了一个事实,即如果没有 B 拥有的东西,A 就无法执行,反之亦然。

    假设我有 Person A 和 Person B。他们都需要运行两行(Row1 和 Row2)。

    • 人员 A 锁定 Row1 并尝试获取 Row2。
    • 人员 B 锁定 Row2 并尝试获取 Row1。

    A 无法运行,因为它需要 Row2,B 无法运行,因为它需要 Row1。任何人都无法执行,因为他们锁定了对方需要的东西,反之亦然。


    减少死锁的一种相当简单的方法是在所有复杂事务中,您应该以相同的顺序执行操作。换句话说,以相同的顺序访问 Table1 然后访问 Table2。这将有助于减少发生的死锁数量。

    【讨论】:

      【解决方案4】:

      当两个(或多个)交易同时发生时可能导致的僵局 等待释放对方持有的锁。

      【讨论】:

        【解决方案5】:

        死锁是当一个进程或线程进入等待状态,因为请求的系统资源被另一个等待进程占用

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2010-09-07
          • 1970-01-01
          • 1970-01-01
          • 2012-09-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-11-27
          相关资源
          最近更新 更多