@@ -2640,17 +2640,17 @@ heap_page_xid_min_max(Page page, bool multi,
2640
2640
}
2641
2641
2642
2642
/*
2643
- * Shift xid epoch in the page.
2643
+ * Shift xid epoch in the page. WAL-logged if buffer is specified.
2644
2644
*/
2645
2645
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 )
2647
2647
{
2648
2648
PageHeader pageHdr = (PageHeader ) page ;
2649
2649
OffsetNumber offnum ,
2650
2650
maxoff ;
2651
2651
2652
+ /* Iterate over page items */
2652
2653
maxoff = PageGetMaxOffsetNumber (page );
2653
-
2654
2654
for (offnum = FirstOffsetNumber ;
2655
2655
offnum <= maxoff ;
2656
2656
offnum = OffsetNumberNext (offnum ))
@@ -2665,6 +2665,7 @@ heap_page_shift_epoch(Page page, bool multi, int64 delta)
2665
2665
2666
2666
htup = (HeapTupleHeader ) PageGetItem (page , itemid );
2667
2667
2668
+ /* Apply xid shift to heap tuple */
2668
2669
if (!multi )
2669
2670
{
2670
2671
if (!HeapTupleHeaderXminFrozen (htup ) &&
@@ -2695,12 +2696,36 @@ heap_page_shift_epoch(Page page, bool multi, int64 delta)
2695
2696
}
2696
2697
}
2697
2698
2699
+ /* Apply xid shift to epoch as well */
2698
2700
if (!multi )
2699
2701
pageHdr -> pd_xid_epoch += delta ;
2700
2702
else
2701
2703
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
+ }
2702
2723
}
2703
2724
2725
+ /*
2726
+ * Freeze xids in the single heap page. Useful when we can't fit new xid even
2727
+ * with epoch shift.
2728
+ */
2704
2729
static int
2705
2730
freeze_single_heap_page (Relation relation , Buffer buffer )
2706
2731
{
@@ -2853,7 +2878,8 @@ heap_page_prepare_for_xid(Relation relation, Buffer buffer,
2853
2878
2854
2879
if (requiredDelta <= freeDelta )
2855
2880
{
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 );
2857
2883
MarkBufferDirty (buffer );
2858
2884
return true;
2859
2885
}
@@ -2865,7 +2891,8 @@ heap_page_prepare_for_xid(Relation relation, Buffer buffer,
2865
2891
2866
2892
if (requiredDelta <= freeDelta )
2867
2893
{
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 );
2869
2896
MarkBufferDirty (buffer );
2870
2897
return true;
2871
2898
}
@@ -2876,7 +2903,7 @@ heap_page_prepare_for_xid(Relation relation, Buffer buffer,
2876
2903
break ;
2877
2904
}
2878
2905
2879
- /* Have to freeze the page... */
2906
+ /* Have to try freeing the page... */
2880
2907
freeze_single_heap_page (relation , buffer );
2881
2908
}
2882
2909
@@ -2929,7 +2956,8 @@ rewrite_page_prepare_for_xid(Page page, TransactionId xid, bool multi)
2929
2956
2930
2957
if (requiredDelta <= freeDelta )
2931
2958
{
2932
- heap_page_shift_epoch (page , multi , - (freeDelta + requiredDelta ) / 2 );
2959
+ heap_page_shift_epoch (InvalidBuffer ,
2960
+ page , multi , - (freeDelta + requiredDelta ) / 2 );
2933
2961
return true;
2934
2962
}
2935
2963
}
@@ -2940,7 +2968,8 @@ rewrite_page_prepare_for_xid(Page page, TransactionId xid, bool multi)
2940
2968
2941
2969
if (requiredDelta <= freeDelta )
2942
2970
{
2943
- heap_page_shift_epoch (page , multi , (freeDelta + requiredDelta ) / 2 );
2971
+ heap_page_shift_epoch (InvalidBuffer ,
2972
+ page , multi , (freeDelta + requiredDelta ) / 2 );
2944
2973
return true;
2945
2974
}
2946
2975
}
@@ -9481,6 +9510,31 @@ heap_xlog_inplace(XLogReaderState *record)
9481
9510
UnlockReleaseBuffer (buffer );
9482
9511
}
9483
9512
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
+
9484
9538
void
9485
9539
heap_redo (XLogReaderState * record )
9486
9540
{
@@ -9502,6 +9556,9 @@ heap_redo(XLogReaderState *record)
9502
9556
case XLOG_HEAP_UPDATE :
9503
9557
heap_xlog_update (record , false);
9504
9558
break ;
9559
+ case XLOG_HEAP_EPOCH_SHIFT :
9560
+ heap_xlog_epoch_shift (record );
9561
+ break ;
9505
9562
case XLOG_HEAP_HOT_UPDATE :
9506
9563
heap_xlog_update (record , true);
9507
9564
break ;
0 commit comments