Separate state from query string in pg_stat_activity

This separates the state (running/idle/idleintransaction etc) into
it's own field ("state"), and leaves the query field containing just
query text.

The query text will now mean "current query" when a query is running
and "last query" in other states. Accordingly,the field has been
renamed from current_query to query.

Since backwards compatibility was broken anyway to make that, the procpid
field has also been renamed to pid - along with the same field in
pg_stat_replication for consistency.

Scott Mead and Magnus Hagander, review work from Greg Smith
This commit is contained in:
Magnus Hagander 2012-01-19 14:19:20 +01:00
parent fa352d662e
commit 4f42b546fd
10 changed files with 380 additions and 87 deletions

View File

@ -242,20 +242,20 @@ postgres: <replaceable>user</> <replaceable>database</> <replaceable>host</> <re
<tbody>
<row>
<entry><structname>pg_stat_activity</><indexterm><primary>pg_stat_activity</primary></indexterm></entry>
<entry>One row per server process, showing database OID, database
name, process <acronym>ID</>, user OID, user name, application name,
client's address, host name (if available), and port number, times at
which the server process, current transaction, and current query began
execution, process's waiting status, and text of the current query.
The columns that report data on the current query are available unless
the parameter <varname>track_activities</varname> has been turned off.
Furthermore, these columns are only visible if the user examining
the view is a superuser or the same as the user owning the process
being reported on. The client's host name will be available only if
<xref linkend="guc-log-hostname"> is set or if the user's host name
needed to be looked up during <filename>pg_hba.conf</filename>
processing.
<entry>
<structname>pg_stat_activity</structname>
<indexterm><primary>pg_stat_activity</primary></indexterm>
</entry>
<entry>
<para>One row per server process, showing information related to
each connection to the server. Unless the
<xref linkend="guc-track-activities"> parameter has been turned
off, it is possible to monitor state and query information of
all running processes.
</para>
<para>
See <xref linkend="pg-stat-activity-view"> for more details.
</para>
</entry>
</row>
@ -529,6 +529,210 @@ postgres: <replaceable>user</> <replaceable>database</> <replaceable>host</> <re
into the kernel's handling of I/O.
</para>
<table id="pg-stat-activity-view" xreflabel="pg_stat_activity">
<title>pg_stat_activity view</title>
<tgroup cols="3">
<thead>
<row>
<entry>Column</entry>
<entry>Type</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry>datid</entry>
<entry><type>oid</></entry>
<entry>The oid of the database the backend is connected to.</entry>
</row>
<row>
<entry>datname</entry>
<entry><type>name</></entry>
<entry>The name of the database the backend is connected to.</entry>
</row>
<row>
<entry>pid</entry>
<entry><type>integer</></entry>
<entry>The process ID of the backend.</entry>
</row>
<row>
<entry>usesysid</entry>
<entry><type>oid</></entry>
<entry>The id of the user logged into the backend.</entry>
</row>
<row>
<entry>usename</entry>
<entry><type>name</></entry>
<entry>The name of the user logged into the backend.</entry>
</row>
<row>
<entry>application_name</entry>
<entry><type>text</></entry>
<entry>The name of the application that has initiated the connection
to the backend.</entry>
</row>
<row>
<entry>client_addr</entry>
<entry><type>inet</></entry>
<entry>The remote IP of the client connected to the backend.
If this field is not set, it indicates that the client is either:
<itemizedlist spacing="compact" mark="bullet">
<listitem>
<para>
Connected via unix sockets on the server machine
</para>
</listitem>
<listitem>
<para>An internal process such as autovacuum</para>
</listitem>
</itemizedlist>
</entry>
</row>
<row>
<entry>client_hostname</entry>
<entry><type>text</></entry>
<entry>
If available, the hostname of the client as reported by a
reverse lookup of <structfield>client_addr</>. This field will
only be set when <xref linkend="guc-log-hostname"> is enabled.
</entry>
</row>
<row>
<entry>client_port</entry>
<entry><type>integer</></entry>
<entry>
The remote TCP port that the client is using for communication
to the backend, or <symbol>NULL</> if a unix socket is used.
</entry>
</row>
<row>
<entry>backend_start</entry>
<entry><type>timestamp with time zone</></entry>
<entry>
The time when this process was started, i.e. when the
client connected to the server.
</entry>
</row>
<row>
<entry>xact_start</entry>
<entry><type>timestamp with time zone</></entry>
<entry>
The time when the current transaction was started. If the client is
using autocommit for transactions, this value is equal to the
query_start column.
</entry>
</row>
<row>
<entry>query_start</entry>
<entry><type>timestamp with time zone</></entry>
<entry>
The time when the currently active query started, or if
<structfield>state</> is <literal>idle</>, when the last query
was started.
</entry>
</row>
<row>
<entry>state_change</entry>
<entry><type>timestamp with time zone</></entry>
<entry>The time when the <structfield>state</> was last changed.</entry>
</row>
<row>
<entry>waiting</entry>
<entry><type>boolean</></entry>
<entry>
Boolean indicating if a backend is currently waiting on a lock.
</entry>
</row>
<row>
<entry>state</entry>
<entry><type>text</></entry>
<entry>
The <structfield>state</> of the currently running query.
Can be one of:
<variablelist>
<varlistentry>
<term>active</term>
<listitem>
<para>
The backend is executing a query.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>idle</term>
<listitem>
<para>
There is no query executing in the backend.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>idle in transaction</term>
<listitem>
<para>
The backend is in a transaction, but is currently not currently
executing a query.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>idle in transaction (aborted)</term>
<listitem>
<para>
This state is similar to <literal>idle in transaction</>,
except one of the statements in the transaction caused an error.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>fastpath function call</term>
<listitem>
<para>
The backend is executing a fast-path function.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>disabled</term>
<listitem>
<para>
This state indicates that <xref linkend="guc-track-activities">
is disabled.
</para>
</listitem>
</varlistentry>
</variablelist>
<note>
<para>
The <structfield>waiting</> and <structfield>state</> columns are
independent. If a query is in the <literal>active</> state,
it may or may not be <literal>waiting</>. If a query is
<literal>active</> and <structfield>waiting</> is true, it means
that the query is being executed, but is being blocked by a lock
somewhere in the system.
</para>
</note>
</entry>
</row>
<row>
<entry>query</entry>
<entry><type>text</></entry>
<entry>
The most recent query that the backend has executed. If
<structfield>state</> is <literal>active</> this means the currently
executing query. In all other states, it means the last query that was
executed.
</entry>
</row>
</tbody>
</tgroup>
</table>
<sect3 id="monitoring-stats-functions">
<title>Statistics Access Functions</title>
<para>
Other ways of looking at the statistics can be set up by writing
queries that use the same underlying statistics access functions as
@ -1264,6 +1468,7 @@ SELECT pg_stat_get_backend_pid(s.backendid) AS procpid,
</programlisting>
</para>
</sect3>
</sect2>
</sect1>

