mirror of
https://github.com/postgres/postgres.git
synced 2026-10-23 13:29:09 +03:00
Avoid setting pd_prune_xid when inserting frozen tuples
378a216187 set pd_prune_xid on inserts so that on-access pruning could
later set the pages all-visible. heap_multi_insert() skipped this only
when setting the page all-frozen, but it can insert frozen tuples even
when not setting the page all-frozen. Inserting frozen tuples should not
set pd_prune_xid as they introduce no work for on-access pruning. Fix by
only setting pd_prune_xid when inserting non-frozen tuples.
Reported-by: Melanie Plageman <melanieplageman@gmail.com>
Reviewed-by: Chao Li <li.evan.chao@gmail.com>
Discussion: https://postgr.es/m/CAAKRu_a02pu7U2S0qPZ5L%2BoWb2m2Zp965sOKCCLnKUAKNo-hfg%40mail.gmail.com
Backpatch-through: 19
This commit is contained in:
@@ -2493,10 +2493,10 @@ heap_multi_insert(Relation relation, TupleTableSlot **slots, int ntuples,
|
||||
|
||||
/*
|
||||
* Set pd_prune_xid. See heap_insert() for more on why we do this when
|
||||
* inserting tuples. This only makes sense if we aren't already
|
||||
* setting the page frozen in the VM and we're not in bootstrap mode.
|
||||
* inserting tuples. This only makes sense if the tuples aren't frozen
|
||||
* and we're not in bootstrap mode.
|
||||
*/
|
||||
if (!all_frozen_set && TransactionIdIsNormal(xid))
|
||||
if (TransactionIdIsNormal(xid) && !(options & HEAP_INSERT_FROZEN))
|
||||
PageSetPrunable(page, xid);
|
||||
|
||||
MarkBufferDirty(buffer);
|
||||
|
||||
@@ -583,6 +583,7 @@ heap_xlog_multi_insert(XLogReaderState *record)
|
||||
char *tupdata;
|
||||
char *endptr;
|
||||
Size len;
|
||||
bool inserted_tuples_frozen = false;
|
||||
|
||||
/* Tuples are stored as block data */
|
||||
tupdata = XLogRecGetBlockData(record, HEAP_MULTI_INSERT_BLKREF_HEAP,
|
||||
@@ -630,6 +631,10 @@ heap_xlog_multi_insert(XLogReaderState *record)
|
||||
ItemPointerSetBlockNumber(&htup->t_ctid, blkno);
|
||||
ItemPointerSetOffsetNumber(&htup->t_ctid, offnum);
|
||||
|
||||
/* If one inserted tuple was frozen, they all were */
|
||||
if (i == 0)
|
||||
inserted_tuples_frozen = HeapTupleHeaderXminFrozen(htup);
|
||||
|
||||
offnum = PageAddItem(page, htup, newlen, offnum, true, true);
|
||||
if (offnum == InvalidOffsetNumber)
|
||||
elog(PANIC, "failed to add tuple");
|
||||
@@ -645,17 +650,23 @@ heap_xlog_multi_insert(XLogReaderState *record)
|
||||
PageClearAllVisible(page);
|
||||
|
||||
/*
|
||||
* XLH_INSERT_ALL_FROZEN_SET implies that all tuples are visible. If
|
||||
* we are not setting the page frozen, then set the page's prunable
|
||||
* hint so that we trigger on-access pruning later which may set the
|
||||
* page all-visible in the VM.
|
||||
* XLH_INSERT_ALL_FROZEN_SET implies that all tuples are visible, so
|
||||
* set PD_ALL_VISIBLE and clear pd_prune_xid.
|
||||
*
|
||||
* If the page isn't being set all-frozen and we aren't inserting
|
||||
* frozen tuples, set pd_prune_xid so that the page gets on-access
|
||||
* pruned.
|
||||
*
|
||||
* Frozen tuples may be added to an already all-frozen page or to a
|
||||
* page containing non-frozen tuples, but they introduce nothing new
|
||||
* for on-access pruning, so preserve the existing hint.
|
||||
*/
|
||||
if (xlrec->flags & XLH_INSERT_ALL_FROZEN_SET)
|
||||
{
|
||||
PageSetAllVisible(page);
|
||||
PageClearPrunable(page);
|
||||
}
|
||||
else
|
||||
else if (!inserted_tuples_frozen)
|
||||
PageSetPrunable(page, XLogRecGetXid(record));
|
||||
|
||||
MarkBufferDirty(buffer);
|
||||
|
||||
Reference in New Issue
Block a user