我有两张桌子:“机器”和“魔法工具”。“magictools”指的是带有外键的“机器”。
在执行其中许多请求时,我遇到了死锁问题:
//this will produce an "AccessExclusiveLock" of type "tuple" on machines
SELECT FROM * machines FOR UPDATE where id = :id;
//this will produce a "RowExclusiveLock" on magictools and a "RowShareLock" on machines
UPDATE magictools SET collections = "large-json" where id = :id
据我了解,运行其中许多请求会产生死锁。也许只是执行此操作的更新,我不知道。在这种情况下我应该如何避免死锁?
我在这些表上有很多索引,也许我有太多索引?
以下是问题发生时 pg_activity 的报告。我不明白不同的模式和锁类型,只是,这里发生了什么?是否有可能只是没有任何事务的更新导致死锁?
没有确定性
ORDER BY
:因此,多个事务可能会尝试以不同(任意)顺序和互锁来获取行锁。
另外,为什么要锁定整个表
machines
以进行单个更新magictools
?如果它确实是每个事务的单个UPDATE
,magictools
则根本不需要machines
手动锁定行。只需放下命令。(如果有多个,那么你的问题是缺乏的。)如果有充分的理由将许多或所有行锁定在 中
machines
,请以确定的顺序执行,例如:或者锁定整个表,这也更便宜:
SHARE MODE
对于您拥有的 FK 案例来说已经足够了。手册中甚至有一个例子也暗示了这一点。INSERT
当然,与示例中的行级锁不同,锁定表也不允许。