Skip to content

Commit 3252ffd

Browse files
charliettxxmy-ship-it
authored andcommitted
fix delete with split update (#15288)
If DELETE operator is generated by SplitUpdate node (SplitUpdate node is generated for updating the partition keys), we raise an error. The root cause is SplitUpdate will split the origin tuple to two tuples, one is for deleting and the other one is for inserting. we can skip the deleting tuple if we found the tuple is updated concurrently by another transaction, but it is difficult to skip the inserting tuple, so it will leads to more tuples after updating.
1 parent 68c758b commit 3252ffd

File tree

4 files changed

+90
-0
lines changed

4 files changed

+90
-0
lines changed

src/backend/executor/nodeModifyTable.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1454,6 +1454,25 @@ ldelete:;
14541454
ereport(ERROR,
14551455
(errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
14561456
errmsg("could not serialize access due to concurrent delete")));
1457+
1458+
/*
1459+
* If DELETE operator is generated by SplitUpdate node (SplitUpdate
1460+
* node is generated for updating the partition keys), we raise an error.
1461+
*
1462+
* The root cause is SplitUpdate will split the origin tuple
1463+
* to two tuples, one is for deleting and the other one
1464+
* is for inserting. we can skip the deleting tuple if we
1465+
* found the tuple is updated concurrently by another
1466+
* transaction, but it is difficult to skip the inserting
1467+
* tuple, so it will leads to more tuples after updating.
1468+
*/
1469+
if (splitUpdate)
1470+
{
1471+
ereport(ERROR,
1472+
(errcode(ERRCODE_IN_FAILED_SQL_TRANSACTION ),
1473+
errmsg("could not split update tuple which has been deleted by other transaction")));
1474+
}
1475+
14571476
/* tuple already deleted; nothing to do */
14581477
return NULL;
14591478

src/test/isolation2/expected/gdd/concurrent_update.out

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,33 @@ DROP
240240
DROP
241241
0q: ... <quitting>
242242

243+
-- test ORCA partition table
244+
create table test(a int, b int, c int) partition by range(b) (start (1) end (7) every (3));
245+
CREATE
246+
insert into test values (1, 1, 1);
247+
INSERT 1
248+
1: begin;
249+
BEGIN
250+
1: delete from test where b = 1;
251+
DELETE 1
252+
-- in session 2, in case of ORCA DML invokes EPQ
253+
-- the following SQL will hang due to XID lock
254+
2&: update test set b = 1; <waiting ...>
255+
1: end;
256+
END
257+
2<: <... completed>
258+
UPDATE 0
259+
260+
0: select * from test;
261+
a | b | c
262+
---+---+---
263+
(0 rows)
264+
0: drop table test;
265+
DROP
266+
0q: ... <quitting>
267+
1q: ... <quitting>
268+
2q: ... <quitting>
269+
243270
-- split update is to implement updating on hash keys,
244271
-- it deletes the tuple and insert a new tuple in a
245272
-- new segment, so it is not easy for other transaction

src/test/isolation2/sql/gdd/concurrent_update.sql

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,23 @@ DROP TABLE t_concurrent_update;
129129
0: drop table tab_update_epq2;
130130
0q:
131131

132+
-- test ORCA partition table
133+
create table test(a int, b int, c int) partition by range(b) (start (1) end (7) every (3));
134+
insert into test values (1, 1, 1);
135+
1: begin;
136+
1: delete from test where b = 1;
137+
-- in session 2, in case of ORCA DML invokes EPQ
138+
-- the following SQL will hang due to XID lock
139+
2&: update test set b = 1;
140+
1: end;
141+
2<:
142+
143+
0: select * from test;
144+
0: drop table test;
145+
0q:
146+
1q:
147+
2q:
148+
132149
-- split update is to implement updating on hash keys,
133150
-- it deletes the tuple and insert a new tuple in a
134151
-- new segment, so it is not easy for other transaction

src/test/singlenode_isolation2/expected/gdd/concurrent_update.out

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,33 @@ DROP
240240
DROP
241241
0q: ... <quitting>
242242

243+
-- test ORCA partition table
244+
create table test(a int, b int, c int) partition by range(b) (start (1) end (7) every (3));
245+
CREATE
246+
insert into test values (1, 1, 1);
247+
INSERT 1
248+
1: begin;
249+
BEGIN
250+
1: delete from test where b = 1;
251+
DELETE 1
252+
-- in session 2, in case of ORCA DML invokes EPQ
253+
-- the following SQL will hang due to XID lock
254+
2&: update test set b = 1; <waiting ...>
255+
1: end;
256+
END
257+
2<: <... completed>
258+
ERROR: could not split update tuple which has been deleted by other transaction (seg1 127.0.0.1:7003 pid=22726)
259+
260+
0: select * from test;
261+
a | b | c
262+
---+---+---
263+
(0 rows)
264+
0: drop table test;
265+
DROP
266+
0q: ... <quitting>
267+
1q: ... <quitting>
268+
2q: ... <quitting>
269+
243270
-- split update is to implement updating on hash keys,
244271
-- it deletes the tuple and insert a new tuple in a
245272
-- new segment, so it is not easy for other transaction

0 commit comments

Comments
 (0)