如果您坚持锁定特定的行,这 不是 一个好主意,那 不是FOR UPDATE NOWAIT
您所需要的。您只需要 任何 符合条件的可用(解锁)行。重要的区别是此(引用Postgres
9.4手册):
使用
NOWAIT,如果无法立即锁定选定的行,该语句将报告错误,而不是等待。
相同的查询很可能会尝试锁定相同的任意选择。
FOR UPDATE NOWAIT只会因出现异常而纾困(除非捕获错误,否则它将回滚整个事务),您必须重试。
我在dba.SE上引用的答案中的解决方案结合使用了plain FOR UPDATE
和以下内容pg_try_advisory_lock()
:
pg_try_advisory_lock与相似pg_advisory_lock,不同之处在于该功能将不等待锁变为可用。它将立即获取锁并返回true,或者如果无法立即获取锁,则返回false。
因此, 最好的选择 是……第三种选择: FOR UPDATE SKIP LOCKED
Postgres
9.5中的新功能,它实现了相同的行为,而没有额外的函数调用。
Postgres 9.5的手册比较了这两个选项,并进一步说明了不同之处:
为防止操作等待其他事务提交,请使用
NOWAIT或SKIPLOCKED选项。使用NOWAIT,如果无法立即锁定选定的行,该语句将报告错误,而不是等待。使用SKIPLOCKED,将跳过所有不能立即锁定的选定行。
在Postgres 9.4或更早的版本上,您的 下一个最佳选择 是
pg_try_advisory_xact_lock(id)与
FORUPDATE参考答案中所示的类似物组合使用:
- Postgres UPDATE-LIMIT 1
(还带有的实现
FOR UPDATE SKIP LOCKED。)
在旁边
严格来说,您会得到任意选择,而不是真正的随机选择。



