From 3041fdff5a05f918807a8f2154d56cbb616a8d7d Mon Sep 17 00:00:00 2001 From: Shlok Kyal Date: Mon, 8 Sep 2025 21:04:42 +0530 Subject: [PATCH v8 1/2] Add stats related to slot sync skip When slot sync is performed, it can happen that it is skipped due to various reason. This patch adds stats for synced slots regarding this slot sync skip. This patch adds new columns slotsync_skip_count, last_slotsync_skip_at to view pg_stat_replication_slots and new column slotsync_skip_reason to view pg_replication_slots. --- contrib/test_decoding/expected/stats.out | 12 +-- doc/src/sgml/monitoring.sgml | 25 ++++++ doc/src/sgml/system-views.sgml | 43 +++++++++++ src/backend/catalog/system_views.sql | 5 +- src/backend/replication/logical/slotsync.c | 81 ++++++++++++++++++++ src/backend/replication/slot.c | 1 + src/backend/replication/slotfuncs.c | 26 ++++++- src/backend/utils/activity/pgstat_replslot.c | 25 ++++++ src/backend/utils/adt/pgstatfuncs.c | 18 ++++- src/include/catalog/pg_proc.dat | 12 +-- src/include/pgstat.h | 3 + src/include/replication/slot.h | 17 ++++ src/test/regress/expected/rules.out | 9 ++- src/tools/pgindent/typedefs.list | 1 + 14 files changed, 257 insertions(+), 21 deletions(-) diff --git a/contrib/test_decoding/expected/stats.out b/contrib/test_decoding/expected/stats.out index 28da9123cc8..7426c48040a 100644 --- a/contrib/test_decoding/expected/stats.out +++ b/contrib/test_decoding/expected/stats.out @@ -78,17 +78,17 @@ SELECT slot_name, spill_txns = 0 AS spill_txns, spill_count = 0 AS spill_count, -- verify accessing/resetting stats for non-existent slot does something reasonable SELECT * FROM pg_stat_get_replication_slot('do-not-exist'); - slot_name | spill_txns | spill_count | spill_bytes | stream_txns | stream_count | stream_bytes | mem_exceeded_count | total_txns | total_bytes | stats_reset ---------------+------------+-------------+-------------+-------------+--------------+--------------+--------------------+------------+-------------+------------- - do-not-exist | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | + slot_name | spill_txns | spill_count | spill_bytes | stream_txns | stream_count | stream_bytes | mem_exceeded_count | total_txns | total_bytes | slotsync_skip_count | last_slotsync_skip_at | stats_reset +--------------+------------+-------------+-------------+-------------+--------------+--------------+--------------------+------------+-------------+---------------------+-----------------------+------------- + do-not-exist | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | | (1 row) SELECT pg_stat_reset_replication_slot('do-not-exist'); ERROR: replication slot "do-not-exist" does not exist SELECT * FROM pg_stat_get_replication_slot('do-not-exist'); - slot_name | spill_txns | spill_count | spill_bytes | stream_txns | stream_count | stream_bytes | mem_exceeded_count | total_txns | total_bytes | stats_reset ---------------+------------+-------------+-------------+-------------+--------------+--------------+--------------------+------------+-------------+------------- - do-not-exist | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | + slot_name | spill_txns | spill_count | spill_bytes | stream_txns | stream_count | stream_bytes | mem_exceeded_count | total_txns | total_bytes | slotsync_skip_count | last_slotsync_skip_at | stats_reset +--------------+------------+-------------+-------------+-------------+--------------+--------------+--------------------+------------+-------------+---------------------+-----------------------+------------- + do-not-exist | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | | (1 row) -- spilling the xact diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml index 436ef0e8bd0..894a972b3c1 100644 --- a/doc/src/sgml/monitoring.sgml +++ b/doc/src/sgml/monitoring.sgml @@ -1659,6 +1659,31 @@ description | Waiting for a newly initialized WAL file to reach durable storage + + + slotsync_skip_countbigint + + + Number of times the slot synchronization is skipped. The value of this + column has no meaning on the primary server; it defaults to 0 for all + slots, but may (if leftover from a promoted standby) also have a + positive value. + + + + + + + last_slotsync_skip_attimestamp with time zone + + + Time at which last slot synchronization was skipped. The value of this + column has no meaning on the primary server; it defaults to NULL for all + slots, but may (if leftover from a promotedstandby) contain a timestamp. + + + + stats_reset timestamp with time zone diff --git a/doc/src/sgml/system-views.sgml b/doc/src/sgml/system-views.sgml index 7971498fe75..08ed9d609e1 100644 --- a/doc/src/sgml/system-views.sgml +++ b/doc/src/sgml/system-views.sgml @@ -3102,6 +3102,49 @@ SELECT * FROM pg_locks pl LEFT JOIN pg_prepared_xacts ppx + + + slotsync_skip_reasontext + + + The reason for the last slot synchronization skip. This field is set only + for logical slots that are being synchronized from a primary server (that + is, those whose synced field is + true). The value of this column has no meaning on the + primary server; it defaults to none for all slots, but + may (if leftover from a promoted standby) also have a value other than + none. Possible values are: + + + + none means that the last slot synchronization + completed successfully. + + + + + remote_behind means that the last slot + synchronization was skipped because the slot is ahead of the + corresponding failover slot on the primary. + + + + + wal_not_flushed means that the last slot + synchronization was skipped because the standby had not flushed the + WAL corresponding to the confirmed flush position on the remote slot. + + + + + no_consistent_snapshot means that the last slot + synchronization was skipped because the standby could not build a + consistent snapshot. + + + + + diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql index 95ad29a64b9..4257e7db9be 100644 --- a/src/backend/catalog/system_views.sql +++ b/src/backend/catalog/system_views.sql @@ -1060,7 +1060,8 @@ CREATE VIEW pg_replication_slots AS L.conflicting, L.invalidation_reason, L.failover, - L.synced + L.synced, + L.slotsync_skip_reason FROM pg_get_replication_slots() AS L LEFT JOIN pg_database D ON (L.datoid = D.oid); @@ -1076,6 +1077,8 @@ CREATE VIEW pg_stat_replication_slots AS s.mem_exceeded_count, s.total_txns, s.total_bytes, + s.slotsync_skip_count, + s.last_slotsync_skip_at, s.stats_reset FROM pg_replication_slots as r, LATERAL pg_stat_get_replication_slot(slot_name) as s diff --git a/src/backend/replication/logical/slotsync.c b/src/backend/replication/logical/slotsync.c index 8b4afd87dc9..b7d8b991d71 100644 --- a/src/backend/replication/logical/slotsync.c +++ b/src/backend/replication/logical/slotsync.c @@ -64,6 +64,7 @@ #include "storage/procarray.h" #include "tcop/tcopprot.h" #include "utils/builtins.h" +#include "utils/injection_point.h" #include "utils/pg_lsn.h" #include "utils/ps_status.h" #include "utils/timeout.h" @@ -148,6 +149,35 @@ typedef struct RemoteSlot static void slotsync_failure_callback(int code, Datum arg); static void update_synced_slots_inactive_since(void); +/* + * Update slot sync skip stats. This function requires the caller to acquire + * the slot. + */ +static void +update_slotsync_skip_stats(SlotSyncSkipReason skip_reason) +{ + ReplicationSlot *slot; + + Assert(MyReplicationSlot); + + slot = MyReplicationSlot; + + /* + * Update the slot sync related stats in pg_stat_replication_slot when a + * slot sync is skipped + */ + if (skip_reason != SS_SKIP_NONE) + pgstat_report_replslotsync_skip(slot); + + /* Update the slot sync skip reason */ + if (slot->slotsync_skip_reason != skip_reason) + { + SpinLockAcquire(&slot->mutex); + slot->slotsync_skip_reason = skip_reason; + SpinLockRelease(&slot->mutex); + } +} + /* * If necessary, update the local synced slot's metadata based on the data * from the remote slot. @@ -218,6 +248,8 @@ update_local_synced_slot(RemoteSlot *remote_slot, Oid remote_dbid, LSN_FORMAT_ARGS(slot->data.restart_lsn), slot->data.catalog_xmin)); + update_slotsync_skip_stats(SS_SKIP_REMOTE_BEHIND); + if (remote_slot_precedes) *remote_slot_precedes = true; @@ -261,6 +293,9 @@ update_local_synced_slot(RemoteSlot *remote_slot, Oid remote_dbid, slot->data.catalog_xmin = remote_slot->catalog_xmin; SpinLockRelease(&slot->mutex); + /* Synchronization happened, update the slot sync skip reason */ + update_slotsync_skip_stats(SS_SKIP_NONE); + if (found_consistent_snapshot) *found_consistent_snapshot = true; } @@ -277,6 +312,17 @@ update_local_synced_slot(RemoteSlot *remote_slot, Oid remote_dbid, errdetail_internal("Remote slot has LSN %X/%08X but local slot has LSN %X/%08X.", LSN_FORMAT_ARGS(remote_slot->confirmed_lsn), LSN_FORMAT_ARGS(slot->data.confirmed_flush))); + + /* + * If found_consistent_snapshot is not NULL, a true value means + * the slot synchronization was successful, while a false value + * means it was skipped (see + * update_and_persist_local_synced_slot()). If + * found_consistent_snapshot is NULL, no such check exists, so the + * stats can be updated directly. + */ + if (!found_consistent_snapshot || *found_consistent_snapshot) + update_slotsync_skip_stats(SS_SKIP_NONE); } updated_xmin_or_lsn = true; @@ -580,6 +626,9 @@ update_and_persist_local_synced_slot(RemoteSlot *remote_slot, Oid remote_dbid) * current location when recreating the slot in the next cycle. It may * take more time to create such a slot. Therefore, we keep this slot * and attempt the synchronization in the next cycle. + * + * We do not need to update the slot sync skip stats here as it will + * be already updated in function update_local_synced_slot. */ return false; } @@ -595,11 +644,21 @@ update_and_persist_local_synced_slot(RemoteSlot *remote_slot, Oid remote_dbid) errdetail("Synchronization could lead to data loss, because the standby could not build a consistent snapshot to decode WALs at LSN %X/%08X.", LSN_FORMAT_ARGS(slot->data.restart_lsn))); + /* + * If a consitent snapshot is not found, update the slot sync skip + * stats + */ + update_slotsync_skip_stats(SS_SKIP_NO_CONSISTENT_SNAPSHOT); + return false; } ReplicationSlotPersist(); + /* + * For the success case we do not update the slot sync skip stats here as + * it is already be updated in update_local_synced_slot. + */ ereport(LOG, errmsg("newly created replication slot \"%s\" is sync-ready now", remote_slot->name)); @@ -634,6 +693,26 @@ synchronize_one_slot(RemoteSlot *remote_slot, Oid remote_dbid) latestFlushPtr = GetStandbyFlushRecPtr(NULL); if (remote_slot->confirmed_lsn > latestFlushPtr) { + /* If slot is present on the local, update the slot sync skip stats */ + if ((slot = SearchNamedReplicationSlot(remote_slot->name, true))) + { + bool synced; + + SpinLockAcquire(&slot->mutex); + synced = slot->data.synced; + SpinLockRelease(&slot->mutex); + + if (synced) + { + ReplicationSlotAcquire(NameStr(slot->data.name), true, false); + + if (slot->data.invalidated == RS_INVAL_NONE) + update_slotsync_skip_stats(SS_SKIP_WAL_NOT_FLUSHED); + + ReplicationSlotRelease(); + } + } + /* * Can get here only if GUC 'synchronized_standby_slots' on the * primary server was not configured correctly. @@ -939,6 +1018,8 @@ synchronize_slots(WalReceiverConn *wrconn) if (started_tx) CommitTransactionCommand(); + INJECTION_POINT("slot-sync-skip", NULL); + return some_slot_updated; } diff --git a/src/backend/replication/slot.c b/src/backend/replication/slot.c index 1ec1e997b27..86ae99a3ca9 100644 --- a/src/backend/replication/slot.c +++ b/src/backend/replication/slot.c @@ -491,6 +491,7 @@ ReplicationSlotCreate(const char *name, bool db_specific, slot->last_saved_confirmed_flush = InvalidXLogRecPtr; slot->last_saved_restart_lsn = InvalidXLogRecPtr; slot->inactive_since = 0; + slot->slotsync_skip_reason = SS_SKIP_NONE; /* * Create the slot on disk. We haven't actually marked the slot allocated diff --git a/src/backend/replication/slotfuncs.c b/src/backend/replication/slotfuncs.c index 0478fc9c977..66b989027a5 100644 --- a/src/backend/replication/slotfuncs.c +++ b/src/backend/replication/slotfuncs.c @@ -228,6 +228,28 @@ pg_drop_replication_slot(PG_FUNCTION_ARGS) PG_RETURN_VOID(); } +/* + * Map a SlotSyncSkipReason enum to a human-readable string + */ +static char * +GetSlotSyncSkipReason(SlotSyncSkipReason reason) +{ + switch (reason) + { + case SS_SKIP_NONE: + return "none"; + case SS_SKIP_REMOTE_BEHIND: + return "remote_behind"; + case SS_SKIP_WAL_NOT_FLUSHED: + return "wal_not_flushed"; + case SS_SKIP_NO_CONSISTENT_SNAPSHOT: + return "no_consistent_snapshot"; + } + + Assert(false); + return "none"; +} + /* * pg_get_replication_slots - SQL SRF showing all replication slots * that currently exist on the database cluster. @@ -235,7 +257,7 @@ pg_drop_replication_slot(PG_FUNCTION_ARGS) Datum pg_get_replication_slots(PG_FUNCTION_ARGS) { -#define PG_GET_REPLICATION_SLOTS_COLS 20 +#define PG_GET_REPLICATION_SLOTS_COLS 21 ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo; XLogRecPtr currlsn; int slotno; @@ -443,6 +465,8 @@ pg_get_replication_slots(PG_FUNCTION_ARGS) values[i++] = BoolGetDatum(slot_contents.data.synced); + values[i++] = CStringGetTextDatum(GetSlotSyncSkipReason(slot_contents.slotsync_skip_reason)); + Assert(i == PG_GET_REPLICATION_SLOTS_COLS); tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, diff --git a/src/backend/utils/activity/pgstat_replslot.c b/src/backend/utils/activity/pgstat_replslot.c index d210c261ac6..10cf97bd29a 100644 --- a/src/backend/utils/activity/pgstat_replslot.c +++ b/src/backend/utils/activity/pgstat_replslot.c @@ -102,6 +102,31 @@ pgstat_report_replslot(ReplicationSlot *slot, const PgStat_StatReplSlotEntry *re pgstat_unlock_entry(entry_ref); } +/* + * Report replication slot sync skip statistics. + * + * We can rely on the stats for the slot to exist and to belong to this + * slot. We can only get here if pgstat_create_replslot() or + * pgstat_acquire_replslot() have already been called. + */ +void +pgstat_report_replslotsync_skip(ReplicationSlot *slot) +{ + PgStat_EntryRef *entry_ref; + PgStatShared_ReplSlot *shstatent; + PgStat_StatReplSlotEntry *statent; + + entry_ref = pgstat_get_entry_ref_locked(PGSTAT_KIND_REPLSLOT, InvalidOid, + ReplicationSlotIndex(slot), false); + shstatent = (PgStatShared_ReplSlot *) entry_ref->shared_stats; + statent = &shstatent->stats; + + statent->slotsync_skip_count += 1; + statent->last_slotsync_skip_at = GetCurrentTimestamp(); + + pgstat_unlock_entry(entry_ref); +} + /* * Report replication slot creation. * diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c index 3d98d064a94..607aa39fd89 100644 --- a/src/backend/utils/adt/pgstatfuncs.c +++ b/src/backend/utils/adt/pgstatfuncs.c @@ -2129,7 +2129,7 @@ pg_stat_get_archiver(PG_FUNCTION_ARGS) Datum pg_stat_get_replication_slot(PG_FUNCTION_ARGS) { -#define PG_STAT_GET_REPLICATION_SLOT_COLS 11 +#define PG_STAT_GET_REPLICATION_SLOT_COLS 13 text *slotname_text = PG_GETARG_TEXT_P(0); NameData slotname; TupleDesc tupdesc; @@ -2160,7 +2160,11 @@ pg_stat_get_replication_slot(PG_FUNCTION_ARGS) INT8OID, -1, 0); TupleDescInitEntry(tupdesc, (AttrNumber) 10, "total_bytes", INT8OID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 11, "stats_reset", + TupleDescInitEntry(tupdesc, (AttrNumber) 11, "slotsync_skip_count", + INT8OID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 12, "last_slotsync_skip_at", + TIMESTAMPTZOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 13, "stats_reset", TIMESTAMPTZOID, -1, 0); BlessTupleDesc(tupdesc); @@ -2186,11 +2190,17 @@ pg_stat_get_replication_slot(PG_FUNCTION_ARGS) values[7] = Int64GetDatum(slotent->mem_exceeded_count); values[8] = Int64GetDatum(slotent->total_txns); values[9] = Int64GetDatum(slotent->total_bytes); + values[10] = Int64GetDatum(slotent->slotsync_skip_count); + + if (slotent->last_slotsync_skip_at == 0) + nulls[11] = true; + else + values[11] = TimestampTzGetDatum(slotent->last_slotsync_skip_at); if (slotent->stat_reset_timestamp == 0) - nulls[10] = true; + nulls[12] = true; else - values[10] = TimestampTzGetDatum(slotent->stat_reset_timestamp); + values[12] = TimestampTzGetDatum(slotent->stat_reset_timestamp); /* Returns the record as Datum */ PG_RETURN_DATUM(HeapTupleGetDatum(heap_form_tuple(tupdesc, values, nulls))); diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat index aaadfd8c748..e1dc1d2e8b1 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -5691,9 +5691,9 @@ { oid => '6169', descr => 'statistics: information about replication slot', proname => 'pg_stat_get_replication_slot', provolatile => 's', proparallel => 'r', prorettype => 'record', proargtypes => 'text', - proallargtypes => '{text,text,int8,int8,int8,int8,int8,int8,int8,int8,int8,timestamptz}', - proargmodes => '{i,o,o,o,o,o,o,o,o,o,o,o}', - proargnames => '{slot_name,slot_name,spill_txns,spill_count,spill_bytes,stream_txns,stream_count,stream_bytes,mem_exceeded_count,total_txns,total_bytes,stats_reset}', + proallargtypes => '{text,text,int8,int8,int8,int8,int8,int8,int8,int8,int8,int8,timestamptz,timestamptz}', + proargmodes => '{i,o,o,o,o,o,o,o,o,o,o,o,o,o}', + proargnames => '{slot_name,slot_name,spill_txns,spill_count,spill_bytes,stream_txns,stream_count,stream_bytes,mem_exceeded_count,total_txns,total_bytes,slotsync_skip_count,last_slotsync_skip_at,stats_reset}', prosrc => 'pg_stat_get_replication_slot' }, { oid => '6230', descr => 'statistics: check if a stats object exists', @@ -11511,9 +11511,9 @@ proname => 'pg_get_replication_slots', prorows => '10', proisstrict => 'f', proretset => 't', provolatile => 's', prorettype => 'record', proargtypes => '', - proallargtypes => '{name,name,text,oid,bool,bool,int4,xid,xid,pg_lsn,pg_lsn,text,int8,bool,pg_lsn,timestamptz,bool,text,bool,bool}', - proargmodes => '{o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}', - proargnames => '{slot_name,plugin,slot_type,datoid,temporary,active,active_pid,xmin,catalog_xmin,restart_lsn,confirmed_flush_lsn,wal_status,safe_wal_size,two_phase,two_phase_at,inactive_since,conflicting,invalidation_reason,failover,synced}', + proallargtypes => '{name,name,text,oid,bool,bool,int4,xid,xid,pg_lsn,pg_lsn,text,int8,bool,pg_lsn,timestamptz,bool,text,bool,bool,text}', + proargmodes => '{o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}', + proargnames => '{slot_name,plugin,slot_type,datoid,temporary,active,active_pid,xmin,catalog_xmin,restart_lsn,confirmed_flush_lsn,wal_status,safe_wal_size,two_phase,two_phase_at,inactive_since,conflicting,invalidation_reason,failover,synced,slotsync_skip_reason}', prosrc => 'pg_get_replication_slots' }, { oid => '3786', descr => 'set up a logical replication slot', proname => 'pg_create_logical_replication_slot', provolatile => 'v', diff --git a/src/include/pgstat.h b/src/include/pgstat.h index a68e725259a..1cb96e6d0a6 100644 --- a/src/include/pgstat.h +++ b/src/include/pgstat.h @@ -400,6 +400,8 @@ typedef struct PgStat_StatReplSlotEntry PgStat_Counter mem_exceeded_count; PgStat_Counter total_txns; PgStat_Counter total_bytes; + PgStat_Counter slotsync_skip_count; + TimestampTz last_slotsync_skip_at; TimestampTz stat_reset_timestamp; } PgStat_StatReplSlotEntry; @@ -745,6 +747,7 @@ extern PgStat_TableStatus *find_tabstat_entry(Oid rel_id); extern void pgstat_reset_replslot(const char *name); struct ReplicationSlot; extern void pgstat_report_replslot(struct ReplicationSlot *slot, const PgStat_StatReplSlotEntry *repSlotStat); +extern void pgstat_report_replslotsync_skip(struct ReplicationSlot *slot); extern void pgstat_create_replslot(struct ReplicationSlot *slot); extern void pgstat_acquire_replslot(struct ReplicationSlot *slot); extern void pgstat_drop_replslot(struct ReplicationSlot *slot); diff --git a/src/include/replication/slot.h b/src/include/replication/slot.h index 09c69f83d57..aebc40f486d 100644 --- a/src/include/replication/slot.h +++ b/src/include/replication/slot.h @@ -71,6 +71,21 @@ typedef enum ReplicationSlotInvalidationCause /* Maximum number of invalidation causes */ #define RS_INVAL_MAX_CAUSES 4 +/* + * When slot sync worker is running or pg_sync_replication_slots is run, the + * slot sync can be skipped. This enum keeps a list of reasons of slot sync + * skip. + */ +typedef enum SlotSyncSkipReason +{ + SS_SKIP_NONE, /* No skip */ + SS_SKIP_WAL_NOT_FLUSHED, /* Standby did not flush the wal coresponding + * to confirmed flush on remote slot */ + SS_SKIP_REMOTE_BEHIND, /* Remote slot is behind the local slot */ + SS_SKIP_NO_CONSISTENT_SNAPSHOT /* Standby could not build a consistent + * snapshot */ +} SlotSyncSkipReason; + /* * On-Disk data of a replication slot, preserved across restarts. */ @@ -249,6 +264,8 @@ typedef struct ReplicationSlot */ XLogRecPtr last_saved_restart_lsn; + /* The reason for last slot sync skip */ + SlotSyncSkipReason slotsync_skip_reason; } ReplicationSlot; #define SlotIsPhysical(slot) ((slot)->data.database == InvalidOid) diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out index 372a2188c22..872116cb02a 100644 --- a/src/test/regress/expected/rules.out +++ b/src/test/regress/expected/rules.out @@ -1507,8 +1507,9 @@ pg_replication_slots| SELECT l.slot_name, l.conflicting, l.invalidation_reason, l.failover, - l.synced - FROM (pg_get_replication_slots() l(slot_name, plugin, slot_type, datoid, temporary, active, active_pid, xmin, catalog_xmin, restart_lsn, confirmed_flush_lsn, wal_status, safe_wal_size, two_phase, two_phase_at, inactive_since, conflicting, invalidation_reason, failover, synced) + l.synced, + l.slotsync_skip_reason + FROM (pg_get_replication_slots() l(slot_name, plugin, slot_type, datoid, temporary, active, active_pid, xmin, catalog_xmin, restart_lsn, confirmed_flush_lsn, wal_status, safe_wal_size, two_phase, two_phase_at, inactive_since, conflicting, invalidation_reason, failover, synced, slotsync_skip_reason) LEFT JOIN pg_database d ON ((l.datoid = d.oid))); pg_roles| SELECT pg_authid.rolname, pg_authid.rolsuper, @@ -2151,9 +2152,11 @@ pg_stat_replication_slots| SELECT s.slot_name, s.mem_exceeded_count, s.total_txns, s.total_bytes, + s.slotsync_skip_count, + s.last_slotsync_skip_at, s.stats_reset FROM pg_replication_slots r, - LATERAL pg_stat_get_replication_slot((r.slot_name)::text) s(slot_name, spill_txns, spill_count, spill_bytes, stream_txns, stream_count, stream_bytes, mem_exceeded_count, total_txns, total_bytes, stats_reset) + LATERAL pg_stat_get_replication_slot((r.slot_name)::text) s(slot_name, spill_txns, spill_count, spill_bytes, stream_txns, stream_count, stream_bytes, mem_exceeded_count, total_txns, total_bytes, slotsync_skip_count, last_slotsync_skip_at, stats_reset) WHERE (r.datoid IS NOT NULL); pg_stat_slru| SELECT name, blks_zeroed, diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list index 23bce72ae64..eb19e2c2363 100644 --- a/src/tools/pgindent/typedefs.list +++ b/src/tools/pgindent/typedefs.list @@ -2799,6 +2799,7 @@ SlabSlot SlotInvalidationCauseMap SlotNumber SlotSyncCtxStruct +SlotSyncSkipReason SlruCtl SlruCtlData SlruErrorCause -- 2.34.1