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 1wIL6Y-007zq9-1Q for pgsql-general@arkaria.postgresql.org; Thu, 30 Apr 2026 06:42:34 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1wIL6X-006LkB-2P for pgsql-general@arkaria.postgresql.org; Thu, 30 Apr 2026 06:42:33 +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 1wIL6X-006Lk2-1G for pgsql-general@lists.postgresql.org; Thu, 30 Apr 2026 06:42:33 +0000 Received: from mail-wr1-x432.google.com ([2a00:1450:4864:20::432]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1wIL6V-00000003wGN-0I19 for pgsql-general@lists.postgresql.org; Thu, 30 Apr 2026 06:42:32 +0000 Received: by mail-wr1-x432.google.com with SMTP id ffacd0b85a97d-44509921fbcso289661f8f.3 for ; Wed, 29 Apr 2026 23:42:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cybertec.at; s=google; t=1777531350; x=1778136150; darn=lists.postgresql.org; h=mime-version:user-agent:content-transfer-encoding:references :in-reply-to:date:cc:to:from:subject:message-id:from:to:cc:subject :date:message-id:reply-to; bh=xOyKfaaBjy/GBQIh/PVJUaxxXBHnKYdwjBvOtv1STF4=; b=eVDxK5xjyJRyftaIRJj6kEkGv7QTsj/PtcTFfMmBUi6eiXEJiZjJr0PhfXTH6lKjaw eFJqmC/XpTs/8c75dbCHuhYOi6aj1x0pndBBA0q8NidbfxYxYmeZQHIuNLHFY36ylAC5 sQ/yOxH3lHSNUNlmqZz5Oh3KoolkrSH4Yj/kqjY/dz1OYhS7/WIqAs/+Q9jRhfsscTCv EWmTtpHXla1QCDIagUPc7sCieHS9pw4BxcVVAFv3Q2qd/vckoyISV4pDtZGLJOiDepMa +ESCDN7ezsXjjIjA+nzCT98aNtWkXDheEeq5noTbMqZ27Oksq6TYzWK98IXad2alTPQ0 EDNw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1777531350; x=1778136150; h=mime-version:user-agent:content-transfer-encoding:references :in-reply-to:date:cc:to:from:subject:message-id:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=xOyKfaaBjy/GBQIh/PVJUaxxXBHnKYdwjBvOtv1STF4=; b=Mo+Tgv2TDVxXj8ZBuYHKwQEtfepzpjosdwk0zsRUeh4lbxkczWJw8ap9pSf2Lhm/Gf kbuaEiEEYSD2QT01WN1EvgmcArsXL4BUJnwFlhdQN9Fbu4ybsw0sNzACQS2S9Z0UdMXy OxGUanw67ChizsLOnOY/DXX+R1ZdnPjRRr77AOPogUkgt6rao0K+izw4ZtWvj8pMQjXO +JWfU911a/ziTNje4qc8ILVQ9AKkXVUG+0zdWIar5sZ7r2ZlOB5B0NLUmwbjkJRMOa4K 15nLbKW18grCT0CmgOlmLr/XHbq6iNChgijmY05kdQLl8yWjFEs7twCWx9SGUs5Mf9cH ygkw== X-Gm-Message-State: AOJu0Yw6Oa4N4aEYfmeWt3H++gXR3lu3/t4Iph9bwlxN1ZCncX/1agqa sJn8N3nzJa5ZQ8f7MsupmYwJFq16yrYS53dPDWw6OqxZR2fqZAbn2sS5qVXD0S8jofxIb605rQg 8EEIE8GI= X-Gm-Gg: AeBDiev2jjJed99m0uVl2S+HL83a+Tt0ALEZjmrf8nLRCaOorDZpLm5tp0SxUMiJOHZ kNXiOUs8hfTt3/6RZwHQXz+YG9F0oAWi62PJuO/qR5krrwNBs+gEstg/yheDlh97dRawWqsBk1f lMyRfiAEJr/8a0yhBTXKj476vXd/O6J5Oelw2+pQYW4sjBhhgejD7IKv/ZULV8fbjoMl/6MliN+ mf62bourFb7f55irxWZH/m7Hu34po0AOS742AIkIfVHnHaHhjbXWgvPleQycBH83rcu5/lVm7Az PxEslFldf0YoVJkwZ1Ig2EGs/FMYiH1NvMRlAbyCGY56UuahV8/sIWCjBDV6D2/9/+pFUoMVZln 4f/XFRARisuASfXav3VOJDAxEDxgjky4MxF0F4wSEpOzimN09bT6/MGvArm1kZiEsw/fMjIq7pB BmabZDN03HxZhBh5JbBFe35igO+g6j/jXxeIQs+klt4CnEaVHGQRBQrlDATyQuJ7saDYOPbyijo T1A X-Received: by 2002:a5d:5c89:0:b0:43c:f583:126a with SMTP id ffacd0b85a97d-4493d412141mr2470938f8f.14.1777531349477; Wed, 29 Apr 2026 23:42:29 -0700 (PDT) Received: from laurenz.albe-K4N0CV00F97414D ([2001:871:270:4fd5:603f:45c2:9807:c104]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-447b7ca64ffsm11232327f8f.37.2026.04.29.23.42.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 29 Apr 2026 23:42:29 -0700 (PDT) Message-ID: Subject: Re: Confirmation on concurrent SELECT FOR UPDATE with ON CONFLICT DO NOTHING From: Laurenz Albe To: Matt Magoffin , Adrian Klaver Cc: pgsql-general@lists.postgresql.org Date: Thu, 30 Apr 2026 08:42:28 +0200 In-Reply-To: <8BCF50C4-D36B-4453-9B09-AA717AE6F563@msqr.us> References: <087DA595-FB65-49F4-89E9-AE9F5CBF6E4C@msqr.us> <8BCF50C4-D36B-4453-9B09-AA717AE6F563@msqr.us> Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable User-Agent: Evolution 3.58.3 (3.58.3-1.fc43) MIME-Version: 1.0 List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk On Thu, 2026-04-30 at 14:48 +1200, Matt Magoffin wrote: > > On 30 Apr 2026, at 11:37=E2=80=AFAM, Adrian Klaver wrote: > >=20 > > So in your first case the INSERT is never done and there is no lock for= the INSERT in any case. >=20 > Thanks for the info, Adrian. And so for my 2nd case, where the INSERT is = blocked by the > DELETE statement, I see the docs say >=20 > The FOR UPDATE lock mode is also acquired by any DELETE on a row=E2=80= =A6 >=20 > But I am not finding the info that talks about why the INSERT =E2=80=A6 O= N CONFLICT DO NOTHING does > block until the DELETE finishes. I guess in my mind the SELECT =E2=80=A6 = FOR UPDATE and DELETE were > acquiring the same kind of row lock, so the behaviour of the INSERT would= be the same across both cases. >=20 > I suppose what I=E2=80=99d be keen to confirm is that the blocking behavi= our I get with the DELETE is > expected behaviour, that I can count on. Do you know if that is true? I admit that the behavior difference surprised me too. I tried to spot the difference, and using the pageinspect extension I see t= he following: - after the DELETE, "infomask" is set to 0x0100 - after the SELECT ... FOR UPDATE, "infomask" is set to 0x01c0 Now 0x0100 is HEAP_XMIN_COMMITTED, a hint bit. The difference is that in the SELECT ... FOR UPDATE case, there are also HE= AP_XMAX_EXCL_LOCK and HEAP_XMAX_LOCK_ONLY set, which means that "xmax" stores an exclusive ro= w lock. In other words, after the DELETE, there is *no* row lock on the row. "xmax= " stores the transaction ID of the transaction that deleted the row - only that tran= saction is still active, and its effects not yet visible. So I'd say that the documentation is not quite accurate. Really, the DELET= E does not place a row lock on the row. That must account for the behavior difference: after the SELECT ... FOR UPD= ATE, the INSERT ... ON CONFLICT interprets the row lock as a conflict and moves on, = while in the DELETE case it sees no conflict (yet), but has to wait for the transaction = to complete before it knows how to proceed. I cannot say if that is intentional; as I said initially, I am surprised to= o. Yours, Laurenz Albe