@@ -764,6 +764,8 @@ static void WALInsertLockAcquireExclusive(void);
764
764
static void WALInsertLockRelease (void );
765
765
static void WALInsertLockUpdateInsertingAt (XLogRecPtr insertingAt );
766
766
767
+ static XLogRecPtr SetLastWrittenLSNForBlockRangeInternal (XLogRecPtr lsn , RelFileLocator rlocator , ForkNumber forknum , BlockNumber from , BlockNumber n_blocks );
768
+
767
769
/*
768
770
* Insert an XLOG record represented by an already-constructed chain of data
769
771
* chunks. This is a low-level routine; to construct the WAL record header
@@ -6709,8 +6711,15 @@ GetLastWrittenLSN(RelFileLocator rlocator, ForkNumber forknum, BlockNumber blkno
6709
6711
lsn = entry -> lsn ;
6710
6712
else
6711
6713
{
6712
- LWLockRelease (LastWrittenLsnLock );
6713
- return SetLastWrittenLSNForBlock (lsn , rlocator , forknum , blkno );
6714
+ /*
6715
+ * In case of statements CREATE TABLE AS SELECT... or INSERT FROM SELECT... we are fetching data from source table
6716
+ * and storing it in destination table. It cause problems with prefetch last-written-lsn is known for the pages of
6717
+ * source table (which for example happens after compute restart). In this case we get get global value of
6718
+ * last-written-lsn which is changed frequently as far as we are writing pages of destination table.
6719
+ * As a result request-lsn for the prefetch and request-let when this page is actually needed are different
6720
+ * and we got exported prefetch request. So it actually disarms prefetch.
6721
+ */
6722
+ lsn = SetLastWrittenLSNForBlockRangeInternal (lsn , rlocator , forknum , blkno , 1 );
6714
6723
}
6715
6724
}
6716
6725
else
@@ -6742,51 +6751,46 @@ GetLastWrittenLSNv(RelFileLocator relfilenode, ForkNumber forknum,
6742
6751
BlockNumber blkno , int nblocks , XLogRecPtr * lsns )
6743
6752
{
6744
6753
LastWrittenLsnCacheEntry * entry ;
6754
+ XLogRecPtr lsn ;
6745
6755
6746
6756
Assert (lastWrittenLsnCacheSize != 0 );
6747
6757
Assert (nblocks > 0 );
6748
6758
Assert (PointerIsValid (lsns ));
6749
6759
6760
+ LWLockAcquire (LastWrittenLsnLock , LW_SHARED );
6761
+
6762
+ lsn = XLogCtl -> maxLastWrittenLsn ;
6763
+
6750
6764
if (relfilenode .relNumber != InvalidOid )
6751
6765
{
6752
6766
BufferTag key ;
6753
- XLogRecPtr max_lsn ;
6754
6767
6755
6768
key .spcOid = relfilenode .spcOid ;
6756
6769
key .dbOid = relfilenode .dbOid ;
6757
6770
key .relNumber = relfilenode .relNumber ;
6758
6771
key .forkNum = forknum ;
6759
6772
6760
- LWLockAcquire (LastWrittenLsnLock , LW_SHARED );
6761
-
6762
6773
for (int i = 0 ; i < nblocks ; i ++ )
6763
6774
{
6764
6775
/* Maximal last written LSN among all non-cached pages */
6765
6776
key .blockNum = blkno + i ;
6766
6777
6767
6778
entry = hash_search (lastWrittenLsnCache , & key , HASH_FIND , NULL );
6768
6779
6769
- lsns [i ] = (entry != NULL ) ? entry -> lsn : InvalidXLogRecPtr ;
6770
- }
6771
- max_lsn = XLogCtl -> maxLastWrittenLsn ;
6772
-
6773
- LWLockRelease (LastWrittenLsnLock );
6774
-
6775
- for (int i = 0 ; i < nblocks ; i ++ )
6776
- {
6777
- if (lsns [i ] == InvalidXLogRecPtr )
6780
+ if (entry != NULL )
6778
6781
{
6779
- lsns [i ] = max_lsn ;
6780
- SetLastWrittenLSNForBlock (max_lsn , relfilenode , forknum , key .blockNum );
6782
+ lsns [i ] = entry -> lsn ;
6783
+ }
6784
+ else
6785
+ {
6786
+ lsns [i ] = lsn ;
6787
+ SetLastWrittenLSNForBlockRangeInternal (lsn , relfilenode , forknum , key .blockNum , 1 );
6781
6788
}
6782
6789
}
6783
6790
}
6784
6791
else
6785
6792
{
6786
6793
HASH_SEQ_STATUS seq ;
6787
- XLogRecPtr lsn = XLogCtl -> maxLastWrittenLsn ;
6788
-
6789
- LWLockAcquire (LastWrittenLsnLock , LW_SHARED );
6790
6794
6791
6795
/* Find maximum of all cached LSNs */
6792
6796
hash_seq_init (& seq , lastWrittenLsnCache );
@@ -6795,30 +6799,16 @@ GetLastWrittenLSNv(RelFileLocator relfilenode, ForkNumber forknum,
6795
6799
if (entry -> lsn > lsn )
6796
6800
lsn = entry -> lsn ;
6797
6801
}
6798
- LWLockRelease (LastWrittenLsnLock );
6799
6802
6800
6803
for (int i = 0 ; i < nblocks ; i ++ )
6801
6804
lsns [i ] = lsn ;
6802
6805
}
6806
+ LWLockRelease (LastWrittenLsnLock );
6803
6807
}
6804
6808
6805
- /*
6806
- * SetLastWrittenLSNForBlockRange -- Set maximal LSN of written page range.
6807
- * We maintain cache of last written LSNs with limited size and LRU replacement
6808
- * policy. Keeping last written LSN for each page allows to use old LSN when
6809
- * requesting pages of unchanged or appended relations. Also it is critical for
6810
- * efficient work of prefetch in case massive update operations (like vacuum or remove).
6811
- *
6812
- * rlocator.relNumber can be InvalidOid, in this case maxLastWrittenLsn is updated.
6813
- * SetLastWrittenLsn with dummy rlocator is used by createdb and dbase_redo functions.
6814
- */
6815
- XLogRecPtr
6816
- SetLastWrittenLSNForBlockRange (XLogRecPtr lsn , RelFileLocator rlocator , ForkNumber forknum , BlockNumber from , BlockNumber n_blocks )
6809
+ static XLogRecPtr
6810
+ SetLastWrittenLSNForBlockRangeInternal (XLogRecPtr lsn , RelFileLocator rlocator , ForkNumber forknum , BlockNumber from , BlockNumber n_blocks )
6817
6811
{
6818
- if (lsn == InvalidXLogRecPtr || n_blocks == 0 || lastWrittenLsnCacheSize == 0 )
6819
- return lsn ;
6820
-
6821
- LWLockAcquire (LastWrittenLsnLock , LW_EXCLUSIVE );
6822
6812
if (rlocator .relNumber == InvalidOid )
6823
6813
{
6824
6814
if (lsn > XLogCtl -> maxLastWrittenLsn )
@@ -6868,7 +6858,29 @@ SetLastWrittenLSNForBlockRange(XLogRecPtr lsn, RelFileLocator rlocator, ForkNumb
6868
6858
dlist_push_tail (& XLogCtl -> lastWrittenLsnLRU , & entry -> lru_node );
6869
6859
}
6870
6860
}
6861
+ return lsn ;
6862
+ }
6863
+
6864
+ /*
6865
+ * SetLastWrittenLSNForBlockRange -- Set maximal LSN of written page range.
6866
+ * We maintain cache of last written LSNs with limited size and LRU replacement
6867
+ * policy. Keeping last written LSN for each page allows to use old LSN when
6868
+ * requesting pages of unchanged or appended relations. Also it is critical for
6869
+ * efficient work of prefetch in case massive update operations (like vacuum or remove).
6870
+ *
6871
+ * rlocator.relNumber can be InvalidOid, in this case maxLastWrittenLsn is updated.
6872
+ * SetLastWrittenLsn with dummy rlocator is used by createdb and dbase_redo functions.
6873
+ */
6874
+ XLogRecPtr
6875
+ SetLastWrittenLSNForBlockRange (XLogRecPtr lsn , RelFileLocator rlocator , ForkNumber forknum , BlockNumber from , BlockNumber n_blocks )
6876
+ {
6877
+ if (lsn == InvalidXLogRecPtr || n_blocks == 0 || lastWrittenLsnCacheSize == 0 )
6878
+ return lsn ;
6879
+
6880
+ LWLockAcquire (LastWrittenLsnLock , LW_EXCLUSIVE );
6881
+ lsn = SetLastWrittenLSNForBlockRangeInternal (lsn , rlocator , forknum , from , n_blocks );
6871
6882
LWLockRelease (LastWrittenLsnLock );
6883
+
6872
6884
return lsn ;
6873
6885
}
6874
6886
0 commit comments