首页 > 解决方案 > PostgreSQL:没有事务的死锁

问题描述

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

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

select * from x where y=$1;

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

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

-- end if

在应用程序的某些实例上,没有太多流量写入自己的表,我有很多死锁。我不明白为什么因为没有事务,只有简单的插入,并且在某些情况下更新。由于节点 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=$1, user_properties=$2 where user_id=$3
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=$1, user_properties=$2 where user_id=$3
2021-04-07T11:55:17+02:00 Process 583789: update x set user_id=$1, user_properties=$2 where user_id=$3

标签: sqlnode.jspostgresqltransactionsdeadlock

解决方案


在 PostgreSQL 中,所有数据修改都发生在事务中。哪怕只是单语句的事务,还是有事务的。

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


推荐阅读