我有大约10个查询同时更新一行,所以我想知道之间的区别
UPDATE account SET balance = balance + 1000
WHERE id = (SELECT id FROM account
where id = 1 FOR UPDATE);
和
BEGIN;
SELECT balance FROM account WHERE id = 1 FOR UPDATE;
-- compute $newval = $balance + 1000
UPDATE account SET balance = $newval WHERE id = 1;
COMMIT;
我使用的是PosgreSQL 11,那么什么是正确的解决方案?在这两个解决方案中,多事务会发生什么?
这两个版本将具有完全相同的效果,并且都可以防止在并发时出现异常,因为行在修改之前已经锁定。
第一种方法更可取,因为只有一个客户端-服务器往返,所以事务更短,锁的持有时间更短,这提高了并发性。
做到这一点并避免并发数据修改的最佳方法是:
UPDATE account
SET balance = balance + 1000
WHERE id = 1;
这样做也是一样的,因为UPDATE
会自动对受影响的行设置排他锁,并且当锁消失时,被阻止的查询将看到该行的更新版本。