From 19dab9f564ebfae88d9937e81adf95aeaea830df Mon Sep 17 00:00:00 2001 From: Konstantin Knizhnik Date: Sun, 12 Jan 2025 09:33:54 +0200 Subject: [PATCH 01/11] Optimize vector get last written LSN --- src/backend/access/transam/xlog.c | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 0c0a737f271..4fc12345ac2 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -6747,16 +6747,18 @@ GetLastWrittenLSNv(RelFileLocator relfilenode, ForkNumber forknum, Assert(nblocks > 0); Assert(PointerIsValid(lsns)); - LWLockAcquire(LastWrittenLsnLock, LW_SHARED); - if (relfilenode.relNumber != InvalidOid) { BufferTag key; + XLogRecPtr max_lsn; + key.spcOid = relfilenode.spcOid; key.dbOid = relfilenode.dbOid; key.relNumber = relfilenode.relNumber; key.forkNum = forknum; + LWLockAcquire(LastWrittenLsnLock, LW_SHARED); + for (int i = 0; i < nblocks; i++) { /* Maximal last written LSN among all non-cached pages */ @@ -6764,16 +6766,18 @@ GetLastWrittenLSNv(RelFileLocator relfilenode, ForkNumber forknum, entry = hash_search(lastWrittenLsnCache, &key, HASH_FIND, NULL); - if (entry != NULL) - lsns[i] = entry->lsn; - else - { - XLogRecPtr lsn; - lsns[i] = lsn = XLogCtl->maxLastWrittenLsn; + lsns[i] = (entry != NULL) ? entry->lsn : InvalidXLogRecPtr; + } + max_lsn = XLogCtl->maxLastWrittenLsn; - LWLockRelease(LastWrittenLsnLock); - SetLastWrittenLSNForBlock(lsn, relfilenode, forknum, key.blockNum); - LWLockAcquire(LastWrittenLsnLock, LW_SHARED); + LWLockRelease(LastWrittenLsnLock); + + for (int i = 0; i < nblocks; i++) + { + if (lsns[i] == InvalidXLogRecPtr) + { + lsns[i] = max_lsn; + SetLastWrittenLSNForBlock(max_lsn, relfilenode, forknum, key.blockNum); } } } @@ -6781,6 +6785,9 @@ GetLastWrittenLSNv(RelFileLocator relfilenode, ForkNumber forknum, { HASH_SEQ_STATUS seq; XLogRecPtr lsn = XLogCtl->maxLastWrittenLsn; + + LWLockAcquire(LastWrittenLsnLock, LW_SHARED); + /* Find maximum of all cached LSNs */ hash_seq_init(&seq, lastWrittenLsnCache); while ((entry = (LastWrittenLsnCacheEntry *) hash_seq_search(&seq)) != NULL) @@ -6788,11 +6795,11 @@ GetLastWrittenLSNv(RelFileLocator relfilenode, ForkNumber forknum, if (entry->lsn > lsn) lsn = entry->lsn; } + LWLockRelease(LastWrittenLsnLock); for (int i = 0; i < nblocks; i++) lsns[i] = lsn; } - LWLockRelease(LastWrittenLsnLock); } /* From 89d27dc03f4b0481c7f3919738f5ebf44dc61f13 Mon Sep 17 00:00:00 2001 From: Konstantin Knizhnik Date: Mon, 13 Jan 2025 16:17:30 +0200 Subject: [PATCH 02/11] Add SetLastWrittenLSNForBlockRangeInternal to avoid redundant unlocking.locking of LwLSN lock --- src/backend/access/transam/xlog.c | 84 ++++++++++++++++++------------- 1 file changed, 48 insertions(+), 36 deletions(-) diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 4fc12345ac2..f283a711e91 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -764,6 +764,8 @@ static void WALInsertLockAcquireExclusive(void); static void WALInsertLockRelease(void); static void WALInsertLockUpdateInsertingAt(XLogRecPtr insertingAt); +static XLogRecPtr SetLastWrittenLSNForBlockRangeInternal(XLogRecPtr lsn, RelFileLocator rlocator, ForkNumber forknum, BlockNumber from, BlockNumber n_blocks); + /* * Insert an XLOG record represented by an already-constructed chain of data * chunks. This is a low-level routine; to construct the WAL record header @@ -6709,8 +6711,15 @@ GetLastWrittenLSN(RelFileLocator rlocator, ForkNumber forknum, BlockNumber blkno lsn = entry->lsn; else { - LWLockRelease(LastWrittenLsnLock); - return SetLastWrittenLSNForBlock(lsn, rlocator, forknum, blkno); + /* + * In case of statements CREATE TABLE AS SELECT... or INSERT FROM SELECT... we are fetching data from source table + * and storing it in destination table. It cause problems with prefetch last-written-lsn is known for the pages of + * source table (which for example happens after compute restart). In this case we get get global value of + * last-written-lsn which is changed frequently as far as we are writing pages of destination table. + * As a result request-lsn for the prefetch and request-let when this page is actually needed are different + * and we got exported prefetch request. So it actually disarms prefetch. + */ + lsn = SetLastWrittenLSNForBlockRangeInternal(lsn, rlocator, forknum, blkno, 1); } } else @@ -6742,23 +6751,25 @@ GetLastWrittenLSNv(RelFileLocator relfilenode, ForkNumber forknum, BlockNumber blkno, int nblocks, XLogRecPtr *lsns) { LastWrittenLsnCacheEntry* entry; + XLogRecPtr lsn; Assert(lastWrittenLsnCacheSize != 0); Assert(nblocks > 0); Assert(PointerIsValid(lsns)); + LWLockAcquire(LastWrittenLsnLock, LW_SHARED); + + lsn = XLogCtl->maxLastWrittenLsn; + if (relfilenode.relNumber != InvalidOid) { BufferTag key; - XLogRecPtr max_lsn; key.spcOid = relfilenode.spcOid; key.dbOid = relfilenode.dbOid; key.relNumber = relfilenode.relNumber; key.forkNum = forknum; - LWLockAcquire(LastWrittenLsnLock, LW_SHARED); - for (int i = 0; i < nblocks; i++) { /* Maximal last written LSN among all non-cached pages */ @@ -6766,27 +6777,20 @@ GetLastWrittenLSNv(RelFileLocator relfilenode, ForkNumber forknum, entry = hash_search(lastWrittenLsnCache, &key, HASH_FIND, NULL); - lsns[i] = (entry != NULL) ? entry->lsn : InvalidXLogRecPtr; - } - max_lsn = XLogCtl->maxLastWrittenLsn; - - LWLockRelease(LastWrittenLsnLock); - - for (int i = 0; i < nblocks; i++) - { - if (lsns[i] == InvalidXLogRecPtr) + if (entry != NULL) { - lsns[i] = max_lsn; - SetLastWrittenLSNForBlock(max_lsn, relfilenode, forknum, key.blockNum); + lsns[i] = entry->lsn; + } + else + { + lsns[i] = lsn; + SetLastWrittenLSNForBlockRangeInternal(lsn, relfilenode, forknum, key.blockNum, 1); } } } else { HASH_SEQ_STATUS seq; - XLogRecPtr lsn = XLogCtl->maxLastWrittenLsn; - - LWLockAcquire(LastWrittenLsnLock, LW_SHARED); /* Find maximum of all cached LSNs */ hash_seq_init(&seq, lastWrittenLsnCache); @@ -6795,30 +6799,16 @@ GetLastWrittenLSNv(RelFileLocator relfilenode, ForkNumber forknum, if (entry->lsn > lsn) lsn = entry->lsn; } - LWLockRelease(LastWrittenLsnLock); for (int i = 0; i < nblocks; i++) lsns[i] = lsn; } + LWLockRelease(LastWrittenLsnLock); } -/* - * SetLastWrittenLSNForBlockRange -- Set maximal LSN of written page range. - * We maintain cache of last written LSNs with limited size and LRU replacement - * policy. Keeping last written LSN for each page allows to use old LSN when - * requesting pages of unchanged or appended relations. Also it is critical for - * efficient work of prefetch in case massive update operations (like vacuum or remove). - * - * rlocator.relNumber can be InvalidOid, in this case maxLastWrittenLsn is updated. - * SetLastWrittenLsn with dummy rlocator is used by createdb and dbase_redo functions. - */ -XLogRecPtr -SetLastWrittenLSNForBlockRange(XLogRecPtr lsn, RelFileLocator rlocator, ForkNumber forknum, BlockNumber from, BlockNumber n_blocks) +static XLogRecPtr +SetLastWrittenLSNForBlockRangeInternal(XLogRecPtr lsn, RelFileLocator rlocator, ForkNumber forknum, BlockNumber from, BlockNumber n_blocks) { - if (lsn == InvalidXLogRecPtr || n_blocks == 0 || lastWrittenLsnCacheSize == 0) - return lsn; - - LWLockAcquire(LastWrittenLsnLock, LW_EXCLUSIVE); if (rlocator.relNumber == InvalidOid) { if (lsn > XLogCtl->maxLastWrittenLsn) @@ -6868,7 +6858,29 @@ SetLastWrittenLSNForBlockRange(XLogRecPtr lsn, RelFileLocator rlocator, ForkNumb dlist_push_tail(&XLogCtl->lastWrittenLsnLRU, &entry->lru_node); } } + return lsn; +} + +/* + * SetLastWrittenLSNForBlockRange -- Set maximal LSN of written page range. + * We maintain cache of last written LSNs with limited size and LRU replacement + * policy. Keeping last written LSN for each page allows to use old LSN when + * requesting pages of unchanged or appended relations. Also it is critical for + * efficient work of prefetch in case massive update operations (like vacuum or remove). + * + * rlocator.relNumber can be InvalidOid, in this case maxLastWrittenLsn is updated. + * SetLastWrittenLsn with dummy rlocator is used by createdb and dbase_redo functions. + */ +XLogRecPtr +SetLastWrittenLSNForBlockRange(XLogRecPtr lsn, RelFileLocator rlocator, ForkNumber forknum, BlockNumber from, BlockNumber n_blocks) +{ + if (lsn == InvalidXLogRecPtr || n_blocks == 0 || lastWrittenLsnCacheSize == 0) + return lsn; + + LWLockAcquire(LastWrittenLsnLock, LW_EXCLUSIVE); + lsn = SetLastWrittenLSNForBlockRangeInternal(lsn, rlocator, forknum, from, n_blocks); LWLockRelease(LastWrittenLsnLock); + return lsn; } From f7f1c57f7c508e27374f6d7eec3af98ff3dcaeae Mon Sep 17 00:00:00 2001 From: Konstantin Knizhnik Date: Mon, 13 Jan 2025 18:28:06 +0200 Subject: [PATCH 03/11] Fix incorrect calls of SetLastWrittenLSNForBlockRangeInternal with shared lock --- src/backend/access/transam/xlog.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index f283a711e91..ee28326a0d9 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -6711,6 +6711,8 @@ GetLastWrittenLSN(RelFileLocator rlocator, ForkNumber forknum, BlockNumber blkno lsn = entry->lsn; else { + LWLockRelease(LastWrittenLsnLock); + LWLockAcquire(LastWrittenLsnLock, LW_EXCLUSIVE); /* * In case of statements CREATE TABLE AS SELECT... or INSERT FROM SELECT... we are fetching data from source table * and storing it in destination table. It cause problems with prefetch last-written-lsn is known for the pages of @@ -6764,6 +6766,7 @@ GetLastWrittenLSNv(RelFileLocator relfilenode, ForkNumber forknum, if (relfilenode.relNumber != InvalidOid) { BufferTag key; + bool missed_keys = false; key.spcOid = relfilenode.spcOid; key.dbOid = relfilenode.dbOid; @@ -6776,15 +6779,29 @@ GetLastWrittenLSNv(RelFileLocator relfilenode, ForkNumber forknum, key.blockNum = blkno + i; entry = hash_search(lastWrittenLsnCache, &key, HASH_FIND, NULL); - if (entry != NULL) { lsns[i] = entry->lsn; } else { - lsns[i] = lsn; - SetLastWrittenLSNForBlockRangeInternal(lsn, relfilenode, forknum, key.blockNum, 1); + lsns[i] = InvalidXLogRecPtr; + missed_keys = true; + } + } + if (missed_keys) + { + LWLockRelease(LastWrittenLsnLock); + LWLockAcquire(LastWrittenLsnLock, LW_EXCLUSIVE); + + lsn = XLogCtl->maxLastWrittenLsn; + + for (int i = 0; i < nblocks; i++) + { + if (lsns[i] == InvalidXLogRecPtr) + { + SetLastWrittenLSNForBlockRangeInternal(lsn, relfilenode, forknum, key.blockNum, 1); + } } } } @@ -6792,6 +6809,7 @@ GetLastWrittenLSNv(RelFileLocator relfilenode, ForkNumber forknum, { HASH_SEQ_STATUS seq; + lsn = XLogCtl->maxLastWrittenLsn; /* Find maximum of all cached LSNs */ hash_seq_init(&seq, lastWrittenLsnCache); while ((entry = (LastWrittenLsnCacheEntry *) hash_seq_search(&seq)) != NULL) From 94f068d63b66946f4502fd127e307d7ee1871d53 Mon Sep 17 00:00:00 2001 From: Konstantin Knizhnik Date: Mon, 13 Jan 2025 19:01:10 +0200 Subject: [PATCH 04/11] Update src/backend/access/transam/xlog.c Co-authored-by: Matthias van de Meent --- src/backend/access/transam/xlog.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index ee28326a0d9..9403350edbe 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -6824,6 +6824,10 @@ GetLastWrittenLSNv(RelFileLocator relfilenode, ForkNumber forknum, LWLockRelease(LastWrittenLsnLock); } +/* + * Guts for SetLastWrittenLSNForBlockRange. + * Caller must ensure LastWrittenLsnLock is held in exclusive mode. + */ static XLogRecPtr SetLastWrittenLSNForBlockRangeInternal(XLogRecPtr lsn, RelFileLocator rlocator, ForkNumber forknum, BlockNumber from, BlockNumber n_blocks) { From 77a12384ade0fcd5b7e1f26687f234ef0abeac95 Mon Sep 17 00:00:00 2001 From: Konstantin Knizhnik Date: Mon, 13 Jan 2025 19:04:53 +0200 Subject: [PATCH 05/11] Update src/backend/access/transam/xlog.c Co-authored-by: Matthias van de Meent --- src/backend/access/transam/xlog.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 9403350edbe..f4bf944fb76 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -6800,7 +6800,7 @@ GetLastWrittenLSNv(RelFileLocator relfilenode, ForkNumber forknum, { if (lsns[i] == InvalidXLogRecPtr) { - SetLastWrittenLSNForBlockRangeInternal(lsn, relfilenode, forknum, key.blockNum, 1); + SetLastWrittenLSNForBlockRangeInternal(XLogCtl->maxLastWrittenLsn, relfilenode, forknum, blkno + i, 1); } } } From 2d8871f7d09a76e89b5d35aaece37489cfda970e Mon Sep 17 00:00:00 2001 From: Konstantin Knizhnik Date: Mon, 13 Jan 2025 19:04:43 +0200 Subject: [PATCH 06/11] Update comments --- src/backend/access/transam/xlog.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index f4bf944fb76..acc704a45e8 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -6683,7 +6683,7 @@ GetInsertRecPtr(void) * either from a cached last written LSN or a global maximum last written LSN. * If rnode is InvalidOid then we calculate maximum among all cached LSN and maxLastWrittenLsn. * If cache is large enough, iterating through all hash items may be rather expensive. - * But GetLastWrittenLSN(InvalidOid) is used only by zenith_dbsize which is not performance critical. + * But GetLastWrittenLSN(InvalidOid) is used only by neon_dbsize which is not performance critical. */ XLogRecPtr GetLastWrittenLSN(RelFileLocator rlocator, ForkNumber forknum, BlockNumber blkno) @@ -6746,7 +6746,7 @@ GetLastWrittenLSN(RelFileLocator rlocator, ForkNumber forknum, BlockNumber blkno * either from a cached last written LSN or a global maximum last written LSN. * If rnode is InvalidOid then we calculate maximum among all cached LSN and maxLastWrittenLsn. * If cache is large enough, iterating through all hash items may be rather expensive. - * But GetLastWrittenLSN(InvalidOid) is used only by zenith_dbsize which is not performance critical. + * But GetLastWrittenLSN(InvalidOid) is used only by neon_dbsize which is not performance critical. */ void GetLastWrittenLSNv(RelFileLocator relfilenode, ForkNumber forknum, From cca215e30abf74bbe02a7d841a7a5a1d4063f689 Mon Sep 17 00:00:00 2001 From: Konstantin Knizhnik Date: Mon, 13 Jan 2025 19:06:26 +0200 Subject: [PATCH 07/11] Remove rediundant use of lsn variable --- src/backend/access/transam/xlog.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index acc704a45e8..66dc11a15f7 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -6753,7 +6753,6 @@ GetLastWrittenLSNv(RelFileLocator relfilenode, ForkNumber forknum, BlockNumber blkno, int nblocks, XLogRecPtr *lsns) { LastWrittenLsnCacheEntry* entry; - XLogRecPtr lsn; Assert(lastWrittenLsnCacheSize != 0); Assert(nblocks > 0); @@ -6761,8 +6760,6 @@ GetLastWrittenLSNv(RelFileLocator relfilenode, ForkNumber forknum, LWLockAcquire(LastWrittenLsnLock, LW_SHARED); - lsn = XLogCtl->maxLastWrittenLsn; - if (relfilenode.relNumber != InvalidOid) { BufferTag key; @@ -6794,8 +6791,6 @@ GetLastWrittenLSNv(RelFileLocator relfilenode, ForkNumber forknum, LWLockRelease(LastWrittenLsnLock); LWLockAcquire(LastWrittenLsnLock, LW_EXCLUSIVE); - lsn = XLogCtl->maxLastWrittenLsn; - for (int i = 0; i < nblocks; i++) { if (lsns[i] == InvalidXLogRecPtr) @@ -6808,8 +6803,7 @@ GetLastWrittenLSNv(RelFileLocator relfilenode, ForkNumber forknum, else { HASH_SEQ_STATUS seq; - - lsn = XLogCtl->maxLastWrittenLsn; + XLogRecPtr lsn = XLogCtl->maxLastWrittenLsn; /* Find maximum of all cached LSNs */ hash_seq_init(&seq, lastWrittenLsnCache); while ((entry = (LastWrittenLsnCacheEntry *) hash_seq_search(&seq)) != NULL) From d7526ad1f33aa3c2513729ded987834e3a6085d1 Mon Sep 17 00:00:00 2001 From: Konstantin Knizhnik Date: Mon, 13 Jan 2025 19:08:01 +0200 Subject: [PATCH 08/11] Update src/backend/access/transam/xlog.c Co-authored-by: Matthias van de Meent --- src/backend/access/transam/xlog.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 66dc11a15f7..9b2df3b95d1 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -6782,10 +6782,16 @@ GetLastWrittenLSNv(RelFileLocator relfilenode, ForkNumber forknum, } else { + /* Mark this block's LSN as missing - we'll update the LwLSN for missing blocks in bulk later */ lsns[i] = InvalidXLogRecPtr; missed_keys = true; } } + + /* + * If we had any missing LwLSN entries, we add the missing ones now. + * By doing the insertions in one batch, we decrease lock contention. + */ if (missed_keys) { LWLockRelease(LastWrittenLsnLock); From bb489948c256e15c0ce17385a2224eb5c8e424dc Mon Sep 17 00:00:00 2001 From: Konstantin Knizhnik Date: Mon, 13 Jan 2025 20:48:47 +0200 Subject: [PATCH 09/11] Update src/backend/access/transam/xlog.c Co-authored-by: Matthias van de Meent --- src/backend/access/transam/xlog.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 9b2df3b95d1..cc0372f2582 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -6720,6 +6720,9 @@ GetLastWrittenLSN(RelFileLocator rlocator, ForkNumber forknum, BlockNumber blkno * last-written-lsn which is changed frequently as far as we are writing pages of destination table. * As a result request-lsn for the prefetch and request-let when this page is actually needed are different * and we got exported prefetch request. So it actually disarms prefetch. + * To prevent that, we re-insert the page with the latest LSN, so that it's + * less likely the LSN for this page will get evicted from the LwLsnCache + * before the page is read. */ lsn = SetLastWrittenLSNForBlockRangeInternal(lsn, rlocator, forknum, blkno, 1); } From e0b3210b97fd5fdebc6946aa23f5da1ecdcee6c7 Mon Sep 17 00:00:00 2001 From: Konstantin Knizhnik Date: Mon, 13 Jan 2025 20:50:35 +0200 Subject: [PATCH 10/11] Fix formatting --- src/backend/access/transam/xlog.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index cc0372f2582..de1ac788390 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -764,7 +764,11 @@ static void WALInsertLockAcquireExclusive(void); static void WALInsertLockRelease(void); static void WALInsertLockUpdateInsertingAt(XLogRecPtr insertingAt); -static XLogRecPtr SetLastWrittenLSNForBlockRangeInternal(XLogRecPtr lsn, RelFileLocator rlocator, ForkNumber forknum, BlockNumber from, BlockNumber n_blocks); +static XLogRecPtr SetLastWrittenLSNForBlockRangeInternal(XLogRecPtr lsn, + RelFileLocator rlocator, + ForkNumber forknum, + BlockNumber from, + BlockNumber n_blocks); /* * Insert an XLOG record represented by an already-constructed chain of data @@ -6832,7 +6836,11 @@ GetLastWrittenLSNv(RelFileLocator relfilenode, ForkNumber forknum, * Caller must ensure LastWrittenLsnLock is held in exclusive mode. */ static XLogRecPtr -SetLastWrittenLSNForBlockRangeInternal(XLogRecPtr lsn, RelFileLocator rlocator, ForkNumber forknum, BlockNumber from, BlockNumber n_blocks) +SetLastWrittenLSNForBlockRangeInternal(XLogRecPtr lsn, + RelFileLocator rlocator, + ForkNumber forknum, + BlockNumber from, + BlockNumber n_blocks) { if (rlocator.relNumber == InvalidOid) { From 0f8da73ed08d4fc4ee58cccea008c75bfb20baa8 Mon Sep 17 00:00:00 2001 From: Konstantin Knizhnik Date: Mon, 13 Jan 2025 21:42:25 +0200 Subject: [PATCH 11/11] Fix bug in GetLastWrittenLSNv --- src/backend/access/transam/xlog.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index de1ac788390..2955e9bf5fb 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -6760,6 +6760,7 @@ GetLastWrittenLSNv(RelFileLocator relfilenode, ForkNumber forknum, BlockNumber blkno, int nblocks, XLogRecPtr *lsns) { LastWrittenLsnCacheEntry* entry; + XLogRecPtr lsn; Assert(lastWrittenLsnCacheSize != 0); Assert(nblocks > 0); @@ -6785,7 +6786,7 @@ GetLastWrittenLSNv(RelFileLocator relfilenode, ForkNumber forknum, entry = hash_search(lastWrittenLsnCache, &key, HASH_FIND, NULL); if (entry != NULL) { - lsns[i] = entry->lsn; + lsns[i] = entry->lsn; } else { @@ -6804,11 +6805,14 @@ GetLastWrittenLSNv(RelFileLocator relfilenode, ForkNumber forknum, LWLockRelease(LastWrittenLsnLock); LWLockAcquire(LastWrittenLsnLock, LW_EXCLUSIVE); + lsn = XLogCtl->maxLastWrittenLsn; + for (int i = 0; i < nblocks; i++) { if (lsns[i] == InvalidXLogRecPtr) { - SetLastWrittenLSNForBlockRangeInternal(XLogCtl->maxLastWrittenLsn, relfilenode, forknum, blkno + i, 1); + lsns[i] = lsn; + SetLastWrittenLSNForBlockRangeInternal(lsn, relfilenode, forknum, blkno + i, 1); } } } @@ -6816,7 +6820,7 @@ GetLastWrittenLSNv(RelFileLocator relfilenode, ForkNumber forknum, else { HASH_SEQ_STATUS seq; - XLogRecPtr lsn = XLogCtl->maxLastWrittenLsn; + lsn = XLogCtl->maxLastWrittenLsn; /* Find maximum of all cached LSNs */ hash_seq_init(&seq, lastWrittenLsnCache); while ((entry = (LastWrittenLsnCacheEntry *) hash_seq_search(&seq)) != NULL)