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

Commit94bc307

Browse files
committed
Fix deletion of speculatively inserted TOAST on conflict
INSERT .. ON CONFLICT runs a pre-check of the possible conflictingconstraints before performing the actual speculative insertion. In casethe inserted tuple included TOASTed columns the ON CONFLICT conditionwould be handled correctly in case the conflict was caught by thepre-check, but if two transactions entered the speculative insertionphase at the same time, one would have to re-try, and the code foraborting a speculative insertion did not handle deleting thespeculatively inserted TOAST datums correctly.TOAST deletion would fail with "ERROR: attempted to delete invisibletuple" as we attempted to remove the TOAST tuples usingsimple_heap_delete which reasoned that the given tuples should not bevisible to the command that wrote them.This commit updates the heap_abort_speculative() function which abortsthe conflicting tuple to use itself, via toast_delete, for deletingassociated TOAST datums. Like before, the inserted toast rows are notmarked as being speculative.This commit also adds a isolationtester spec test, exercising therelevant code path. Unfortunately 9.5 cannot handle two waitingsessions, and thus cannot execute this test.Reported-By: Viren Negi, Oskari SaarenmaaAuthor: Oskari Saarenmaa, edited a bit by meBug: #14150Discussion: <20160519123338.12513.20271@wrigleys.postgresql.org>Backpatch: 9.5, where ON CONFLICT was introduced
1 parentde396a1 commit94bc307

File tree

4 files changed

+20
-13
lines changed

4 files changed

+20
-13
lines changed

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

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3112,7 +3112,7 @@ heap_delete(Relation relation, ItemPointer tid,
31123112
Assert(!HeapTupleHasExternal(&tp));
31133113
}
31143114
elseif (HeapTupleHasExternal(&tp))
3115-
toast_delete(relation,&tp);
3115+
toast_delete(relation,&tp, false);
31163116

31173117
/*
31183118
* Mark tuple for invalidation from system caches at next command
@@ -5723,7 +5723,8 @@ heap_finish_speculative(Relation relation, HeapTuple tuple)
57235723
* could deadlock with each other, which would not be acceptable.
57245724
*
57255725
* This is somewhat redundant with heap_delete, but we prefer to have a
5726-
* dedicated routine with stripped down requirements.
5726+
* dedicated routine with stripped down requirements. Note that this is also
5727+
* used to delete the TOAST tuples created during speculative insertion.
57275728
*
57285729
* This routine does not affect logical decoding as it only looks at
57295730
* confirmation records.
@@ -5767,7 +5768,7 @@ heap_abort_speculative(Relation relation, HeapTuple tuple)
57675768
*/
57685769
if (tp.t_data->t_choice.t_heap.t_xmin!=xid)
57695770
elog(ERROR,"attempted to kill a tuple inserted by another transaction");
5770-
if (!HeapTupleHeaderIsSpeculative(tp.t_data))
5771+
if (!(IsToastRelation(relation)||HeapTupleHeaderIsSpeculative(tp.t_data)))
57715772
elog(ERROR,"attempted to kill a non-speculative tuple");
57725773
Assert(!HeapTupleHeaderIsHeapOnly(tp.t_data));
57735774

@@ -5837,7 +5838,10 @@ heap_abort_speculative(Relation relation, HeapTuple tuple)
58375838
LockBuffer(buffer,BUFFER_LOCK_UNLOCK);
58385839

58395840
if (HeapTupleHasExternal(&tp))
5840-
toast_delete(relation,&tp);
5841+
{
5842+
Assert(!IsToastRelation(relation));
5843+
toast_delete(relation,&tp, true);
5844+
}
58415845

58425846
/*
58435847
* Never need to mark tuple for invalidation, since catalogs don't support

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

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ typedef struct toast_compress_header
6666
#defineTOAST_COMPRESS_SET_RAWSIZE(ptr,len) \
6767
(((toast_compress_header *) (ptr))->rawsize = (len))
6868

69-
staticvoidtoast_delete_datum(Relationrel,Datumvalue);
69+
staticvoidtoast_delete_datum(Relationrel,Datumvalue,boolis_speculative);
7070
staticDatumtoast_save_datum(Relationrel,Datumvalue,
7171
structvarlena*oldexternal,intoptions);
7272
staticbooltoastrel_valueid_exists(Relationtoastrel,Oidvalueid);
@@ -459,7 +459,7 @@ toast_datum_size(Datum value)
459459
* ----------
460460
*/
461461
void
462-
toast_delete(Relationrel,HeapTupleoldtup)
462+
toast_delete(Relationrel,HeapTupleoldtup,boolis_speculative)
463463
{
464464
TupleDesctupleDesc;
465465
Form_pg_attribute*att;
@@ -506,7 +506,7 @@ toast_delete(Relation rel, HeapTuple oldtup)
506506
if (toast_isnull[i])
507507
continue;
508508
elseif (VARATT_IS_EXTERNAL_ONDISK(PointerGetDatum(value)))
509-
toast_delete_datum(rel,value);
509+
toast_delete_datum(rel,value,is_speculative);
510510
}
511511
}
512512
}
@@ -1062,7 +1062,7 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup,
10621062
if (need_delold)
10631063
for (i=0;i<numAttrs;i++)
10641064
if (toast_delold[i])
1065-
toast_delete_datum(rel,toast_oldvalues[i]);
1065+
toast_delete_datum(rel,toast_oldvalues[i], false);
10661066

10671067
returnresult_tuple;
10681068
}
@@ -1654,7 +1654,7 @@ toast_save_datum(Relation rel, Datum value,
16541654
* ----------
16551655
*/
16561656
staticvoid
1657-
toast_delete_datum(Relationrel,Datumvalue)
1657+
toast_delete_datum(Relationrel,Datumvalue,boolis_speculative)
16581658
{
16591659
structvarlena*attr= (structvarlena*)DatumGetPointer(value);
16601660
structvaratt_externaltoast_pointer;
@@ -1703,7 +1703,10 @@ toast_delete_datum(Relation rel, Datum value)
17031703
/*
17041704
* Have a chunk, delete it
17051705
*/
1706-
simple_heap_delete(toastrel,&toasttup->t_self);
1706+
if (is_speculative)
1707+
heap_abort_speculative(toastrel,toasttup);
1708+
else
1709+
simple_heap_delete(toastrel,&toasttup->t_self);
17071710
}
17081711

17091712
/*

‎src/backend/utils/time/tqual.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -408,8 +408,8 @@ HeapTupleSatisfiesToast(HeapTuple htup, Snapshot snapshot,
408408

409409
/*
410410
* An invalid Xmin can be left behind by a speculative insertion that
411-
* iscancelled by super-deleting the tuple.We shouldn't see any of
412-
*those inTOASTtables, but better safe than sorry.
411+
* iscanceled by super-deleting the tuple.This also applies to
412+
* TOASTtuples created during speculative insertion.
413413
*/
414414
elseif (!TransactionIdIsValid(HeapTupleHeaderGetXmin(tuple)))
415415
return false;

‎src/include/access/tuptoaster.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ extern HeapTuple toast_insert_or_update(Relation rel,
142142
*Called by heap_delete().
143143
* ----------
144144
*/
145-
externvoidtoast_delete(Relationrel,HeapTupleoldtup);
145+
externvoidtoast_delete(Relationrel,HeapTupleoldtup,boolis_speculative);
146146

147147
/* ----------
148148
* heap_tuple_fetch_attr() -

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp