曾尝试研究现有问题,但未找到明确答案的帖子。
我们要实现的是原子地更新一个postgres表中两行的值。我们想实现类似于打击的逻辑。我们可以在一个事务中捕获整个逻辑,并将事务级别设置为可序列化以保证原子性。我的理解是,这将使数据库锁定整个表,并减少并发性和吞吐量。在保证原子性的同时提高并发性的最佳实践是什么?
create table accounts (
id int,
remain double
}
remain = account1.remain
if val <= remain:
account1.remain = account1.remain - val
account2.remain = account2.remain + val
答案 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(必须对其进行锁定才能进行更新),而表中的其余行仍处于未锁定状态,因此并发性最高。