0

We're getting deadlocks in a situation where I thought they wouldn't happen due to sorting.

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)

Here, since the ids from the (admittedly unnecessary) subquery will be sorted, I'd think a deadlock shouldn't be possible. Does IN not follow the ordering of the passed array? If not, how can I fix this?

(The subquery is coming from our ORM.)

Andrew
  • 562
  • 5
  • 15

1 Answers1

1

What's the ORM you're using?

You could use advisory locking to mitigate the deadlocks:

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")

Honestly, IMHO relying on an order by clause to avoid deadlocks seems a bit fragile solution.

More info about advisory locking functions here.

Michel Milezzi
  • 10,087
  • 3
  • 21
  • 36