1
0
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:
Melanie Plageman
2026-09-14 10:42:55 -04:00
parent 60feb4bc2e
commit 41a8548ad4
2 changed files with 19 additions and 8 deletions

View File

@@ -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);

View File

@@ -586,6 +586,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,
@@ -633,6 +634,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");
@@ -648,17 +653,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);