Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit60f2273

Browse files
committed
Fix assertions with RI triggers in heap_update and heap_delete.
If the tuple being updated is not visible to the crosscheck snapshot,we return TM_Updated but the assertions would not hold in that case.Move them to before the cross-check.Fixes bug #17893. Backpatch to all supported versions.Author: Alexander LakhinBackpatch-through: 12Discussion:https://www.postgresql.org/message-id/17893-35847009eec517b5%40postgresql.org
1 parentcd34247 commit60f2273

File tree

4 files changed

+64
-20
lines changed

4 files changed

+64
-20
lines changed

‎src/backend/access/heap/heapam.c

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2708,13 +2708,7 @@ heap_delete(Relation relation, ItemPointer tid,
27082708
result=TM_Deleted;
27092709
}
27102710

2711-
if (crosscheck!=InvalidSnapshot&&result==TM_Ok)
2712-
{
2713-
/* Perform additional check for transaction-snapshot mode RI updates */
2714-
if (!HeapTupleSatisfiesVisibility(&tp,crosscheck,buffer))
2715-
result=TM_Updated;
2716-
}
2717-
2711+
/* sanity check the result HeapTupleSatisfiesUpdate() and the logic above */
27182712
if (result!=TM_Ok)
27192713
{
27202714
Assert(result==TM_SelfModified||
@@ -2724,6 +2718,17 @@ heap_delete(Relation relation, ItemPointer tid,
27242718
Assert(!(tp.t_data->t_infomask&HEAP_XMAX_INVALID));
27252719
Assert(result!=TM_Updated||
27262720
!ItemPointerEquals(&tp.t_self,&tp.t_data->t_ctid));
2721+
}
2722+
2723+
if (crosscheck!=InvalidSnapshot&&result==TM_Ok)
2724+
{
2725+
/* Perform additional check for transaction-snapshot mode RI updates */
2726+
if (!HeapTupleSatisfiesVisibility(&tp,crosscheck,buffer))
2727+
result=TM_Updated;
2728+
}
2729+
2730+
if (result!=TM_Ok)
2731+
{
27272732
tmfd->ctid=tp.t_data->t_ctid;
27282733
tmfd->xmax=HeapTupleHeaderGetUpdateXid(tp.t_data);
27292734
if (result==TM_SelfModified)
@@ -3342,16 +3347,7 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
33423347
result=TM_Deleted;
33433348
}
33443349

3345-
if (crosscheck!=InvalidSnapshot&&result==TM_Ok)
3346-
{
3347-
/* Perform additional check for transaction-snapshot mode RI updates */
3348-
if (!HeapTupleSatisfiesVisibility(&oldtup,crosscheck,buffer))
3349-
{
3350-
result=TM_Updated;
3351-
Assert(!ItemPointerEquals(&oldtup.t_self,&oldtup.t_data->t_ctid));
3352-
}
3353-
}
3354-
3350+
/* Sanity check the result HeapTupleSatisfiesUpdate() and the logic above */
33553351
if (result!=TM_Ok)
33563352
{
33573353
Assert(result==TM_SelfModified||
@@ -3361,6 +3357,17 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
33613357
Assert(!(oldtup.t_data->t_infomask&HEAP_XMAX_INVALID));
33623358
Assert(result!=TM_Updated||
33633359
!ItemPointerEquals(&oldtup.t_self,&oldtup.t_data->t_ctid));
3360+
}
3361+
3362+
if (crosscheck!=InvalidSnapshot&&result==TM_Ok)
3363+
{
3364+
/* Perform additional check for transaction-snapshot mode RI updates */
3365+
if (!HeapTupleSatisfiesVisibility(&oldtup,crosscheck,buffer))
3366+
result=TM_Updated;
3367+
}
3368+
3369+
if (result!=TM_Ok)
3370+
{
33643371
tmfd->ctid=oldtup.t_data->t_ctid;
33653372
tmfd->xmax=HeapTupleHeaderGetUpdateXid(oldtup.t_data);
33663373
if (result==TM_SelfModified)

‎src/include/access/tableam.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1479,8 +1479,8 @@ table_multi_insert(Relation rel, TupleTableSlot **slots, int nslots,
14791479
* TM_BeingModified (the last only possible if wait == false).
14801480
*
14811481
* In the failure cases, the routine fills *tmfd with the tuple's t_ctid,
1482-
* t_xmax, and, if possible,and, if possible,t_cmax. See comments for
1483-
*structTM_FailureData for additional info.
1482+
* t_xmax, and, if possible, t_cmax. See comments for struct
1483+
* TM_FailureData for additional info.
14841484
*/
14851485
staticinlineTM_Result
14861486
table_tuple_delete(Relationrel,ItemPointertid,CommandIdcid,

‎src/test/isolation/expected/fk-snapshot.out

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,3 +122,25 @@ a
122122
1
123123
(1 row)
124124

125+
126+
starting permutation: s2ip2 s1brr s1ifp2 s2brr s2dp2 s1c s2c
127+
step s2ip2: INSERT INTO pk_noparted VALUES (2);
128+
step s1brr: BEGIN ISOLATION LEVEL REPEATABLE READ;
129+
step s1ifp2: INSERT INTO fk_parted_pk VALUES (2);
130+
step s2brr: BEGIN ISOLATION LEVEL REPEATABLE READ;
131+
step s2dp2: DELETE FROM pk_noparted WHERE a = 2; <waiting ...>
132+
step s1c: COMMIT;
133+
step s2dp2: <... completed>
134+
ERROR: could not serialize access due to concurrent update
135+
step s2c: COMMIT;
136+
137+
starting permutation: s2ip2 s1brr s1ifn2 s2brr s2dp2 s1c s2c
138+
step s2ip2: INSERT INTO pk_noparted VALUES (2);
139+
step s1brr: BEGIN ISOLATION LEVEL REPEATABLE READ;
140+
step s1ifn2: INSERT INTO fk_noparted_sn VALUES (2);
141+
step s2brr: BEGIN ISOLATION LEVEL REPEATABLE READ;
142+
step s2dp2: DELETE FROM pk_noparted WHERE a = 2; <waiting ...>
143+
step s1c: COMMIT;
144+
step s2dp2: <... completed>
145+
ERROR: could not serialize access due to concurrent update
146+
step s2c: COMMIT;

‎src/test/isolation/specs/fk-snapshot.spec

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,21 +13,27 @@ setup
1313
CREATETABLEfk_noparted (
1414
aintREFERENCESfk_parted_pkONDELETENOACTIONINITIALLYDEFERRED
1515
);
16+
17+
CREATETABLEfk_noparted_sn (
18+
aintREFERENCESpk_nopartedONDELETESETNULL
19+
);
20+
1621
INSERTINTOpk_nopartedVALUES (1);
1722
INSERTINTOfk_parted_pkVALUES (1);
1823
INSERTINTOfk_nopartedVALUES (1);
1924
}
2025

2126
teardown
2227
{
23-
DROPTABLEpk_noparted,fk_parted_pk,fk_noparted;
28+
DROPTABLEpk_noparted,fk_parted_pk,fk_noparted,fk_noparted_sn;
2429
}
2530

2631
sessions1
2732
steps1brr{BEGINISOLATIONLEVELREPEATABLEREAD; }
2833
steps1brc{BEGINISOLATIONLEVELREADCOMMITTED; }
2934
steps1ifp2{INSERTINTOfk_parted_pkVALUES (2); }
3035
steps1ifp1{INSERTINTOfk_parted_pkVALUES (1); }
36+
steps1ifn2{INSERTINTOfk_noparted_snVALUES (2); }
3137
steps1dfp{DELETEFROMfk_parted_pkWHEREa=1; }
3238
steps1c{COMMIT; }
3339
steps1sfp{SELECT*FROMfk_parted_pk; }
@@ -38,6 +44,7 @@ session s2
3844
steps2brr{BEGINISOLATIONLEVELREPEATABLEREAD; }
3945
steps2brc{BEGINISOLATIONLEVELREADCOMMITTED; }
4046
steps2ip2{INSERTINTOpk_nopartedVALUES (2); }
47+
steps2dp2{DELETEFROMpk_nopartedWHEREa=2; }
4148
steps2ifn2{INSERTINTOfk_nopartedVALUES (2); }
4249
steps2c{COMMIT; }
4350
steps2sfp{SELECT*FROMfk_parted_pk; }
@@ -59,3 +66,11 @@ permutation s1brc s2brc s2ip2 s1sp s2c s1sp s1ifp2 s2brc s2sfp s1c s1sfp s2ifn2
5966
# the same no matter the snapshot mode
6067
permutations1brrs1dfps1ifp1s1cs1sfn
6168
permutations1brcs1dfps1ifp1s1cs1sfn
69+
70+
# trying to delete a row through DELETE CASCADE, whilst that row is deleted
71+
# in a concurrent transaction
72+
permutations2ip2s1brrs1ifp2s2brrs2dp2s1cs2c
73+
74+
# trying to update a row through DELETE SET NULL, whilst that row is deleted
75+
# in a concurrent transaction
76+
permutations2ip2s1brrs1ifn2s2brrs2dp2s1cs2c

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp