Postgres 锁和死锁问题

问题描述 投票:0回答:1

我有一个 postgres 表:

CREATE TABLE clicks (
  page_id UUID REFERENCES pages (id) ON DELETE CASCADE,
  status                TEXT        NOT NULL,
  click                 BIGINT      NOT NULL,
  PRIMARY KEY (page_id, status)
);

和两个执行块:

代码块_1:

BEGIN;
LOCK TABLE clicks IN SHARE UPDATE EXCLUSIVE MODE;
INSERT INTO clicks (page_id, status, count)
            VALUES ($1, $2, $3 )
            ON CONFLICT (page_id, status) DO UPDATE SET count = clicks.count + EXCLUDED.count;
-- that insert query can run more than once on different rows in the table. so imagine that there is a code that generates that INSERT INTO inside a for loop inside that one transaction 
COMMIT;

代码块_2:

BEGIN;
LOCK TABLE clicks IN SHARE ROW EXCLUSIVE MODE;
INSERT INTO clicks (page_id, status, count)
VALUES ($1, $2, $3)
ON CONFLICT (page_id, status) DO UPDATE SET
count = EXCLUDED.count;
-- that insert query can run more than once on different rows in the table. so imagine that there is a code that generates that INSERT INTO inside a for loop inside that one transaction.
COMMIT;
    

由 code_block_1 更新的行可能由多个线程并行更新。 但是由 code_block_2 更新的行可以保证它们不会被另一个线程并行更新。 有了这些信息,如果我不想陷入死锁,我可以放弃哪个锁(如果有)?

postgresql database-deadlocks
1个回答
0
投票

您不需要任何一把锁。 两个插入都是原子的

ON CONFLICT DO UPDATE 保证原子 INSERT 或 UPDATE 结果;只要不存在独立错误,即使在高并发情况下,也可以保证这两种结果之一。这也称为 UPSERT —“更新或插入”。

© www.soinside.com 2019 - 2024. All rights reserved.