“select for update” 语句何时锁定并解锁?

31

这是我的伪代码:

re = [select **result** from table where **condition**=key for update]

if[re satisfies]
{
    delete from table where **condition** = key;
}

commit

我想问一下,如果满足条件的行等于"key"已经被删除了,那么被"select for update"锁住的锁是否可以自动解锁,也就是说,如果另一个进程在此时进入并选择相同的"key",它不会被此进程阻塞吗?

1个回答

45
锁通常在命令执行期间(通常是在开始时或接近开始时)被占用。锁(除了advisory locks)只有在事务提交或回滚时才会释放。没有FOR UNLOCK,也没有UNLOCK命令来撤销表级LOCK命令的影响。这一切在PostgreSQL文档的并发控制部分中都有解释。
必须提交或回滚事务才能释放锁。
此外,询问“另一个并发事务是否已经删除了该行”并不是很有意义。直到删除该行的事务提交之前,它才真正被删除...即使在这种情况下,它可能已经被删除并重新插入或者另一个并发事务可能再次插入该行。

你是否正在构建一个任务队列或消息队列系统?如果是的话,那么这个问题已经解决了,你不应该试图重新发明这个异常复杂的轮子。可以参考 PGQ, ActiveMQ, RabbitMQ, ZeroMQ 等(未来的 PostgreSQL 版本可能包括 FOR UPDATE SKIP LOCKED,因为正在测试中,但在撰写本文时尚未发布)。

我建议您发布一个新问题,并更详细地描述您试图解决的根本问题。 您假设问题的解决方案是“找出行是否已经被删除”或“解锁该行”。 实际上,那可能不是解决方案。 这有点像有人说“我在哪里买汽油”,当他们的脚踏车不转时,他们就认为它没有燃料。 燃料不是问题,问题是脚踏车不需要燃料,你必须蹬它们。
解释一下背景。 解释您试图实现什么。 最重要的是,不要发布伪代码,而要发布您遇到问题的实际代码,最好是自包含且可运行的形式。

4
由于这是一个旧答案,当时Pg 9还很新,值得一提的是,PostgreSQL现在已经包含了“FOR UPDATE SKIP LOCKED”很长时间了,并且“SKIP LOCKED”非常适合与队列一起使用。 - BigSmoke

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接