【问题标题】:Concurrent update in PostgreSQL 11PostgreSQL 11 中的并发更新
【发布时间】:2020-11-22 23:05:13
【问题描述】:

我有大约 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,那么正确的解决方案是什么?这两个解决方案中的多事务会发生什么?

【问题讨论】:

    标签: postgresql concurrency transactions postgresql-11


    【解决方案1】:

    两个版本会产生完全相同的效果,并且都可以防止在面对并发时出现异常,因为行在被修改之前就被锁定了。

    第一种方式更可取,因为只有一次客户端-服务器往返,所以事务更短,持有锁的时间也更短,提高了并发性。

    做到这一点并避免并发数据修改的最佳方法是:

    UPDATE account
    SET balance = balance + 1000
    WHERE id = 1;
    

    这也是一样的,因为UPDATE 会自动在受影响的行上放置一个排他锁,当锁消失时,阻塞的查询会看到该行的更新版本。

    【讨论】:

    • 感谢您的回答,但我刚刚阅读了有关此案例的并发文档,所以我很困惑...link
    • 这不是 PostgreSQL 中发生的事情,请参见下一张幻灯片。 READ COMMITTED 是默认隔离级别。我会更新答案。
    • 顺便说一下,这些幻灯片已经过时了。 Tom 所说的另一个隔离级别称为REPEATABLE READ,而不是今天的SERIALIZABLE。除此之外,一本好书。
    • 是的,因为语句更简单。
    • 这同样适用,因为条件将使用更新后的值重新检查。
    猜你喜欢
    • 2020-01-11
    • 2017-03-31
    • 2013-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-02
    相关资源
    最近更新 更多