PostgreSQL:没有事务的死锁

PostgreSQL: deadlock without a transaction

我有一个路由(在节点 JS 应用程序中)在 PostgreSQL 数据库(版本 13)中插入和更新一些数据。

在伪代码中,以下是按顺序完成的所有查询:

select * from x where y=;

-- if there is no result
   insert into x (y,z) values (,) returning *;

-- else if there is a result
   insert into x (y,z) values (,) returning *; -- values are different
   update x set y= where z= returning *;
   update x set a= where b= returning *;

-- end if

在一些没有那么多流量的应用程序实例上,它们自己写入 table,我有很多死锁。我不明白为什么没有事务,只有简单的插入,在某些情况下更新。由于 node postgres.

,我使用准备好的语句(以避免 SQL 注入)

我以前从来没有遇到过死锁(或者我没有注意到),所以我不明白为什么会发生。

出现死锁的原因可能是什么?以及如何避免死锁?

编辑

来自服务器的日志(我没有更详细的日志,因为它在平台即服务上):

2021-04-07T11:55:17+02:00 Process 583773 waits for ShareLock on transaction 2408877; blocked by process 583789.
2021-04-07T11:55:17+02:00 2021-04-07 09:55:17.084 GMT [583789] DETAIL: Process 583789 waits for ShareLock on transaction 2408880; blocked by process 583773.
2021-04-07T11:55:17+02:00 2021-04-07 09:55:17.084 GMT [583789] ERROR: deadlock detected
2021-04-07T11:55:17+02:00 2021-04-07 09:55:17.084 GMT [583789] STATEMENT: update x set user_id=, user_properties= where user_id=
2021-04-07T11:55:17+02:00 2021-04-07 09:55:17.084 GMT [583789] HINT: See server log for query details.
2021-04-07T11:55:17+02:00 2021-04-07 09:55:17.084 GMT [583789] CONTEXT: while rechecking updated tuple (119,3) in relation "x"
2021-04-07T11:55:17+02:00 Process 583773: update x set user_id=, user_properties= where user_id=
2021-04-07T11:55:17+02:00 Process 583789: update x set user_id=, user_properties= where user_id=

在 PostgreSQL 中,所有数据修改都发生在事务中。就算只是单语句交易,也是有交易的。

日志条目不足以给出明确的答案,但看起来您的更新每次都更新了不止一行。如果它们偶尔更新相同的行但顺序不同,它们可能会相互死锁。我认为这对于您的日志中的查询来说应该很少见,因为我认为他们会根据对同一索引的单值扫描来选择要更新的行,因此通常以相同的顺序执行。