From: Robert Haas Date: Thu, 11 Jan 2024 17:41:18 +0000 (-0500) Subject: Add new function pg_get_wal_summarizer_state(). X-Git-Tag: REL_17_BETA1~1140 X-Git-Url: http://git.postgresql.org/gitweb/?a=commitdiff_plain;h=d9ef650fca7bc574586f4171cd929cfd5240326e;p=postgresql.git Add new function pg_get_wal_summarizer_state(). This makes it possible to access information about the progress of WAL summarization from SQL. The previously-added functions pg_available_wal_summaries() and pg_wal_summary_contents() only examine on-disk state, but this function exposes information from the server's shared memory. Discussion: http://postgr.es/m/CA+Tgmobvqqj-DW9F7uUzT-cQqs6wcVb-Xhs=w=hzJnXSE-kRGw@mail.gmail.com --- diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index de78d58d4bc..0f7d409e601 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -26554,6 +26554,34 @@ SELECT collation for ('foo' COLLATE "de_DE"); relblocknumber will be zero. + + + + + pg_get_wal_summarizer_state + + pg_get_wal_summarizer_state () + record + ( summarized_tli bigint, + summarized_lsn pg_lsn, + pending_lsn pg_lsn, + summarizer_pid int ) + + + Returns information about the progress of the WAL summarizer. If the + WAL summarizer has never run since the instance was started, then + summarized_tli and summarized_lsn + will be 0 and 0/0 respectively; + otherwise, they will be the TLI and ending LSN of the last WAL summary + file written to disk. If the WAL summarizer is currently running, + pending_lsn will be the ending LSN of the last + record that it has consumed, which must always be greater than or + equal to summarized_lsn; if the WAL summarizer is + not running, it will be equal to summarized_lsn. + summarized_pid is the PID of the WAL summarizer + process, if it is running, and otherwise NULL. + + diff --git a/src/backend/backup/walsummaryfuncs.c b/src/backend/backup/walsummaryfuncs.c index 89c660c6969..f082488b33f 100644 --- a/src/backend/backup/walsummaryfuncs.c +++ b/src/backend/backup/walsummaryfuncs.c @@ -16,11 +16,13 @@ #include "common/blkreftable.h" #include "funcapi.h" #include "miscadmin.h" +#include "postmaster/walsummarizer.h" #include "utils/fmgrprotos.h" #include "utils/pg_lsn.h" #define NUM_WS_ATTS 3 #define NUM_SUMMARY_ATTS 6 +#define NUM_STATE_ATTS 4 #define MAX_BLOCKS_PER_CALL 256 /* @@ -167,3 +169,40 @@ pg_wal_summary_contents(PG_FUNCTION_ARGS) return (Datum) 0; } + +/* + * Returns information about the state of the WAL summarizer process. + */ +Datum +pg_get_wal_summarizer_state(PG_FUNCTION_ARGS) +{ + Datum values[NUM_STATE_ATTS]; + bool nulls[NUM_STATE_ATTS]; + TimeLineID summarized_tli; + XLogRecPtr summarized_lsn; + XLogRecPtr pending_lsn; + int summarizer_pid; + TupleDesc tupdesc; + HeapTuple htup; + + GetWalSummarizerState(&summarized_tli, &summarized_lsn, &pending_lsn, + &summarizer_pid); + + if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) + elog(ERROR, "return type must be a row type"); + + memset(nulls, 0, sizeof(nulls)); + + values[0] = Int64GetDatum((int64) summarized_tli); + values[1] = LSNGetDatum(summarized_lsn); + values[2] = LSNGetDatum(pending_lsn); + + if (summarizer_pid < 0) + nulls[3] = true; + else + values[3] = Int32GetDatum(summarizer_pid); + + htup = heap_form_tuple(tupdesc, values, nulls); + + PG_RETURN_DATUM(HeapTupleGetDatum(htup)); +} diff --git a/src/backend/postmaster/walsummarizer.c b/src/backend/postmaster/walsummarizer.c index f828cc436a6..7287f07529e 100644 --- a/src/backend/postmaster/walsummarizer.c +++ b/src/backend/postmaster/walsummarizer.c @@ -142,6 +142,7 @@ static XLogRecPtr redo_pointer_at_last_summary_removal = InvalidXLogRecPtr; bool summarize_wal = false; int wal_summary_keep_time = 10 * 24 * 60; +static void WalSummarizerShutdown(int code, Datum arg); static XLogRecPtr GetLatestLSN(TimeLineID *tli); static void HandleWalSummarizerInterrupts(void); static XLogRecPtr SummarizeWAL(TimeLineID tli, XLogRecPtr start_lsn, @@ -245,6 +246,7 @@ WalSummarizerMain(void) pqsignal(SIGUSR2, SIG_IGN); /* not used */ /* Advertise ourselves. */ + on_shmem_exit(WalSummarizerShutdown, (Datum) 0); LWLockAcquire(WALSummarizerLock, LW_EXCLUSIVE); WalSummarizerCtl->summarizer_pgprocno = MyProc->pgprocno; LWLockRelease(WALSummarizerLock); @@ -417,6 +419,57 @@ WalSummarizerMain(void) } } +/* + * Get information about the state of the WAL summarizer. + */ +void +GetWalSummarizerState(TimeLineID *summarized_tli, XLogRecPtr *summarized_lsn, + XLogRecPtr *pending_lsn, int *summarizer_pid) +{ + LWLockAcquire(WALSummarizerLock, LW_SHARED); + if (!WalSummarizerCtl->initialized) + { + /* + * If initialized is false, the rest of the structure contents are + * undefined. + */ + *summarized_tli = 0; + *summarized_lsn = InvalidXLogRecPtr; + *pending_lsn = InvalidXLogRecPtr; + *summarizer_pid = -1; + } + else + { + int summarizer_pgprocno = WalSummarizerCtl->summarizer_pgprocno; + + *summarized_tli = WalSummarizerCtl->summarized_tli; + *summarized_lsn = WalSummarizerCtl->summarized_lsn; + if (summarizer_pgprocno == INVALID_PGPROCNO) + { + /* + * If the summarizer has exited, the fact that it had processed + * beyond summarized_lsn is irrelevant now. + */ + *pending_lsn = WalSummarizerCtl->summarized_lsn; + *summarizer_pid = -1; + } + else + { + *pending_lsn = WalSummarizerCtl->pending_lsn; + + /* + * We're not fussed about inexact answers here, since they could + * become stale instantly, so we don't bother taking the lock, but + * make sure that invalid PID values are normalized to -1. + */ + *summarizer_pid = GetPGProcByNumber(summarizer_pgprocno)->pid; + if (*summarizer_pid <= 0) + *summarizer_pid = -1; + } + } + LWLockRelease(WALSummarizerLock); +} + /* * Get the oldest LSN in this server's timeline history that has not yet been * summarized. @@ -622,6 +675,18 @@ WaitForWalSummarization(XLogRecPtr lsn, long timeout, XLogRecPtr *pending_lsn) return summarized_lsn; } +/* + * On exit, update shared memory to make it clear that we're no longer + * running. + */ +static void +WalSummarizerShutdown(int code, Datum arg) +{ + LWLockAcquire(WALSummarizerLock, LW_EXCLUSIVE); + WalSummarizerCtl->summarizer_pgprocno = INVALID_PGPROCNO; + LWLockRelease(WALSummarizerLock); +} + /* * Get the latest LSN that is eligible to be summarized, and set *tli to the * corresponding timeline. diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index 686667a0f88..a94dcdc2713 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -57,6 +57,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 202401041 +#define CATALOG_VERSION_NO 202401111 #endif diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat index 7979392776d..58811a6530b 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -12142,5 +12142,14 @@ 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' }, +{ oid => '8438', + descr => 'WAL summarizer state', + proname => 'pg_get_wal_summarizer_state', + provolatile => 'v', proparallel => 's', + prorettype => 'record', proargtypes => '', + proallargtypes => '{int8,pg_lsn,pg_lsn,int4}', + proargmodes => '{o,o,o,o}', + proargnames => '{summarized_tli,summarized_lsn,pending_lsn,summarizer_pid}', + prosrc => 'pg_get_wal_summarizer_state' }, ] diff --git a/src/include/postmaster/walsummarizer.h b/src/include/postmaster/walsummarizer.h index 75cb1d709fc..d6e61b59ac7 100644 --- a/src/include/postmaster/walsummarizer.h +++ b/src/include/postmaster/walsummarizer.h @@ -23,6 +23,10 @@ extern Size WalSummarizerShmemSize(void); extern void WalSummarizerShmemInit(void); extern void WalSummarizerMain(void) pg_attribute_noreturn(); +extern void GetWalSummarizerState(TimeLineID *summarized_tli, + XLogRecPtr *summarized_lsn, + XLogRecPtr *pending_lsn, + int *summarizer_pid); extern XLogRecPtr GetOldestUnsummarizedLSN(TimeLineID *tli, bool *lsn_is_exact, bool reset_pending_lsn);