医生说(重点是我):
FOR UPDATE,FOR NO KEY UPDATE,FOR SHARE和FOR KEY SHARE是锁定子句;它们会影响SELECT如何锁定从表中获取的行。
如果无法立即锁定所选行,则使用NOWAIT,该语句报告错误,而不是等待。
因此,我不确定是否可能发生以下行为。
想象一下,从并发连接S1和S2运行同一条SELECT ... NOWAIT
语句,该语句返回R1和R2行。
问题是步骤4是否实际上可以发生在步骤3和5之间,还是相对于并发选择自动执行步骤3和5。
我猜测它不会发生,因为如果没有NOWAIT
(或SKIP LOCKED
),此行为将导致死锁(S1等待S2完成并释放R2,而S2等待S1完成并发布R1),但也许可以通过其他方式解决这种情况。
那么,这里有哪些保证?
答案 0 :(得分:3)
在您的方案中,如果第3步试图使用NOWAIT
选项获得R2,则该步骤应该失败。如果失败,则立即释放S1的所有锁,并且必须回滚S1。因此,S2可以在步骤4中获得R1。这种情况不会死锁。
如果您尝试在步骤3 中没有 NOWAIT
选项中获得R2,则步骤4将由于检测到死锁而失败,并且S2将立即释放其所有锁。
保证是关系数据库中锁的定义行为,如documentation中所述:
要防止操作等待其他事务提交,请使用NOWAIT选项。使用NOWAIT时,如果无法立即锁定选定的行,该语句将报告错误,而不是等待。
报告错误表示事务已中断,必须回滚。事务是原子的。简而言之,这意味着只有成功完成了它包含的所有步骤后,才能终止提交。