Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 1489b1c

Browse files
Standardize rmgrdesc recovery conflict XID output.
Standardize on the name snapshotConflictHorizon for all XID fields from WAL records that generate recovery conflicts when in hot standby mode. This supersedes the previous latestRemovedXid naming convention. The new naming convention places emphasis on how the values are actually used by REDO routines. How the values are generated during original execution (details of which vary by record type) is deemphasized. Users of tools like pg_waldump can now grep for snapshotConflictHorizon to see all potential sources of recovery conflicts in a standardized way, without necessarily having to consider which specific record types might be involved. Also bring a couple of WAL record types that didn't follow any kind of naming convention into line. These are heapam's VISIBLE record type and SP-GiST's VACUUM_REDIRECT record type. Now every WAL record whose REDO routine calls ResolveRecoveryConflictWithSnapshot() passes through the snapshotConflictHorizon field from its WAL record. This is follow-up work to the refactoring from commit 9e54059 that made FREEZE_PAGE WAL records use a standard snapshotConflictHorizon style XID cutoff. No bump in XLOG_PAGE_MAGIC, since the underlying format of affected WAL records doesn't change. Author: Peter Geoghegan <pg@bowt.ie> Reviewed-By: Andres Freund <andres@anarazel.de> Discussion: https://postgr.es/m/CAH2-Wzm2CQUmViUq7Opgk=McVREHSOorYaAjR1ZpLYkRN7_dPw@mail.gmail.com
1 parent 6ff5aa1 commit 1489b1c

27 files changed

+179
-150
lines changed

src/backend/access/gist/gist.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -1665,10 +1665,10 @@ gistprunepage(Relation rel, Page page, Buffer buffer, Relation heapRel)
16651665

16661666
if (ndeletable > 0)
16671667
{
1668-
TransactionId latestRemovedXid = InvalidTransactionId;
1668+
TransactionId snapshotConflictHorizon = InvalidTransactionId;
16691669

16701670
if (XLogStandbyInfoActive() && RelationNeedsWAL(rel))
1671-
latestRemovedXid =
1671+
snapshotConflictHorizon =
16721672
index_compute_xid_horizon_for_tuples(rel, heapRel, buffer,
16731673
deletable, ndeletable);
16741674

@@ -1694,7 +1694,7 @@ gistprunepage(Relation rel, Page page, Buffer buffer, Relation heapRel)
16941694

16951695
recptr = gistXLogDelete(buffer,
16961696
deletable, ndeletable,
1697-
latestRemovedXid);
1697+
snapshotConflictHorizon);
16981698

16991699
PageSetLSN(page, recptr);
17001700
}

src/backend/access/gist/gistxlog.c

+9-8
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ gistRedoDeleteRecord(XLogReaderState *record)
195195

196196
XLogRecGetBlockTag(record, 0, &rlocator, NULL, NULL);
197197

198-
ResolveRecoveryConflictWithSnapshot(xldata->latestRemovedXid,
198+
ResolveRecoveryConflictWithSnapshot(xldata->snapshotConflictHorizon,
199199
rlocator);
200200
}
201201

@@ -388,14 +388,14 @@ gistRedoPageReuse(XLogReaderState *record)
388388
* PAGE_REUSE records exist to provide a conflict point when we reuse
389389
* pages in the index via the FSM. That's all they do though.
390390
*
391-
* latestRemovedXid was the page's deleteXid. The
391+
* snapshotConflictHorizon was the page's deleteXid. The
392392
* GlobalVisCheckRemovableFullXid(deleteXid) test in gistPageRecyclable()
393393
* conceptually mirrors the PGPROC->xmin > limitXmin test in
394394
* GetConflictingVirtualXIDs(). Consequently, one XID value achieves the
395395
* same exclusion effect on primary and standby.
396396
*/
397397
if (InHotStandby)
398-
ResolveRecoveryConflictWithSnapshotFullXid(xlrec->latestRemovedFullXid,
398+
ResolveRecoveryConflictWithSnapshotFullXid(xlrec->snapshotConflictHorizon,
399399
xlrec->locator);
400400
}
401401

