交易僵局开始

时间:2020-03-19 15:25:58

标签: postgresql transactions deadlock

我将Postgres 12与autocommit = off一起使用,并尝试通过使用显式锁定来避免死锁。当我执行时:

ROLLBACK;
SELECT * FROM account WHERE id = 12345 FOR UPDATE;

其中idaccount的主键。有时我在第二条陈述上陷入僵局。我希望执行能够等到释放该行上的所有其他锁为止。

服务器日志通常为此显示几个(> 1)冲突的事务。但是与用户一起进行的所有交易也应如上所述锁定行。

如何发生上述死锁?如何避免这些死锁?

编辑:令人惊讶的是,服务器日志显示给我的其他进程的锁也位于完全不同的表中,例如:

HINT:  See server log for query details.
CONTEXT:  while locking tuple (2892,8) in relation "account"
LOCATION:  DeadLockReport, deadlock.c:1146
STATEMENT:  SELECT * FROM account WHERE id = 197375 FOR UPDATE
LOG:  00000: process 17583 detected deadlock while waiting for ShareLock on transaction 1091990904 after 1000.057 ms
DETAIL:  Process holding the lock: 17438. Wait queue: .
CONTEXT:  while updating tuple (4588,22) in relation "subscription"

编辑2:我在日志中发现了第二个死锁,这很有趣:

冲突的过程A:

SQL statement "SELECT 1 FROM ONLY "public"."account" x WHERE "id" OPERATOR(pg_catalog.=) $1 FOR KEY SHARE OF x"
SQL statement "WITH inserted_rows AS (
    INSERT INTO payment_token (
        account_id, ..., blocking_time
    )
    VALUES (
        account_id, ..., the_blocking_time
    )
    RETURNING *
)
SELECT * FROM inserted_rows"

第一个语句不是直接来自我的代码,而第二个语句是存储函数的一部分。

冲突的流程B:

UPDATE account SET address_id = $2, update_time = CURRENT_TIMESTAMP WHERE id = $1

0 个答案:

没有答案