Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vyntz-000R61-3D for pgsql-general@arkaria.postgresql.org; Sat, 07 Mar 2026 09:24:52 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1vyntw-008HyI-2p for pgsql-general@arkaria.postgresql.org; Sat, 07 Mar 2026 09:24:49 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vyntw-008Hy9-1h for pgsql-general@lists.postgresql.org; Sat, 07 Mar 2026 09:24:49 +0000 Received: from mail-wr1-x431.google.com ([2a00:1450:4864:20::431]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1vyntu-00000001KFQ-1r2F for pgsql-general@lists.postgresql.org; Sat, 07 Mar 2026 09:24:48 +0000 Received: by mail-wr1-x431.google.com with SMTP id ffacd0b85a97d-439af7d77f0so6053254f8f.0 for ; Sat, 07 Mar 2026 01:24:45 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1772875484; cv=none; d=google.com; s=arc-20240605; b=OB6HzQjDZxHpqHv2+SIsfhDC1T9aA1FqJNBxrcR1k2hXOyBmgCNKPzT4Iog7iiiHh2 oNi7+sQGczy+2iHPvxZ7DTRKDQJs8GgE26zWih2l6t7vBqyFlO8rfIJnc/F+2VdXA0wp KHMC+RFirJZEPsIEOHjZVZULD93BT2uorjtN7ecaIYfM2PSTVfrc65vNjgJqmaGRx6PP znH89r/mNJZiezVnn5a+VcJsaUwWNbGH+pnePNXx5D4ds1F1hm3p4HUNXwWsEU0Zdr/s qJhN1UKqfWshbl9YY2qC6puyYh2v1/iIKhjb0YZ0i2fdc/y29XNVGa9oE43Ms4dmLRH1 8lyw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=to:subject:message-id:date:from:mime-version:dkim-signature; bh=5ytL1jSTVFuOL4BevmE+QQyGElaYJbUpzGy4BdBqaU0=; fh=7KNJTaIGVFzktmFetTGKv4cT+KHwSjxCpcwdnv/lk2U=; b=Fe7VaoPpEIVyXFb/72S85Y4A3jm1cZLizSYWPY6cJwG9SM1mRaWnzoQBVwCc/LsNkW GWaIcf27RCMDsTfJf405cUr7lvAa06WfjuTO6BCgNRJpzcis1/LcsCqWFsCByJqqdqtb Q3XmWs6eYkIMtcUUk8BVPkl9kK+IWE6K5oxBaWC13B5xN9c25O+SwD2N0K4a4dh/akvn MhecoITNSGZuAexS9JK204Fu/NkUqQNN+S0v7U3wvlp9Y6KCwOiLrimy4HZcttkk0Smy fZHYOBNx0Vif3h2RyHkWkRpmev7J6pZQhK0bYEVhMkCN3yYYk2n87J25Vfgt8h7t6/P3 relw==; darn=lists.postgresql.org ARC-Authentication-Results: i=1; mx.google.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1772875484; x=1773480284; darn=lists.postgresql.org; h=to:subject:message-id:date:from:mime-version:from:to:cc:subject :date:message-id:reply-to; bh=5ytL1jSTVFuOL4BevmE+QQyGElaYJbUpzGy4BdBqaU0=; b=BegwDb50imypLmmK4gVMuClFg/wc2D/LQ6COOkvdpCJuU6dep3W9qxGgQ48gne14l9 +gI14tyN07JHdhIHlkAmcXcglREHTu9fiQYGjikzZvx/BOg0Vr4VOAKyg5fA7B8lLn1m J73E1u5cjEujDFuPjXDDb0Aba3sXGEawl1jG6dZP449cQkFLLq4HcA/YGNCNJBxVd0qx 2OqW4x7p0LRz7hybjIzBb21LjvBAqejU5b3/WXOOm+XklugBNbprDozhUn4G264tx27m 0s6Wj7nOPybvyIZNzu5SDvows+m6WcTfRADOR2sOyOI8flVLtn4tKlB24XU/V1gia+Un YsdA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772875484; x=1773480284; h=to:subject:message-id:date:from:mime-version:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=5ytL1jSTVFuOL4BevmE+QQyGElaYJbUpzGy4BdBqaU0=; b=GI/Lw/S9/rz8DOaViaVPa+zraDJhodyEpO6WADTKOiNydGa129D5XAq3W108YdT2Ln drgbH/A7/zRFL2ABwaqGNtsgymFWZwyzH+prTn14lmnYXh17ZEZw/Khl84ge40+DTQ4R w102HWudOO/hNL68pH4qngbcVH5HNzujmOOnhBP9r9oVysFYTQPdRi/06am0/BJjjWz5 4U8E/xCoU/jIKxhC7UaBmtgl7HaRjag3jLbBO4CpfOQCkBtP7lzHeI62QYGxd34X5Uab r8is/r/HFw1AurPit/pD7fCZjZdSQOmLzmyYtYFGnQcNyyJPqA9j/YGzh79Oh5ba0csL qtyg== X-Gm-Message-State: AOJu0Yyw4IKp5PKrssjYKRHnhujIWGFr6yKNRn+Yy/A1/5R5q+ukvJ/B GZSp8z93Vq0///vvZEwq13Z38Qe1FG8MzKvjRWYtORVlsdkPuQ2zKvh/M393TRNQVNVebcuCAN2 lp2qSMFKtvM1oznJlBpa6bVNYwpOAm8gg3AON X-Gm-Gg: ATEYQzz/gkI8McN8kzIOMbi+QjuUTOJnOXNJUVNy4IWowF4D+NIwQX47KULF1vytEpp 98yaNx6fG0U2F5Wp8an+KJ53Z6c9Z1p1nxgH8hPIZptsoh5iQJQs/6blov9aTcTYFds9x1mvyCN KE/izFo8VhgYuFDMGr+27S6EwjvspU4uwsitNTPT5SwRt/0b4bam+lNwaVwC4/WnoyMKMBWp9HZ u7gfaFyWIqjGBU8CXswuKY+0qeXCKsiF7gfqCFf87przPmiQv6md3f1MZPO9faaUA13bgegFbiF TrRoyx8= X-Received: by 2002:a05:6000:250c:b0:439:afcd:b629 with SMTP id ffacd0b85a97d-439da87bf34mr8389801f8f.55.1772875483992; Sat, 07 Mar 2026 01:24:43 -0800 (PST) MIME-Version: 1.0 From: Shaheed Haque Date: Sat, 7 Mar 2026 09:24:32 +0000 X-Gm-Features: AaiRm52ZxKeyqmRIbJhV5X1kq6zc8lp1MCGZjUGjk-W5KagyHzNOSfKo-KhSlp0 Message-ID: Subject: Unexpected deadlock across two separate rows, using Postgres 17 and Django's select_for_update() To: pgsql-general list Content-Type: multipart/alternative; boundary="000000000000745674064c6bbd3d" List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --000000000000745674064c6bbd3d Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable [I originally posted this over at https://forum.djangoproject.com/t/unexpected-deadlock-across-two-separate-r= ows-using-postgres-17-and-select-for-update/44294/1, but that 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 that the deadlock involves two processes running exactly the same code/query, each of which (tries to) avoid issues by locking exactly one row for update. In Django-speak, the code does this: # # Select-for-update exactly one row by id. # qs =3D Endpoint.objects.select_for_update().filter(id=3Dinstance.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 =E2=80=9Cpaiyroll_endpoint=E2=80=9D.=E2=80=9Cid=E2=80= =9D, =E2=80=9Cpaiyroll_endpoint=E2=80=9D.=E2=80=9Cop_id=E2=80=9D, =E2=80=9Cpaiyr= oll_endpoint=E2=80=9D.=E2=80=9Cclient_id=E2=80=9D, =E2=80=9Cpaiyroll_endpoint=E2=80=9D.=E2=80=9Cclient_private=E2=80=9D, =E2= =80=9Cpaiyroll_endpoint=E2=80=9D.=E2=80=9Cnetloc=E2=80=9D, =E2=80=9Cpaiyroll_endpoint=E2=80=9D.=E2=80=9Ccalls=E2=80=9D, =E2=80=9Cpaiyr= oll_endpoint=E2=80=9D.=E2=80=9Cms=E2=80=9D, =E2=80=9Cpaiyroll_endpoint=E2=80=9D.=E2=80=9Chistory=E2=80=9D, =E2=80=9Cpai= yroll_endpoint=E2=80=9D.=E2=80=9Ccurrent_history=E2=80=9D FROM =E2=80=9Cpaiyroll_endpoint=E2=80=9D *WHERE =E2=80=9Cpaiyroll_endpoint=E2=80= =9D.=E2=80=9Cid=E2=80=9D =3D 1 FOR UPDATE* Process 16953: SELECT =E2=80=9Cpaiyroll_endpoint=E2=80=9D.=E2=80=9Cid=E2=80= =9D, =E2=80=9Cpaiyroll_endpoint=E2=80=9D.=E2=80=9Cop_id=E2=80=9D, =E2=80=9Cpaiyr= oll_endpoint=E2=80=9D.=E2=80=9Cclient_id=E2=80=9D, =E2=80=9Cpaiyroll_endpoint=E2=80=9D.=E2=80=9Cclient_private=E2=80=9D, =E2= =80=9Cpaiyroll_endpoint=E2=80=9D.=E2=80=9Cnetloc=E2=80=9D, =E2=80=9Cpaiyroll_endpoint=E2=80=9D.=E2=80=9Ccalls=E2=80=9D, =E2=80=9Cpaiyr= oll_endpoint=E2=80=9D.=E2=80=9Cms=E2=80=9D, =E2=80=9Cpaiyroll_endpoint=E2=80=9D.=E2=80=9Chistory=E2=80=9D, =E2=80=9Cpai= yroll_endpoint=E2=80=9D.=E2=80=9Ccurrent_history=E2=80=9D FROM =E2=80=9Cpaiyroll_endpoint=E2=80=9D *WHERE =E2=80=9Cpaiyroll_endpoint=E2=80= =9D.=E2=80=9Cid=E2=80=9D =3D 2 FOR UPDATE* HINT: See server log for query details. CONTEXT: while locking tuple (7,15) in relation =E2=80=9Cpaiyroll_endpoint= =E2=80=9D STATEMENT: SELECT =E2=80=9Cpaiyroll_endpoint=E2=80=9D.=E2=80=9Cid=E2=80=9D,= =E2=80=9Cpaiyroll_endpoint=E2=80=9D.=E2=80=9Cop_id=E2=80=9D, =E2=80=9Cpaiyroll_endpoint=E2=80=9D.=E2=80=9Cclient_id=E2=80=9D, =E2=80=9Cp= aiyroll_endpoint=E2=80=9D.=E2=80=9Cclient_private=E2=80=9D, =E2=80=9Cpaiyroll_endpoint=E2=80=9D.=E2=80=9Cnetloc=E2=80=9D, =E2=80=9Cpaiy= roll_endpoint=E2=80=9D.=E2=80=9Ccalls=E2=80=9D, =E2=80=9Cpaiyroll_endpoint=E2=80=9D.=E2=80=9Cms=E2=80=9D, =E2=80=9Cpaiyroll= _endpoint=E2=80=9D.=E2=80=9Chistory=E2=80=9D, =E2=80=9Cpaiyroll_endpoint=E2=80=9D.=E2=80=9Ccurrent_history=E2=80=9D FROM = =E2=80=9Cpaiyroll_endpoint=E2=80=9D WHERE =E2=80=9Cpaiyroll_endpoint=E2=80=9D.=E2=80=9Cid=E2=80=9D =3D 1 FOR UPDATE How can there be a deadlock between updates to different rows (as per the bolded WHERE clauses)? Have I somehow turned off row-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 --000000000000745674064c6bbd3d Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
[I originally posted this over at=C2=A0https://forum.djan= goproject.com/t/unexpected-deadlock-across-two-separate-rows-using-postgres= -17-and-select-for-update/44294/1, but that thread ran into a dead end.= Apologies for the cross-post]

Hi,

I&= #39;m trying to understand/fix a rare deadlock in my application. Given my = limited knowledge, what seems odd to me is that the deadlock involves two p= rocesses=C2=A0running exactly the same code/query, each of which (tries to)= avoid issues by locking exactly one row for update. In Django-speak, the c= ode does this:
#
# Select-for-update exactly one row= by id.
#
qs =3D Endpoint.objects.select_for_update().filter(id=3Dinstance.id)
#
# The above returns a = queryset of one row which we loop over:
#
for item in qs:
<= /pre>
    ...do stuff with item...
    item.save() 
The deadlock is reported i= n 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 proce= ss 15576.
Process 15576: SELECT =E2=80=9Cpaiyroll_endpoint=E2=80=9D.=E2=80=9Cid=E2=80= =9D,=20 =E2=80=9Cpaiyroll_endpoint=E2=80=9D.=E2=80=9Cop_id=E2=80=9D, =E2=80=9Cpaiyr= oll_endpoint=E2=80=9D.=E2=80=9Cclient_id=E2=80=9D,=20 =E2=80=9Cpaiyroll_endpoint=E2=80=9D.=E2=80=9Cclient_private=E2=80=9D, =E2= =80=9Cpaiyroll_endpoint=E2=80=9D.=E2=80=9Cnetloc=E2=80=9D,=20 =E2=80=9Cpaiyroll_endpoint=E2=80=9D.=E2=80=9Ccalls=E2=80=9D, =E2=80=9Cpaiyr= oll_endpoint=E2=80=9D.=E2=80=9Cms=E2=80=9D,=20 =E2=80=9Cpaiyroll_endpoint=E2=80=9D.=E2=80=9Chistory=E2=80=9D, =E2=80=9Cpai= yroll_endpoint=E2=80=9D.=E2=80=9Ccurrent_history=E2=80=9D=20 FROM =E2=80=9Cpaiyroll_endpoint=E2=80=9D WHERE =E2=80=9Cpaiyroll_en= dpoint=E2=80=9D.=E2=80=9Cid=E2=80=9D =3D 1 FOR UPDATE
Process 16953: SELECT =E2=80=9Cpaiyroll_endpoint=E2=80=9D.=E2=80=9Cid=E2=80= =9D,=20 =E2=80=9Cpaiyroll_endpoint=E2=80=9D.=E2=80=9Cop_id=E2=80=9D, =E2=80=9Cpaiyr= oll_endpoint=E2=80=9D.=E2=80=9Cclient_id=E2=80=9D,=20 =E2=80=9Cpaiyroll_endpoint=E2=80=9D.=E2=80=9Cclient_private=E2=80=9D, =E2= =80=9Cpaiyroll_endpoint=E2=80=9D.=E2=80=9Cnetloc=E2=80=9D,=20 =E2=80=9Cpaiyroll_endpoint=E2=80=9D.=E2=80=9Ccalls=E2=80=9D, =E2=80=9Cpaiyr= oll_endpoint=E2=80=9D.=E2=80=9Cms=E2=80=9D,=20 =E2=80=9Cpaiyroll_endpoint=E2=80=9D.=E2=80=9Chistory=E2=80=9D, =E2=80=9Cpai= yroll_endpoint=E2=80=9D.=E2=80=9Ccurrent_history=E2=80=9D=20 FROM =E2=80=9Cpaiyroll_endpoint=E2=80=9D WHERE =E2=80=9Cpaiyroll_en= dpoint=E2=80=9D.=E2=80=9Cid=E2=80=9D =3D 2 FOR UPDATE
HINT: See server log for query details.
CONTEXT: while locking tuple (7,15) in relation =E2=80=9Cpaiyroll_endpoint= =E2=80=9D
STATEMENT: SELECT =E2=80=9Cpaiyroll_endpoint=E2=80=9D.=E2=80=9Cid=E2=80=9D= ,=20 =E2=80=9Cpaiyroll_endpoint=E2=80=9D.=E2=80=9Cop_id=E2=80=9D, =E2=80=9Cpaiyr= oll_endpoint=E2=80=9D.=E2=80=9Cclient_id=E2=80=9D,=20 =E2=80=9Cpaiyroll_endpoint=E2=80=9D.=E2=80=9Cclient_private=E2=80=9D, =E2= =80=9Cpaiyroll_endpoint=E2=80=9D.=E2=80=9Cnetloc=E2=80=9D,=20 =E2=80=9Cpaiyroll_endpoint=E2=80=9D.=E2=80=9Ccalls=E2=80=9D, =E2=80=9Cpaiyr= oll_endpoint=E2=80=9D.=E2=80=9Cms=E2=80=9D,=20 =E2=80=9Cpaiyroll_endpoint=E2=80=9D.=E2=80=9Chistory=E2=80=9D, =E2=80=9Cpai= yroll_endpoint=E2=80=9D.=E2=80=9Ccurrent_history=E2=80=9D=20 FROM =E2=80=9Cpaiyroll_endpoint=E2=80=9D WHERE =E2=80=9Cpaiyroll_endpoint= =E2=80=9D.=E2=80=9Cid=E2=80=9D =3D 1 FOR UPDATE

How can there be a deadlock between updates to different rows (as = per the bolded WHERE clauses)? Have I somehow turned off row-level locks? I= s there some additional logging I could enable to try to catch=C2=A0the dat= a needed to root-cause this?

Any help appreciated.
<= div>
Thanks, Shaheed
--000000000000745674064c6bbd3d--