Re: Unexpected deadlock across two separate rows, using Postgres 17 and Django's select_for_update()
| От | felix.quintgz@yahoo.com |
|---|---|
| Тема | Re: Unexpected deadlock across two separate rows, using Postgres 17 and Django's select_for_update() |
| Дата | |
| Msg-id | 1164079167.6346688.1772982934392@mail.yahoo.com обсуждение исходный текст |
| Ответ на | Unexpected deadlock across two separate rows, using Postgres 17 and Django's select_for_update() (Shaheed Haque <shaheedhaque@gmail.com>) |
| Ответы |
Re: Unexpected deadlock across two separate rows, using Postgres 17 and Django's select_for_update()
Re: Unexpected deadlock across two separate rows, using Postgres 17 and Django's select_for_update() |
| Список | pgsql-general |
This is pure speculation. It's possible that using SELECT FOR UPDATE also locks the rows in the parent tables referenced in the field list. I believe this happened in older versions of PostgreSQL. On Saturday, March 7, 2026 at 04:25:01 AM GMT-5, Shaheed Haque <shaheedhaque@gmail.com> wrote: [I originally posted this over at https://forum.djangoproject.com/t/unexpected-deadlock-across-two-separate-rows-using-postgres-17-and-select-for-update/44294/1, butthat thread ran into a dead end. Apologies for the cross-post] Hi, I'm trying to understand/fix a rare deadlock in my application. Given my limited knowledge, what seems odd to me is thatthe deadlock involves two processes running exactly the same code/query, each of which (tries to) avoid issues by lockingexactly one row for update. In Django-speak, the code does this: # # Select-for-update exactly one row by id. # qs = Endpoint.objects.select_for_update().filter(id=instance.id) # # The above returns a queryset of one row which we loop over: # for item in qs: ...do stuff with item... item.save() The deadlock is reported in the Postgres server log like this: ERROR: deadlock detected DETAIL: Process 15576 waits for ShareLock on transaction 31053599; blocked by process 16953. Process 16953 waits for ShareLock on transaction 31053597; blocked by process 15576. Process 15576: SELECT “paiyroll_endpoint”.“id”, “paiyroll_endpoint”.“op_id”, “paiyroll_endpoint”.“client_id”, “paiyroll_endpoint”.“client_private”, “paiyroll_endpoint”.“netloc”, “paiyroll_endpoint”.“calls”, “paiyroll_endpoint”.“ms”, “paiyroll_endpoint”.“history”, “paiyroll_endpoint”.“current_history” FROM “paiyroll_endpoint” WHERE “paiyroll_endpoint”.“id” = 1 FOR UPDATE Process 16953: SELECT “paiyroll_endpoint”.“id”, “paiyroll_endpoint”.“op_id”, “paiyroll_endpoint”.“client_id”, “paiyroll_endpoint”.“client_private”, “paiyroll_endpoint”.“netloc”, “paiyroll_endpoint”.“calls”, “paiyroll_endpoint”.“ms”, “paiyroll_endpoint”.“history”, “paiyroll_endpoint”.“current_history” FROM “paiyroll_endpoint” WHERE “paiyroll_endpoint”.“id” = 2 FOR UPDATE HINT: See server log for query details. CONTEXT: while locking tuple (7,15) in relation “paiyroll_endpoint” STATEMENT: SELECT “paiyroll_endpoint”.“id”, “paiyroll_endpoint”.“op_id”, “paiyroll_endpoint”.“client_id”, “paiyroll_endpoint”.“client_private”, “paiyroll_endpoint”.“netloc”, “paiyroll_endpoint”.“calls”, “paiyroll_endpoint”.“ms”, “paiyroll_endpoint”.“history”, “paiyroll_endpoint”.“current_history” FROM “paiyroll_endpoint” WHERE “paiyroll_endpoint”.“id” = 1 FOR UPDATE How can there be a deadlock between updates to different rows (as per the bolded WHERE clauses)? Have I somehow turned offrow-level locks? Is there some additional logging I could enable to try to catch the data needed to root-cause this? Any help appreciated. Thanks, Shaheed
В списке pgsql-general по дате отправления: