New system view pg_stat_replication displays activity of wal sender processes.
Itagaki Takahiro and Simon Riggs.
This commit is contained in:
parent
46d28820b6
commit
a755ea33ae
@ -492,6 +492,21 @@ CREATE VIEW pg_stat_activity AS
|
||||
WHERE S.datid = D.oid AND
|
||||
S.usesysid = U.oid;
|
||||
|
||||
CREATE VIEW pg_stat_replication AS
|
||||
SELECT
|
||||
S.procpid,
|
||||
S.usesysid,
|
||||
U.rolname AS usename,
|
||||
S.application_name,
|
||||
S.client_addr,
|
||||
S.client_port,
|
||||
S.backend_start,
|
||||
W.sent_location
|
||||
FROM pg_stat_get_activity(NULL) AS S, pg_authid U,
|
||||
pg_stat_get_wal_senders() AS W
|
||||
WHERE S.usesysid = U.oid AND
|
||||
S.procpid = W.procpid;
|
||||
|
||||
CREATE VIEW pg_stat_database AS
|
||||
SELECT
|
||||
D.oid AS datid,
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "funcapi.h"
|
||||
#include "access/xlog_internal.h"
|
||||
#include "catalog/pg_type.h"
|
||||
#include "libpq/libpq.h"
|
||||
@ -49,6 +50,7 @@
|
||||
#include "storage/ipc.h"
|
||||
#include "storage/pmsignal.h"
|
||||
#include "tcop/tcopprot.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/guc.h"
|
||||
#include "utils/memutils.h"
|
||||
#include "utils/ps_status.h"
|
||||
@ -942,6 +944,78 @@ WalSndWakeup(void)
|
||||
SetLatch(&WalSndCtl->walsnds[i].latch);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns activity of walsenders, including pids and xlog locations sent to
|
||||
* standby servers.
|
||||
*/
|
||||
Datum
|
||||
pg_stat_get_wal_senders(PG_FUNCTION_ARGS)
|
||||
{
|
||||
#define PG_STAT_GET_WAL_SENDERS_COLS 2
|
||||
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
|
||||
TupleDesc tupdesc;
|
||||
Tuplestorestate *tupstore;
|
||||
MemoryContext per_query_ctx;
|
||||
MemoryContext oldcontext;
|
||||
int i;
|
||||
|
||||
/* check to see if caller supports us returning a tuplestore */
|
||||
if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("set-valued function called in context that cannot accept a set")));
|
||||
if (!(rsinfo->allowedModes & SFRM_Materialize))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("materialize mode required, but it is not " \
|
||||
"allowed in this context")));
|
||||
|
||||
/* Build a tuple descriptor for our result type */
|
||||
if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
|
||||
elog(ERROR, "return type must be a row type");
|
||||
|
||||
per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
|
||||
oldcontext = MemoryContextSwitchTo(per_query_ctx);
|
||||
|
||||
tupstore = tuplestore_begin_heap(true, false, work_mem);
|
||||
rsinfo->returnMode = SFRM_Materialize;
|
||||
rsinfo->setResult = tupstore;
|
||||
rsinfo->setDesc = tupdesc;
|
||||
|
||||
MemoryContextSwitchTo(oldcontext);
|
||||
|
||||
for (i = 0; i < max_wal_senders; i++)
|
||||
{
|
||||
/* use volatile pointer to prevent code rearrangement */
|
||||
volatile WalSnd *walsnd = &WalSndCtl->walsnds[i];
|
||||
char sent_location[MAXFNAMELEN];
|
||||
XLogRecPtr sentPtr;
|
||||
Datum values[PG_STAT_GET_WAL_SENDERS_COLS];
|
||||
bool nulls[PG_STAT_GET_WAL_SENDERS_COLS];
|
||||
|
||||
if (walsnd->pid == 0)
|
||||
continue;
|
||||
|
||||
SpinLockAcquire(&walsnd->mutex);
|
||||
sentPtr = walsnd->sentPtr;
|
||||
SpinLockRelease(&walsnd->mutex);
|
||||
|
||||
snprintf(sent_location, sizeof(sent_location), "%X/%X",
|
||||
sentPtr.xlogid, sentPtr.xrecoff);
|
||||
|
||||
memset(nulls, 0, sizeof(nulls));
|
||||
values[0] = Int32GetDatum(walsnd->pid);
|
||||
values[1] = CStringGetTextDatum(sent_location);
|
||||
|
||||
tuplestore_putvalues(tupstore, tupdesc, values, nulls);
|
||||
}
|
||||
|
||||
/* clean up and return the tuplestore */
|
||||
tuplestore_donestoring(tupstore);
|
||||
|
||||
return (Datum) 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This isn't currently used for anything. Monitoring tools might be
|
||||
* interested in the future, and we'll need something like this in the
|
||||
|
@ -3075,6 +3075,8 @@ DATA(insert OID = 1936 ( pg_stat_get_backend_idset PGNSP PGUID 12 1 100 0 f f
|
||||
DESCR("statistics: currently active backend IDs");
|
||||
DATA(insert OID = 2022 ( pg_stat_get_activity PGNSP PGUID 12 1 100 0 f f f f t s 1 0 2249 "23" "{23,26,23,26,25,25,16,1184,1184,1184,869,23}" "{i,o,o,o,o,o,o,o,o,o,o,o}" "{pid,datid,procpid,usesysid,application_name,current_query,waiting,xact_start,query_start,backend_start,client_addr,client_port}" _null_ pg_stat_get_activity _null_ _null_ _null_ ));
|
||||
DESCR("statistics: information about currently active backends");
|
||||
DATA(insert OID = 3099 ( pg_stat_get_wal_senders PGNSP PGUID 12 1 10 0 f f f f t s 0 0 2249 "" "{23,25}" "{o,o}" "{procpid,sent_location}" _null_ pg_stat_get_wal_senders _null_ _null_ _null_ ));
|
||||
DESCR("statistics: information about currently active replication");
|
||||
DATA(insert OID = 2026 ( pg_backend_pid PGNSP PGUID 12 1 0 0 f f f t f s 0 0 23 "" _null_ _null_ _null_ _null_ pg_backend_pid _null_ _null_ _null_ ));
|
||||
DESCR("statistics: current backend PID");
|
||||
DATA(insert OID = 1937 ( pg_stat_get_backend_pid PGNSP PGUID 12 1 0 0 f f f t f s 1 0 23 "23" _null_ _null_ _null_ _null_ pg_stat_get_backend_pid _null_ _null_ _null_ ));
|
||||
|
@ -54,4 +54,6 @@ extern Size WalSndShmemSize(void);
|
||||
extern void WalSndShmemInit(void);
|
||||
extern void WalSndWakeup(void);
|
||||
|
||||
extern Datum pg_stat_get_wal_senders(PG_FUNCTION_ARGS);
|
||||
|
||||
#endif /* _WALSENDER_H */
|
||||
|
@ -1296,6 +1296,7 @@ SELECT viewname, definition FROM pg_views WHERE schemaname <> 'information_schem
|
||||
pg_stat_bgwriter | 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_clean() AS buffers_clean, pg_stat_get_bgwriter_maxwritten_clean() AS maxwritten_clean, pg_stat_get_buf_written_backend() AS buffers_backend, pg_stat_get_buf_fsync_backend() AS buffers_backend_fsync, pg_stat_get_buf_alloc() AS buffers_alloc;
|
||||
pg_stat_database | SELECT d.oid AS datid, d.datname, pg_stat_get_db_numbackends(d.oid) AS numbackends, pg_stat_get_db_xact_commit(d.oid) AS xact_commit, pg_stat_get_db_xact_rollback(d.oid) AS xact_rollback, (pg_stat_get_db_blocks_fetched(d.oid) - pg_stat_get_db_blocks_hit(d.oid)) AS blks_read, pg_stat_get_db_blocks_hit(d.oid) AS blks_hit, pg_stat_get_db_tuples_returned(d.oid) AS tup_returned, pg_stat_get_db_tuples_fetched(d.oid) AS tup_fetched, pg_stat_get_db_tuples_inserted(d.oid) AS tup_inserted, pg_stat_get_db_tuples_updated(d.oid) AS tup_updated, pg_stat_get_db_tuples_deleted(d.oid) AS tup_deleted, pg_stat_get_db_conflict_all(d.oid) AS conflicts FROM pg_database d;
|
||||
pg_stat_database_conflicts | SELECT d.oid AS datid, d.datname, pg_stat_get_db_conflict_tablespace(d.oid) AS confl_tablespace, pg_stat_get_db_conflict_lock(d.oid) AS confl_lock, pg_stat_get_db_conflict_snapshot(d.oid) AS confl_snapshot, pg_stat_get_db_conflict_bufferpin(d.oid) AS confl_bufferpin, pg_stat_get_db_conflict_startup_deadlock(d.oid) AS confl_deadlock FROM pg_database d;
|
||||
pg_stat_replication | SELECT s.procpid, s.usesysid, u.rolname AS usename, s.application_name, s.client_addr, s.client_port, s.backend_start, w.sent_location FROM pg_stat_get_activity(NULL::integer) s(datid, procpid, usesysid, application_name, current_query, waiting, xact_start, query_start, backend_start, client_addr, client_port), pg_authid u, pg_stat_get_wal_senders() w(procpid, sent_location) WHERE ((s.usesysid = u.oid) AND (s.procpid = w.procpid));
|
||||
pg_stat_sys_indexes | SELECT pg_stat_all_indexes.relid, pg_stat_all_indexes.indexrelid, pg_stat_all_indexes.schemaname, pg_stat_all_indexes.relname, pg_stat_all_indexes.indexrelname, pg_stat_all_indexes.idx_scan, pg_stat_all_indexes.idx_tup_read, pg_stat_all_indexes.idx_tup_fetch FROM pg_stat_all_indexes WHERE ((pg_stat_all_indexes.schemaname = ANY (ARRAY['pg_catalog'::name, 'information_schema'::name])) OR (pg_stat_all_indexes.schemaname ~ '^pg_toast'::text));
|
||||
pg_stat_sys_tables | SELECT pg_stat_all_tables.relid, pg_stat_all_tables.schemaname, pg_stat_all_tables.relname, pg_stat_all_tables.seq_scan, pg_stat_all_tables.seq_tup_read, pg_stat_all_tables.idx_scan, pg_stat_all_tables.idx_tup_fetch, pg_stat_all_tables.n_tup_ins, pg_stat_all_tables.n_tup_upd, pg_stat_all_tables.n_tup_del, pg_stat_all_tables.n_tup_hot_upd, pg_stat_all_tables.n_live_tup, pg_stat_all_tables.n_dead_tup, pg_stat_all_tables.last_vacuum, pg_stat_all_tables.last_autovacuum, pg_stat_all_tables.last_analyze, pg_stat_all_tables.last_autoanalyze, pg_stat_all_tables.vacuum_count, pg_stat_all_tables.autovacuum_count, pg_stat_all_tables.analyze_count, pg_stat_all_tables.autoanalyze_count FROM pg_stat_all_tables WHERE ((pg_stat_all_tables.schemaname = ANY (ARRAY['pg_catalog'::name, 'information_schema'::name])) OR (pg_stat_all_tables.schemaname ~ '^pg_toast'::text));
|
||||
pg_stat_user_functions | SELECT p.oid AS funcid, n.nspname AS schemaname, p.proname AS funcname, pg_stat_get_function_calls(p.oid) AS calls, (pg_stat_get_function_time(p.oid) / 1000) AS total_time, (pg_stat_get_function_self_time(p.oid) / 1000) AS self_time FROM (pg_proc p LEFT JOIN pg_namespace n ON ((n.oid = p.pronamespace))) WHERE ((p.prolang <> (12)::oid) AND (pg_stat_get_function_calls(p.oid) IS NOT NULL));
|
||||
@ -1335,7 +1336,7 @@ SELECT viewname, definition FROM pg_views WHERE schemaname <> 'information_schem
|
||||
shoelace_obsolete | SELECT shoelace.sl_name, shoelace.sl_avail, shoelace.sl_color, shoelace.sl_len, shoelace.sl_unit, shoelace.sl_len_cm FROM shoelace WHERE (NOT (EXISTS (SELECT shoe.shoename FROM shoe WHERE (shoe.slcolor = shoelace.sl_color))));
|
||||
street | SELECT r.name, r.thepath, c.cname FROM ONLY road r, real_city c WHERE (c.outline ## r.thepath);
|
||||
toyemp | SELECT emp.name, emp.age, emp.location, (12 * emp.salary) AS annualsal FROM emp;
|
||||
(57 rows)
|
||||
(58 rows)
|
||||
|
||||
SELECT tablename, rulename, definition FROM pg_rules
|
||||
ORDER BY tablename, rulename;
|
||||
|
Loading…
x
Reference in New Issue
Block a user