首页 > 解决方案 > PostgreSQL中的子查询死锁

问题描述

在我认为由于排序而不会发生的情况下,我们遇到了死锁。

2019-09-11T20:21:59.505804531Z 2019-09-11 20:21:59.505 UTC [67] ERROR:  deadlock detected
2019-09-11T20:21:59.505824424Z 2019-09-11 20:21:59.505 UTC [67] DETAIL:  Process 67 waits for ShareLock on transaction 1277067; blocked by process 35.
2019-09-11T20:21:59.505829400Z  Process 35 waits for ShareLock on transaction 1277065; blocked by process 67.
2019-09-11T20:21:59.505833648Z  Process 67: UPDATE "records" SET "last_data_at" = '2019-09-11 20:21:58.493184' WHERE "records"."id" IN (SELECT "records"."id" FROM "records" WHERE "records"."id" IN ($1, $2) ORDER BY id asc)
2019-09-11T20:21:59.505843428Z  Process 35: UPDATE "records" SET "last_data_at" = '2019-09-11 20:21:58.496318' WHERE "records"."id" IN (SELECT "records"."id" FROM "records" WHERE "records"."id" IN ($1, $2) ORDER BY id asc)

在这里,由于(诚然不必要的)子查询中的 id 将被排序,我认为死锁不应该是可能的。不IN遵循传递数组的顺序?如果没有,我该如何解决这个问题?

(子查询来自我们的 ORM。)

标签: postgresql

解决方案


你使用的 ORM 是什么?

您可以使用咨询锁定来缓解死锁:

UPDATE 
    "records" 
SET 
    "last_data_at" = '2019-09-11 20:21:58.496318' 
WHERE 
    "records"."id" IN ($1, $2)
    --This function will return TRUE if getting 
    --a lock is possible for current transaction
    AND pg_try_advisory_xact_lock("records"."id")

老实说,恕我直言,依靠一个order by条款来避免死锁似乎有点脆弱。

有关咨询锁定功能的更多信息,请点击此处


推荐阅读