我有一个死锁错误
deadlock detected
DETAIL: Process 14565 waits for ShareLock on transaction 1986906143; blocked by process 14567.
Process 14567 waits for ShareLock on transaction 1986906141; blocked by process 14565.
HINT: See server log for query details.
CONTEXT: while locking tuple (966,253) in relation
我有两个交易:交易 1 创建了一些对象并更新了一堆东西 交易 2 由于死锁而失败。根据哨兵错误,它在SELECT FOR UPDATE
步骤上失败了。SELECT
它是交易中的第一条语句,在交易开始之前只有简单的语句。
PostgreSQL 日志没有用。它们显示冲突查询来自SELECT
事务 2,而只是COMMIT
来自事务 1 的(无额外信息)
我认为要出现死锁,两个事务都应该获取对行的锁定。但在我的例子中,当事务 2 试图获取锁时,死锁似乎出现了。
看了很多文章,都没有发现相同的情况。也许社区可以为我指明正确的方向?
如果
COMMIT
涉及死锁,则指向延迟约束或延迟约束触发器。由于单个SELECT ... FOR UPDATE
可以锁定多行,因此没有理由不涉及死锁(如果一个语句锁定多行,它会一个接一个地执行,而不是以原子方式执行,因此它是可能当语句被阻塞等待另一个锁时某些行已经被锁定)。作为第一个措施,尝试将锁定级别降低到
SELECT ... FOR NO KEY UPDATE
,这就足够了,除非您想要DELETE
或修改键列。这将消除与外键的冲突。下一个想法是减少锁定的行数SELECT ... FOR UPDATE
。然后尝试减少这些事务的持续时间,这是减少死锁和避免其他麻烦的好方法。如果所有这些都没有帮助,您将不得不更深入地挖掘并确保所有事务都以相同的顺序获取行上的锁。