1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-16 06:01:02 +03:00

Provide much better wait information in pg_stat_activity.

When a process is waiting for a heavyweight lock, we will now indicate
the type of heavyweight lock for which it is waiting.  Also, you can
now see when a process is waiting for a lightweight lock - in which
case we will indicate the individual lock name or the tranche, as
appropriate - or for a buffer pin.

Amit Kapila, Ildus Kurbangaliev, reviewed by me.  Lots of helpful
discussion and suggestions by many others, including Alexander
Korotkov, Vladimir Borodin, and many others.
This commit is contained in:
Robert Haas
2016-03-10 12:44:09 -05:00
parent a3a8309d45
commit 53be0b1add
24 changed files with 796 additions and 104 deletions

View File

@ -20,6 +20,8 @@
#include "libpq/ip.h"
#include "miscadmin.h"
#include "pgstat.h"
#include "storage/proc.h"
#include "storage/procarray.h"
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/inet.h"
@ -58,7 +60,8 @@ extern Datum pg_stat_get_backend_pid(PG_FUNCTION_ARGS);
extern Datum pg_stat_get_backend_dbid(PG_FUNCTION_ARGS);
extern Datum pg_stat_get_backend_userid(PG_FUNCTION_ARGS);
extern Datum pg_stat_get_backend_activity(PG_FUNCTION_ARGS);
extern Datum pg_stat_get_backend_waiting(PG_FUNCTION_ARGS);
extern Datum pg_stat_get_backend_wait_event_type(PG_FUNCTION_ARGS);
extern Datum pg_stat_get_backend_wait_event(PG_FUNCTION_ARGS);
extern Datum pg_stat_get_backend_activity_start(PG_FUNCTION_ARGS);
extern Datum pg_stat_get_backend_xact_start(PG_FUNCTION_ARGS);
extern Datum pg_stat_get_backend_start(PG_FUNCTION_ARGS);
@ -633,7 +636,7 @@ pg_stat_get_progress_info(PG_FUNCTION_ARGS)
Datum
pg_stat_get_activity(PG_FUNCTION_ARGS)
{
#define PG_STAT_GET_ACTIVITY_COLS 22
#define PG_STAT_GET_ACTIVITY_COLS 23
int num_backends = pgstat_fetch_stat_numbackends();
int curr_backend;
int pid = PG_ARGISNULL(0) ? -1 : PG_GETARG_INT32(0);
@ -676,6 +679,9 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
bool nulls[PG_STAT_GET_ACTIVITY_COLS];
LocalPgBackendStatus *local_beentry;
PgBackendStatus *beentry;
PGPROC *proc;
const char *wait_event_type;
const char *wait_event;
MemSet(values, 0, sizeof(values));
MemSet(nulls, 0, sizeof(nulls));
@ -720,28 +726,28 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
nulls[3] = true;
if (TransactionIdIsValid(local_beentry->backend_xid))
values[14] = TransactionIdGetDatum(local_beentry->backend_xid);
else
nulls[14] = true;
if (TransactionIdIsValid(local_beentry->backend_xmin))
values[15] = TransactionIdGetDatum(local_beentry->backend_xmin);
values[15] = TransactionIdGetDatum(local_beentry->backend_xid);
else
nulls[15] = true;
if (TransactionIdIsValid(local_beentry->backend_xmin))
values[16] = TransactionIdGetDatum(local_beentry->backend_xmin);
else
nulls[16] = true;
if (beentry->st_ssl)
{
values[16] = BoolGetDatum(true); /* ssl */
values[17] = CStringGetTextDatum(beentry->st_sslstatus->ssl_version);
values[18] = CStringGetTextDatum(beentry->st_sslstatus->ssl_cipher);
values[19] = Int32GetDatum(beentry->st_sslstatus->ssl_bits);
values[20] = BoolGetDatum(beentry->st_sslstatus->ssl_compression);
values[21] = CStringGetTextDatum(beentry->st_sslstatus->ssl_clientdn);
values[17] = BoolGetDatum(true); /* ssl */
values[18] = CStringGetTextDatum(beentry->st_sslstatus->ssl_version);
values[19] = CStringGetTextDatum(beentry->st_sslstatus->ssl_cipher);
values[20] = Int32GetDatum(beentry->st_sslstatus->ssl_bits);
values[21] = BoolGetDatum(beentry->st_sslstatus->ssl_compression);
values[22] = CStringGetTextDatum(beentry->st_sslstatus->ssl_clientdn);
}
else
{
values[16] = BoolGetDatum(false); /* ssl */
nulls[17] = nulls[18] = nulls[19] = nulls[20] = nulls[21] = true;
values[17] = BoolGetDatum(false); /* ssl */
nulls[18] = nulls[19] = nulls[20] = nulls[21] = nulls[22] = true;
}
/* Values only available to role member */
@ -775,36 +781,48 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
}
values[5] = CStringGetTextDatum(beentry->st_activity);
values[6] = BoolGetDatum(beentry->st_waiting);
if (beentry->st_xact_start_timestamp != 0)
values[7] = TimestampTzGetDatum(beentry->st_xact_start_timestamp);
proc = BackendPidGetProc(beentry->st_procpid);
wait_event_type = pgstat_get_wait_event_type(proc->wait_event_info);
if (wait_event_type)
values[6] = CStringGetTextDatum(wait_event_type);
else
nulls[6] = true;
wait_event = pgstat_get_wait_event(proc->wait_event_info);
if (wait_event)
values[7] = CStringGetTextDatum(wait_event);
else
nulls[7] = true;
if (beentry->st_activity_start_timestamp != 0)
values[8] = TimestampTzGetDatum(beentry->st_activity_start_timestamp);
if (beentry->st_xact_start_timestamp != 0)
values[8] = TimestampTzGetDatum(beentry->st_xact_start_timestamp);
else
nulls[8] = true;
if (beentry->st_proc_start_timestamp != 0)
values[9] = TimestampTzGetDatum(beentry->st_proc_start_timestamp);
if (beentry->st_activity_start_timestamp != 0)
values[9] = TimestampTzGetDatum(beentry->st_activity_start_timestamp);
else
nulls[9] = true;
if (beentry->st_state_start_timestamp != 0)
values[10] = TimestampTzGetDatum(beentry->st_state_start_timestamp);
if (beentry->st_proc_start_timestamp != 0)
values[10] = TimestampTzGetDatum(beentry->st_proc_start_timestamp);
else
nulls[10] = true;
if (beentry->st_state_start_timestamp != 0)
values[11] = TimestampTzGetDatum(beentry->st_state_start_timestamp);
else
nulls[11] = 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[11] = true;
nulls[12] = true;
nulls[13] = true;
nulls[14] = true;
}
else
{
@ -828,20 +846,20 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
if (ret == 0)
{
clean_ipv6_addr(beentry->st_clientaddr.addr.ss_family, remote_host);
values[11] = DirectFunctionCall1(inet_in,
values[12] = DirectFunctionCall1(inet_in,
CStringGetDatum(remote_host));
if (beentry->st_clienthostname &&
beentry->st_clienthostname[0])
values[12] = CStringGetTextDatum(beentry->st_clienthostname);
values[13] = CStringGetTextDatum(beentry->st_clienthostname);
else
nulls[12] = true;
values[13] = Int32GetDatum(atoi(remote_port));
nulls[13] = true;
values[14] = Int32GetDatum(atoi(remote_port));
}
else
{
nulls[11] = true;
nulls[12] = true;
nulls[13] = true;
nulls[14] = true;
}
}
else if (beentry->st_clientaddr.addr.ss_family == AF_UNIX)
@ -852,16 +870,16 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
* connections we have no permissions to view, or with
* errors.
*/
nulls[11] = true;
nulls[12] = true;
values[13] = DatumGetInt32(-1);
nulls[13] = true;
values[14] = DatumGetInt32(-1);
}
else
{
/* Unknown address type, should never happen */
nulls[11] = true;
nulls[12] = true;
nulls[13] = true;
nulls[14] = true;
}
}
}
@ -878,6 +896,7 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
nulls[11] = true;
nulls[12] = true;
nulls[13] = true;
nulls[14] = true;
}
tuplestore_putvalues(tupstore, tupdesc, values, nulls);
@ -959,23 +978,52 @@ pg_stat_get_backend_activity(PG_FUNCTION_ARGS)
PG_RETURN_TEXT_P(cstring_to_text(activity));
}
Datum
pg_stat_get_backend_waiting(PG_FUNCTION_ARGS)
pg_stat_get_backend_wait_event_type(PG_FUNCTION_ARGS)
{
int32 beid = PG_GETARG_INT32(0);
bool result;
PgBackendStatus *beentry;
PGPROC *proc;
const char *wait_event_type;
if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
wait_event_type = "<backend information not available>";
else if (!has_privs_of_role(GetUserId(), beentry->st_userid))
wait_event_type = "<insufficient privilege>";
else
{
proc = BackendPidGetProc(beentry->st_procpid);
wait_event_type = pgstat_get_wait_event_type(proc->wait_event_info);
}
if (!wait_event_type)
PG_RETURN_NULL();
if (!has_privs_of_role(GetUserId(), beentry->st_userid))
PG_RETURN_TEXT_P(cstring_to_text(wait_event_type));
}
Datum
pg_stat_get_backend_wait_event(PG_FUNCTION_ARGS)
{
int32 beid = PG_GETARG_INT32(0);
PgBackendStatus *beentry;
PGPROC *proc;
const char *wait_event;
if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
wait_event = "<backend information not available>";
else if (!has_privs_of_role(GetUserId(), beentry->st_userid))
wait_event = "<insufficient privilege>";
else
{
proc = BackendPidGetProc(beentry->st_procpid);
wait_event = pgstat_get_wait_event(proc->wait_event_info);
}
if (!wait_event)
PG_RETURN_NULL();
result = beentry->st_waiting;
PG_RETURN_BOOL(result);
PG_RETURN_TEXT_P(cstring_to_text(wait_event));
}