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

Commit2873fbf

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 parentfef92f9 commit2873fbf

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
@@ -2856,13 +2856,7 @@ heap_delete(Relation relation, ItemPointer tid,
28562856
result=TM_Deleted;
28572857
}
28582858

2859-
if (crosscheck!=InvalidSnapshot&&result==TM_Ok)
2860-
{
2861-
/* Perform additional check for transaction-snapshot mode RI updates */
2862-
if (!HeapTupleSatisfiesVisibility(&tp,crosscheck,buffer))
2863-
result=TM_Updated;
2864-
}
2865-
2859+
/* sanity check the result HeapTupleSatisfiesUpdate() and the logic above */
28662860
if (result!=TM_Ok)
28672861
{
28682862
Assert(result==TM_SelfModified||
@@ -2872,6 +2866,17 @@ heap_delete(Relation relation, ItemPointer tid,
28722866
Assert(!(tp.t_data->t_infomask&HEAP_XMAX_INVALID));
28732867
Assert(result!=TM_Updated||
28742868
!ItemPointerEquals(&tp.t_self,&tp.t_data->t_ctid));
2869+
}
2870+
2871+
if (crosscheck!=InvalidSnapshot&&result==TM_Ok)
2872+
{
2873+
/* Perform additional check for transaction-snapshot mode RI updates */
2874+
if (!HeapTupleSatisfiesVisibility(&tp,crosscheck,buffer))
2875+
result=TM_Updated;
2876+
}
2877+
2878+
if (result!=TM_Ok)
2879+
{
28752880
tmfd->ctid=tp.t_data->t_ctid;
28762881
tmfd->xmax=HeapTupleHeaderGetUpdateXid(tp.t_data);
28772882
if (result==TM_SelfModified)
@@ -3483,16 +3488,7 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
34833488
result=TM_Deleted;
34843489
}
34853490

3486-
if (crosscheck!=InvalidSnapshot&&result==TM_Ok)
3487-
{
3488-
/* Perform additional check for transaction-snapshot mode RI updates */
3489-
if (!HeapTupleSatisfiesVisibility(&oldtup,crosscheck,buffer))
3490-
{
3491-
result=TM_Updated;
3492-
Assert(!ItemPointerEquals(&oldtup.t_self,&oldtup.t_data->t_ctid));
3493-
}
3494-
}
3495-
3491+
/* Sanity check the result HeapTupleSatisfiesUpdate() and the logic above */
34963492
if (result!=TM_Ok)
34973493
{
34983494
Assert(result==TM_SelfModified||
@@ -3502,6 +3498,17 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
35023498
Assert(!(oldtup.t_data->t_infomask&HEAP_XMAX_INVALID));
35033499
Assert(result!=TM_Updated||
35043500
!ItemPointerEquals(&oldtup.t_self,&oldtup.t_data->t_ctid));
3501+
}
3502+
3503+
if (crosscheck!=InvalidSnapshot&&result==TM_Ok)
3504+
{
3505+
/* Perform additional check for transaction-snapshot mode RI updates */
3506+
if (!HeapTupleSatisfiesVisibility(&oldtup,crosscheck,buffer))
3507+
result=TM_Updated;
3508+
}
3509+
3510+
if (result!=TM_Ok)
3511+
{
35053512
tmfd->ctid=oldtup.t_data->t_ctid;
35063513
tmfd->xmax=HeapTupleHeaderGetUpdateXid(oldtup.t_data);
35073514
if (result==TM_SelfModified)

‎src/include/access/tableam.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1455,8 +1455,8 @@ table_multi_insert(Relation rel, TupleTableSlot **slots, int nslots,
14551455
* TM_BeingModified (the last only possible if wait == false).
14561456
*
14571457
* In the failure cases, the routine fills *tmfd with the tuple's t_ctid,
1458-
* t_xmax, and, if possible,and, if possible,t_cmax. See comments for
1459-
*structTM_FailureData for additional info.
1458+
* t_xmax, and, if possible, t_cmax. See comments for struct
1459+
* TM_FailureData for additional info.
14601460
*/
14611461
staticinlineTM_Result
14621462
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