From e1e533243b98e723f4e6991e4165b1c9859722dc Mon Sep 17 00:00:00 2001 From: Konstantin Knizhnik Date: Thu, 15 Dec 2022 10:37:44 +0200 Subject: [PATCH] Do not set last written LSN for target page prefetch request --- pgxn/neon/pagestore_smgr.c | 54 +++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/pgxn/neon/pagestore_smgr.c b/pgxn/neon/pagestore_smgr.c index a7745713cf..bf0af964a4 100644 --- a/pgxn/neon/pagestore_smgr.c +++ b/pgxn/neon/pagestore_smgr.c @@ -675,39 +675,39 @@ prefetch_do_request(PrefetchRequest *slot, bool *force_latest, XLogRecPtr *force request.req.lsn = lsn; prefetch_lsn = Max(prefetch_lsn, lsn); slot->effective_request_lsn = prefetch_lsn; + + /* + * Remember request LSN in the last-written LSN cache to avoid false + * prefetch invalidations. + * + * Imagine what would happen without this, when you perform a large + * sequential scan with UPDATE. The sequential scan issues a prefetch + * request for each page in order, and every page is also dirtied. On + * each page, the oldest page in the last-written LSN cache is evicted, + * which advances the global last-written LSN. The pages being scanned are + * not in the last-written cache, so each prefetch request will use the + * global last-written LSN in the request and memorize that in the + * slot. However, when we receive the response to the prefetch request, + * the global last-written LSN has already moved forwards, and the + * cross-check we make that the last-written LSN matches will fail, and we + * discard the prefetched response unnecessary. + * + * Inserting the LSN we use in the prefetch request to the last-written LSN + * cache avoids that problem. With that, we will use the cached value in + * the cross-check, instead of the more recent global last-written LSN value. + */ + SetLastWrittenLSNForBlock( + request.req.lsn, + slot->buftag.rnode, + slot->buftag.forkNum, + slot->buftag.blockNum + ); } Assert(slot->response == NULL); Assert(slot->my_ring_index == MyPState->ring_unused); page_server->send((NeonRequest *) &request); - /* - * Remember request LSN in the last-written LSN cache to avoid false - * prefetch invalidations. - * - * Imagine what would happen without this, when you perform a large - * sequential scan with UPDATE. The sequential scan issues a prefetch - * request for each page in order, and every page is also dirtied. On - * each page, the oldest page in the last-written LSN cache is evicted, - * which advances the global last-written LSN. The pages being scanned are - * not in the last-written cache, so each prefetch request will use the - * global last-written LSN in the request and memorize that in the - * slot. However, when we receive the response to the prefetch request, - * the global last-written LSN has already moved forwards, and the - * cross-check we make that the last-written LSN matches will fail, and we - * discard the prefetched response unnecessary. - * - * Inserting the LSN we use in the prefetch request to the last-written LSN - * cache avoids that problem. With that, we will use the cached value in - * the cross-check, instead of the more recent global last-written LSN value. - */ - SetLastWrittenLSNForBlock( - request.req.lsn, - slot->buftag.rnode, - slot->buftag.forkNum, - slot->buftag.blockNum - ); - /* update prefetch state */ MyPState->n_requests_inflight += 1; MyPState->n_unused -= 1;