View File

@ -520,7 +520,7 @@ CREATE VIEW pg_stat_activity AS
SELECT
S.datid AS datid,
D.datname AS datname,
S.procpid,
S.pid,
S.usesysid,
U.rolname AS usename,
S.application_name,
@ -530,15 +530,17 @@ CREATE VIEW pg_stat_activity AS
S.backend_start,
S.xact_start,
S.query_start,
S.state_change,
S.waiting,
S.current_query
S.state,
S.query
FROM pg_database D, pg_stat_get_activity(NULL) AS S, pg_authid U
WHERE S.datid = D.oid AND
S.usesysid = U.oid;
CREATE VIEW pg_stat_replication AS
SELECT
S.procpid,
S.pid,
S.usesysid,
U.rolname AS usename,
S.application_name,
@ -556,7 +558,7 @@ CREATE VIEW pg_stat_replication AS
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;
S.pid = W.pid;
CREATE VIEW pg_stat_database AS
SELECT

View File

@ -2781,7 +2781,7 @@ autovac_report_activity(autovac_table *tab)
/* Set statement_timestamp() to current time for pg_stat_activity */
SetCurrentStatementStartTimestamp();
pgstat_report_activity(activity);
pgstat_report_activity(STATE_RUNNING, activity);
}
/*

View File

@ -2410,12 +2410,14 @@ pgstat_bestart(void)
beentry->st_procpid = MyProcPid;
beentry->st_proc_start_timestamp = proc_start_timestamp;
beentry->st_activity_start_timestamp = 0;
beentry->st_state_start_timestamp = 0;
beentry->st_xact_start_timestamp = 0;
beentry->st_databaseid = MyDatabaseId;
beentry->st_userid = userid;
beentry->st_clientaddr = clientaddr;
beentry->st_clienthostname[0] = '\0';
beentry->st_waiting = false;
beentry->st_state = STATE_UNDEFINED;
beentry->st_appname[0] = '\0';
beentry->st_activity[0] = '\0';
/* Also make sure the last byte in each string area is always 0 */
@ -2476,39 +2478,70 @@ pgstat_beshutdown_hook(int code, Datum arg)
*
* Called from tcop/postgres.c to report what the backend is actually doing
* (usually "<IDLE>" or the start of the query to be executed).
*
* All updates of the status entry follow the protocol of bumping
* st_changecount before and after. We use a volatile pointer here to
* ensure the compiler doesn't try to get cute.
* ----------
*/
void
pgstat_report_activity(const char *cmd_str)
pgstat_report_activity(BackendState state, const char *cmd_str)
{
volatile PgBackendStatus *beentry = MyBEEntry;
TimestampTz start_timestamp;
TimestampTz current_timestamp;
int len;
TRACE_POSTGRESQL_STATEMENT_STATUS(cmd_str);
if (!pgstat_track_activities || !beentry)
if (!beentry)
return;
/*
* To minimize the time spent modifying the entry, fetch all the needed
* data first.
*/
start_timestamp = GetCurrentStatementStartTimestamp();
current_timestamp = GetCurrentTimestamp();
len = strlen(cmd_str);
len = pg_mbcliplen(cmd_str, len, pgstat_track_activity_query_size - 1);
if (!pgstat_track_activities && beentry->st_state != STATE_DISABLED)
{
/*
* Track activities is disabled, but we have a non-disabled state set.
* That means the status changed - so as our last update, tell the
* collector that we disabled it and will no longer update.
*/
beentry->st_changecount++;
beentry->st_state = STATE_DISABLED;
beentry->st_state_start_timestamp = current_timestamp;
beentry->st_changecount++;
Assert((beentry->st_changecount & 1) == 0);
return;
}
/*
* Update my status entry, following the protocol of bumping
* st_changecount before and after. We use a volatile pointer here to
* ensure the compiler doesn't try to get cute.
* Fetch more data before we start modifying the entry
*/
start_timestamp = GetCurrentStatementStartTimestamp();
if (cmd_str != NULL)
{
len = strlen(cmd_str);
len = pg_mbcliplen(cmd_str, len, pgstat_track_activity_query_size - 1);
}
/*
* Now update the status entry
*/
beentry->st_changecount++;
beentry->st_activity_start_timestamp = start_timestamp;
memcpy((char *) beentry->st_activity, cmd_str, len);
beentry->st_activity[len] = '\0';
beentry->st_state = state;
beentry->st_state_start_timestamp = current_timestamp;
if (cmd_str != NULL)
{
memcpy((char *) beentry->st_activity, cmd_str, len);
beentry->st_activity[len] = '\0';
beentry->st_activity_start_timestamp = start_timestamp;
}
beentry->st_changecount++;
Assert((beentry->st_changecount & 1) == 0);

View File

@ -809,7 +809,7 @@ exec_simple_query(const char *query_string)
*/
debug_query_string = query_string;
pgstat_report_activity(query_string);
pgstat_report_activity(STATE_RUNNING, query_string);
TRACE_POSTGRESQL_QUERY_START(query_string);
@ -1134,7 +1134,7 @@ exec_parse_message(const char *query_string, /* string to execute */
*/
debug_query_string = query_string;
pgstat_report_activity(query_string);
pgstat_report_activity(STATE_RUNNING, query_string);
set_ps_display("PARSE", false);
@ -1429,7 +1429,7 @@ exec_bind_message(StringInfo input_message)
*/
debug_query_string = psrc->query_string;
pgstat_report_activity(psrc->query_string);
pgstat_report_activity(STATE_RUNNING, psrc->query_string);
set_ps_display("BIND", false);
@ -1836,7 +1836,7 @@ exec_execute_message(const char *portal_name, long max_rows)
*/
debug_query_string = sourceText;
pgstat_report_activity(sourceText);
pgstat_report_activity(STATE_RUNNING, sourceText);
set_ps_display(portal->commandTag, false);
@ -3811,12 +3811,12 @@ PostgresMain(int argc, char *argv[], const char *username)
if (IsAbortedTransactionBlockState())
{
set_ps_display("idle in transaction (aborted)", false);
pgstat_report_activity("<IDLE> in transaction (aborted)");
pgstat_report_activity(STATE_IDLEINTRANSACTION_ABORTED, NULL);
}
else if (IsTransactionOrTransactionBlock())
{
set_ps_display("idle in transaction", false);
pgstat_report_activity("<IDLE> in transaction");
pgstat_report_activity(STATE_IDLEINTRANSACTION, NULL);
}
else
{
@ -3824,7 +3824,7 @@ PostgresMain(int argc, char *argv[], const char *username)
pgstat_report_stat(false);
set_ps_display("idle", false);
pgstat_report_activity("<IDLE>");
pgstat_report_activity(STATE_IDLE, NULL);
}
ReadyForQuery(whereToSendOutput);
@ -3944,7 +3944,7 @@ PostgresMain(int argc, char *argv[], const char *username)
SetCurrentStatementStartTimestamp();
/* Report query to various monitoring facilities. */
pgstat_report_activity("<FASTPATH> function call");
pgstat_report_activity(STATE_FASTPATH, NULL);
set_ps_display("<FASTPATH>", false);
/* start an xact for this function invocation */

View File

@ -507,31 +507,34 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
tupdesc = CreateTemplateTupleDesc(12, false);
tupdesc = CreateTemplateTupleDesc(14, false);
TupleDescInitEntry(tupdesc, (AttrNumber) 1, "datid",
OIDOID, -1, 0);
/* This should have been called 'pid'; can't change it. 2011-06-11 */
TupleDescInitEntry(tupdesc, (AttrNumber) 2, "procpid",
TupleDescInitEntry(tupdesc, (AttrNumber) 2, "pid",
INT4OID, -1, 0);
TupleDescInitEntry(tupdesc, (AttrNumber) 3, "usesysid",
OIDOID, -1, 0);
TupleDescInitEntry(tupdesc, (AttrNumber) 4, "application_name",
TEXTOID, -1, 0);
TupleDescInitEntry(tupdesc, (AttrNumber) 5, "current_query",
TupleDescInitEntry(tupdesc, (AttrNumber) 5, "state",
TEXTOID, -1, 0);
TupleDescInitEntry(tupdesc, (AttrNumber) 6, "waiting",
TupleDescInitEntry(tupdesc, (AttrNumber) 6, "query",
TEXTOID, -1, 0);
TupleDescInitEntry(tupdesc, (AttrNumber) 7, "waiting",
BOOLOID, -1, 0);
TupleDescInitEntry(tupdesc, (AttrNumber) 7, "act_start",
TupleDescInitEntry(tupdesc, (AttrNumber) 8, "act_start",
TIMESTAMPTZOID, -1, 0);
TupleDescInitEntry(tupdesc, (AttrNumber) 8, "query_start",
TupleDescInitEntry(tupdesc, (AttrNumber) 9, "query_start",
TIMESTAMPTZOID, -1, 0);
TupleDescInitEntry(tupdesc, (AttrNumber) 9, "backend_start",
TupleDescInitEntry(tupdesc, (AttrNumber) 10, "backend_start",
TIMESTAMPTZOID, -1, 0);
TupleDescInitEntry(tupdesc, (AttrNumber) 10, "client_addr",
TupleDescInitEntry(tupdesc, (AttrNumber) 11, "state_change",
TIMESTAMPTZOID, -1, 0);
TupleDescInitEntry(tupdesc, (AttrNumber) 12, "client_addr",
INETOID, -1, 0);
TupleDescInitEntry(tupdesc, (AttrNumber) 11, "client_hostname",
TupleDescInitEntry(tupdesc, (AttrNumber) 13, "client_hostname",
TEXTOID, -1, 0);
TupleDescInitEntry(tupdesc, (AttrNumber) 12, "client_port",
TupleDescInitEntry(tupdesc, (AttrNumber) 14, "client_port",
INT4OID, -1, 0);
funcctx->tuple_desc = BlessTupleDesc(tupdesc);
@ -584,8 +587,8 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
if (funcctx->call_cntr < funcctx->max_calls)
{
/* for each row */
Datum values[12];
bool nulls[12];
Datum values[14];
bool nulls[14];
HeapTuple tuple;
PgBackendStatus *beentry;
SockAddr zero_clientaddr;
@ -610,8 +613,8 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
for (i = 0; i < sizeof(nulls) / sizeof(nulls[0]); i++)
nulls[i] = true;
nulls[4] = false;
values[4] = CStringGetTextDatum("<backend information not available>");
nulls[5] = false;
values[5] = CStringGetTextDatum("<backend information not available>");
tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls);
SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(tuple));
@ -629,40 +632,69 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
/* Values only available to same user or superuser */
if (superuser() || beentry->st_userid == GetUserId())
{
if (*(beentry->st_activity) == '\0')
switch (beentry->st_state)
{
values[4] = CStringGetTextDatum("<command string not enabled>");
case STATE_IDLE:
values[4] = CStringGetTextDatum("idle");
break;
case STATE_RUNNING:
values[4] = CStringGetTextDatum("active");
break;
case STATE_IDLEINTRANSACTION:
values[4] = CStringGetTextDatum("idle in transaction");
break;
case STATE_FASTPATH:
values[4] = CStringGetTextDatum("fastpath function call");
break;
case STATE_IDLEINTRANSACTION_ABORTED:
values[4] = CStringGetTextDatum("idle in transaction (aborted)");
break;
case STATE_DISABLED:
values[4] = CStringGetTextDatum("disabled");
break;
case STATE_UNDEFINED:
nulls[4] = true;
break;
}
if (beentry->st_state == STATE_UNDEFINED ||
beentry->st_state == STATE_DISABLED)
{
values[5] = CStringGetTextDatum("");
}
else
{
values[4] = CStringGetTextDatum(beentry->st_activity);
values[5] = CStringGetTextDatum(beentry->st_activity);
}
values[5] = BoolGetDatum(beentry->st_waiting);
values[6] = BoolGetDatum(beentry->st_waiting);
if (beentry->st_xact_start_timestamp != 0)
values[6] = TimestampTzGetDatum(beentry->st_xact_start_timestamp);
else
nulls[6] = true;
if (beentry->st_activity_start_timestamp != 0)
values[7] = TimestampTzGetDatum(beentry->st_activity_start_timestamp);
values[7] = TimestampTzGetDatum(beentry->st_xact_start_timestamp);
else
nulls[7] = true;
if (beentry->st_proc_start_timestamp != 0)
values[8] = TimestampTzGetDatum(beentry->st_proc_start_timestamp);
if (beentry->st_activity_start_timestamp != 0)
values[8] = TimestampTzGetDatum(beentry->st_activity_start_timestamp);
else
nulls[8] = true;
if (beentry->st_proc_start_timestamp != 0)
values[9] = TimestampTzGetDatum(beentry->st_proc_start_timestamp);
else
nulls[9] = true;
if (beentry->st_state_start_timestamp != 0)
values[10] = TimestampTzGetDatum(beentry->st_state_start_timestamp);
else
nulls[10] = true;
/* A zeroed client addr means we don't know */
memset(&zero_clientaddr, 0, sizeof(zero_clientaddr));
if (memcmp(&(beentry->st_clientaddr), &zero_clientaddr,
sizeof(zero_clientaddr) == 0))
{
nulls[9] = true;
nulls[10] = true;
nulls[11] = true;
nulls[12] = true;
nulls[13] = true;
}
else
{
@ -686,19 +718,19 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
if (ret == 0)
{
clean_ipv6_addr(beentry->st_clientaddr.addr.ss_family, remote_host);
values[9] = DirectFunctionCall1(inet_in,
values[11] = DirectFunctionCall1(inet_in,
CStringGetDatum(remote_host));
if (beentry->st_clienthostname)
values[10] = CStringGetTextDatum(beentry->st_clienthostname);
values[12] = CStringGetTextDatum(beentry->st_clienthostname);
else
nulls[10] = true;
values[11] = Int32GetDatum(atoi(remote_port));
nulls[12] = true;
values[13] = Int32GetDatum(atoi(remote_port));
}
else
{
nulls[9] = true;
nulls[10] = true;
nulls[11] = true;
nulls[12] = true;
nulls[13] = true;
}
}
else if (beentry->st_clientaddr.addr.ss_family == AF_UNIX)
@ -709,30 +741,32 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
* connections we have no permissions to view, or with
* errors.
*/
nulls[9] = true;
nulls[10] = true;
values[11] = DatumGetInt32(-1);
nulls[11] = true;
nulls[12] = true;
values[13] = DatumGetInt32(-1);
}
else
{
/* Unknown address type, should never happen */
nulls[9] = true;
nulls[10] = true;
nulls[11] = true;
nulls[12] = true;
nulls[13] = true;
}
}
}
else
{
/* No permissions to view data about this session */
values[4] = CStringGetTextDatum("<insufficient privilege>");
nulls[5] = true;
values[5] = CStringGetTextDatum("<insufficient privilege>");
nulls[4] = true;
nulls[6] = true;
nulls[7] = true;
nulls[8] = true;
nulls[9] = true;
nulls[10] = true;
nulls[11] = true;
nulls[12] = true;
nulls[13] = true;
}
tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls);

View File

@ -53,6 +53,6 @@
*/
/* yyyymmddN */
#define CATALOG_VERSION_NO 201112241
#define CATALOG_VERSION_NO 201201191
#endif

View File

@ -2573,9 +2573,9 @@ DATA(insert OID = 3057 ( pg_stat_get_autoanalyze_count PGNSP PGUID 12 1 0 0 0 f
DESCR("statistics: number of auto analyzes for a table");
DATA(insert OID = 1936 ( pg_stat_get_backend_idset PGNSP PGUID 12 1 100 0 0 f f f t t s 0 0 23 "" _null_ _null_ _null_ _null_ pg_stat_get_backend_idset _null_ _null_ _null_ ));
DESCR("statistics: currently active backend IDs");
DATA(insert OID = 2022 ( pg_stat_get_activity PGNSP PGUID 12 1 100 0 0 f f f f t s 1 0 2249 "23" "{23,26,23,26,25,25,16,1184,1184,1184,869,25,23}" "{i,o,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_hostname,client_port}" _null_ pg_stat_get_activity _null_ _null_ _null_ ));
DATA(insert OID = 2022 ( pg_stat_get_activity PGNSP PGUID 12 1 100 0 0 f f f f t s 1 0 2249 "23" "{23,26,23,26,25,25,25,16,1184,1184,1184,1184,869,25,23}" "{i,o,o,o,o,o,o,o,o,o,o,o,o,o,o}" "{pid,datid,pid,usesysid,application_name,state,query,waiting,xact_start,query_start,backend_start,state_change,client_addr,client_hostname,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 0 f f f f t s 0 0 2249 "" "{23,25,25,25,25,25,23,25}" "{o,o,o,o,o,o,o,o}" "{procpid,state,sent_location,write_location,flush_location,replay_location,sync_priority,sync_state}" _null_ pg_stat_get_wal_senders _null_ _null_ _null_ ));
DATA(insert OID = 3099 ( pg_stat_get_wal_senders PGNSP PGUID 12 1 10 0 0 f f f f t s 0 0 2249 "" "{23,25,25,25,25,25,23,25}" "{o,o,o,o,o,o,o,o}" "{pid,state,sent_location,write_location,flush_location,replay_location,sync_priority,sync_state}" _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 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");

View File

@ -588,11 +588,26 @@ typedef struct PgStat_GlobalStats
} PgStat_GlobalStats;
/* ----------
* Backend states
* ----------
*/
typedef enum BackendState {
STATE_UNDEFINED,
STATE_IDLE,
STATE_RUNNING,
STATE_IDLEINTRANSACTION,
STATE_FASTPATH,
STATE_IDLEINTRANSACTION_ABORTED,
STATE_DISABLED,
} BackendState;
/* ----------
* Shared-memory data structures
* ----------
*/
/* ----------
* PgBackendStatus
*
@ -622,6 +637,7 @@ typedef struct PgBackendStatus
TimestampTz st_proc_start_timestamp;
TimestampTz st_xact_start_timestamp;
TimestampTz st_activity_start_timestamp;
TimestampTz st_state_start_timestamp;
/* Database OID, owning user's OID, connection client address */
Oid st_databaseid;
@ -632,6 +648,9 @@ typedef struct PgBackendStatus
/* Is backend currently waiting on an lmgr lock? */
bool st_waiting;
/* current state */
BackendState st_state;
/* application name; MUST be null-terminated */
char *st_appname;
@ -715,7 +734,7 @@ extern void pgstat_report_recovery_conflict(int reason);
extern void pgstat_initialize(void);
extern void pgstat_bestart(void);
extern void pgstat_report_activity(const char *cmd_str);
extern void pgstat_report_activity(BackendState state, const char *cmd_str);
extern void pgstat_report_appname(const char *appname);
extern void pgstat_report_xact_timestamp(TimestampTz tstamp);
extern void pgstat_report_waiting(bool waiting);

View File

@ -1292,13 +1292,13 @@ SELECT viewname, definition FROM pg_views WHERE schemaname <> 'information_schem
pg_seclabels | ((((((((SELECT l.objoid, l.classoid, l.objsubid, CASE WHEN (rel.relkind = 'r'::"char") THEN 'table'::text WHEN (rel.relkind = 'v'::"char") THEN 'view'::text WHEN (rel.relkind = 'S'::"char") THEN 'sequence'::text WHEN (rel.relkind = 'f'::"char") THEN 'foreign table'::text ELSE NULL::text END AS objtype, rel.relnamespace AS objnamespace, CASE WHEN pg_table_is_visible(rel.oid) THEN quote_ident((rel.relname)::text) ELSE ((quote_ident((nsp.nspname)::text) || '.'::text) || quote_ident((rel.relname)::text)) END AS objname, l.provider, l.label FROM ((pg_seclabel l JOIN pg_class rel ON (((l.classoid = rel.tableoid) AND (l.objoid = rel.oid)))) JOIN pg_namespace nsp ON ((rel.relnamespace = nsp.oid))) WHERE (l.objsubid = 0) UNION ALL SELECT l.objoid, l.classoid, l.objsubid, 'column'::text AS objtype, rel.relnamespace AS objnamespace, ((CASE WHEN pg_table_is_visible(rel.oid) THEN quote_ident((rel.relname)::text) ELSE ((quote_ident((nsp.nspname)::text) || '.'::text) || quote_ident((rel.relname)::text)) END || '.'::text) || (att.attname)::text) AS objname, l.provider, l.label FROM (((pg_seclabel l JOIN pg_class rel ON (((l.classoid = rel.tableoid) AND (l.objoid = rel.oid)))) JOIN pg_attribute att ON (((rel.oid = att.attrelid) AND (l.objsubid = att.attnum)))) JOIN pg_namespace nsp ON ((rel.relnamespace = nsp.oid))) WHERE (l.objsubid <> 0)) UNION ALL SELECT l.objoid, l.classoid, l.objsubid, CASE WHEN (pro.proisagg = true) THEN 'aggregate'::text WHEN (pro.proisagg = false) THEN 'function'::text ELSE NULL::text END AS objtype, pro.pronamespace AS objnamespace, (((CASE WHEN pg_function_is_visible(pro.oid) THEN quote_ident((pro.proname)::text) ELSE ((quote_ident((nsp.nspname)::text) || '.'::text) || quote_ident((pro.proname)::text)) END || '('::text) || pg_get_function_arguments(pro.oid)) || ')'::text) AS objname, l.provider, l.label FROM ((pg_seclabel l JOIN pg_proc pro ON (((l.classoid = pro.tableoid) AND (l.objoid = pro.oid)))) JOIN pg_namespace nsp ON ((pro.pronamespace = nsp.oid))) WHERE (l.objsubid = 0)) UNION ALL SELECT l.objoid, l.classoid, l.objsubid, CASE WHEN (typ.typtype = 'd'::"char") THEN 'domain'::text ELSE 'type'::text END AS objtype, typ.typnamespace AS objnamespace, CASE WHEN pg_type_is_visible(typ.oid) THEN quote_ident((typ.typname)::text) ELSE ((quote_ident((nsp.nspname)::text) || '.'::text) || quote_ident((typ.typname)::text)) END AS objname, l.provider, l.label FROM ((pg_seclabel l JOIN pg_type typ ON (((l.classoid = typ.tableoid) AND (l.objoid = typ.oid)))) JOIN pg_namespace nsp ON ((typ.typnamespace = nsp.oid))) WHERE (l.objsubid = 0)) UNION ALL SELECT l.objoid, l.classoid, l.objsubid, 'large object'::text AS objtype, NULL::oid AS objnamespace, (l.objoid)::text AS objname, l.provider, l.label FROM (pg_seclabel l JOIN pg_largeobject_metadata lom ON ((l.objoid = lom.oid))) WHERE ((l.classoid = ('pg_largeobject'::regclass)::oid) AND (l.objsubid = 0))) UNION ALL SELECT l.objoid, l.classoid, l.objsubid, 'language'::text AS objtype, NULL::oid AS objnamespace, quote_ident((lan.lanname)::text) AS objname, l.provider, l.label FROM (pg_seclabel l JOIN pg_language lan ON (((l.classoid = lan.tableoid) AND (l.objoid = lan.oid)))) WHERE (l.objsubid = 0)) UNION ALL SELECT l.objoid, l.classoid, l.objsubid, 'schema'::text AS objtype, nsp.oid AS objnamespace, quote_ident((nsp.nspname)::text) AS objname, l.provider, l.label FROM (pg_seclabel l JOIN pg_namespace nsp ON (((l.classoid = nsp.tableoid) AND (l.objoid = nsp.oid)))) WHERE (l.objsubid = 0)) UNION ALL SELECT l.objoid, l.classoid, 0 AS objsubid, 'database'::text AS objtype, NULL::oid AS objnamespace, quote_ident((dat.datname)::text) AS objname, l.provider, l.label FROM (pg_shseclabel l JOIN pg_database dat ON (((l.classoid = dat.tableoid) AND (l.objoid = dat.oid))))) UNION ALL SELECT l.objoid, l.classoid, 0 AS objsubid, 'tablespace'::text AS objtype, NULL::oid AS objnamespace, quote_ident((spc.spcname)::text) AS objname, l.provider, l.label FROM (pg_shseclabel l JOIN pg_tablespace spc ON (((l.classoid = spc.tableoid) AND (l.objoid = spc.oid))))) UNION ALL SELECT l.objoid, l.classoid, 0 AS objsubid, 'role'::text AS objtype, NULL::oid AS objnamespace, quote_ident((rol.rolname)::text) AS objname, l.provider, l.label FROM (pg_shseclabel l JOIN pg_authid rol ON (((l.classoid = rol.tableoid) AND (l.objoid = rol.oid))));
pg_settings | SELECT a.name, a.setting, a.unit, a.category, a.short_desc, a.extra_desc, a.context, a.vartype, a.source, a.min_val, a.max_val, a.enumvals, a.boot_val, a.reset_val, a.sourcefile, a.sourceline FROM pg_show_all_settings() a(name, setting, unit, category, short_desc, extra_desc, context, vartype, source, min_val, max_val, enumvals, boot_val, reset_val, sourcefile, sourceline);
pg_shadow | SELECT pg_authid.rolname AS usename, pg_authid.oid AS usesysid, pg_authid.rolcreatedb AS usecreatedb, pg_authid.rolsuper AS usesuper, pg_authid.rolcatupdate AS usecatupd, pg_authid.rolreplication AS userepl, pg_authid.rolpassword AS passwd, (pg_authid.rolvaliduntil)::abstime AS valuntil, s.setconfig AS useconfig FROM (pg_authid LEFT JOIN pg_db_role_setting s ON (((pg_authid.oid = s.setrole) AND (s.setdatabase = (0)::oid)))) WHERE pg_authid.rolcanlogin;
pg_stat_activity | SELECT s.datid, d.datname, s.procpid, s.usesysid, u.rolname AS usename, s.application_name, s.client_addr, s.client_hostname, s.client_port, s.backend_start, s.xact_start, s.query_start, s.waiting, s.current_query FROM pg_database d, pg_stat_get_activity(NULL::integer) s(datid, procpid, usesysid, application_name, current_query, waiting, xact_start, query_start, backend_start, client_addr, client_hostname, client_port), pg_authid u WHERE ((s.datid = d.oid) AND (s.usesysid = u.oid));
pg_stat_activity | SELECT s.datid, d.datname, s.pid, s.usesysid, u.rolname AS usename, s.application_name, s.client_addr, s.client_hostname, s.client_port, s.backend_start, s.xact_start, s.query_start, s.state_change, s.waiting, s.state, s.query FROM pg_database d, pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, waiting, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port), pg_authid u WHERE ((s.datid = d.oid) AND (s.usesysid = u.oid));
pg_stat_all_indexes | SELECT c.oid AS relid, i.oid AS indexrelid, n.nspname AS schemaname, c.relname, i.relname AS indexrelname, pg_stat_get_numscans(i.oid) AS idx_scan, pg_stat_get_tuples_returned(i.oid) AS idx_tup_read, pg_stat_get_tuples_fetched(i.oid) AS idx_tup_fetch FROM (((pg_class c JOIN pg_index x ON ((c.oid = x.indrelid))) JOIN pg_class i ON ((i.oid = x.indexrelid))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) WHERE (c.relkind = ANY (ARRAY['r'::"char", 't'::"char"]));
pg_stat_all_tables | SELECT c.oid AS relid, n.nspname AS schemaname, c.relname, pg_stat_get_numscans(c.oid) AS seq_scan, pg_stat_get_tuples_returned(c.oid) AS seq_tup_read, (sum(pg_stat_get_numscans(i.indexrelid)))::bigint AS idx_scan, ((sum(pg_stat_get_tuples_fetched(i.indexrelid)))::bigint + pg_stat_get_tuples_fetched(c.oid)) AS idx_tup_fetch, pg_stat_get_tuples_inserted(c.oid) AS n_tup_ins, pg_stat_get_tuples_updated(c.oid) AS n_tup_upd, pg_stat_get_tuples_deleted(c.oid) AS n_tup_del, pg_stat_get_tuples_hot_updated(c.oid) AS n_tup_hot_upd, pg_stat_get_live_tuples(c.oid) AS n_live_tup, pg_stat_get_dead_tuples(c.oid) AS n_dead_tup, pg_stat_get_last_vacuum_time(c.oid) AS last_vacuum, pg_stat_get_last_autovacuum_time(c.oid) AS last_autovacuum, pg_stat_get_last_analyze_time(c.oid) AS last_analyze, pg_stat_get_last_autoanalyze_time(c.oid) AS last_autoanalyze, pg_stat_get_vacuum_count(c.oid) AS vacuum_count, pg_stat_get_autovacuum_count(c.oid) AS autovacuum_count, pg_stat_get_analyze_count(c.oid) AS analyze_count, pg_stat_get_autoanalyze_count(c.oid) AS autoanalyze_count FROM ((pg_class c LEFT JOIN pg_index i ON ((c.oid = i.indrelid))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) WHERE (c.relkind = ANY (ARRAY['r'::"char", 't'::"char"])) GROUP BY c.oid, n.nspname, c.relname;
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_get_bgwriter_stat_reset_time() AS stats_reset;
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, pg_stat_get_db_stat_reset_time(d.oid) AS stats_reset 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_hostname, s.client_port, s.backend_start, w.state, w.sent_location, w.write_location, w.flush_location, w.replay_location, w.sync_priority, w.sync_state 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_hostname, client_port), pg_authid u, pg_stat_get_wal_senders() w(procpid, state, sent_location, write_location, flush_location, replay_location, sync_priority, sync_state) WHERE ((s.usesysid = u.oid) AND (s.procpid = w.procpid));
pg_stat_replication | SELECT s.pid, s.usesysid, u.rolname AS usename, s.application_name, s.client_addr, s.client_hostname, s.client_port, s.backend_start, w.state, w.sent_location, w.write_location, w.flush_location, w.replay_location, w.sync_priority, w.sync_state FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, waiting, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port), pg_authid u, pg_stat_get_wal_senders() w(pid, state, sent_location, write_location, flush_location, replay_location, sync_priority, sync_state) WHERE ((s.usesysid = u.oid) AND (s.pid = w.pid));
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));