diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml index 5b67def..ef6bc1c 100644 --- a/doc/src/sgml/monitoring.sgml +++ b/doc/src/sgml/monitoring.sgml @@ -357,6 +357,14 @@ postgres 27093 0.0 0.0 30096 2752 ? Ss 11:34 0:00 postgres: ser + pg_stat_walwritespg_stat_walwrites + One row only, showing statistics about the + wal writing activity. See + for details. + + + + pg_stat_databasepg_stat_database One row per database, showing database-wide statistics. See for details. @@ -1833,6 +1841,70 @@ SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event i single row, containing global data for the cluster. + + <structname>pg_stat_walwrites</structname> View + + + + + Column + Type + Description + + + + + + backend_writes + bigint + Number of wal writes that are carried out by the backend process + + + writes + bigint + + Number of wal writes that are carried out by background workers such as checkpointer, + writer and walwriter. + + + + write_blocks + bigint + Number of wal pages written to the disk + + + write_time + double precision + + Total amount of time that has been spent in the portion of wal write processing where files + are written to disk, in milliseconds. + This field data will be populated only when the track_io_timing GUC is enabled + + + + sync_time + double precision + + Total amount of time that has been spent in the portion of wal write processing where files + are synchronized to disk, in milliseconds. + This field data will be populated only when the track_io_timing GUC is enabled + + + + stats_reset + timestamp with time zone + Time at which these statistics were last reset + + + +
+ + + The pg_stat_walwrites view will always have a + single row, containing data about the wal writing activity of the cluster. + + + <structname>pg_stat_database</structname> View @@ -2612,6 +2684,8 @@ SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event i counters shown in the pg_stat_bgwriter view. Calling pg_stat_reset_shared('archiver') will zero all the counters shown in the pg_stat_archiver view. + Calling pg_stat_reset_shared('walwrites') will zero all the + counters shown in the pg_stat_walwrites view. diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index f23e108..2219433 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -2333,6 +2333,8 @@ XLogWrite(XLogwrtRqst WriteRqst, bool flexible) int npages; int startidx; uint32 startoffset; + instr_time io_start, + io_time; /* We should always be inside a critical section here */ Assert(CritSectionCount > 0); @@ -2450,6 +2452,11 @@ XLogWrite(XLogwrtRqst WriteRqst, bool flexible) /* OK to write the page(s) */ from = XLogCtl->pages + startidx * (Size) XLOG_BLCKSZ; nbytes = npages * (Size) XLOG_BLCKSZ; + + /* Start timer to acquire start time of the wal write */ + if (track_io_timing) + INSTR_TIME_SET_CURRENT(io_start); + nleft = nbytes; do { @@ -2470,6 +2477,33 @@ XLogWrite(XLogwrtRqst WriteRqst, bool flexible) from += written; } while (nleft > 0); + /* calculate the total time spent for wal writing */ + if (track_io_timing) + { + INSTR_TIME_SET_CURRENT(io_time); + INSTR_TIME_SUBTRACT(io_time, io_start); + + LocalWalWritesStats.m_wal_total_write_time += INSTR_TIME_GET_MILLISEC(io_time); + } + else + { + LocalWalWritesStats.m_wal_total_write_time = 0; + } + + /* check whether writer is a background process or not? */ + if (AmBackgroundWriterProcess() || + AmWalWriterProcess() || + AmCheckpointerProcess()) + { + LocalWalWritesStats.m_writes++; + } + else + { + LocalWalWritesStats.m_backend_writes++; + } + + LocalWalWritesStats.m_write_blocks += npages; + /* Update state for write */ openLogOff += nbytes; npages = 0; @@ -2489,8 +2523,25 @@ XLogWrite(XLogwrtRqst WriteRqst, bool flexible) */ if (finishing_seg) { + /* Start timer to acquire start time of the wal sync */ + if (track_io_timing) + INSTR_TIME_SET_CURRENT(io_start); + issue_xlog_fsync(openLogFile, openLogSegNo); + /* calculate the total time spent for wal sync */ + if (track_io_timing) + { + INSTR_TIME_SET_CURRENT(io_time); + INSTR_TIME_SUBTRACT(io_time, io_start); + + LocalWalWritesStats.m_wal_total_sync_time += INSTR_TIME_GET_MILLISEC(io_time); + } + else + { + LocalWalWritesStats.m_wal_total_sync_time = 0; + } + /* signal that we need to wakeup walsenders later */ WalSndWakeupRequest(); @@ -2558,7 +2609,24 @@ XLogWrite(XLogwrtRqst WriteRqst, bool flexible) openLogOff = 0; } + /* Start timer to acquire start time of the wal sync */ + if (track_io_timing) + INSTR_TIME_SET_CURRENT(io_start); + issue_xlog_fsync(openLogFile, openLogSegNo); + + /* calculate the total time spent for wal sync */ + if (track_io_timing) + { + INSTR_TIME_SET_CURRENT(io_time); + INSTR_TIME_SUBTRACT(io_time, io_start); + + LocalWalWritesStats.m_wal_total_sync_time += INSTR_TIME_GET_MILLISEC(io_time); + } + else + { + LocalWalWritesStats.m_wal_total_sync_time = 0; + } } /* signal that we need to wakeup walsenders later */ diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql index 38be9cf..27223e2 100644 --- a/src/backend/catalog/system_views.sql +++ b/src/backend/catalog/system_views.sql @@ -854,6 +854,16 @@ CREATE VIEW pg_stat_bgwriter AS pg_stat_get_buf_alloc() AS buffers_alloc, pg_stat_get_bgwriter_stat_reset_time() AS stats_reset; +CREATE VIEW pg_stat_walwrites as + SELECT + pg_stat_get_wal_backend_writes() AS backend_writes, + pg_stat_get_wal_writes() AS writes, + pg_stat_get_wal_write_blocks() AS write_blocks, + pg_stat_get_wal_write_time() AS write_time, + pg_stat_get_wal_sync_time() AS sync_time, + pg_stat_get_wal_stat_reset_time() AS stats_reset; + + CREATE VIEW pg_stat_progress_vacuum AS SELECT S.pid AS pid, S.datid AS datid, D.datname AS datname, diff --git a/src/backend/postmaster/bgwriter.c b/src/backend/postmaster/bgwriter.c index dcb4cf2..1cd623d 100644 --- a/src/backend/postmaster/bgwriter.c +++ b/src/backend/postmaster/bgwriter.c @@ -284,6 +284,7 @@ BackgroundWriterMain(void) * Send off activity statistics to the stats collector */ pgstat_send_bgwriter(); + pgstat_send_walwrites(); if (FirstCallSinceLastCheckpoint()) { diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c index fe9041f..8549f8f 100644 --- a/src/backend/postmaster/checkpointer.c +++ b/src/backend/postmaster/checkpointer.c @@ -538,6 +538,7 @@ CheckpointerMain(void) * stats message types.) */ pgstat_send_bgwriter(); + pgstat_send_walwrites(); /* * Sleep until we are signaled or it's time for another checkpoint or diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c index 7176cf1..fe88411 100644 --- a/src/backend/postmaster/pgstat.c +++ b/src/backend/postmaster/pgstat.c @@ -126,6 +126,15 @@ char *pgstat_stat_tmpname = NULL; */ PgStat_MsgBgWriter BgWriterStats; +/* + * WalWrites Local statistics counters. + * The statistics data gets populated in XLogWrite function. + * Stored directly in a stats message structure so it can be sent + * to stats collector process without needing to copy things around. + * We assume this inits to zeroes. + */ +PgStat_MsgWalWrites LocalWalWritesStats; + /* ---------- * Local data * ---------- @@ -222,6 +231,7 @@ static int localNumBackends = 0; */ static PgStat_ArchiverStats archiverStats; static PgStat_GlobalStats globalStats; +static PgStat_WalWritesStats walwritesStats; /* * List of OIDs of databases we need to write out. If an entry is InvalidOid, @@ -301,6 +311,7 @@ static void pgstat_recv_funcpurge(PgStat_MsgFuncpurge *msg, int len); static void pgstat_recv_recoveryconflict(PgStat_MsgRecoveryConflict *msg, int len); static void pgstat_recv_deadlock(PgStat_MsgDeadlock *msg, int len); static void pgstat_recv_tempfile(PgStat_MsgTempFile *msg, int len); +static void pgstat_recv_walwrites(PgStat_MsgWalWrites * msg, int len); /* ------------------------------------------------------------ * Public functions called from postmaster follow @@ -834,6 +845,9 @@ pgstat_report_stat(bool force) /* Now, send function statistics */ pgstat_send_funcstats(); + + /* Now, send wal writes statistics */ + pgstat_send_walwrites(); } /* @@ -1260,11 +1274,13 @@ pgstat_reset_shared_counters(const char *target) msg.m_resettarget = RESET_ARCHIVER; else if (strcmp(target, "bgwriter") == 0) msg.m_resettarget = RESET_BGWRITER; + else if (strcmp(target, "walwrites") == 0) + msg.m_resettarget = RESET_WALWRITES; else ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("unrecognized reset target: \"%s\"", target), - errhint("Target must be \"archiver\" or \"bgwriter\"."))); + errhint("Target must be \"archiver\" or \"bgwriter\" or \"walwrites\"."))); pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_RESETSHAREDCOUNTER); pgstat_send(&msg, sizeof(msg)); @@ -2478,6 +2494,21 @@ pgstat_fetch_global(void) return &globalStats; } +/* + * --------- + * pgstat_fetch_stat_walwrites() - + * + * Support function for the SQL-callable pgstat* functions. Returns + * a pointer to the walwrites statistics struct. + * --------- + */ +PgStat_WalWritesStats * +pgstat_fetch_stat_walwrites(void) +{ + backend_read_statsfile(); + + return &walwritesStats; +} /* ------------------------------------------------------------ * Functions for management of the shared-memory PgBackendStatus array @@ -3687,6 +3718,39 @@ pgstat_send_bgwriter(void) MemSet(&BgWriterStats, 0, sizeof(BgWriterStats)); } +/* ---------- + * pgstat_send_walwrites() - + * + * Send wal writes statistics to the collector + * ---------- + */ + +void +pgstat_send_walwrites(void) +{ + /* We assume this initializes to zeroes */ + static const PgStat_MsgWalWrites all_zeroes; + + /* + * This function can be called even if nothing at all has happened. In + * this case, avoid sending a completely empty message to the stats + * collector. + */ + if (memcmp(&LocalWalWritesStats, &all_zeroes, sizeof(PgStat_MsgWalWrites)) == 0) + return; + + /* + * Prepare and send the message + */ + pgstat_setheader(&LocalWalWritesStats.m_hdr, PGSTAT_MTYPE_WALWRITES); + pgstat_send(&LocalWalWritesStats, sizeof(LocalWalWritesStats)); + + /* + * Clear out the statistics buffer, so it can be re-used. + */ + MemSet(&LocalWalWritesStats, 0, sizeof(LocalWalWritesStats)); +} + /* ---------- * PgstatCollectorMain() - @@ -3903,6 +3967,10 @@ PgstatCollectorMain(int argc, char *argv[]) pgstat_recv_tempfile((PgStat_MsgTempFile *) &msg, len); break; + case PGSTAT_MTYPE_WALWRITES: + pgstat_recv_walwrites((PgStat_MsgWalWrites *) &msg, len); + break; + default: break; } @@ -4169,6 +4237,12 @@ pgstat_write_statsfiles(bool permanent, bool allDbs) (void) rc; /* we'll check for error with ferror */ /* + * Write wal writes stats struct + */ + rc = fwrite(&walwritesStats, sizeof(walwritesStats), 1, fpout); + (void) rc; /* we'll check for error with ferror */ + + /* * Walk through the database table. */ hash_seq_init(&hstat, pgStatDBHash); @@ -4425,6 +4499,7 @@ pgstat_read_statsfiles(Oid onlydb, bool permanent, bool deep) */ memset(&globalStats, 0, sizeof(globalStats)); memset(&archiverStats, 0, sizeof(archiverStats)); + memset(&walwritesStats, 0, sizeof(walwritesStats)); /* * Set the current timestamp (will be kept only in case we can't load an @@ -4432,6 +4507,7 @@ pgstat_read_statsfiles(Oid onlydb, bool permanent, bool deep) */ globalStats.stat_reset_timestamp = GetCurrentTimestamp(); archiverStats.stat_reset_timestamp = globalStats.stat_reset_timestamp; + walwritesStats.stat_reset_timestamp = globalStats.stat_reset_timestamp; /* * Try to open the stats file. If it doesn't exist, the backends simply @@ -4484,6 +4560,16 @@ pgstat_read_statsfiles(Oid onlydb, bool permanent, bool deep) } /* + * Read wal writes stats struct + */ + if (fread(&walwritesStats, 1, sizeof(walwritesStats), fpin) != sizeof(walwritesStats)) + { + ereport(pgStatRunningInCollector ? LOG : WARNING, + (errmsg("corrupted statistics file \"%s\"", statfile))); + goto done; + } + + /* * We found an existing collector stats file. Read it and put all the * hashtable entries into place. */ @@ -4772,6 +4858,7 @@ pgstat_read_db_statsfile_timestamp(Oid databaseid, bool permanent, PgStat_StatDBEntry dbentry; PgStat_GlobalStats myGlobalStats; PgStat_ArchiverStats myArchiverStats; + PgStat_WalWritesStats myWalwritesStats; FILE *fpin; int32 format_id; const char *statfile = permanent ? PGSTAT_STAT_PERMANENT_FILENAME : pgstat_stat_filename; @@ -4826,6 +4913,18 @@ pgstat_read_db_statsfile_timestamp(Oid databaseid, bool permanent, return false; } + /* + * Read wal writes stats struct + */ + if (fread(&myWalwritesStats, 1, sizeof(myWalwritesStats), + fpin) != sizeof(myWalwritesStats)) + { + ereport(pgStatRunningInCollector ? LOG : WARNING, + (errmsg("corrupted statistics file \"%s\"", statfile))); + FreeFile(fpin); + return false; + } + /* By default, we're going to return the timestamp of the global file. */ *ts = myGlobalStats.stats_timestamp; @@ -5388,6 +5487,12 @@ pgstat_recv_resetsharedcounter(PgStat_MsgResetsharedcounter *msg, int len) memset(&archiverStats, 0, sizeof(archiverStats)); archiverStats.stat_reset_timestamp = GetCurrentTimestamp(); } + else if (msg->m_resettarget == RESET_WALWRITES) + { + /* Reset the wal writes statistics of the cluster. */ + memset(&walwritesStats, 0, sizeof(walwritesStats)); + walwritesStats.stat_reset_timestamp = GetCurrentTimestamp(); + } /* * Presumably the sender of this message validated the target, don't @@ -5568,6 +5673,22 @@ pgstat_recv_bgwriter(PgStat_MsgBgWriter *msg, int len) } /* ---------- + * pgstat_recv_walwrites() - + * + * Process a WALWRITES message. + * ---------- + */ +static void +pgstat_recv_walwrites(PgStat_MsgWalWrites * msg, int len) +{ + walwritesStats.backend_writes += msg->m_backend_writes; + walwritesStats.writes += msg->m_writes; + walwritesStats.write_blocks += msg->m_write_blocks; + walwritesStats.total_write_time += msg->m_wal_total_write_time; + walwritesStats.total_sync_time += msg->m_wal_total_sync_time; +} + +/* ---------- * pgstat_recv_recoveryconflict() - * * Process a RECOVERYCONFLICT message. diff --git a/src/backend/postmaster/walwriter.c b/src/backend/postmaster/walwriter.c index a575d8f..cf0c279 100644 --- a/src/backend/postmaster/walwriter.c +++ b/src/backend/postmaster/walwriter.c @@ -280,6 +280,8 @@ WalWriterMain(void) else if (left_till_hibernate > 0) left_till_hibernate--; + pgstat_send_walwrites(); + /* * Sleep until we are signaled or WalWriterDelay has elapsed. If we * haven't done anything useful for quite some time, lengthen the diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c index a987d0d..b8dcfc8 100644 --- a/src/backend/utils/adt/pgstatfuncs.c +++ b/src/backend/utils/adt/pgstatfuncs.c @@ -1521,6 +1521,44 @@ pg_stat_get_buf_alloc(PG_FUNCTION_ARGS) } Datum +pg_stat_get_wal_backend_writes(PG_FUNCTION_ARGS) +{ + PG_RETURN_INT64(pgstat_fetch_stat_walwrites()->backend_writes); +} + +Datum +pg_stat_get_wal_writes(PG_FUNCTION_ARGS) +{ + PG_RETURN_INT64(pgstat_fetch_stat_walwrites()->writes); +} + +Datum +pg_stat_get_wal_write_blocks(PG_FUNCTION_ARGS) +{ + PG_RETURN_INT64(pgstat_fetch_stat_walwrites()->write_blocks); +} + +Datum +pg_stat_get_wal_write_time(PG_FUNCTION_ARGS) +{ + /* time is already in msec, just convert to double for presentation */ + PG_RETURN_FLOAT8((double) pgstat_fetch_stat_walwrites()->total_write_time); +} + +Datum +pg_stat_get_wal_sync_time(PG_FUNCTION_ARGS) +{ + /* time is already in msec, just convert to double for presentation */ + PG_RETURN_FLOAT8((double) pgstat_fetch_stat_walwrites()->total_sync_time); +} + +Datum +pg_stat_get_wal_stat_reset_time(PG_FUNCTION_ARGS) +{ + PG_RETURN_TIMESTAMPTZ(pgstat_fetch_stat_walwrites()->stat_reset_timestamp); +} + +Datum pg_stat_get_xact_numscans(PG_FUNCTION_ARGS) { Oid relid = PG_GETARG_OID(0); diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index 41c12af..722ad53 100644 --- a/src/include/catalog/pg_proc.h +++ b/src/include/catalog/pg_proc.h @@ -2871,6 +2871,18 @@ DESCR("statistics: number of backend buffer writes that did their own fsync"); DATA(insert OID = 2859 ( pg_stat_get_buf_alloc PGNSP PGUID 12 1 0 0 0 f f f f t f s r 0 0 20 "" _null_ _null_ _null_ _null_ _null_ pg_stat_get_buf_alloc _null_ _null_ _null_ )); DESCR("statistics: number of buffer allocations"); +DATA(insert OID = 3354 ( pg_stat_get_wal_backend_writes PGNSP PGUID 12 1 0 0 0 f f f f t f s r 0 0 20 "" _null_ _null_ _null_ _null_ _null_ pg_stat_get_wal_backend_writes _null_ _null_ _null_ )); +DESCR("statistics: number of backend wal writes statistics"); +DATA(insert OID = 3355 ( pg_stat_get_wal_writes PGNSP PGUID 12 1 0 0 0 f f f f t f s r 0 0 20 "" _null_ _null_ _null_ _null_ _null_ pg_stat_get_wal_writes _null_ _null_ _null_ )); +DESCR("statistics: number of background process wal writes statistics"); +DATA(insert OID = 3356 ( pg_stat_get_wal_write_blocks PGNSP PGUID 12 1 0 0 0 f f f f t f s r 0 0 20 "" _null_ _null_ _null_ _null_ _null_ pg_stat_get_wal_write_blocks _null_ _null_ _null_ )); +DESCR("statistics: number of wal blocks written statistics"); +DATA(insert OID = 3357 ( pg_stat_get_wal_write_time PGNSP PGUID 12 1 0 0 0 f f f f t f s r 0 0 701 "" _null_ _null_ _null_ _null_ _null_ pg_stat_get_wal_write_time _null_ _null_ _null_ )); +DESCR("statistics: get total time spent in writing wal blocks to disk, in milliseconds"); +DATA(insert OID = 3358 ( pg_stat_get_wal_sync_time PGNSP PGUID 12 1 0 0 0 f f f f t f s r 0 0 701 "" _null_ _null_ _null_ _null_ _null_ pg_stat_get_wal_sync_time _null_ _null_ _null_ )); +DESCR("statistics: get total time spent in synchronizing buffers to disk, in milliseconds"); +DATA(insert OID = 3359 ( pg_stat_get_wal_stat_reset_time PGNSP PGUID 12 1 0 0 0 f f f f t f s r 0 0 1184 "" _null_ _null_ _null_ _null_ _null_ pg_stat_get_wal_stat_reset_time _null_ _null_ _null_ )); +DESCR("statistics: last reset for the wal writes statistics"); DATA(insert OID = 2978 ( pg_stat_get_function_calls PGNSP PGUID 12 1 0 0 0 f f f f t f s r 1 0 20 "26" _null_ _null_ _null_ _null_ _null_ pg_stat_get_function_calls _null_ _null_ _null_ )); DESCR("statistics: number of function calls"); DATA(insert OID = 2979 ( pg_stat_get_function_total_time PGNSP PGUID 12 1 0 0 0 f f f f t f s r 1 0 701 "26" _null_ _null_ _null_ _null_ _null_ pg_stat_get_function_total_time _null_ _null_ _null_ )); diff --git a/src/include/pgstat.h b/src/include/pgstat.h index de8225b..1c62e5a 100644 --- a/src/include/pgstat.h +++ b/src/include/pgstat.h @@ -64,7 +64,8 @@ typedef enum StatMsgType PGSTAT_MTYPE_FUNCPURGE, PGSTAT_MTYPE_RECOVERYCONFLICT, PGSTAT_MTYPE_TEMPFILE, - PGSTAT_MTYPE_DEADLOCK + PGSTAT_MTYPE_DEADLOCK, + PGSTAT_MTYPE_WALWRITES } StatMsgType; /* ---------- @@ -119,7 +120,8 @@ typedef struct PgStat_TableCounts typedef enum PgStat_Shared_Reset_Target { RESET_ARCHIVER, - RESET_BGWRITER + RESET_BGWRITER, + RESET_WALWRITES } PgStat_Shared_Reset_Target; /* Possible object types for resetting single counters */ @@ -423,6 +425,22 @@ typedef struct PgStat_MsgBgWriter } PgStat_MsgBgWriter; /* ---------- + * PgStat_MsgWalWrites Sent by the backend or walwriter or writer + * or checkpointer process + * ---------- + */ +typedef struct PgStat_MsgWalWrites +{ + PgStat_MsgHdr m_hdr; + + PgStat_Counter m_backend_writes; /* No of writes by backend */ + PgStat_Counter m_writes; /* No of writes by background processes */ + PgStat_Counter m_write_blocks; /* Total no of pages written */ + PgStat_Counter m_wal_total_write_time; /* times in milliseconds */ + PgStat_Counter m_wal_total_sync_time; /* times in milliseconds */ +} PgStat_MsgWalWrites; + +/* ---------- * PgStat_MsgRecoveryConflict Sent by the backend upon recovery conflict * ---------- */ @@ -555,6 +573,7 @@ typedef union PgStat_Msg PgStat_MsgFuncpurge msg_funcpurge; PgStat_MsgRecoveryConflict msg_recoveryconflict; PgStat_MsgDeadlock msg_deadlock; + PgStat_MsgWalWrites msg_walwrites; } PgStat_Msg; @@ -694,6 +713,18 @@ typedef struct PgStat_GlobalStats TimestampTz stat_reset_timestamp; } PgStat_GlobalStats; +/* + * Walwrites statistics kept in the stats collector + */ +typedef struct PgStat_WalWritesStats +{ + PgStat_Counter backend_writes; /* No of writes by backend */ + PgStat_Counter writes; /* No of writes by background processes */ + PgStat_Counter write_blocks; /* Total no of pages written */ + PgStat_Counter total_write_time; /* Total write time */ + PgStat_Counter total_sync_time; /* Total sync time */ + TimestampTz stat_reset_timestamp; /* Last time when the stats reset */ +} PgStat_WalWritesStats; /* ---------- * Backend states @@ -1008,6 +1039,11 @@ extern char *pgstat_stat_filename; extern PgStat_MsgBgWriter BgWriterStats; /* + * Wal writes statistics updated in XLogWrite function + */ +extern PgStat_MsgWalWrites LocalWalWritesStats; + +/* * Updated by pgstat_count_buffer_*_time macros */ extern PgStat_Counter pgStatBlockReadTime; @@ -1200,6 +1236,7 @@ extern void pgstat_twophase_postabort(TransactionId xid, uint16 info, extern void pgstat_send_archiver(const char *xlog, bool failed); extern void pgstat_send_bgwriter(void); +extern void pgstat_send_walwrites(void); /* ---------- * Support functions for the SQL-callable functions to @@ -1214,5 +1251,7 @@ extern PgStat_StatFuncEntry *pgstat_fetch_stat_funcentry(Oid funcid); extern int pgstat_fetch_stat_numbackends(void); extern PgStat_ArchiverStats *pgstat_fetch_stat_archiver(void); extern PgStat_GlobalStats *pgstat_fetch_global(void); +extern PgStat_WalWritesStats *pgstat_fetch_stat_walwrites(void); + #endif /* PGSTAT_H */ diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out index c661f1d..402a396 100644 --- a/src/test/regress/expected/rules.out +++ b/src/test/regress/expected/rules.out @@ -1945,6 +1945,12 @@ pg_stat_wal_receiver| SELECT s.pid, s.conninfo FROM pg_stat_get_wal_receiver() s(pid, status, receive_start_lsn, receive_start_tli, received_lsn, received_tli, last_msg_send_time, last_msg_receipt_time, latest_end_lsn, latest_end_time, slot_name, conninfo) WHERE (s.pid IS NOT NULL); +pg_stat_walwrites| SELECT pg_stat_get_wal_backend_writes() AS backend_writes, + pg_stat_get_wal_writes() AS writes, + pg_stat_get_wal_write_blocks() AS write_blocks, + pg_stat_get_wal_write_time() AS write_time, + pg_stat_get_wal_sync_time() AS sync_time, + pg_stat_get_wal_stat_reset_time() AS stats_reset; pg_stat_xact_all_tables| SELECT c.oid AS relid, n.nspname AS schemaname, c.relname, diff --git a/src/test/regress/expected/sysviews.out b/src/test/regress/expected/sysviews.out index d48abd7..b852069 100644 --- a/src/test/regress/expected/sysviews.out +++ b/src/test/regress/expected/sysviews.out @@ -67,6 +67,13 @@ select count(*) >= 0 as ok from pg_prepared_xacts; t (1 row) +-- There will surely and maximum one record +select count(*) > 0 as ok from pg_stat_walwrites; + ok +---- + t +(1 row) + -- This is to record the prevailing planner enable_foo settings during -- a regression test run. select name, setting from pg_settings where name like 'enable%'; diff --git a/src/test/regress/sql/sysviews.sql b/src/test/regress/sql/sysviews.sql index 28e412b..3769880 100644 --- a/src/test/regress/sql/sysviews.sql +++ b/src/test/regress/sql/sysviews.sql @@ -32,6 +32,9 @@ select count(*) = 0 as ok from pg_prepared_statements; -- See also prepared_xacts.sql select count(*) >= 0 as ok from pg_prepared_xacts; +-- There will surely and maximum one record +select count(*) > 0 as ok from pg_stat_walwrites; + -- This is to record the prevailing planner enable_foo settings during -- a regression test run. select name, setting from pg_settings where name like 'enable%';