postgresql - 如何手动锁定和解锁一行?

标签 postgresql concurrency transactions sql-update

我试图通过锁定和解锁某些行来避免重复写入。

我有一个表personnel,只要用户尝试编辑一行,我就想锁定该行。

所以

BEGIN;
// I guess I have to lock it somehow here
SELECT * FROM personnel WHERE id = 12;
COMMIT;

一旦完成编辑,我想以相同的样式提交 UPDATE:

BEGIN;
//Unlocking
UPDATE personnel SET ...
WHERE id = 12;
COMMIT;

在此期间,当另一个用户试图编辑同一行时,他会收到一条消息。

最佳答案

锁在事务结束时释放。因此,您需要保持事务打开以维持锁定并在单个事务中完成所有操作:

BEGIN;
SELECT * FROM personnel WHERE id = 12 <b>FOR UPDATE NOWAIT</b>;  -- row level locking
<strike>COMMIT;</strike>

<strike>BEGIN;</strike>
UPDATE personnel SET ...
WHERE id = 12;
COMMIT;

或者,您可以使用限制较少的 FOR SHARE 子句。
Details in the manual on SELECT in the chapter "The Locking Clause".

允许并发读取。引用章节"Row-level Locks" in the manual :

In addition to table-level locks, there are row-level locks, which can be exclusive or shared locks. An exclusive row-level lock on a specific row is automatically acquired when the row is updated or deleted. The lock is held until the transaction commits or rolls back, just like table-level locks. Row-level locks do not affect data querying; they block only writers to the same row.

要让并发尝试立即失败,请使用 NOWAIT 选项 - 对于所有竞争查询。

关于postgresql - 如何手动锁定和解锁一行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23702284/

相关文章:

java - 如何使用 JProgressBar

c# - 托管和非托管代码在一个事务中更新数据库?

sql - 不运行查询的 PostgreSQL 语法检查

arrays - 将数组从node-postgres传递到plpgsql函数

c# - 在 Azure Function 中按顺序处理服务总线消息(无并发调用)

java - 停止 ExecutorService 中的可调用任务

php - 死锁和超时破坏 ACID 事务

mysql - iBatis selectKey 和事务

ruby-on-rails - 如何通过 ransack gem 搜索数组?

sql - 在 PostgreSQL 中转换时间戳