Skip to content

Commit e083296

Browse files
author
Alexander Korotkov
committed
WAL-logged shift of xid epoch.
1 parent 5dcc84b commit e083296

File tree

4 files changed

+89
-11
lines changed

4 files changed

+89
-11
lines changed

src/backend/access/heap/heapam.c

Lines changed: 65 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2640,17 +2640,17 @@ heap_page_xid_min_max(Page page, bool multi,
26402640
}
26412641

26422642
/*
2643-
* Shift xid epoch in the page.
2643+
* Shift xid epoch in the page. WAL-logged if buffer is specified.
26442644
*/
26452645
static void
2646-
heap_page_shift_epoch(Page page, bool multi, int64 delta)
2646+
heap_page_shift_epoch(Buffer buffer, Page page, bool multi, int64 delta)
26472647
{
26482648
PageHeader pageHdr = (PageHeader) page;
26492649
OffsetNumber offnum,
26502650
maxoff;
26512651

2652+
/* Iterate over page items */
26522653
maxoff = PageGetMaxOffsetNumber(page);
2653-
26542654
for (offnum = FirstOffsetNumber;
26552655
offnum <= maxoff;
26562656
offnum = OffsetNumberNext(offnum))
@@ -2665,6 +2665,7 @@ heap_page_shift_epoch(Page page, bool multi, int64 delta)
26652665

26662666
htup = (HeapTupleHeader) PageGetItem(page, itemid);
26672667

2668+
/* Apply xid shift to heap tuple */
26682669
if (!multi)
26692670
{
26702671
if (!HeapTupleHeaderXminFrozen(htup) &&
@@ -2695,12 +2696,36 @@ heap_page_shift_epoch(Page page, bool multi, int64 delta)
26952696
}
26962697
}
26972698

2699+
/* Apply xid shift to epoch as well */
26982700
if (!multi)
26992701
pageHdr->pd_xid_epoch += delta;
27002702
else
27012703
pageHdr->pd_multi_epoch += delta;
2704+
2705+
/* Write WAL record if needed */
2706+
if (BufferIsValid(buffer))
2707+
{
2708+
XLogRecPtr recptr;
2709+
xl_heap_epoch_shift xlrec;
2710+
2711+
xlrec.multi = multi;
2712+
xlrec.delta = delta;
2713+
2714+
XLogBeginInsert();
2715+
XLogRegisterData((char *) &xlrec, SizeOfHeapEpochShift);
2716+
2717+
XLogRegisterBuffer(0, buffer, REGBUF_STANDARD);
2718+
2719+
recptr = XLogInsert(RM_HEAP_ID, XLOG_HEAP_EPOCH_SHIFT);
2720+
2721+
PageSetLSN(page, recptr);
2722+
}
27022723
}
27032724

2725+
/*
2726+
* Freeze xids in the single heap page. Useful when we can't fit new xid even
2727+
* with epoch shift.
2728+
*/
27042729
static int
27052730
freeze_single_heap_page(Relation relation, Buffer buffer)
27062731
{
@@ -2853,7 +2878,8 @@ heap_page_prepare_for_xid(Relation relation, Buffer buffer,
28532878

28542879
if (requiredDelta <= freeDelta)
28552880
{
2856-
heap_page_shift_epoch(page, multi, - (freeDelta + requiredDelta) / 2);
2881+
heap_page_shift_epoch(RelationNeedsWAL(relation) ? buffer : InvalidBuffer,
2882+
page, multi, - (freeDelta + requiredDelta) / 2);
28572883
MarkBufferDirty(buffer);
28582884
return true;
28592885
}
@@ -2865,7 +2891,8 @@ heap_page_prepare_for_xid(Relation relation, Buffer buffer,
28652891

28662892
if (requiredDelta <= freeDelta)
28672893
{
2868-
heap_page_shift_epoch(page, multi, (freeDelta + requiredDelta) / 2);
2894+
heap_page_shift_epoch(RelationNeedsWAL(relation) ? buffer : InvalidBuffer,
2895+
page, multi, (freeDelta + requiredDelta) / 2);
28692896
MarkBufferDirty(buffer);
28702897
return true;
28712898
}
@@ -2876,7 +2903,7 @@ heap_page_prepare_for_xid(Relation relation, Buffer buffer,
28762903
break;
28772904
}
28782905

2879-
/* Have to freeze the page... */
2906+
/* Have to try freeing the page... */
28802907
freeze_single_heap_page(relation, buffer);
28812908
}
28822909

@@ -2929,7 +2956,8 @@ rewrite_page_prepare_for_xid(Page page, TransactionId xid, bool multi)
29292956

29302957
if (requiredDelta <= freeDelta)
29312958
{
2932-
heap_page_shift_epoch(page, multi, - (freeDelta + requiredDelta) / 2);
2959+
heap_page_shift_epoch(InvalidBuffer,
2960+
page, multi, - (freeDelta + requiredDelta) / 2);
29332961
return true;
29342962
}
29352963
}
@@ -2940,7 +2968,8 @@ rewrite_page_prepare_for_xid(Page page, TransactionId xid, bool multi)
29402968

29412969
if (requiredDelta <= freeDelta)
29422970
{
2943-
heap_page_shift_epoch(page, multi, (freeDelta + requiredDelta) / 2);
2971+
heap_page_shift_epoch(InvalidBuffer,
2972+
page, multi, (freeDelta + requiredDelta) / 2);
29442973
return true;
29452974
}
29462975
}
@@ -9481,6 +9510,31 @@ heap_xlog_inplace(XLogReaderState *record)
94819510
UnlockReleaseBuffer(buffer);
94829511
}
94839512

