使用postgres事务以最大的并发性自动比较和更新多行

时间:2018-07-22 06:53:25

标签: sql postgresql transactions

曾尝试研究现有问题,但未找到明确答案的帖子。

我们要实现的是原子地更新一个postgres表中两行的值。我们想实现类似于打击的逻辑。我们可以在一个事务中捕获整个逻辑,并将事务级别设置为可序列化以保证原子性。我的理解是,这将使数据库锁定整个表,并减少并发性和吞吐量。在保证原子性的同时提高并发性的最佳实践是什么?

 create table accounts (
     id  int,
     remain double
}

remain = account1.remain
if val <= remain:   
    account1.remain = account1.remain - val
    account2.remain = account2.remain + val

1 个答案:

答案 0 :(得分:1)

最简单的方法是使用单个UPDATE语句,因为每个单独的SQL语句始终是原子的。

一个例子-假设:

account1_id = 222
account2_id = 333
val = 567

然后更新可能看起来像这样:

UPDATE accounts
SET remain = remain + 567 * CASE id
         WHEN 222 THEN -1
         WHEN 333 THEN 1
    END
WHERE id IN ( 222,333 )
  AND 567 >= (
     SELECT remain FROM accounts
     WHERE id = 222
);
COMMIT;

此语句将仅锁定两行222和333(必须对其进行锁定才能进行更新),而表中的其余行仍处于未锁定状态,因此并发性最高。