Postgresql 可以选择。。。NOWAIT“是的;死锁;?

Postgresql 可以选择。。。NOWAIT“是的;死锁;?,postgresql,Postgresql,医生说(我的重点): 对于更新,对于无密钥更新,对于共享和对于密钥共享是锁定子句;当从表中获取行时,它们会影响选择锁定行的方式 对于NOWAIT,如果无法立即锁定所选行,则语句将报告错误,而不是等待 因此,我不确定以下行为是否可能 想象一下同样的SELECT。。。NOWAIT语句返回行R1和R2,从并发连接S1和S2运行 S1获取并锁定R1 S2获取并锁定R2 S1试图获取R2,但被S2锁定 S2试图获取R1,但被S1锁定 由于S1故障,R1上的锁被解除 问题是步骤4是否真的可以发生在步骤3和步

医生说(我的重点):

对于更新,对于无密钥更新,对于共享和对于密钥共享是锁定子句;当从表中获取行时,它们会影响选择锁定行的方式

对于NOWAIT,如果无法立即锁定所选行,则语句将报告错误,而不是等待

因此,我不确定以下行为是否可能

想象一下同样的
SELECT。。。NOWAIT
语句返回行R1和R2,从并发连接S1和S2运行

  • S1获取并锁定R1
  • S2获取并锁定R2
  • S1试图获取R2,但被S2锁定
  • S2试图获取R1,但被S1锁定
  • 由于S1故障,R1上的锁被解除
  • 问题是步骤4是否真的可以发生在步骤3和步骤5之间,或者步骤3和步骤5是针对并发选择以原子方式执行的

    我猜这不可能发生,因为如果没有
    NOWAIT
    (或
    SKIP LOCKED
    ),这种行为将导致死锁(S1等待S2完成并释放R2,而S2等待S1完成并释放R1),但这种情况可能会以其他方式得到解决


    那么,这里有哪些保证呢?

    在您的场景中,如果第3步尝试使用
    NOWAIT
    选项获取R2,那么它应该失败。当它失败时,S1的所有锁立即释放,S1必须回滚。因此,S2可以在步骤4中获得R1。这个场景不能死锁

    如果在步骤3中尝试在没有
    NOWAIT
    选项的情况下获取R2,步骤4将因检测到死锁而失败,S2将立即释放其所有锁

    保证是关系数据库中锁的定义行为,如中所述:

    要防止操作等待其他事务提交,请使用NOWAIT选项。对于NOWAIT,如果无法立即锁定所选行,则语句将报告错误,而不是等待


    报告错误意味着事务已中断,必须回滚。事务是原子的。简单地说,这意味着只有当它包含的所有步骤都已成功完成时,才可以通过提交来终止它。

    谢谢。但我的问题是,文件中的这一措辞也与两项交易的失败相一致。它只是说当前语句失败,不,其他语句没有。除了查看代码之外,还有什么东西可以真正、明确地保证其中一条语句会成功吗?是的,这被称为ACID范例。在您的情况下:每个事务都是原子的。这意味着,它要么成功完成,要么失败。而且它是独立的–没有任何事务可以访问另一个未完成的事务的修改。抱歉,但我也不明白ACID是如何保证这一点的,它是非常通用的。这两种行为都可以被认为是ACID兼容的。注意:您不必查看代码,因为您问题的答案与您使用的DBMS无关
    NOWAIT
    表示如果存在锁,则报告错误。报告错误意味着中断事务。中断事务意味着释放它持有的所有锁。这直接源于ACID范例。两种场景都符合ACID。唯一的区别是它们导致错误并强制事务终止。而
    NOWAIT
    的行为,尤其是当它报告错误时,都有很好的记录。