mirror of
https://github.com/postgres/postgres.git
synced 2025-10-24 01:29:19 +03:00
Optionally prefetch referenced data in recovery.
Introduce a new GUC recovery_prefetch, disabled by default. When enabled, look ahead in the WAL and try to initiate asynchronous reading of referenced data blocks that are not yet cached in our buffer pool. For now, this is done with posix_fadvise(), which has several caveats. Better mechanisms will follow in later work on the I/O subsystem. The GUC maintenance_io_concurrency is used to limit the number of concurrent I/Os we allow ourselves to initiate, based on pessimistic heuristics used to infer that I/Os have begun and completed. The GUC wal_decode_buffer_size is used to limit the maximum distance we are prepared to read ahead in the WAL to find uncached blocks. Reviewed-by: Alvaro Herrera <alvherre@2ndquadrant.com> (parts) Reviewed-by: Andres Freund <andres@anarazel.de> (parts) Reviewed-by: Tomas Vondra <tomas.vondra@2ndquadrant.com> (parts) Tested-by: Tomas Vondra <tomas.vondra@2ndquadrant.com> Tested-by: Jakub Wartak <Jakub.Wartak@tomtom.com> Tested-by: Dmitry Dolgov <9erthalion6@gmail.com> Tested-by: Sait Talha Nisanci <Sait.Nisanci@microsoft.com> Discussion: https://postgr.es/m/CA%2BhUKGJ4VJN8ttxScUFM8dOKX0BrBiboo5uz1cq%3DAovOddfHpA%40mail.gmail.com
This commit is contained in:
@@ -132,6 +132,7 @@ extern char *PrimaryConnInfo;
|
||||
extern char *PrimarySlotName;
|
||||
extern bool wal_receiver_create_temp_slot;
|
||||
extern bool track_wal_io_timing;
|
||||
extern int wal_decode_buffer_size;
|
||||
|
||||
/* indirectly set via GUC system */
|
||||
extern TransactionId recoveryTargetXid;
|
||||
|
||||
82
src/include/access/xlogprefetch.h
Normal file
82
src/include/access/xlogprefetch.h
Normal file
@@ -0,0 +1,82 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* xlogprefetch.h
|
||||
* Declarations for the recovery prefetching module.
|
||||
*
|
||||
* Portions Copyright (c) 2021, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* src/include/access/xlogprefetch.h
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#ifndef XLOGPREFETCH_H
|
||||
#define XLOGPREFETCH_H
|
||||
|
||||
#include "access/xlogdefs.h"
|
||||
|
||||
/* GUCs */
|
||||
extern bool recovery_prefetch;
|
||||
extern bool recovery_prefetch_fpw;
|
||||
|
||||
struct XLogPrefetcher;
|
||||
typedef struct XLogPrefetcher XLogPrefetcher;
|
||||
|
||||
extern int XLogPrefetchReconfigureCount;
|
||||
|
||||
typedef struct XLogPrefetchState
|
||||
{
|
||||
XLogReaderState *reader;
|
||||
XLogPrefetcher *prefetcher;
|
||||
int reconfigure_count;
|
||||
} XLogPrefetchState;
|
||||
|
||||
extern size_t XLogPrefetchShmemSize(void);
|
||||
extern void XLogPrefetchShmemInit(void);
|
||||
|
||||
extern void XLogPrefetchReconfigure(void);
|
||||
extern void XLogPrefetchRequestResetStats(void);
|
||||
|
||||
extern void XLogPrefetchBegin(XLogPrefetchState *state, XLogReaderState *reader);
|
||||
extern void XLogPrefetchEnd(XLogPrefetchState *state);
|
||||
|
||||
/* Functions exposed only for the use of XLogPrefetch(). */
|
||||
extern XLogPrefetcher *XLogPrefetcherAllocate(XLogReaderState *reader);
|
||||
extern void XLogPrefetcherFree(XLogPrefetcher *prefetcher);
|
||||
extern bool XLogPrefetcherReadAhead(XLogPrefetcher *prefetch,
|
||||
XLogRecPtr replaying_lsn);
|
||||
|
||||
/*
|
||||
* Tell the prefetching module that we are now replaying a given LSN, so that
|
||||
* it can decide how far ahead to read in the WAL, if configured. Return
|
||||
* true if more data is needed by the reader.
|
||||
*/
|
||||
static inline bool
|
||||
XLogPrefetch(XLogPrefetchState *state, XLogRecPtr replaying_lsn)
|
||||
{
|
||||
/*
|
||||
* Handle any configuration changes. Rather than trying to deal with
|
||||
* various parameter changes, we just tear down and set up a new
|
||||
* prefetcher if anything we depend on changes.
|
||||
*/
|
||||
if (unlikely(state->reconfigure_count != XLogPrefetchReconfigureCount))
|
||||
{
|
||||
/* If we had a prefetcher, tear it down. */
|
||||
if (state->prefetcher)
|
||||
{
|
||||
XLogPrefetcherFree(state->prefetcher);
|
||||
state->prefetcher = NULL;
|
||||
}
|
||||
/* If we want a prefetcher, set it up. */
|
||||
if (recovery_prefetch)
|
||||
state->prefetcher = XLogPrefetcherAllocate(state->reader);
|
||||
state->reconfigure_count = XLogPrefetchReconfigureCount;
|
||||
}
|
||||
|
||||
if (state->prefetcher)
|
||||
return XLogPrefetcherReadAhead(state->prefetcher, replaying_lsn);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -39,6 +39,7 @@
|
||||
#endif
|
||||
|
||||
#include "access/xlogrecord.h"
|
||||
#include "storage/buf.h"
|
||||
|
||||
/* WALOpenSegment represents a WAL segment being read. */
|
||||
typedef struct WALOpenSegment
|
||||
@@ -77,6 +78,9 @@ typedef struct
|
||||
ForkNumber forknum;
|
||||
BlockNumber blkno;
|
||||
|
||||
/* Workspace for remembering last known buffer holding this block. */
|
||||
Buffer recent_buffer;
|
||||
|
||||
/* copy of the fork_flags field from the XLogRecordBlockHeader */
|
||||
uint8 flags;
|
||||
|
||||
@@ -397,5 +401,8 @@ extern char *XLogRecGetBlockData(XLogReaderState *record, uint8 block_id, Size *
|
||||
extern bool XLogRecGetBlockTag(XLogReaderState *record, uint8 block_id,
|
||||
RelFileNode *rnode, ForkNumber *forknum,
|
||||
BlockNumber *blknum);
|
||||
extern bool XLogRecGetRecentBuffer(XLogReaderState *record, uint8 block_id,
|
||||
RelFileNode *rnode, ForkNumber *forknum,
|
||||
BlockNumber *blknum, Buffer *recent_buffer);
|
||||
|
||||
#endif /* XLOGREADER_H */
|
||||
|
||||
@@ -42,7 +42,8 @@ extern XLogRedoAction XLogReadBufferForRedoExtended(XLogReaderState *record,
|
||||
Buffer *buf);
|
||||
|
||||
extern Buffer XLogReadBufferExtended(RelFileNode rnode, ForkNumber forknum,
|
||||
BlockNumber blkno, ReadBufferMode mode);
|
||||
BlockNumber blkno, ReadBufferMode mode,
|
||||
Buffer recent_buffer);
|
||||
|
||||
extern Relation CreateFakeRelcacheEntry(RelFileNode rnode);
|
||||
extern void FreeFakeRelcacheEntry(Relation fakerel);
|
||||
|
||||
Reference in New Issue
Block a user