diff options
| author | Robert Haas | 2023-12-20 13:41:09 +0000 |
|---|---|---|
| committer | Robert Haas | 2023-12-20 13:42:28 +0000 |
| commit | 174c480508ac25568561443e6d4a82d5c1103487 (patch) | |
| tree | f42caba7a5f9a468e927107a58406a28a9f28ef2 /src/include | |
| parent | 00498b718564cee3530b76d860b328718aed672b (diff) | |
Add a new WAL summarizer process.
When active, this process writes WAL summary files to
$PGDATA/pg_wal/summaries. Each summary file contains information for a
certain range of LSNs on a certain TLI. For each relation, it stores a
"limit block" which is 0 if a relation is created or destroyed within
a certain range of WAL records, or otherwise the shortest length to
which the relation was truncated during that range of WAL records, or
otherwise InvalidBlockNumber. In addition, it stores a list of blocks
which have been modified during that range of WAL records, but
excluding blocks which were removed by truncation after they were
modified and never subsequently modified again.
In other words, it tells us which blocks need to copied in case of an
incremental backup covering that range of WAL records. But this
doesn't yet add the capability to actually perform an incremental
backup; the next patch will do that.
A new parameter summarize_wal enables or disables this new background
process. The background process also automatically deletes summary
files that are older than wal_summarize_keep_time, if that parameter
has a non-zero value and the summarizer is configured to run.
Patch by me, with some design help from Dilip Kumar and Andres Freund.
Reviewed by Matthias van de Meent, Dilip Kumar, Jakub Wartak, Peter
Eisentraut, and Álvaro Herrera.
Discussion: http://postgr.es/m/CA+TgmoYOYZfMCyOXFyC-P+-mdrZqm5pP2N7S-r0z3_402h9rsA@mail.gmail.com
Diffstat (limited to 'src/include')
| -rw-r--r-- | src/include/access/xlog.h | 1 | ||||
| -rw-r--r-- | src/include/backup/walsummary.h | 49 | ||||
| -rw-r--r-- | src/include/catalog/pg_proc.dat | 19 | ||||
| -rw-r--r-- | src/include/common/blkreftable.h | 116 | ||||
| -rw-r--r-- | src/include/miscadmin.h | 3 | ||||
| -rw-r--r-- | src/include/postmaster/walsummarizer.h | 33 | ||||
| -rw-r--r-- | src/include/storage/proc.h | 9 | ||||
| -rw-r--r-- | src/include/utils/guc_tables.h | 1 |
8 files changed, 227 insertions, 4 deletions
diff --git a/src/include/access/xlog.h b/src/include/access/xlog.h index a14126d164f..da715803644 100644 --- a/src/include/access/xlog.h +++ b/src/include/access/xlog.h @@ -209,6 +209,7 @@ extern int XLogFileOpen(XLogSegNo segno, TimeLineID tli); extern void CheckXLogRemoved(XLogSegNo segno, TimeLineID tli); extern XLogSegNo XLogGetLastRemovedSegno(void); +extern XLogSegNo XLogGetOldestSegno(TimeLineID tli); extern void XLogSetAsyncXactLSN(XLogRecPtr asyncXactLSN); extern void XLogSetReplicationSlotMinimumLSN(XLogRecPtr lsn); diff --git a/src/include/backup/walsummary.h b/src/include/backup/walsummary.h new file mode 100644 index 00000000000..8e3dc7b837b --- /dev/null +++ b/src/include/backup/walsummary.h @@ -0,0 +1,49 @@ +/*------------------------------------------------------------------------- + * + * walsummary.h + * WAL summary management + * + * Portions Copyright (c) 2010-2022, PostgreSQL Global Development Group + * + * src/include/backup/walsummary.h + * + *------------------------------------------------------------------------- + */ +#ifndef WALSUMMARY_H +#define WALSUMMARY_H + +#include <time.h> + +#include "access/xlogdefs.h" +#include "nodes/pg_list.h" +#include "storage/fd.h" + +typedef struct WalSummaryIO +{ + File file; + off_t filepos; +} WalSummaryIO; + +typedef struct WalSummaryFile +{ + XLogRecPtr start_lsn; + XLogRecPtr end_lsn; + TimeLineID tli; +} WalSummaryFile; + +extern List *GetWalSummaries(TimeLineID tli, XLogRecPtr start_lsn, + XLogRecPtr end_lsn); +extern List *FilterWalSummaries(List *wslist, TimeLineID tli, + XLogRecPtr start_lsn, XLogRecPtr end_lsn); +extern bool WalSummariesAreComplete(List *wslist, + XLogRecPtr start_lsn, XLogRecPtr end_lsn, + XLogRecPtr *missing_lsn); +extern File OpenWalSummaryFile(WalSummaryFile *ws, bool missing_ok); +extern void RemoveWalSummaryIfOlderThan(WalSummaryFile *ws, + time_t cutoff_time); + +extern int ReadWalSummary(void *wal_summary_io, void *data, int length); +extern int WriteWalSummary(void *wal_summary_io, void *data, int length); +extern void ReportWalSummaryError(void *callback_arg, char *fmt,...) pg_attribute_printf(2, 3); + +#endif /* WALSUMMARY_H */ diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat index 77e8b137649..916c8ec8d0e 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -12099,4 +12099,23 @@ proname => 'any_value_transfn', prorettype => 'anyelement', proargtypes => 'anyelement anyelement', prosrc => 'any_value_transfn' }, +{ oid => '8436', + descr => 'list of available WAL summary files', + proname => 'pg_available_wal_summaries', prorows => '100', + proretset => 't', provolatile => 'v', proparallel => 's', + prorettype => 'record', proargtypes => '', + proallargtypes => '{int8,pg_lsn,pg_lsn}', + proargmodes => '{o,o,o}', + proargnames => '{tli,start_lsn,end_lsn}', + prosrc => 'pg_available_wal_summaries' }, +{ oid => '8437', + descr => 'contents of a WAL sumamry file', + proname => 'pg_wal_summary_contents', prorows => '100', + proretset => 't', provolatile => 'v', proparallel => 's', + prorettype => 'record', proargtypes => 'int8 pg_lsn pg_lsn', + proallargtypes => '{int8,pg_lsn,pg_lsn,oid,oid,oid,int2,int8,bool}', + proargmodes => '{i,i,i,o,o,o,o,o,o}', + proargnames => '{tli,start_lsn,end_lsn,relfilenode,reltablespace,reldatabase,relforknumber,relblocknumber,is_limit_block}', + prosrc => 'pg_wal_summary_contents' }, + ] diff --git a/src/include/common/blkreftable.h b/src/include/common/blkreftable.h new file mode 100644 index 00000000000..5141f3acd50 --- /dev/null +++ b/src/include/common/blkreftable.h @@ -0,0 +1,116 @@ +/*------------------------------------------------------------------------- + * + * blkreftable.h + * Block reference tables. + * + * A block reference table is used to keep track of which blocks have + * been modified by WAL records within a certain LSN range. + * + * For each relation fork, there is a "limit block number". All existing + * blocks greater than or equal to the limit block number must be + * considered modified; for those less than the limit block number, + * we maintain a bitmap. When a relation fork is created or dropped, + * the limit block number should be set to 0. When it's truncated, + * the limit block number should be set to the length in blocks to + * which it was truncated. + * + * Portions Copyright (c) 2010-2022, PostgreSQL Global Development Group + * + * src/include/common/blkreftable.h + * + *------------------------------------------------------------------------- + */ +#ifndef BLKREFTABLE_H +#define BLKREFTABLE_H + +#include "storage/block.h" +#include "storage/relfilelocator.h" + +/* Magic number for serialization file format. */ +#define BLOCKREFTABLE_MAGIC 0x652b137b + +typedef struct BlockRefTable BlockRefTable; +typedef struct BlockRefTableEntry BlockRefTableEntry; +typedef struct BlockRefTableReader BlockRefTableReader; +typedef struct BlockRefTableWriter BlockRefTableWriter; + +/* + * The return value of io_callback_fn should be the number of bytes read + * or written. If an error occurs, the functions should report it and + * not return. When used as a write callback, short writes should be retried + * or treated as errors, so that if the callback returns, the return value + * is always the request length. + * + * report_error_fn should not return. + */ +typedef int (*io_callback_fn) (void *callback_arg, void *data, int length); +typedef void (*report_error_fn) (void *calblack_arg, char *msg,...) pg_attribute_printf(2, 3); + + +/* + * Functions for manipulating an entire in-memory block reference table. + */ +extern BlockRefTable *CreateEmptyBlockRefTable(void); +extern void BlockRefTableSetLimitBlock(BlockRefTable *brtab, + const RelFileLocator *rlocator, + ForkNumber forknum, + BlockNumber limit_block); +extern void BlockRefTableMarkBlockModified(BlockRefTable *brtab, + const RelFileLocator *rlocator, + ForkNumber forknum, + BlockNumber blknum); +extern void WriteBlockRefTable(BlockRefTable *brtab, + io_callback_fn write_callback, + void *write_callback_arg); + +extern BlockRefTableEntry *BlockRefTableGetEntry(BlockRefTable *brtab, + const RelFileLocator *rlocator, + ForkNumber forknum, + BlockNumber *limit_block); +extern int BlockRefTableEntryGetBlocks(BlockRefTableEntry *entry, + BlockNumber start_blkno, + BlockNumber stop_blkno, + BlockNumber *blocks, + int nblocks); + +/* + * Functions for reading a block reference table incrementally from disk. + */ +extern BlockRefTableReader *CreateBlockRefTableReader(io_callback_fn read_callback, + void *read_callback_arg, + char *error_filename, + report_error_fn error_callback, + void *error_callback_arg); +extern bool BlockRefTableReaderNextRelation(BlockRefTableReader *reader, + RelFileLocator *rlocator, + ForkNumber *forknum, + BlockNumber *limit_block); +extern unsigned BlockRefTableReaderGetBlocks(BlockRefTableReader *reader, + BlockNumber *blocks, + int nblocks); +extern void DestroyBlockRefTableReader(BlockRefTableReader *reader); + +/* + * Functions for writing a block reference table incrementally to disk. + * + * Note that entries must be written in the proper order, that is, sorted by + * database, then tablespace, then relfilenumber, then fork number. Caller + * is responsible for supplying data in the correct order. If that seems hard, + * use an in-memory BlockRefTable instead. + */ +extern BlockRefTableWriter *CreateBlockRefTableWriter(io_callback_fn write_callback, + void *write_callback_arg); +extern void BlockRefTableWriteEntry(BlockRefTableWriter *writer, + BlockRefTableEntry *entry); +extern void DestroyBlockRefTableWriter(BlockRefTableWriter *writer); + +extern BlockRefTableEntry *CreateBlockRefTableEntry(RelFileLocator rlocator, + ForkNumber forknum); +extern void BlockRefTableEntrySetLimitBlock(BlockRefTableEntry *entry, + BlockNumber limit_block); +extern void BlockRefTableEntryMarkBlockModified(BlockRefTableEntry *entry, + ForkNumber forknum, + BlockNumber blknum); +extern void BlockRefTableFreeEntry(BlockRefTableEntry *entry); + +#endif /* BLKREFTABLE_H */ diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h index 1043a4d7821..74bc2f97cbd 100644 --- a/src/include/miscadmin.h +++ b/src/include/miscadmin.h @@ -336,6 +336,7 @@ typedef enum BackendType B_STARTUP, B_WAL_RECEIVER, B_WAL_SENDER, + B_WAL_SUMMARIZER, B_WAL_WRITER, } BackendType; @@ -442,6 +443,7 @@ typedef enum CheckpointerProcess, WalWriterProcess, WalReceiverProcess, + WalSummarizerProcess, NUM_AUXPROCTYPES /* Must be last! */ } AuxProcType; @@ -454,6 +456,7 @@ extern PGDLLIMPORT AuxProcType MyAuxProcType; #define AmCheckpointerProcess() (MyAuxProcType == CheckpointerProcess) #define AmWalWriterProcess() (MyAuxProcType == WalWriterProcess) #define AmWalReceiverProcess() (MyAuxProcType == WalReceiverProcess) +#define AmWalSummarizerProcess() (MyAuxProcType == WalSummarizerProcess) /***************************************************************************** diff --git a/src/include/postmaster/walsummarizer.h b/src/include/postmaster/walsummarizer.h new file mode 100644 index 00000000000..180d3f34b9b --- /dev/null +++ b/src/include/postmaster/walsummarizer.h @@ -0,0 +1,33 @@ +/*------------------------------------------------------------------------- + * + * walsummarizer.h + * + * Header file for background WAL summarization process. + * + * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group + * + * IDENTIFICATION + * src/include/postmaster/walsummarizer.h + * + *------------------------------------------------------------------------- + */ +#ifndef WALSUMMARIZER_H +#define WALSUMMARIZER_H + +#include "access/xlogdefs.h" + +extern bool summarize_wal; +extern int wal_summary_keep_time; + +extern Size WalSummarizerShmemSize(void); +extern void WalSummarizerShmemInit(void); +extern void WalSummarizerMain(void) pg_attribute_noreturn(); + +extern XLogRecPtr GetOldestUnsummarizedLSN(TimeLineID *tli, + bool *lsn_is_exact, + bool reset_pending_lsn); +extern void SetWalSummarizerLatch(void); +extern XLogRecPtr WaitForWalSummarization(XLogRecPtr lsn, long timeout, + XLogRecPtr *pending_lsn); + +#endif diff --git a/src/include/storage/proc.h b/src/include/storage/proc.h index 4b259612495..e87fd25d643 100644 --- a/src/include/storage/proc.h +++ b/src/include/storage/proc.h @@ -417,11 +417,12 @@ extern PGDLLIMPORT PGPROC *PreparedXactProcs; * We set aside some extra PGPROC structures for auxiliary processes, * ie things that aren't full-fledged backends but need shmem access. * - * Background writer, checkpointer, WAL writer and archiver run during normal - * operation. Startup process and WAL receiver also consume 2 slots, but WAL - * writer is launched only after startup has exited, so we only need 5 slots. + * Background writer, checkpointer, WAL writer, WAL summarizer, and archiver + * run during normal operation. Startup process and WAL receiver also consume + * 2 slots, but WAL writer is launched only after startup has exited, so we + * only need 6 slots. */ -#define NUM_AUXILIARY_PROCS 5 +#define NUM_AUXILIARY_PROCS 6 /* configurable options */ extern PGDLLIMPORT int DeadlockTimeout; diff --git a/src/include/utils/guc_tables.h b/src/include/utils/guc_tables.h index 0c382559617..eaa8c46ddac 100644 --- a/src/include/utils/guc_tables.h +++ b/src/include/utils/guc_tables.h @@ -72,6 +72,7 @@ enum config_group WAL_RECOVERY, WAL_ARCHIVE_RECOVERY, WAL_RECOVERY_TARGET, + WAL_SUMMARIZATION, REPLICATION_SENDING, REPLICATION_PRIMARY, REPLICATION_STANDBY, |
