From 2018607f26f9a532f23a059bc8819b9fedf8ff20 Mon Sep 17 00:00:00 2001 From: Shinya Kato Date: Fri, 2 May 2025 18:13:45 +0900 Subject: [PATCH v1 7/9] Make pg_stat_reset_replication_slot() return the reset time --- contrib/test_decoding/expected/stats.out | 35 +++++++++++++++----- contrib/test_decoding/sql/stats.sql | 9 +++-- doc/src/sgml/monitoring.sgml | 9 ++--- src/backend/utils/activity/pgstat_replslot.c | 9 +++-- src/backend/utils/adt/pgstatfuncs.c | 10 ++++-- src/include/catalog/pg_proc.dat | 2 +- src/include/pgstat.h | 2 +- 7 files changed, 55 insertions(+), 21 deletions(-) diff --git a/contrib/test_decoding/expected/stats.out b/contrib/test_decoding/expected/stats.out index de6dc416130..874a52eb28e 100644 --- a/contrib/test_decoding/expected/stats.out +++ b/contrib/test_decoding/expected/stats.out @@ -47,10 +47,10 @@ SELECT slot_name, spill_txns = 0 AS spill_txns, spill_count = 0 AS spill_count, RESET logical_decoding_work_mem; -- reset stats for one slot, others should be unaffected -SELECT pg_stat_reset_replication_slot('regression_slot_stats1'); - pg_stat_reset_replication_slot --------------------------------- - +SELECT pg_stat_reset_replication_slot('regression_slot_stats1') IS NOT NULL AS t; + t +--- + t (1 row) SELECT slot_name, spill_txns = 0 AS spill_txns, spill_count = 0 AS spill_count, total_txns > 0 AS total_txns, total_bytes > 0 AS total_bytes FROM pg_stat_replication_slots ORDER BY slot_name; @@ -62,10 +62,10 @@ SELECT slot_name, spill_txns = 0 AS spill_txns, spill_count = 0 AS spill_count, (3 rows) -- reset stats for all slots -SELECT pg_stat_reset_replication_slot(NULL); - pg_stat_reset_replication_slot --------------------------------- - +SELECT pg_stat_reset_replication_slot(NULL) IS NOT NULL AS t; + t +--- + t (1 row) SELECT slot_name, spill_txns = 0 AS spill_txns, spill_count = 0 AS spill_count, total_txns > 0 AS total_txns, total_bytes > 0 AS total_bytes FROM pg_stat_replication_slots ORDER BY slot_name; @@ -91,6 +91,25 @@ SELECT * FROM pg_stat_get_replication_slot('do-not-exist'); do-not-exist | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | (1 row) +-- verify physical replication slot stats are not reset +SELECT 'init' FROM pg_create_physical_replication_slot('regression_slot_stats_physical') ps; + ?column? +---------- + init +(1 row) + +SELECT pg_stat_reset_replication_slot('regression_slot_stats_physical'); + pg_stat_reset_replication_slot +-------------------------------- + +(1 row) + +SELECT pg_drop_replication_slot('regression_slot_stats_physical'); + pg_drop_replication_slot +-------------------------- + +(1 row) + -- spilling the xact BEGIN; INSERT INTO stats_test SELECT 'serialize-topbig--1:'||g.i FROM generate_series(1, 5000) g(i); diff --git a/contrib/test_decoding/sql/stats.sql b/contrib/test_decoding/sql/stats.sql index a022fe1bf07..8ca60f788e3 100644 --- a/contrib/test_decoding/sql/stats.sql +++ b/contrib/test_decoding/sql/stats.sql @@ -19,11 +19,11 @@ SELECT slot_name, spill_txns = 0 AS spill_txns, spill_count = 0 AS spill_count, RESET logical_decoding_work_mem; -- reset stats for one slot, others should be unaffected -SELECT pg_stat_reset_replication_slot('regression_slot_stats1'); +SELECT pg_stat_reset_replication_slot('regression_slot_stats1') IS NOT NULL AS t; SELECT slot_name, spill_txns = 0 AS spill_txns, spill_count = 0 AS spill_count, total_txns > 0 AS total_txns, total_bytes > 0 AS total_bytes FROM pg_stat_replication_slots ORDER BY slot_name; -- reset stats for all slots -SELECT pg_stat_reset_replication_slot(NULL); +SELECT pg_stat_reset_replication_slot(NULL) IS NOT NULL AS t; SELECT slot_name, spill_txns = 0 AS spill_txns, spill_count = 0 AS spill_count, total_txns > 0 AS total_txns, total_bytes > 0 AS total_bytes FROM pg_stat_replication_slots ORDER BY slot_name; -- verify accessing/resetting stats for non-existent slot does something reasonable @@ -31,6 +31,11 @@ SELECT * FROM pg_stat_get_replication_slot('do-not-exist'); SELECT pg_stat_reset_replication_slot('do-not-exist'); SELECT * FROM pg_stat_get_replication_slot('do-not-exist'); +-- verify physical replication slot stats are not reset +SELECT 'init' FROM pg_create_physical_replication_slot('regression_slot_stats_physical') ps; +SELECT pg_stat_reset_replication_slot('regression_slot_stats_physical'); +SELECT pg_drop_replication_slot('regression_slot_stats_physical'); + -- spilling the xact BEGIN; INSERT INTO stats_test SELECT 'serialize-topbig--1:'||g.i FROM generate_series(1, 5000) g(i); diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml index df90f4668c4..27f22e6fd76 100644 --- a/doc/src/sgml/monitoring.sgml +++ b/doc/src/sgml/monitoring.sgml @@ -5183,12 +5183,13 @@ description | Waiting for a newly initialized WAL file to reach durable storage pg_stat_reset_replication_slot pg_stat_reset_replication_slot ( text ) - void + timestamp with time zone - Resets statistics of the replication slot defined by the argument. If - the argument is NULL, resets statistics for all - the replication slots. + Resets statistics of the replication slot defined by the argument, and + returns the time of the reset or NULL if the replication + slot defined by the argument is a physical slot. If the argument is + NULL, resets statistics for all the replication slots. This function is restricted to superusers by default, but other users diff --git a/src/backend/utils/activity/pgstat_replslot.c b/src/backend/utils/activity/pgstat_replslot.c index ccfb11c49bf..67f5c53989e 100644 --- a/src/backend/utils/activity/pgstat_replslot.c +++ b/src/backend/utils/activity/pgstat_replslot.c @@ -37,11 +37,14 @@ static int get_replslot_index(const char *name, bool need_lock); * * Permission checking for this function is managed through the normal * GRANT system. + * + * NB: Returns the time of the reset or 0 if it is a physical slot. */ -void +TimestampTz pgstat_reset_replslot(const char *name) { ReplicationSlot *slot; + TimestampTz ts = 0; Assert(name != NULL); @@ -61,10 +64,12 @@ pgstat_reset_replslot(const char *name) * as we collect stats only for logical slots. */ if (SlotIsLogical(slot)) - pgstat_reset(PGSTAT_KIND_REPLSLOT, InvalidOid, + ts = pgstat_reset(PGSTAT_KIND_REPLSLOT, InvalidOid, ReplicationSlotIndex(slot)); LWLockRelease(ReplicationSlotControlLock); + + return ts; } /* diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c index b28ceab91d9..7d9df708266 100644 --- a/src/backend/utils/adt/pgstatfuncs.c +++ b/src/backend/utils/adt/pgstatfuncs.c @@ -1999,16 +1999,20 @@ Datum pg_stat_reset_replication_slot(PG_FUNCTION_ARGS) { char *target = NULL; + TimestampTz ts; if (PG_ARGISNULL(0)) - pgstat_reset_of_kind(PGSTAT_KIND_REPLSLOT); + ts = pgstat_reset_of_kind(PGSTAT_KIND_REPLSLOT); else { target = text_to_cstring(PG_GETARG_TEXT_PP(0)); - pgstat_reset_replslot(target); + ts = pgstat_reset_replslot(target); } - PG_RETURN_VOID(); + if (ts == 0) + PG_RETURN_NULL(); + else + PG_RETURN_TIMESTAMPTZ(ts); } /* Reset subscription stats (a specific one or all of them) */ diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat index 6edc8ae67e4..fa1a26d3f03 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -6168,7 +6168,7 @@ { oid => '6170', descr => 'statistics: reset collected statistics for a single replication slot', proname => 'pg_stat_reset_replication_slot', proisstrict => 'f', - provolatile => 'v', prorettype => 'void', proargtypes => 'text', + provolatile => 'v', prorettype => 'timestamptz', proargtypes => 'text', prosrc => 'pg_stat_reset_replication_slot' }, { oid => '6232', descr => 'statistics: reset collected statistics for a single subscription', diff --git a/src/include/pgstat.h b/src/include/pgstat.h index 809c00dec6f..96cfbaab798 100644 --- a/src/include/pgstat.h +++ b/src/include/pgstat.h @@ -733,7 +733,7 @@ extern PgStat_TableStatus *find_tabstat_entry(Oid rel_id); * Functions in pgstat_replslot.c */ -extern void pgstat_reset_replslot(const char *name); +extern TimestampTz pgstat_reset_replslot(const char *name); struct ReplicationSlot; extern void pgstat_report_replslot(struct ReplicationSlot *slot, const PgStat_StatReplSlotEntry *repSlotStat); extern void pgstat_create_replslot(struct ReplicationSlot *slot); -- 2.47.1