PostgreSQL:没有事务的死锁

PostgreSQL:没有事务的死锁,sql,node.js,postgresql,transactions,deadlock,Sql,Node.js,Postgresql,Transactions,Deadlock,我在NodeJS应用程序中有一个路由,可以在PostgreSQL数据库版本13中插入和更新一些数据 在伪代码中,以下是按顺序执行的所有查询: 从x中选择*其中y=$1; -如果没有结果 插入x y,z值$1,$2返回*; -否则,如果有结果 插入x y,z值$1,$2返回*;-价值观是不同的 更新x集y=$1,其中z=$2返回*; 更新x集合a=$1,其中b=$2返回*; -如果结束 在应用程序的某些实例中,如果没有在自己的表中写入那么多流量,我会遇到很多死锁。我不明白为什么,因为没有事务,只有

我在NodeJS应用程序中有一个路由,可以在PostgreSQL数据库版本13中插入和更新一些数据

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

从x中选择*其中y=$1; -如果没有结果 插入x y,z值$1,$2返回*; -否则,如果有结果 插入x y,z值$1,$2返回*;-价值观是不同的 更新x集y=$1,其中z=$2返回*; 更新x集合a=$1,其中b=$2返回*; -如果结束 在应用程序的某些实例中,如果没有在自己的表中写入那么多流量,我会遇到很多死锁。我不明白为什么,因为没有事务,只有简单的插入,在某些情况下更新。我使用预先准备好的语句来避免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

在PostgreSQL中,所有数据修改都发生在事务中。即使它只是一个单语句事务,仍然存在一个事务


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

您的更新很可能会更新多行,这很容易导致死锁。但是为什么要猜测呢?查看日志文件并查看。如果您不理解日志条目的含义,请将它们显示给我们,以便我们能够提供帮助。@jjanes感谢您的提示!我从服务器复制粘贴了一个锁定错误的日志。您认为给出一个答案就足够了吗?根据:PostgreSQL实际上将每个SQL语句都视为在事务中执行。如果不发出BEGIN命令,则每个语句都有一个隐式BEGIN。。。