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 1vzFr6-000qGe-2H for pgsql-general@arkaria.postgresql.org; Sun, 08 Mar 2026 15:15:45 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1vzFr4-00AsKa-0M for pgsql-general@arkaria.postgresql.org; Sun, 08 Mar 2026 15:15:42 +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 1vzFr3-00AsKP-2L for pgsql-general@lists.postgresql.org; Sun, 08 Mar 2026 15:15:42 +0000 Received: from sonic308-9.consmr.mail.ne1.yahoo.com ([66.163.187.32]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1vzFr0-00000001VMY-3ir3 for pgsql-general@lists.postgresql.org; Sun, 08 Mar 2026 15:15:41 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.com; s=s2048; t=1772982935; bh=jpGKPh1C5whIv5gbJsLKTy8jZSET6IByPzte3/a+PJQ=; h=Date:From:To:In-Reply-To:References:Subject:From:Subject:Reply-To; b=ivgM+k4vkWSf6+d8WHr0mT2ASmr9J3IpTLHwJJPrefZtjX7KZ03hNmIj5KpO35H3peuzFH0tjhaWt/MCTQhA37ug8L3IfDO1V0+fW4L2PcOWg+JlJqkZHEebAA4eaBFOhEjXx5h09PB8L/n5tBvm0xR/0mlSbTZ6z2DkJqgLgGcb/ItxI0/SNk2zl9xuPy/xjzs2m5FTILFaeGU9cGKhz7/4x/dIxnkgSBg9Zl5u4WVCFGZcY/ACXM2dJ+BLerH6VOapw3bLkL89oyinO8v6nfgqsDkSeKOZeF5s5hjquTh/Zo6Hey/roXRonaT8qmRcNxXuMPe8TfvCpnYI7gaiSA== X-SONIC-DKIM-SIGN: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.com; s=s2048; t=1772982935; bh=5t9hVWONee6GDCbe7ib042QJxEjBzBn+qdX+kln9UQk=; h=X-Sonic-MF:Date:From:To:Subject:From:Subject; b=ZNULbb7DZjga+0i/2hJVoiMj09YqXcdes/rAhB9XMGbQjjRJpVTlxM/6GJuk92Goqi8Txa/hI8MHQefD8mInLN77f1Z7mFIZfaE7vRchT+cLjluANchTTIbX77JlZpbFCYQekVr46cDd3I8tHkKKAmYHNFTA3kxTwUe7uOFHaO3zFs2p+q7qABFGIJEq7RN3uqZMKJX0dgQ3Tt30Laalwq2uLM6DklDFY3wjXOgazym5/A6pMXnUCvf7OhTCDV2pAJ3PYTMpxUYiEYykRzPVakFQtrz9ixpbtlFpj6JHExgkjcAYjC3liQOCBPtiqTMsHatUjB0VaFE6mU5OQ+4srw== X-YMail-OSG: snQyYRwVM1mCGkxRu76lb8WydaBDgy.fzSvqZUGUzvtzAs2e7.2YJFvLZSRMMtq f0yPX_6GxSifcvVUBppoLC99IALNxldwkZrF0E7SbFm5QgIryVmA5ehxCyIn5qJN5p9vRPbzzU.H de5d4cNHf_mhD8x5Z9P1gEgLByKdb2VXV0qH5tUUMbw.3K7tpeaGSPKUp6TG7i0sBrm97WlaAo5H 9Jz8b5mmNzph_1SNn4m7I1SIwELAAO0vAID10H8eYZQ4XKZV7yfXmJ2wGtpQIE6tzWmllgGX5Z7T re88p3jmL_cTyXJbAFvCYyC3UpfMmejNudWUy9KPdvqCB4g3eY56DXgvjxYATDyA3lAwB0Ti7nxc UirL6EuiEXOX2bq3apUCINnCNegMRSMoUPzbuil.7BSLsNcq6M4ehFCMVpRfJRO4Jf5Nv52lQpE4 bbEKBVqTSE7F5GaM4N9ttrCEMaZPNmFX19fGYFCmgS4ndh5yq2WXOc18Xytc0hlqmFy4uDrzQQBd MkaHIq5mLaZ4K0fxHhZiOeh6Agv6BlUKHjPbCiJHzhE2t09idwu6ZD65t75gNFDYRUAf8RCM8SVg CZA43yXDkzIkWWh6xVA7qgqBxNrwHt7AWsVFGLkiKAVxN5ftFaotr.if7ZJg55A_PDghdpmYfeLi RecRyx9m046aZpBS2oEZHXoi8CsftuneOoL1Nxe9ucSjyALksGGAGsHdZPPcW4.R_57Jx6mNNXNZ kNETkEefk0e5p1.uUodwKmpR5Th6PpfN3KXSGwHJvUnT4SbdUxtBDwoyCERk.xFE2dBEQu7XT5SI 9c.ttvwot6GC6v7WyEdsvqgA.CpdJbTXb2ttjMS6gCqkg5WcildQWThKkB8xOH8jwhKiN_1LEg94 AfolQLf6pNalg8wSDAAyufv1XGazWGBNWrAxyTY14Rk.V1Rt7T44Rvm_SP89BwyixPrsfsY6pJR3 IBYCcQ.pKCUCf3rwuODSGCRLYK1UUV7eI1yR_nj_F1X3mnA5YaODQZAYGT_mSGpDZbz3Hwcq0IXE u3USebZ.nSiWdCgWxuJnJqdHpyTDjHa2i7ET2MBlbQELbmjfCCkdg66Lfm5jeIc9KLRaS_IHPpN3 aTwIljRIAZbytfQKsvXmtscojTJoAvzBs7vcm5jMcNbreRWkQOkOXKWtymbjzV8v_6V5LAUQDwZE snxNodL3EPR8uek7wMRd7iuvpfzgdt0o9I9psOm01WufTim3feS.AApEcugIPB1HIBbwcRi8S4lo QEYwa.JNv5id1qrRIY7V4pMetN2kT2Xq_I.mT7.xezCn_LQ8qtzR9GjJJQ496GnNqbe3ZLTxZkDj F3KZ4w5ILMGs2VHocFMbA16z8tN4o2RRXryqGsj6OEryXYyKDJ6C9chNUpqwwci8B9G0PTxAUrlp 34pZJimcLdk0nT37pAuRpCqRlG2WJZSsPLvcpTr0DbdvD_FXLiiUtJmAqc96eDNerEcgi8PTi6e9 XJqMOXd7oML1P8KysPzmCwY_R9iNRzrxkH6tuQyKILH6uqCUFhxWckkBRj3wR9iL_Kum05_eAz3z 8hcG.tnOFWkpfH_pN2CtzetjfSAJyFqBz0MhAmhl6SZmEr4qDASIjTWko5b6UdBXGSD52WklHYw4 KNT3PrQygAdvI5FBrGUER2e0XQ9lTsIIOOikR6AQYRthHubZ5w4dAh8OhuyZI0N6Iq26d5QSh.Tf OO7gSw5PwrRr2OaMRytLIU58CPEyckLvM8Dwwjc8XN2J.7X_r3hIirJgvb4ZjDVq.lprSQ64z0Ux wGJ1Q8.ok61ZwNu4XT5MGPSxnj9fW81CkNXsInZdFtg18ZAwlnZQnd1omz1re5F2KVuGnAyl1Ybx sNFj6IGmY5UgBeiBV8AP8kQoWMxev3fMQfJPcmBaumIuZ0Moj2PyJf1AjtuOb__nhBv9oTwCQ_Ve dqIg1fKjO7fFEcl2tDv5sBBm7SSK0.YiD4hlXdzg.ma7OO3z5hAV8EhuNoOlN1UwqCKXp_2AEq2V K21FJJCZ8Al4lVwdvDdbI8Q_dR16hDF_Lft1jiXbo6J_IckzTCDhyj17444Ea_DQ73W3RPF8roBZ ._dtHev9tXl3eeQe1xuuMq0vqNxKK8ITkxw9mj04GUpAetks0DCStOFHyipFer4D.7PwMw4zCv90 mmQeeh0jqsBy5egXIL9JszMfaA59fnMdVkoBCO5nWQsgHRsdroT6wf4qqKt7LWBIL4CBnBrleEud Hl.26XC69O.BP7g-- X-Sonic-MF: X-Sonic-ID: 5c24e3da-be6f-4705-b753-70daa7d8f69e Received: from sonic.gate.mail.ne1.yahoo.com by sonic308.consmr.mail.ne1.yahoo.com with HTTP; Sun, 8 Mar 2026 15:15:35 +0000 Date: Sun, 8 Mar 2026 15:15:34 +0000 (UTC) From: felix.quintgz@yahoo.com To: pgsql-general@lists.postgresql.org Message-ID: <1164079167.6346688.1772982934392@mail.yahoo.com> In-Reply-To: References: Subject: Re: Unexpected deadlock across two separate rows, using Postgres 17 and Django's select_for_update() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable X-Mailer: WebService/1.1.25198 YMailNodin Content-Length: 3961 List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk This is pure speculation. It's possible that using SELECT FOR UPDATE also locks the rows in the paren= t 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 wrote: [I originally posted this over at=C2=A0https://forum.djangoproject.com/t/u= nexpected-deadlock-across-two-separate-rows-using-postgres-17-and-select-fo= r-update/44294/1, but that thread ran into a dead end. Apologies for the cr= oss-post] Hi, I'm trying to understand/fix a rare deadlock in my application. Given my li= mited knowledge, what seems odd to me is that the deadlock involves two pro= cesses=C2=A0running exactly the same code/query, each of which (tries to) a= void issues by locking exactly one row for update. In Django-speak, the cod= e 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 proce= ss 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=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 How can there be a deadlock between updates to different rows (as per the b= olded WHERE clauses)? Have I somehow turned off row-level locks? Is there s= ome additional logging I could enable to try to catch=C2=A0the data needed = to root-cause this? Any help appreciated. Thanks, Shaheed