Thread
Commits
-
Fix handling of updated tuples in the MERGE statement
- f6e63d4b8b2e 16.14 landed
- 8bfaae6fb20c 15.18 landed
- 2dcac93c0065 17.10 landed
- 13fab378e630 18.4 landed
- 177037341a44 19 (unreleased) landed
-
MERGE behavior with REPEATABLE READ isolation level
Alexander Korotkov <aekorotkov@gmail.com> — 2026-02-15T01:20:49Z
Hi hackers, I found it strange that ExecMergeMatched() checks for IsolationUsesXactSnapshot() in the TM_Deleted case, but not in the TM_Updated case. Indeed, EPQ works on the repeatable read isolation level! s1# create table test (id int primary key, val int); s1# insert into test values (1,0); s2# begin; s2# update test set val = val + 100; s1# MERGE INTO test t USING (VALUES (1, 100)) AS s (id, inc) ON t.id = s.id WHEN MATCHED THEN UPDATE SET val = t.val + s.inc WHEN NOT MATCHED THEN INSERT (id, val) VALUES (s.id, s.inc); (waiting ...) s2# commit; s1# MERGE 1 s1# select * from test; id | val ----+----- 1 | 200 (1 row) Quick search didn't give an explanation of this to me. I also don't see this covered by an isolation test. Is it an intended behavior or a bug? (Sorry for buzz if this was discussed before) ------ Regards, Alexander Korotkov Supabase -
Re: MERGE behavior with REPEATABLE READ isolation level
Alexander Korotkov <aekorotkov@gmail.com> — 2026-02-15T01:22:43Z
On Sun, Feb 15, 2026 at 3:20 AM Alexander Korotkov <aekorotkov@gmail.com> wrote: > Hi hackers, > > I found it strange that ExecMergeMatched() checks for > IsolationUsesXactSnapshot() in the TM_Deleted case, but not in the > TM_Updated case. Indeed, EPQ works on the repeatable read isolation level! > > s1# create table test (id int primary key, val int); > s1# insert into test values (1,0); > > s2# begin; > s2# update test set val = val + 100; > > s1# MERGE INTO test t USING (VALUES (1, 100)) AS s (id, inc) > ON t.id = s.id > WHEN MATCHED THEN > UPDATE SET val = t.val + s.inc > WHEN NOT MATCHED THEN > INSERT (id, val) VALUES (s.id, s.inc); > (waiting ...) > > s2# commit; > s1# MERGE 1 > s1# select * from test; > id | val > ----+----- > 1 | 200 > (1 row) > Oh, sorry I missed the begin statement for s1. The complete case should look like this. s1# create table test (id int primary key, val int); s1# insert into test values (1,0); s2# begin; s2# update test set val = val + 100; s1# begin isolation level repeatable read; s1# MERGE INTO test t USING (VALUES (1, 100)) AS s (id, inc) ON t.id = s.id WHEN MATCHED THEN UPDATE SET val = t.val + s.inc WHEN NOT MATCHED THEN INSERT (id, val) VALUES (s.id, s.inc); (waiting ...) s2# commit; s1# MERGE 1 s1# select * from test; id | val ----+----- 1 | 200 (1 row) ------ Regards, Alexander Korotkov Supabase -
Re: MERGE behavior with REPEATABLE READ isolation level
Tender Wang <tndrwang@gmail.com> — 2026-02-24T03:12:20Z
Hi Alexander, Alexander Korotkov <aekorotkov@gmail.com> 于2026年2月15日周日 09:23写道: > Oh, sorry I missed the begin statement for s1. The complete case should look like this. > > s1# create table test (id int primary key, val int); > s1# insert into test values (1,0); > > s2# begin; > s2# update test set val = val + 100; > > s1# begin isolation level repeatable read; > s1# MERGE INTO test t USING (VALUES (1, 100)) AS s (id, inc) > ON t.id = s.id > WHEN MATCHED THEN > UPDATE SET val = t.val + s.inc > WHEN NOT MATCHED THEN > INSERT (id, val) VALUES (s.id, s.inc); > (waiting ...) > > s2# commit; > > s1# MERGE 1 > s1# select * from test; > id | val > ----+----- > 1 | 200 > (1 row) > I tried "update test set val = val + 100;" but the SQL reported a "could not serialize access due to concurrent update" error. It seems that the MERGE command should behave identically to UPDATE when performing a match action. I wrote a fix patch and attached it, and added your test case, too. -- Thanks, Tender Wang
-
Re: MERGE behavior with REPEATABLE READ isolation level
Dean Rasheed <dean.a.rasheed@gmail.com> — 2026-02-24T09:09:54Z
On Tue, 24 Feb 2026 at 03:13, Tender Wang <tndrwang@gmail.com> wrote: > > Alexander Korotkov <aekorotkov@gmail.com> 于2026年2月15日周日 09:23写道: > > > > I found it strange that ExecMergeMatched() checks for IsolationUsesXactSnapshot() in the TM_Deleted case, but not in the TM_Updated case. > > I tried "update test set val = val + 100;" but the SQL reported a > "could not serialize access due to concurrent update" error. > It seems that the MERGE command should behave identically to UPDATE > when performing a match action. > Yes, I agree. I think this is a bug (probably just an oversight in the original MERGE commit). Regards, Dean
-
Re: MERGE behavior with REPEATABLE READ isolation level
Alexander Korotkov <aekorotkov@gmail.com> — 2026-02-26T17:03:01Z
On Tue, Feb 24, 2026 at 5:13 AM Tender Wang <tndrwang@gmail.com> wrote: > Alexander Korotkov <aekorotkov@gmail.com> 于2026年2月15日周日 09:23写道: > > Oh, sorry I missed the begin statement for s1. The complete case should look like this. > > > > s1# create table test (id int primary key, val int); > > s1# insert into test values (1,0); > > > > s2# begin; > > s2# update test set val = val + 100; > > > > s1# begin isolation level repeatable read; > > s1# MERGE INTO test t USING (VALUES (1, 100)) AS s (id, inc) > > ON t.id = s.id > > WHEN MATCHED THEN > > UPDATE SET val = t.val + s.inc > > WHEN NOT MATCHED THEN > > INSERT (id, val) VALUES (s.id, s.inc); > > (waiting ...) > > > > s2# commit; > > > > s1# MERGE 1 > > s1# select * from test; > > id | val > > ----+----- > > 1 | 200 > > (1 row) > > > > I tried "update test set val = val + 100;" but the SQL reported a > "could not serialize access due to concurrent update" error. > It seems that the MERGE command should behave identically to UPDATE > when performing a match action. > > I wrote a fix patch and attached it, and added your test case, too. Thank you for the confirmation and for the patch. Regarding the test case, can we handle this without introducing a new .spec file? I think we can add 1-2 permutations to merge-update.spec. Even existing step should work, you only need one new which begins transaction in RR isolation mode. ------ Regards, Alexander Korotkov Supabase
-
Re: MERGE behavior with REPEATABLE READ isolation level
Tender Wang <tndrwang@gmail.com> — 2026-02-27T12:54:06Z
Hi all, Alexander Korotkov <aekorotkov@gmail.com> 于2026年2月27日周五 01:03写道: > Thank you for the confirmation and for the patch. Regarding the test > case, can we handle this without introducing a new .spec file? I > think we can add 1-2 permutations to merge-update.spec. Even existing > step should work, you only need one new which begins transaction in RR > isolation mode. Done Please see the v2 patch. -- Thanks, Tender Wang
-
Re: MERGE behavior with REPEATABLE READ isolation level
Alexander Korotkov <aekorotkov@gmail.com> — 2026-03-01T22:32:12Z
On Fri, Feb 27, 2026 at 2:54 PM Tender Wang <tndrwang@gmail.com> wrote: > Alexander Korotkov <aekorotkov@gmail.com> 于2026年2月27日周五 01:03写道: > > Thank you for the confirmation and for the patch. Regarding the test > > case, can we handle this without introducing a new .spec file? I > > think we can add 1-2 permutations to merge-update.spec. Even existing > > step should work, you only need one new which begins transaction in RR > > isolation mode. > > Done > Please see the v2 patch. Looks good to me. I'll push it if no objections. ------ Regards, Alexander Korotkov Supabase