mirror of
https://github.com/postgres/postgres.git
synced 2025-11-25 12:03:53 +03:00
Add some instrumentation to the bgwriter, through the stats collector.
New view pg_stat_bgwriter, and the functions required to build it.
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (c) 1996-2007, PostgreSQL Global Development Group
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/backend/catalog/system_views.sql,v 1.36 2007/03/16 17:57:36 mha Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/catalog/system_views.sql,v 1.37 2007/03/30 18:34:55 mha Exp $
|
||||
*/
|
||||
|
||||
CREATE VIEW pg_roles AS
|
||||
@@ -364,3 +364,13 @@ CREATE VIEW pg_stat_database AS
|
||||
pg_stat_get_db_tuples_updated(D.oid) AS tup_updated,
|
||||
pg_stat_get_db_tuples_deleted(D.oid) AS tup_deleted
|
||||
FROM pg_database D;
|
||||
|
||||
CREATE VIEW pg_stat_bgwriter AS
|
||||
SELECT
|
||||
pg_stat_get_bgwriter_timed_checkpoints() AS checkpoints_timed,
|
||||
pg_stat_get_bgwriter_requested_checkpoints() AS checkpoints_req,
|
||||
pg_stat_get_bgwriter_buf_written_checkpoints() AS buffers_checkpoint,
|
||||
pg_stat_get_bgwriter_buf_written_lru() AS buffers_lru,
|
||||
pg_stat_get_bgwriter_buf_written_all() AS buffers_all,
|
||||
pg_stat_get_bgwriter_maxwritten_lru() AS maxwritten_lru,
|
||||
pg_stat_get_bgwriter_maxwritten_all() AS maxwritten_all;
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/postmaster/bgwriter.c,v 1.36 2007/01/17 16:25:01 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/postmaster/bgwriter.c,v 1.37 2007/03/30 18:34:55 mha Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -50,6 +50,7 @@
|
||||
#include "access/xlog_internal.h"
|
||||
#include "libpq/pqsignal.h"
|
||||
#include "miscadmin.h"
|
||||
#include "pgstat.h"
|
||||
#include "postmaster/bgwriter.h"
|
||||
#include "storage/fd.h"
|
||||
#include "storage/freespace.h"
|
||||
@@ -124,6 +125,13 @@ typedef struct
|
||||
|
||||
static BgWriterShmemStruct *BgWriterShmem;
|
||||
|
||||
/*
|
||||
* BgWriter statistics counters.
|
||||
* Stored directly in a stats message structure so it can be sent
|
||||
* without needing to copy things around.
|
||||
*/
|
||||
PgStat_MsgBgWriter BgWriterStats;
|
||||
|
||||
/*
|
||||
* GUC parameters
|
||||
*/
|
||||
@@ -242,6 +250,11 @@ BackgroundWriterMain(void)
|
||||
ALLOCSET_DEFAULT_MAXSIZE);
|
||||
MemoryContextSwitchTo(bgwriter_context);
|
||||
|
||||
/*
|
||||
* Initialize statistics counters to zero
|
||||
*/
|
||||
memset(&BgWriterStats, 0, sizeof(BgWriterStats));
|
||||
|
||||
/*
|
||||
* If an exception is encountered, processing resumes here.
|
||||
*
|
||||
@@ -354,6 +367,7 @@ BackgroundWriterMain(void)
|
||||
checkpoint_requested = false;
|
||||
do_checkpoint = true;
|
||||
force_checkpoint = true;
|
||||
BgWriterStats.m_requested_checkpoints++;
|
||||
}
|
||||
if (shutdown_requested)
|
||||
{
|
||||
@@ -376,7 +390,11 @@ BackgroundWriterMain(void)
|
||||
now = time(NULL);
|
||||
elapsed_secs = now - last_checkpoint_time;
|
||||
if (elapsed_secs >= CheckPointTimeout)
|
||||
{
|
||||
do_checkpoint = true;
|
||||
if (!force_checkpoint)
|
||||
BgWriterStats.m_timed_checkpoints++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do a checkpoint if requested, otherwise do one cycle of
|
||||
@@ -473,6 +491,11 @@ BackgroundWriterMain(void)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Send off activity statistics to the stats collector
|
||||
*/
|
||||
pgstat_send_bgwriter();
|
||||
|
||||
/*
|
||||
* Nap for the configured time, or sleep for 10 seconds if there is no
|
||||
* bgwriter activity configured.
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*
|
||||
* Copyright (c) 2001-2007, PostgreSQL Global Development Group
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.151 2007/03/28 22:17:12 alvherre Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.152 2007/03/30 18:34:55 mha Exp $
|
||||
* ----------
|
||||
*/
|
||||
#include "postgres.h"
|
||||
@@ -135,6 +135,18 @@ static HTAB *pgStatDBHash = NULL;
|
||||
static PgBackendStatus *localBackendStatusTable = NULL;
|
||||
static int localNumBackends = 0;
|
||||
|
||||
/*
|
||||
* BgWriter global statistics counters, from bgwriter.c
|
||||
*/
|
||||
extern PgStat_MsgBgWriter BgWriterStats;
|
||||
|
||||
/*
|
||||
* Cluster wide statistics, kept in the stats collector.
|
||||
* Contains statistics that are not collected per database
|
||||
* or per table.
|
||||
*/
|
||||
static PgStat_GlobalStats globalStats;
|
||||
|
||||
static volatile bool need_exit = false;
|
||||
static volatile bool need_statwrite = false;
|
||||
|
||||
@@ -171,6 +183,7 @@ static void pgstat_recv_resetcounter(PgStat_MsgResetcounter *msg, int len);
|
||||
static void pgstat_recv_autovac(PgStat_MsgAutovacStart *msg, int len);
|
||||
static void pgstat_recv_vacuum(PgStat_MsgVacuum *msg, int len);
|
||||
static void pgstat_recv_analyze(PgStat_MsgAnalyze *msg, int len);
|
||||
static void pgstat_recv_bgwriter(PgStat_MsgBgWriter *msg, int len);
|
||||
|
||||
|
||||
/* ------------------------------------------------------------
|
||||
@@ -1288,6 +1301,22 @@ pgstat_fetch_stat_numbackends(void)
|
||||
return localNumBackends;
|
||||
}
|
||||
|
||||
/*
|
||||
* ---------
|
||||
* pgstat_fetch_global() -
|
||||
*
|
||||
* Support function for the SQL-callable pgstat* functions. Returns
|
||||
* a pointer to the global statistics struct.
|
||||
* ---------
|
||||
*/
|
||||
PgStat_GlobalStats *
|
||||
pgstat_fetch_global(void)
|
||||
{
|
||||
backend_read_statsfile();
|
||||
|
||||
return &globalStats;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------
|
||||
* Functions for management of the shared-memory PgBackendStatus array
|
||||
@@ -1646,6 +1675,42 @@ pgstat_send(void *msg, int len)
|
||||
#endif
|
||||
}
|
||||
|
||||
/* ----------
|
||||
* pgstat_send_bgwriter() -
|
||||
*
|
||||
* Send bgwriter statistics to the collector
|
||||
* ----------
|
||||
*/
|
||||
void
|
||||
pgstat_send_bgwriter(void)
|
||||
{
|
||||
/*
|
||||
* 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 (BgWriterStats.m_timed_checkpoints == 0 &&
|
||||
BgWriterStats.m_requested_checkpoints == 0 &&
|
||||
BgWriterStats.m_buf_written_checkpoints == 0 &&
|
||||
BgWriterStats.m_buf_written_lru == 0 &&
|
||||
BgWriterStats.m_buf_written_all == 0 &&
|
||||
BgWriterStats.m_maxwritten_lru == 0 &&
|
||||
BgWriterStats.m_maxwritten_all == 0)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Prepare and send the message
|
||||
*/
|
||||
pgstat_setheader(&BgWriterStats.m_hdr, PGSTAT_MTYPE_BGWRITER);
|
||||
pgstat_send(&BgWriterStats, sizeof(BgWriterStats));
|
||||
|
||||
/*
|
||||
* Clear out the bgwriter statistics buffer, so it can be
|
||||
* re-used.
|
||||
*/
|
||||
memset(&BgWriterStats, 0, sizeof(BgWriterStats));
|
||||
}
|
||||
|
||||
|
||||
/* ----------
|
||||
* PgstatCollectorMain() -
|
||||
@@ -1892,6 +1957,10 @@ PgstatCollectorMain(int argc, char *argv[])
|
||||
pgstat_recv_analyze((PgStat_MsgAnalyze *) &msg, len);
|
||||
break;
|
||||
|
||||
case PGSTAT_MTYPE_BGWRITER:
|
||||
pgstat_recv_bgwriter((PgStat_MsgBgWriter *) &msg, len);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -2030,6 +2099,11 @@ pgstat_write_statsfile(void)
|
||||
format_id = PGSTAT_FILE_FORMAT_ID;
|
||||
fwrite(&format_id, sizeof(format_id), 1, fpout);
|
||||
|
||||
/*
|
||||
* Write global stats struct
|
||||
*/
|
||||
fwrite(&globalStats, sizeof(globalStats), 1, fpout);
|
||||
|
||||
/*
|
||||
* Walk through the database table.
|
||||
*/
|
||||
@@ -2132,6 +2206,12 @@ pgstat_read_statsfile(Oid onlydb)
|
||||
dbhash = hash_create("Databases hash", PGSTAT_DB_HASH_SIZE, &hash_ctl,
|
||||
HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT);
|
||||
|
||||
/*
|
||||
* Clear out global statistics so they start from zero in case we can't
|
||||
* load an existing statsfile.
|
||||
*/
|
||||
memset(&globalStats, 0, sizeof(globalStats));
|
||||
|
||||
/*
|
||||
* Try to open the status file. If it doesn't exist, the backends simply
|
||||
* return zero for anything and the collector simply starts from scratch
|
||||
@@ -2151,6 +2231,16 @@ pgstat_read_statsfile(Oid onlydb)
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read global stats struct
|
||||
*/
|
||||
if (fread(&globalStats, 1, sizeof(globalStats), fpin) != sizeof(globalStats))
|
||||
{
|
||||
ereport(pgStatRunningInCollector ? LOG : WARNING,
|
||||
(errmsg("corrupted pgstat.stat file")));
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
* We found an existing collector stats file. Read it and put all the
|
||||
* hashtable entries into place.
|
||||
@@ -2656,3 +2746,22 @@ pgstat_recv_analyze(PgStat_MsgAnalyze *msg, int len)
|
||||
tabentry->n_dead_tuples = msg->m_dead_tuples;
|
||||
tabentry->last_anl_tuples = msg->m_live_tuples + msg->m_dead_tuples;
|
||||
}
|
||||
|
||||
|
||||
/* ----------
|
||||
* pgstat_recv_bgwriter() -
|
||||
*
|
||||
* Process a BGWRITER message.
|
||||
* ----------
|
||||
*/
|
||||
static void
|
||||
pgstat_recv_bgwriter(PgStat_MsgBgWriter *msg, int len)
|
||||
{
|
||||
globalStats.timed_checkpoints += msg->m_timed_checkpoints;
|
||||
globalStats.requested_checkpoints += msg->m_requested_checkpoints;
|
||||
globalStats.buf_written_checkpoints += msg->m_buf_written_checkpoints;
|
||||
globalStats.buf_written_lru += msg->m_buf_written_lru;
|
||||
globalStats.buf_written_all += msg->m_buf_written_all;
|
||||
globalStats.maxwritten_lru += msg->m_maxwritten_lru;
|
||||
globalStats.maxwritten_all += msg->m_maxwritten_all;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/storage/buffer/bufmgr.c,v 1.215 2007/02/01 19:10:27 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/storage/buffer/bufmgr.c,v 1.216 2007/03/30 18:34:55 mha Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -80,6 +80,12 @@ static bool IsForInput;
|
||||
/* local state for LockBufferForCleanup */
|
||||
static volatile BufferDesc *PinCountWaitBuf = NULL;
|
||||
|
||||
/*
|
||||
* Global statistics for the bgwriter. The contents of this variable
|
||||
* only makes sense in the bgwriter process.
|
||||
*/
|
||||
extern PgStat_MsgBgWriter BgWriterStats;
|
||||
|
||||
|
||||
static bool PinBuffer(volatile BufferDesc *buf);
|
||||
static void PinBuffer_Locked(volatile BufferDesc *buf);
|
||||
@@ -964,6 +970,8 @@ BufferSync(void)
|
||||
{
|
||||
if (SyncOneBuffer(buf_id, false))
|
||||
{
|
||||
BgWriterStats.m_buf_written_checkpoints++;
|
||||
|
||||
/*
|
||||
* If in bgwriter, absorb pending fsync requests after each
|
||||
* WRITES_PER_ABSORB write operations, to prevent overflow of the
|
||||
@@ -1027,9 +1035,13 @@ BgBufferSync(void)
|
||||
if (SyncOneBuffer(buf_id1, false))
|
||||
{
|
||||
if (++num_written >= bgwriter_all_maxpages)
|
||||
{
|
||||
BgWriterStats.m_maxwritten_all++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
BgWriterStats.m_buf_written_all += num_written;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1048,11 +1060,15 @@ BgBufferSync(void)
|
||||
if (SyncOneBuffer(buf_id2, true))
|
||||
{
|
||||
if (++num_written >= bgwriter_lru_maxpages)
|
||||
{
|
||||
BgWriterStats.m_maxwritten_lru++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (++buf_id2 >= NBuffers)
|
||||
buf_id2 = 0;
|
||||
}
|
||||
BgWriterStats.m_buf_written_lru += num_written;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/pgstatfuncs.c,v 1.40 2007/03/16 17:57:36 mha Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/pgstatfuncs.c,v 1.41 2007/03/30 18:34:55 mha Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -61,9 +61,19 @@ extern Datum pg_stat_get_db_tuples_inserted(PG_FUNCTION_ARGS);
|
||||
extern Datum pg_stat_get_db_tuples_updated(PG_FUNCTION_ARGS);
|
||||
extern Datum pg_stat_get_db_tuples_deleted(PG_FUNCTION_ARGS);
|
||||
|
||||
extern Datum pg_stat_get_bgwriter_timed_checkpoints(PG_FUNCTION_ARGS);
|
||||
extern Datum pg_stat_get_bgwriter_requested_checkpoints(PG_FUNCTION_ARGS);
|
||||
extern Datum pg_stat_get_bgwriter_buf_written_checkpoints(PG_FUNCTION_ARGS);
|
||||
extern Datum pg_stat_get_bgwriter_buf_written_lru(PG_FUNCTION_ARGS);
|
||||
extern Datum pg_stat_get_bgwriter_buf_written_all(PG_FUNCTION_ARGS);
|
||||
extern Datum pg_stat_get_bgwriter_maxwritten_lru(PG_FUNCTION_ARGS);
|
||||
extern Datum pg_stat_get_bgwriter_maxwritten_all(PG_FUNCTION_ARGS);
|
||||
|
||||
extern Datum pg_stat_clear_snapshot(PG_FUNCTION_ARGS);
|
||||
extern Datum pg_stat_reset(PG_FUNCTION_ARGS);
|
||||
|
||||
/* Global bgwriter statistics, from bgwriter.c */
|
||||
extern PgStat_MsgBgWriter bgwriterStats;
|
||||
|
||||
Datum
|
||||
pg_stat_get_numscans(PG_FUNCTION_ARGS)
|
||||
@@ -756,6 +766,48 @@ pg_stat_get_db_tuples_deleted(PG_FUNCTION_ARGS)
|
||||
PG_RETURN_INT64(result);
|
||||
}
|
||||
|
||||
Datum
|
||||
pg_stat_get_bgwriter_timed_checkpoints(PG_FUNCTION_ARGS)
|
||||
{
|
||||
PG_RETURN_INT64(pgstat_fetch_global()->timed_checkpoints);
|
||||
}
|
||||
|
||||
Datum
|
||||
pg_stat_get_bgwriter_requested_checkpoints(PG_FUNCTION_ARGS)
|
||||
{
|
||||
PG_RETURN_INT64(pgstat_fetch_global()->requested_checkpoints);
|
||||
}
|
||||
|
||||
Datum
|
||||
pg_stat_get_bgwriter_buf_written_checkpoints(PG_FUNCTION_ARGS)
|
||||
{
|
||||
PG_RETURN_INT64(pgstat_fetch_global()->buf_written_checkpoints);
|
||||
}
|
||||
|
||||
Datum
|
||||
pg_stat_get_bgwriter_buf_written_lru(PG_FUNCTION_ARGS)
|
||||
{
|
||||
PG_RETURN_INT64(pgstat_fetch_global()->buf_written_lru);
|
||||
}
|
||||
|
||||
Datum
|
||||
pg_stat_get_bgwriter_buf_written_all(PG_FUNCTION_ARGS)
|
||||
{
|
||||
PG_RETURN_INT64(pgstat_fetch_global()->buf_written_all);
|
||||
}
|
||||
|
||||
Datum
|
||||
pg_stat_get_bgwriter_maxwritten_lru(PG_FUNCTION_ARGS)
|
||||
{
|
||||
PG_RETURN_INT64(pgstat_fetch_global()->maxwritten_lru);
|
||||
}
|
||||
|
||||
Datum
|
||||
pg_stat_get_bgwriter_maxwritten_all(PG_FUNCTION_ARGS)
|
||||
{
|
||||
PG_RETURN_INT64(pgstat_fetch_global()->maxwritten_all);
|
||||
}
|
||||
|
||||
|
||||
/* Discard the active statistics snapshot */
|
||||
Datum
|
||||
|
||||
Reference in New Issue
Block a user