From 9b4727e20cd7df7d2acde17610c8612d07aac789 Mon Sep 17 00:00:00 2001 From: Shinya Kato Date: Fri, 2 May 2025 14:58:07 +0900 Subject: [PATCH v3 2/9] Make pg_stat_reset_shared() return the reset time --- doc/src/sgml/monitoring.sgml | 5 +- src/backend/access/transam/xlogprefetcher.c | 6 ++- src/backend/catalog/system_functions.sql | 2 +- src/backend/utils/activity/pgstat.c | 5 +- src/backend/utils/adt/pgstatfuncs.c | 21 ++++---- src/include/access/xlogprefetcher.h | 3 +- src/include/catalog/pg_proc.dat | 2 +- src/include/pgstat.h | 2 +- src/test/regress/expected/stats.out | 56 ++++++++++----------- src/test/regress/sql/stats.sql | 14 +++--- 10 files changed, 61 insertions(+), 55 deletions(-) diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml index 6ebb205bb3f..e5edee97e94 100644 --- a/doc/src/sgml/monitoring.sgml +++ b/doc/src/sgml/monitoring.sgml @@ -5086,11 +5086,12 @@ description | Waiting for a newly initialized WAL file to reach durable storage pg_stat_reset_shared pg_stat_reset_shared ( [ target text DEFAULT NULL ] ) - void + timestamp with time zone Resets some cluster-wide statistics counters to zero, depending on the - argument. target can be: + argument, and returns the time of the reset. + target can be: diff --git a/src/backend/access/transam/xlogprefetcher.c b/src/backend/access/transam/xlogprefetcher.c index ed3aacabc98..bc033ae1842 100644 --- a/src/backend/access/transam/xlogprefetcher.c +++ b/src/backend/access/transam/xlogprefetcher.c @@ -299,16 +299,18 @@ XLogPrefetchShmemSize(void) /* * Reset all counters to zero. */ -void +TimestampTz XLogPrefetchResetStats(void) { - pg_atomic_write_u64(&SharedStats->reset_time, GetCurrentTimestamp()); + TimestampTz ts = GetCurrentTimestamp(); + pg_atomic_write_u64(&SharedStats->reset_time, ts); pg_atomic_write_u64(&SharedStats->prefetch, 0); pg_atomic_write_u64(&SharedStats->hit, 0); pg_atomic_write_u64(&SharedStats->skip_init, 0); pg_atomic_write_u64(&SharedStats->skip_new, 0); pg_atomic_write_u64(&SharedStats->skip_fpw, 0); pg_atomic_write_u64(&SharedStats->skip_rep, 0); + return ts; } void diff --git a/src/backend/catalog/system_functions.sql b/src/backend/catalog/system_functions.sql index 2d946d6d9e9..0d679e6a8d4 100644 --- a/src/backend/catalog/system_functions.sql +++ b/src/backend/catalog/system_functions.sql @@ -638,7 +638,7 @@ AS 'unicode_is_normalized'; CREATE OR REPLACE FUNCTION pg_stat_reset_shared(target text DEFAULT NULL) -RETURNS void +RETURNS timestamp with time zone LANGUAGE INTERNAL CALLED ON NULL INPUT VOLATILE PARALLEL SAFE AS 'pg_stat_reset_shared'; diff --git a/src/backend/utils/activity/pgstat.c b/src/backend/utils/activity/pgstat.c index 510e6cb11b6..1fcd140a589 100644 --- a/src/backend/utils/activity/pgstat.c +++ b/src/backend/utils/activity/pgstat.c @@ -875,7 +875,7 @@ pgstat_reset(PgStat_Kind kind, Oid dboid, uint64 objid) * Permission checking for this function is managed through the normal * GRANT system. */ -void +TimestampTz pgstat_reset_of_kind(PgStat_Kind kind) { const PgStat_KindInfo *kind_info = pgstat_get_kind_info(kind); @@ -885,8 +885,9 @@ pgstat_reset_of_kind(PgStat_Kind kind) kind_info->reset_all_cb(ts); else pgstat_reset_entries_of_kind(kind, ts); -} + return ts; +} /* ------------------------------------------------------------ * Fetching of stats diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c index 393958be632..4a84575e7a7 100644 --- a/src/backend/utils/adt/pgstatfuncs.c +++ b/src/backend/utils/adt/pgstatfuncs.c @@ -1893,6 +1893,7 @@ Datum pg_stat_reset_shared(PG_FUNCTION_ARGS) { char *target = NULL; + TimestampTz ts; if (PG_ARGISNULL(0)) { @@ -1903,34 +1904,34 @@ pg_stat_reset_shared(PG_FUNCTION_ARGS) pgstat_reset_of_kind(PGSTAT_KIND_IO); XLogPrefetchResetStats(); pgstat_reset_of_kind(PGSTAT_KIND_SLRU); - pgstat_reset_of_kind(PGSTAT_KIND_WAL); + ts = pgstat_reset_of_kind(PGSTAT_KIND_WAL); - PG_RETURN_VOID(); + PG_RETURN_TIMESTAMPTZ(ts); } target = text_to_cstring(PG_GETARG_TEXT_PP(0)); if (strcmp(target, "archiver") == 0) - pgstat_reset_of_kind(PGSTAT_KIND_ARCHIVER); + ts = pgstat_reset_of_kind(PGSTAT_KIND_ARCHIVER); else if (strcmp(target, "bgwriter") == 0) - pgstat_reset_of_kind(PGSTAT_KIND_BGWRITER); + ts = pgstat_reset_of_kind(PGSTAT_KIND_BGWRITER); else if (strcmp(target, "checkpointer") == 0) - pgstat_reset_of_kind(PGSTAT_KIND_CHECKPOINTER); + ts = pgstat_reset_of_kind(PGSTAT_KIND_CHECKPOINTER); else if (strcmp(target, "io") == 0) - pgstat_reset_of_kind(PGSTAT_KIND_IO); + ts = pgstat_reset_of_kind(PGSTAT_KIND_IO); else if (strcmp(target, "recovery_prefetch") == 0) - XLogPrefetchResetStats(); + ts = XLogPrefetchResetStats(); else if (strcmp(target, "slru") == 0) - pgstat_reset_of_kind(PGSTAT_KIND_SLRU); + ts = pgstat_reset_of_kind(PGSTAT_KIND_SLRU); else if (strcmp(target, "wal") == 0) - pgstat_reset_of_kind(PGSTAT_KIND_WAL); + ts = pgstat_reset_of_kind(PGSTAT_KIND_WAL); else ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("unrecognized reset target: \"%s\"", target), errhint("Target must be \"archiver\", \"bgwriter\", \"checkpointer\", \"io\", \"recovery_prefetch\", \"slru\", or \"wal\"."))); - PG_RETURN_VOID(); + PG_RETURN_TIMESTAMPTZ(ts); } /* diff --git a/src/include/access/xlogprefetcher.h b/src/include/access/xlogprefetcher.h index 50b39c1fb0d..6cc95b70c6e 100644 --- a/src/include/access/xlogprefetcher.h +++ b/src/include/access/xlogprefetcher.h @@ -16,6 +16,7 @@ #include "access/xlogdefs.h" #include "access/xlogreader.h" #include "access/xlogrecord.h" +#include "utils/timestamp.h" /* GUCs */ extern PGDLLIMPORT int recovery_prefetch; @@ -37,7 +38,7 @@ extern void XLogPrefetchReconfigure(void); extern size_t XLogPrefetchShmemSize(void); extern void XLogPrefetchShmemInit(void); -extern void XLogPrefetchResetStats(void); +extern TimestampTz XLogPrefetchResetStats(void); extern XLogPrefetcher *XLogPrefetcherAllocate(XLogReaderState *reader); extern void XLogPrefetcherFree(XLogPrefetcher *prefetcher); diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat index 1d1edf67ac5..df291d21ef7 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -6164,7 +6164,7 @@ { oid => '3775', descr => 'statistics: reset collected statistics shared across the cluster', proname => 'pg_stat_reset_shared', proisstrict => 'f', provolatile => 'v', - prorettype => 'void', proargtypes => 'text', + prorettype => 'timestamptz', proargtypes => 'text', prosrc => 'pg_stat_reset_shared' }, { oid => '3776', descr => 'statistics: reset collected statistics for a single table or index in the current database or shared across all databases in the cluster', diff --git a/src/include/pgstat.h b/src/include/pgstat.h index 33b3bd242a8..a91984f086f 100644 --- a/src/include/pgstat.h +++ b/src/include/pgstat.h @@ -531,7 +531,7 @@ extern void pgstat_force_next_flush(void); extern TimestampTz pgstat_reset_counters(void); extern void pgstat_reset(PgStat_Kind kind, Oid dboid, uint64 objid); -extern void pgstat_reset_of_kind(PgStat_Kind kind); +extern TimestampTz pgstat_reset_of_kind(PgStat_Kind kind); /* stats accessors */ extern void pgstat_clear_snapshot(void); diff --git a/src/test/regress/expected/stats.out b/src/test/regress/expected/stats.out index c150229da52..9b93d257992 100644 --- a/src/test/regress/expected/stats.out +++ b/src/test/regress/expected/stats.out @@ -1045,10 +1045,10 @@ SELECT stats_reset > :'slru_notify_reset_ts'::timestamptz FROM pg_stat_slru WHER -- Test that reset_shared with archiver specified as the stats type works SELECT stats_reset AS archiver_reset_ts FROM pg_stat_archiver \gset -SELECT pg_stat_reset_shared('archiver'); - pg_stat_reset_shared ----------------------- - +SELECT pg_stat_reset_shared('archiver') IS NOT NULL AS t; + t +--- + t (1 row) SELECT stats_reset > :'archiver_reset_ts'::timestamptz FROM pg_stat_archiver; @@ -1059,10 +1059,10 @@ SELECT stats_reset > :'archiver_reset_ts'::timestamptz FROM pg_stat_archiver; -- Test that reset_shared with bgwriter specified as the stats type works SELECT stats_reset AS bgwriter_reset_ts FROM pg_stat_bgwriter \gset -SELECT pg_stat_reset_shared('bgwriter'); - pg_stat_reset_shared ----------------------- - +SELECT pg_stat_reset_shared('bgwriter') IS NOT NULL AS t; + t +--- + t (1 row) SELECT stats_reset > :'bgwriter_reset_ts'::timestamptz FROM pg_stat_bgwriter; @@ -1073,10 +1073,10 @@ SELECT stats_reset > :'bgwriter_reset_ts'::timestamptz FROM pg_stat_bgwriter; -- Test that reset_shared with checkpointer specified as the stats type works SELECT stats_reset AS checkpointer_reset_ts FROM pg_stat_checkpointer \gset -SELECT pg_stat_reset_shared('checkpointer'); - pg_stat_reset_shared ----------------------- - +SELECT pg_stat_reset_shared('checkpointer') IS NOT NULL AS t; + t +--- + t (1 row) SELECT stats_reset > :'checkpointer_reset_ts'::timestamptz FROM pg_stat_checkpointer; @@ -1087,10 +1087,10 @@ SELECT stats_reset > :'checkpointer_reset_ts'::timestamptz FROM pg_stat_checkpoi -- Test that reset_shared with recovery_prefetch specified as the stats type works SELECT stats_reset AS recovery_prefetch_reset_ts FROM pg_stat_recovery_prefetch \gset -SELECT pg_stat_reset_shared('recovery_prefetch'); - pg_stat_reset_shared ----------------------- - +SELECT pg_stat_reset_shared('recovery_prefetch') IS NOT NULL AS t; + t +--- + t (1 row) SELECT stats_reset > :'recovery_prefetch_reset_ts'::timestamptz FROM pg_stat_recovery_prefetch; @@ -1101,10 +1101,10 @@ SELECT stats_reset > :'recovery_prefetch_reset_ts'::timestamptz FROM pg_stat_rec -- Test that reset_shared with slru specified as the stats type works SELECT max(stats_reset) AS slru_reset_ts FROM pg_stat_slru \gset -SELECT pg_stat_reset_shared('slru'); - pg_stat_reset_shared ----------------------- - +SELECT pg_stat_reset_shared('slru') IS NOT NULL AS t; + t +--- + t (1 row) SELECT max(stats_reset) > :'slru_reset_ts'::timestamptz FROM pg_stat_slru; @@ -1115,10 +1115,10 @@ SELECT max(stats_reset) > :'slru_reset_ts'::timestamptz FROM pg_stat_slru; -- Test that reset_shared with wal specified as the stats type works SELECT stats_reset AS wal_reset_ts FROM pg_stat_wal \gset -SELECT pg_stat_reset_shared('wal'); - pg_stat_reset_shared ----------------------- - +SELECT pg_stat_reset_shared('wal') IS NOT NULL AS t; + t +--- + t (1 row) SELECT stats_reset > :'wal_reset_ts'::timestamptz FROM pg_stat_wal; @@ -1727,10 +1727,10 @@ SELECT sum(evictions) + sum(reuses) + sum(extends) + sum(fsyncs) + sum(reads) + FROM pg_stat_io \gset SELECT sum(evictions) + sum(reuses) + sum(extends) + sum(fsyncs) + sum(reads) + sum(writes) + sum(writebacks) + sum(hits) AS my_io_stats_pre_reset FROM pg_stat_get_backend_io(pg_backend_pid()) \gset -SELECT pg_stat_reset_shared('io'); - pg_stat_reset_shared ----------------------- - +SELECT pg_stat_reset_shared('io') IS NOT NULL AS t; + t +--- + t (1 row) SELECT sum(evictions) + sum(reuses) + sum(extends) + sum(fsyncs) + sum(reads) + sum(writes) + sum(writebacks) + sum(hits) AS io_stats_post_reset diff --git a/src/test/regress/sql/stats.sql b/src/test/regress/sql/stats.sql index 86690e41b69..07fcff8215a 100644 --- a/src/test/regress/sql/stats.sql +++ b/src/test/regress/sql/stats.sql @@ -492,32 +492,32 @@ SELECT stats_reset > :'slru_notify_reset_ts'::timestamptz FROM pg_stat_slru WHER -- Test that reset_shared with archiver specified as the stats type works SELECT stats_reset AS archiver_reset_ts FROM pg_stat_archiver \gset -SELECT pg_stat_reset_shared('archiver'); +SELECT pg_stat_reset_shared('archiver') IS NOT NULL AS t; SELECT stats_reset > :'archiver_reset_ts'::timestamptz FROM pg_stat_archiver; -- Test that reset_shared with bgwriter specified as the stats type works SELECT stats_reset AS bgwriter_reset_ts FROM pg_stat_bgwriter \gset -SELECT pg_stat_reset_shared('bgwriter'); +SELECT pg_stat_reset_shared('bgwriter') IS NOT NULL AS t; SELECT stats_reset > :'bgwriter_reset_ts'::timestamptz FROM pg_stat_bgwriter; -- Test that reset_shared with checkpointer specified as the stats type works SELECT stats_reset AS checkpointer_reset_ts FROM pg_stat_checkpointer \gset -SELECT pg_stat_reset_shared('checkpointer'); +SELECT pg_stat_reset_shared('checkpointer') IS NOT NULL AS t; SELECT stats_reset > :'checkpointer_reset_ts'::timestamptz FROM pg_stat_checkpointer; -- Test that reset_shared with recovery_prefetch specified as the stats type works SELECT stats_reset AS recovery_prefetch_reset_ts FROM pg_stat_recovery_prefetch \gset -SELECT pg_stat_reset_shared('recovery_prefetch'); +SELECT pg_stat_reset_shared('recovery_prefetch') IS NOT NULL AS t; SELECT stats_reset > :'recovery_prefetch_reset_ts'::timestamptz FROM pg_stat_recovery_prefetch; -- Test that reset_shared with slru specified as the stats type works SELECT max(stats_reset) AS slru_reset_ts FROM pg_stat_slru \gset -SELECT pg_stat_reset_shared('slru'); +SELECT pg_stat_reset_shared('slru') IS NOT NULL AS t; SELECT max(stats_reset) > :'slru_reset_ts'::timestamptz FROM pg_stat_slru; -- Test that reset_shared with wal specified as the stats type works SELECT stats_reset AS wal_reset_ts FROM pg_stat_wal \gset -SELECT pg_stat_reset_shared('wal'); +SELECT pg_stat_reset_shared('wal') IS NOT NULL AS t; SELECT stats_reset > :'wal_reset_ts'::timestamptz FROM pg_stat_wal; -- Test error case for reset_shared with unknown stats type @@ -827,7 +827,7 @@ SELECT sum(evictions) + sum(reuses) + sum(extends) + sum(fsyncs) + sum(reads) + FROM pg_stat_io \gset SELECT sum(evictions) + sum(reuses) + sum(extends) + sum(fsyncs) + sum(reads) + sum(writes) + sum(writebacks) + sum(hits) AS my_io_stats_pre_reset FROM pg_stat_get_backend_io(pg_backend_pid()) \gset -SELECT pg_stat_reset_shared('io'); +SELECT pg_stat_reset_shared('io') IS NOT NULL AS t; SELECT sum(evictions) + sum(reuses) + sum(extends) + sum(fsyncs) + sum(reads) + sum(writes) + sum(writebacks) + sum(hits) AS io_stats_post_reset FROM pg_stat_io \gset SELECT :io_stats_post_reset < :io_stats_pre_reset; -- 2.47.3