PostgreSQL - 如何在函数中创建关键部分

时间:2016-09-04 09:37:20

标签: database postgresql concurrency locking

我需要为一个用户锁定行,以防止其他任何内容更改内容。

User A: call function lock_row() to lock row X
User B: call function lock_row() to lock row X (lock cant be created and "exception" should be triggered as row X is already locked)

当用户A和B使用相同的会话连接时,情况不可能。

那么如何确保这样的事情不会发生:

User A: check if lock == 0
User B: check if lock == 0
User A: lock == 0 so SET lock = 1
User B: lock == 0 is also here so SET lock = 1

我想通过触发器(行上的UPDATE)而不是直接在SQL语句上创建锁,而是通过函数来​​允许用户在意外错误的情况下释放锁。

如何创建"关键部分"?如何确保我的函数中的关键部分能够正确执行?

PostgreSQL版本9.x。

1 个答案:

答案 0 :(得分:0)

您需要的只是同一交易中 独家row lock
如果无法获取锁定(由另一个交易锁定),请添加 NOWAIT 以使交易立即失败。

BEGIN;

SELECT 1
FROM   tbl
WHERE  tbl_id = x
FOR    UPDATE NOWAIT;

- do something

COMMIT; -- lock released automatically

根据您打算做的事情,限制较少的FOR NO KEY UPDATE可能已经足够了。

相关:

或者,您可以将SELECT或完整事务包装到函数中。同样的效果。异常总是会跳过整个事务(除非您捕获错误)。

咨询锁是另一种选择,但不太可靠。当您可以通过行级锁实现相同的功能时,无需回退到这个通用工具。