@@ -597,7 +597,7 @@ gistXLogAssignLSN(void)
597597
* Write XLOG record about reuse of a deleted page.
598598
*/
599599
void
600-
gistXLogPageReuse(Relation rel, BlockNumber blkno, FullTransactionId latestRemovedXid)
600+
gistXLogPageReuse(Relation rel, BlockNumber blkno, FullTransactionId deleteXid)
601601
{
602602
gistxlogPageReuse xlrec_reuse;
603603

@@ -610,7 +610,7 @@ gistXLogPageReuse(Relation rel, BlockNumber blkno, FullTransactionId latestRemov
610610
/* XLOG stuff */
611611
xlrec_reuse.locator = rel->rd_locator;
612612
xlrec_reuse.block = blkno;
613-
xlrec_reuse.latestRemovedFullXid = latestRemovedXid;
613+
xlrec_reuse.snapshotConflictHorizon = deleteXid;
614614

615615
XLogBeginInsert();
616616
XLogRegisterData((char *) &xlrec_reuse, SizeOfGistxlogPageReuse);
@@ -672,20 +672,21 @@ gistXLogUpdate(Buffer buffer,
672672
*/
673673
XLogRecPtr
674674
gistXLogDelete(Buffer buffer, OffsetNumber *todelete, int ntodelete,
675-
TransactionId latestRemovedXid)
675+
TransactionId snapshotConflictHorizon)
676676
{
677677
gistxlogDelete xlrec;
678678
XLogRecPtr recptr;
679679

680-
xlrec.latestRemovedXid = latestRemovedXid;
680+
xlrec.snapshotConflictHorizon = snapshotConflictHorizon;
681681
xlrec.ntodelete = ntodelete;
682682

683683
XLogBeginInsert();
684684
XLogRegisterData((char *) &xlrec, SizeOfGistxlogDelete);
685685

686686
/*
687687
* We need the target-offsets array whether or not we store the whole
688-
* buffer, to allow us to find the latestRemovedXid on a standby server.
688+
* buffer, to allow us to find the snapshotConflictHorizon on a standby
689+
* server.
689690
*/
690691
XLogRegisterData((char *) todelete, ntodelete * sizeof(OffsetNumber));
691692

src/backend/access/hash/hash_xlog.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -1000,7 +1000,8 @@ hash_xlog_vacuum_one_page(XLogReaderState *record)
10001000
RelFileLocator rlocator;
10011001

10021002
XLogRecGetBlockTag(record, 0, &rlocator, NULL, NULL);
1003-
ResolveRecoveryConflictWithSnapshot(xldata->latestRemovedXid, rlocator);
1003+
ResolveRecoveryConflictWithSnapshot(xldata->snapshotConflictHorizon,
1004+
rlocator);
10041005
}
10051006

10061007
action = XLogReadBufferForRedoExtended(record, 0, RBM_NORMAL, true, &buffer);

src/backend/access/hash/hashinsert.c

+5-5
Original file line numberDiff line numberDiff line change
@@ -360,9 +360,9 @@ _hash_vacuum_one_page(Relation rel, Relation hrel, Buffer metabuf, Buffer buf)
360360

361361
if (ndeletable > 0)
362362
{
363-
TransactionId latestRemovedXid;
363+
TransactionId snapshotConflictHorizon;
364364

365-
latestRemovedXid =
365+
snapshotConflictHorizon =
366366
index_compute_xid_horizon_for_tuples(rel, hrel, buf,
367367
deletable, ndeletable);
368368

@@ -399,7 +399,7 @@ _hash_vacuum_one_page(Relation rel, Relation hrel, Buffer metabuf, Buffer buf)
399399
xl_hash_vacuum_one_page xlrec;
400400
XLogRecPtr recptr;
401401

402-
xlrec.latestRemovedXid = latestRemovedXid;
402+
xlrec.snapshotConflictHorizon = snapshotConflictHorizon;
403403
xlrec.ntuples = ndeletable;
404404

405405
XLogBeginInsert();
@@ -408,8 +408,8 @@ _hash_vacuum_one_page(Relation rel, Relation hrel, Buffer metabuf, Buffer buf)
408408

409409
/*
410410
* We need the target-offsets array whether or not we store the
411-
* whole buffer, to allow us to find the latestRemovedXid on a
412-
* standby server.
411+
* whole buffer, to allow us to find the snapshotConflictHorizon
412+
* on a standby server.
413413
*/
414414
XLogRegisterData((char *) deletable,
415415
ndeletable * sizeof(OffsetNumber));

src/backend/access/heap/heapam.c

+43-33
Original file line numberDiff line numberDiff line change
@@ -6792,7 +6792,7 @@ heap_freeze_execute_prepared(Relation rel, Buffer buffer,
67926792
Page page = BufferGetPage(buffer);
67936793

67946794
Assert(ntuples > 0);
6795-
Assert(TransactionIdIsValid(FreezeLimit));
6795+
Assert(TransactionIdIsNormal(FreezeLimit));
67966796

67976797
START_CRIT_SECTION();
67986798

@@ -6815,21 +6815,20 @@ heap_freeze_execute_prepared(Relation rel, Buffer buffer,
68156815
int nplans;
68166816
xl_heap_freeze_page xlrec;
68176817
XLogRecPtr recptr;
6818-
TransactionId latestRemovedXid;
6818+
TransactionId snapshotConflictHorizon;
68196819

68206820
/* Prepare deduplicated representation for use in WAL record */
68216821
nplans = heap_xlog_freeze_plan(tuples, ntuples, plans, offsets);
68226822

68236823
/*
6824-
* latestRemovedXid describes the latest processed XID, whereas
68256824
* FreezeLimit is (approximately) the first XID not frozen by VACUUM.
68266825
* Back up caller's FreezeLimit to avoid false conflicts when
68276826
* FreezeLimit is precisely equal to VACUUM's OldestXmin cutoff.
68286827
*/
6829-
latestRemovedXid = FreezeLimit;
6830-
TransactionIdRetreat(latestRemovedXid);
6828+
snapshotConflictHorizon = FreezeLimit;
6829+
TransactionIdRetreat(snapshotConflictHorizon);
68316830

6832-
xlrec.latestRemovedXid = latestRemovedXid;
6831+
xlrec.snapshotConflictHorizon = snapshotConflictHorizon;
68336832
xlrec.nplans = nplans;
68346833

68356834
XLogBeginInsert();
@@ -7401,24 +7400,30 @@ heap_tuple_would_freeze(HeapTupleHeader tuple, TransactionId cutoff_xid,
74017400
}
74027401

74037402
/*
7404-
* If 'tuple' contains any visible XID greater than latestRemovedXid,
7405-
* ratchet forwards latestRemovedXid to the greatest one found.
7406-
* This is used as the basis for generating Hot Standby conflicts, so
7407-
* if a tuple was never visible then removing it should not conflict
7408-
* with queries.
7403+
* Maintain snapshotConflictHorizon for caller by ratcheting forward its value
7404+
* using any committed XIDs contained in 'tuple', an obsolescent heap tuple
7405+
* that caller is in the process of physically removing, e.g. via HOT pruning
7406+
* or index deletion.
7407+
*
7408+
* Caller must initialize its value to InvalidTransactionId, which is
7409+
* generally interpreted as "definitely no need for a recovery conflict".
7410+
* Final value must reflect all heap tuples that caller will physically remove
7411+
* (or remove TID references to) via its ongoing pruning/deletion operation.
7412+
* ResolveRecoveryConflictWithSnapshot() is passed the final value (taken from
7413+
* caller's WAL record) by REDO routine when it replays caller's operation.
74097414
*/
74107415
void
7411-
HeapTupleHeaderAdvanceLatestRemovedXid(HeapTupleHeader tuple,
7412-
TransactionId *latestRemovedXid)
7416+
HeapTupleHeaderAdvanceConflictHorizon(HeapTupleHeader tuple,
7417+
TransactionId *snapshotConflictHorizon)
74137418
{
74147419
TransactionId xmin = HeapTupleHeaderGetXmin(tuple);
74157420
TransactionId xmax = HeapTupleHeaderGetUpdateXid(tuple);
74167421
TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
74177422

74187423
if (tuple->t_infomask & HEAP_MOVED)
74197424
{
7420-
if (TransactionIdPrecedes(*latestRemovedXid, xvac))
7421-
*latestRemovedXid = xvac;
7425+
if (TransactionIdPrecedes(*snapshotConflictHorizon, xvac))
7426+
*snapshotConflictHorizon = xvac;
74227427
}
74237428

74247429
/*
@@ -7431,11 +7436,9 @@ HeapTupleHeaderAdvanceLatestRemovedXid(HeapTupleHeader tuple,
74317436
(!HeapTupleHeaderXminInvalid(tuple) && TransactionIdDidCommit(xmin)))
74327437
{
74337438
if (xmax != xmin &&
7434-
TransactionIdFollows(xmax, *latestRemovedXid))
7435-
*latestRemovedXid = xmax;
7439+
TransactionIdFollows(xmax, *snapshotConflictHorizon))
7440+
*snapshotConflictHorizon = xmax;
74367441
}
7437-
7438-
/* *latestRemovedXid may still be invalid at end */
74397442
}
74407443

74417444
#ifdef USE_PREFETCH
@@ -7558,7 +7561,7 @@ TransactionId
75587561
heap_index_delete_tuples(Relation rel, TM_IndexDeleteOp *delstate)
75597562
{
75607563
/* Initial assumption is that earlier pruning took care of conflict */
7561-
TransactionId latestRemovedXid = InvalidTransactionId;
7564+
TransactionId snapshotConflictHorizon = InvalidTransactionId;
75627565
BlockNumber blkno = InvalidBlockNumber;
75637566
Buffer buf = InvalidBuffer;
75647567
Page page = NULL;
@@ -7769,8 +7772,8 @@ heap_index_delete_tuples(Relation rel, TM_IndexDeleteOp *delstate)
77697772
}
77707773

77717774
/*
7772-
* Maintain latestRemovedXid value for deletion operation as a whole
7773-
* by advancing current value using heap tuple headers. This is
7775+
* Maintain snapshotConflictHorizon value for deletion operation as a
7776+
* whole by advancing current value using heap tuple headers. This is
77747777
* loosely based on the logic for pruning a HOT chain.
77757778
*/
77767779
offnum = ItemPointerGetOffsetNumber(htid);
@@ -7805,12 +7808,12 @@ heap_index_delete_tuples(Relation rel, TM_IndexDeleteOp *delstate)
78057808
* LP_DEAD item. This is okay because the earlier pruning
78067809
* operation that made the line pointer LP_DEAD in the first place
78077810
* must have considered the original tuple header as part of
7808-
* generating its own latestRemovedXid value.
7811+
* generating its own snapshotConflictHorizon value.
78097812
*
78107813
* Relying on XLOG_HEAP2_PRUNE records like this is the same
78117814
* strategy that index vacuuming uses in all cases. Index VACUUM
7812-
* WAL records don't even have a latestRemovedXid field of their
7813-
* own for this reason.
7815+
* WAL records don't even have a snapshotConflictHorizon field of
7816+
* their own for this reason.
78147817
*/
78157818
if (!ItemIdIsNormal(lp))
78167819
break;
@@ -7824,7 +7827,8 @@ heap_index_delete_tuples(Relation rel, TM_IndexDeleteOp *delstate)
78247827
!TransactionIdEquals(HeapTupleHeaderGetXmin(htup), priorXmax))
78257828
break;
78267829

7827-
HeapTupleHeaderAdvanceLatestRemovedXid(htup, &latestRemovedXid);
7830+
HeapTupleHeaderAdvanceConflictHorizon(htup,
7831+
&snapshotConflictHorizon);
78287832

78297833
/*
78307834
* If the tuple is not HOT-updated, then we are at the end of this
@@ -7856,7 +7860,7 @@ heap_index_delete_tuples(Relation rel, TM_IndexDeleteOp *delstate)
78567860
Assert(finalndeltids > 0 || delstate->bottomup);
78577861
delstate->ndeltids = finalndeltids;
78587862

7859-
return latestRemovedXid;
7863+
return snapshotConflictHorizon;
78607864
}
78617865

78627866
/*
@@ -8232,14 +8236,17 @@ bottomup_sort_and_shrink(TM_IndexDeleteOp *delstate)
82328236
* corresponding visibility map block. Both should have already been modified
82338237
* and dirtied.
82348238
*
8239+
* snapshotConflictHorizon comes from the largest xmin on the page being
8240+
* marked all-visible. REDO routine uses it to generate recovery conflicts.
8241+
*
82358242
* If checksums or wal_log_hints are enabled, we may also generate a full-page
82368243
* image of heap_buffer. Otherwise, we optimize away the FPI (by specifying
82378244
* REGBUF_NO_IMAGE for the heap buffer), in which case the caller should *not*
82388245
* update the heap page's LSN.
82398246
*/
82408247
XLogRecPtr
82418248
log_heap_visible(RelFileLocator rlocator, Buffer heap_buffer, Buffer vm_buffer,
8242-
TransactionId cutoff_xid, uint8 vmflags)
8249+
TransactionId snapshotConflictHorizon, uint8 vmflags)
82438250
{
82448251
xl_heap_visible xlrec;
82458252
XLogRecPtr recptr;
@@ -8248,7 +8255,7 @@ log_heap_visible(RelFileLocator rlocator, Buffer heap_buffer, Buffer vm_buffer,
82488255
Assert(BufferIsValid(heap_buffer));
82498256
Assert(BufferIsValid(vm_buffer));
82508257

8251-
xlrec.cutoff_xid = cutoff_xid;
8258+
xlrec.snapshotConflictHorizon = snapshotConflictHorizon;
82528259
xlrec.flags = vmflags;
82538260
XLogBeginInsert();
82548261
XLogRegisterData((char *) &xlrec, SizeOfHeapVisible);
@@ -8683,7 +8690,8 @@ heap_xlog_prune(XLogReaderState *record)
86838690
* no queries running for which the removed tuples are still visible.
86848691
*/
86858692
if (InHotStandby)
8686-
ResolveRecoveryConflictWithSnapshot(xlrec->latestRemovedXid, rlocator);
8693+
ResolveRecoveryConflictWithSnapshot(xlrec->snapshotConflictHorizon,
8694+
rlocator);
86878695

86888696
/*
86898697
* If we have a full-page image, restore it (using a cleanup lock) and
@@ -8851,7 +8859,8 @@ heap_xlog_visible(XLogReaderState *record)
88518859
* rather than killing the transaction outright.
88528860
*/
88538861
if (InHotStandby)
8854-
ResolveRecoveryConflictWithSnapshot(xlrec->cutoff_xid, rlocator);
8862+
ResolveRecoveryConflictWithSnapshot(xlrec->snapshotConflictHorizon,
8863+
rlocator);
88558864

88568865
/*
88578866
* Read the heap page, if it still exists. If the heap file has dropped or
@@ -8939,7 +8948,7 @@ heap_xlog_visible(XLogReaderState *record)
89398948
visibilitymap_pin(reln, blkno, &vmbuffer);
89408949

89418950
visibilitymap_set(reln, blkno, InvalidBuffer, lsn, vmbuffer,
8942-
xlrec->cutoff_xid, xlrec->flags);
8951+
xlrec->snapshotConflictHorizon, xlrec->flags);
89438952

89448953
ReleaseBuffer(vmbuffer);
89458954
FreeFakeRelcacheEntry(reln);
@@ -9105,7 +9114,8 @@ heap_xlog_freeze_page(XLogReaderState *record)
91059114
RelFileLocator rlocator;
91069115

91079116
XLogRecGetBlockTag(record, 0, &rlocator, NULL, NULL);
9108-
ResolveRecoveryConflictWithSnapshot(xlrec->latestRemovedXid, rlocator);
9117+
ResolveRecoveryConflictWithSnapshot(xlrec->snapshotConflictHorizon,
9118+
rlocator);
91099119
}
91109120

91119121
if (XLogReadBufferForRedo(record, 0, &buffer) == BLK_NEEDS_REDO)

src/backend/access/heap/pruneheap.c

+7-7
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ typedef struct
4949
bool old_snap_used;
5050

5151
TransactionId new_prune_xid; /* new prune hint value for page */
52-
TransactionId latestRemovedXid; /* latest xid to be removed by this prune */
52+
TransactionId snapshotConflictHorizon; /* latest xid removed */
5353
int nredirected; /* numbers of entries in arrays below */
5454
int ndead;
5555
int nunused;
@@ -295,7 +295,7 @@ heap_page_prune(Relation relation, Buffer buffer,
295295
prstate.old_snap_xmin = old_snap_xmin;
296296
prstate.old_snap_ts = old_snap_ts;
297297
prstate.old_snap_used = false;
298-
prstate.latestRemovedXid = InvalidTransactionId;
298+
prstate.snapshotConflictHorizon = InvalidTransactionId;
299299
prstate.nredirected = prstate.ndead = prstate.nunused = 0;
300300
memset(prstate.marked, 0, sizeof(prstate.marked));
301301

@@ -418,7 +418,7 @@ heap_page_prune(Relation relation, Buffer buffer,
418418
xl_heap_prune xlrec;
419419
XLogRecPtr recptr;
420420

421-
xlrec.latestRemovedXid = prstate.latestRemovedXid;
421+
xlrec.snapshotConflictHorizon = prstate.snapshotConflictHorizon;
422422
xlrec.nredirected = prstate.nredirected;
423423
xlrec.ndead = prstate.ndead;
424424

@@ -636,8 +636,8 @@ heap_prune_chain(Buffer buffer, OffsetNumber rootoffnum, PruneState *prstate)
636636
!HeapTupleHeaderIsHotUpdated(htup))
637637
{
638638
heap_prune_record_unused(prstate, rootoffnum);
639-
HeapTupleHeaderAdvanceLatestRemovedXid(htup,
640-
&prstate->latestRemovedXid);
639+
HeapTupleHeaderAdvanceConflictHorizon(htup,
640+
&prstate->snapshotConflictHorizon);
641641
ndeleted++;
642642
}
643643

@@ -773,8 +773,8 @@ heap_prune_chain(Buffer buffer, OffsetNumber rootoffnum, PruneState *prstate)
773773
if (tupdead)
774774
{
775775
latestdead = offnum;
776-
HeapTupleHeaderAdvanceLatestRemovedXid(htup,
777-
&prstate->latestRemovedXid);
776+
HeapTupleHeaderAdvanceConflictHorizon(htup,
777+
&prstate->snapshotConflictHorizon);
778778
}
779779
else if (!recent_dead)
780780
break;

0 commit comments

Comments
 (0)