9513+
static void
9514+
heap_xlog_epoch_shift(XLogReaderState *record)
9515+
{
9516+
XLogRecPtr lsn = record->EndRecPtr;
9517+
xl_heap_epoch_shift *xlrec = (xl_heap_epoch_shift *) XLogRecGetData(record);
9518+
Buffer buffer;
9519+
Page page;
9520+
BlockNumber blkno;
9521+
RelFileNode target_node;
9522+
9523+
XLogRecGetBlockTag(record, 0, &target_node, NULL, &blkno);
9524+
9525+
if (XLogReadBufferForRedo(record, 0, &buffer) == BLK_NEEDS_REDO)
9526+
{
9527+
page = BufferGetPage(buffer);
9528+
heap_page_shift_epoch(InvalidBuffer, page, xlrec->multi, xlrec->delta);
9529+
PageSetLSN(page, lsn);
9530+
MarkBufferDirty(buffer);
9531+
}
9532+
9533+
if (BufferIsValid(buffer))
9534+
UnlockReleaseBuffer(buffer);
9535+
}
9536+
9537+
94849538
void
94859539
heap_redo(XLogReaderState *record)
94869540
{
@@ -9502,6 +9556,9 @@ heap_redo(XLogReaderState *record)
95029556
case XLOG_HEAP_UPDATE:
95039557
heap_xlog_update(record, false);
95049558
break;
9559+
case XLOG_HEAP_EPOCH_SHIFT:
9560+
heap_xlog_epoch_shift(record);
9561+
break;
95059562
case XLOG_HEAP_HOT_UPDATE:
95069563
heap_xlog_update(record, true);
95079564
break;

src/backend/access/heap/rewriteheap.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -719,9 +719,9 @@ raw_heap_insert(RewriteState state, HeapTuple tup)
719719
rewrite_page_prepare_for_xid(page, HeapTupleGetRawXmax(heaptup),
720720
(heaptup->t_data->t_infomask & HEAP_XMAX_IS_MULTI) ? true : false);
721721

722-
HeapTupleHeaderSetXmin(page, heaptup->t_data, HeapTupleGetXmin(heaptup));
723-
HeapTupleHeaderSetXmax(page, heaptup->t_data, HeapTupleGetRawXmax(heaptup));
724722
HeapTupleCopyEpochFromPage(heaptup, page);
723+
HeapTupleSetXmin(heaptup, HeapTupleGetXmin(heaptup));
724+
HeapTupleSetXmax(heaptup, HeapTupleGetRawXmax(heaptup));
725725

726726
/* And now we can insert the tuple into the page */
727727
newoff = PageAddItem(page, (Item) heaptup->t_data, heaptup->t_len,

src/backend/access/rmgrdesc/heapdesc.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,14 @@ heap_desc(StringInfo buf, XLogReaderState *record)
6363
xlrec->new_offnum,
6464
xlrec->new_xmax);
6565
}
66+
else if (info == XLOG_HEAP_EPOCH_SHIFT)
67+
{
68+
xl_heap_epoch_shift *xlrec = (xl_heap_epoch_shift *) rec;
69+
70+
appendStringInfo(buf, "%s delta " INT64_FORMAT " ",
71+
xlrec->multi ? "MultiXactId" : "XactId",
72+
xlrec->delta);
73+
}
6674
else if (info == XLOG_HEAP_HOT_UPDATE)
6775
{
6876
xl_heap_update *xlrec = (xl_heap_update *) rec;
@@ -180,6 +188,9 @@ heap_identify(uint8 info)
180188
case XLOG_HEAP_UPDATE | XLOG_HEAP_INIT_PAGE:
181189
id = "UPDATE+INIT";
182190
break;
191+
case XLOG_HEAP_EPOCH_SHIFT:
192+
id = "EPOCH_SHIFT";
193+
break;
183194
case XLOG_HEAP_HOT_UPDATE:
184195
id = "HOT_UPDATE";
185196
break;

src/include/access/heapam_xlog.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
#define XLOG_HEAP_INSERT 0x00
3333
#define XLOG_HEAP_DELETE 0x10
3434
#define XLOG_HEAP_UPDATE 0x20
35-
/* 0x030 is free, was XLOG_HEAP_MOVE */
35+
#define XLOG_HEAP_EPOCH_SHIFT 0x30
3636
#define XLOG_HEAP_HOT_UPDATE 0x40
3737
#define XLOG_HEAP_CONFIRM 0x50
3838
#define XLOG_HEAP_LOCK 0x60
@@ -367,6 +367,16 @@ typedef struct xl_heap_rewrite_mapping
367367
XLogRecPtr start_lsn; /* Insert LSN at begin of rewrite */
368368
} xl_heap_rewrite_mapping;
369369

370+
/* shift the epoch of xids on heap page */
371+
typedef struct xl_heap_epoch_shift
372+
{
373+
int64 delta; /* delta value to shift the epoch */
374+
bool multi; /* true to shift multixact epoch */
375+
} xl_heap_epoch_shift;
376+
377+
#define SizeOfHeapEpochShift (offsetof(xl_heap_epoch_shift, multi) + sizeof(bool))
378+
379+
370380
extern void HeapTupleHeaderAdvanceLatestRemovedXid(HeapTuple tuple,
371381
TransactionId *latestRemovedXid);
372382

0 commit comments

Comments
 (0)