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 1vXhFm-0028dw-2z for pgsql-bugs@arkaria.postgresql.org; Mon, 22 Dec 2025 14:51:19 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1vXhFl-00F1ej-30 for pgsql-bugs@arkaria.postgresql.org; Mon, 22 Dec 2025 14:51:18 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vXhFl-00F1eb-1v for pgsql-bugs@lists.postgresql.org; Mon, 22 Dec 2025 14:51:18 +0000 Received: from mail-qk1-x72c.google.com ([2607:f8b0:4864:20::72c]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.96) (envelope-from ) id 1vXhFk-0020is-2s for pgsql-bugs@lists.postgresql.org; Mon, 22 Dec 2025 14:51:17 +0000 Received: by mail-qk1-x72c.google.com with SMTP id af79cd13be357-8b1bb9c3c04so80134685a.3 for ; Mon, 22 Dec 2025 06:51:16 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1766415076; x=1767019876; darn=lists.postgresql.org; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=282tlDe1kqZkuKf5eQPSHfeGtkmA1KJ+7sGnfTIcTs8=; b=QLSIgyWQCPmTsQIzKVHgz5wScxU8K1O+i/I+ogn2nzOhj82Qb6gxGcjRVnxF/Gn+GN r+Z1VN1qPcRyk7FnG96sme6rjtfI837Z+OV2Hq5NaPD6vEWtrsqmREsKSGNFFJe9EfcJ jYXEebyeArjA4qtcEg/GAy3edZJOqfUyEtk7e7wv3AZprisO/XqNcN5eF8ObX4qmupJ/ ufuhiPrfZrsLFpCeIOJwtX8gQ+5Z8dZ3v1ZKRUaOBOH029GKZ1rFR38yH3uskFZ5jkm8 km4ry0PPHijyMNm7Pl+UC3/Lqhlb9quszEk2Jycvd+/NcnldNndnUDQYmETayPs+b5xY 3+Vg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1766415076; x=1767019876; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=282tlDe1kqZkuKf5eQPSHfeGtkmA1KJ+7sGnfTIcTs8=; b=P1kL5EMHsvNVVZS179Y9wAqjmRFOb7J67zLZpYYGKBwAHOYmyEe+322SQjzPARez0K SkfGSNVfbrLDJo+2f8E/wukubZFK4FkTKasdihprt4zA+mSVG8SxBx9sWAKDWZ8rHLFn CSrQLJ1aar0ITgsi0az4hBPT45gQOH1WBZ37Wk2mvNSQXwjuJ9IgxTomXhF/krQWUST5 V7tvG7pCHd6ekOTPuC88/+ZHuRmT4WwSnDQWLI6mgMXG7SRB2kFZI2ihqH1P6KQceF7M PsjxrpQbhfm+ceJ3HUHjY7Ph3707epLVYjPhWwLCLs/8b+DZXFLHvF+Ge4Q0zg8PHDXx QpBA== X-Gm-Message-State: AOJu0Ywkyl7UOsntfNyDucHWoMQ5dpel/h52hjl8haiKc1MbGA4A/Yky wqx2UPGTltytqmJbLNpwADrbDCUC0NuctIGJpyXAxxIz3n7aYPFpNKyzDvwYN0d+LriZXjchZJv BF8IFZWgscpDpoNvsaN25qC/1rIdRydo= X-Gm-Gg: AY/fxX6v1af8S+m0M7hKnNbhWagbLtTXUlh17FUKoTW8oO/5SbpcsKl3D11IDir8MOV rVhraJ6DQFqYoAbthXamuWwvPV6KWpUh1cN88Zg5HpAVsDbftmP1nNGp83KSHKUvQo7KblmzVwK yClS2DDzI56CHrzogtw6yxfOQqZEnD5bgiSgdomsd/tNLIr5LnO0gBQy2Oh244XpTX5tBCU+f0+ NsHrQFunyiaK0eli/AQPf9Ulp0/uIpsDbkRfrHJMHkGEyGJ+SYfOCfuy+YvwXBJQ1iqfQ== X-Google-Smtp-Source: AGHT+IFkQCDkZ1/rsXpVPQrTlR9NxQsqxY0hMXNuQw9q6x4V1XqK2f8J2bFTsvsR0oG3v7YGU1boRxAHEMAYFlKsX4s= X-Received: by 2002:ad4:5d64:0:b0:880:115f:7f6 with SMTP id 6a1803df08f44-88d84536842mr131087726d6.8.1766415075564; Mon, 22 Dec 2025 06:51:15 -0800 (PST) MIME-Version: 1.0 References: <19355-57d7d52ea4980dc6@postgresql.org> <868ff2a518820c8864b6d28510294b2457a126af.camel@cybertec.at> In-Reply-To: <868ff2a518820c8864b6d28510294b2457a126af.camel@cybertec.at> From: Bh W Date: Mon, 22 Dec 2025 22:51:02 +0800 X-Gm-Features: AQt7F2ojvUONcaotI_XQShpWzip9_zBWQCcbvvaRUnGXLJQLMnTBQqr8UlzbgrA Message-ID: Subject: Re: BUG #19355: Attempt to insert data unexpectedly during concurrent update To: Laurenz Albe Cc: pgsql-bugs@lists.postgresql.org Content-Type: multipart/alternative; boundary="0000000000001ae02006468b8f5d" List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --0000000000001ae02006468b8f5d Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable The issue is that the MERGE INTO match condition is not updated. In the MATCHED path of MERGE INTO, when the target row satisfies the match condition and the condition itself has not changed, the system should still be able to handle concurrent updates to the same target row by relying on EvalPlanQual (EPQ) to refetch the latest version of the tuple, and then proceed with the intended update. However, in the current implementation, even though the concurrent update does not modify any columns relevant to the ON condition, the EPQ recheck unexpectedly results in a match condition failure, causing the update path that should remain MATCHED to be treated as NOT MATCHED. In the scenario shown above, if no primary key exists, an extra row will be inserted. Further investigation shows that execution plans using Hash Join do not exhibit this problem. Could you please take a look at my explanation and let me know if anything is inaccurate? I=E2=80=99d also appreciate it if you could check the test s= cenario I provided. Thanks a lot! Laurenz Albe =E4=BA=8E2025=E5=B9=B412=E6=9C=8815= =E6=97=A5=E5=91=A8=E4=B8=80 14:25=E5=86=99=E9=81=93=EF=BC=9A > On Mon, 2025-12-15 at 01:40 +0000, PG Bug reporting form wrote: > > Start two transaction and update on same tuple, raise concurrent update > and > > evalplanqual. It will be found out that the session with evalplanqual > did > > not successfully update the data, but instead attempted to insert a row > of > > data incorrectly. > > I'd say that is expected. > > If you need a guarantee that either INSERT or UPDATE succeed, you have to > use > INSERT ... ON CONFLICT ... DO UPDATE > > Yours, > Laurenz Albe > --0000000000001ae02006468b8f5d Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
The issue is that the MERGE INTO match condition is not up= dated.
In the MATCHED path of MERGE INTO, when the target row satisfies= the match condition and the condition itself has not changed, the system s= hould still be able to handle concurrent updates to the same target row by = relying on EvalPlanQual (EPQ) to refetch the latest version of the tuple, a= nd then proceed with the intended update.
However, in the current implem= entation, even though the concurrent update does not modify any columns rel= evant to the ON condition, the EPQ recheck unexpectedly results in a match = condition failure, causing the update path that should remain MATCHED to be= treated as NOT MATCHED.

In the scenario shown above, if no primary= key exists, an extra row will be inserted.

Further investigation sh= ows that execution plans using Hash Join do not exhibit this problem.

Could you please take a look at my explanatio= n and let me know if anything is inaccurate? I=E2=80=99d also appreciate it= if you could check the test scenario I provided. Thanks a lot!
=
Laurenz Albe <laurenz.albe@cybertec.at> =E4=BA=8E2025=E5=B9=B412=E6=9C=8815=E6= =97=A5=E5=91=A8=E4=B8=80 14:25=E5=86=99=E9=81=93=EF=BC=9A
On Mon, 2025-12-15 at 01:40 +0000, PG Bug reporting form wrote: > Start two transaction and update on same tuple, raise concurrent updat= e and
> evalplanqual.=C2=A0 It will be found out that the session with evalpla= nqual did
> not successfully update the data, but instead attempted to insert a ro= w of
> data incorrectly.

I'd say that is expected.

If you need a guarantee that either INSERT or UPDATE succeed, you have to u= se
INSERT ... ON CONFLICT ... DO UPDATE

Yours,
Laurenz Albe
--0000000000001ae02006468b8f5d--