我有一个表和几个线程(系统),它们从表中读取特定列并更新它。所以我的查询如下:
Begin;
SELECT col FROM tbl WHERE <condition1>
UPDATE tbl SET col = col + 1 WHERE <condition1>
Commit;
我想确保在任何时候都只有一个线程可以选择和更新该列。什么是最佳解决方案?
PS:据我所知,在 SQL Server 中使用事务会锁定事务中的所有资源,但我对 PostgreSQL 一无所知。
谢谢!
最佳答案
SQL 中最高级的锁是行锁。
无法锁定列,数据库总是在整行(该行的所有列)上加锁。
您可以使用 a SELECT .. FOR UPDATE
clause :
Begin;
SELECT col FROM tbl WHERE <condition1> FOR UPDATE;
UPDATE tbl SET col = col + 1 WHERE <condition1> ;
Commit;
SELECT .. FOR UPDATE
的工作方式类似于普通的 select(它从表中检索行),但除此之外,它还会对所有检索到的行进行锁定,以防止它们被其他事务修改,直到当前交易结束。
您还可以使用 RETURNING
clause in UPDATE
statement :
Begin;
UPDATE tbl SET col = col + 1 WHERE <condition1>
RETURNING col - 1 AS col;
Commit;
UPDATE
语句总是在修改后的记录上放置写锁。
RETURNING
子句导致返回值,就像普通的 SELECT
一样,但是它返回修改后的行值(更新后的行值),因此 col - 1
表达式在上面的示例中使用,用于在列值递增之前计算列值。
请看一下这个演示 --> http://www.sqlfiddle.com/#!15/4d0f4/3
第二种方法(UPDATE+RETURNING 子句)的优点是记录只被访问一次,与第一种方法相比,当行必须首先被 SELECT
语句选择时(第一次访问),然后使用 UPDATE
语句(第二次访问)对其进行更新。
关于postgresql - 在 Postgresql 中锁定事务(一系列选择和更新),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21097246/