diff options
author | Robert Haas <rhaas@postgresql.org> | 2014-02-25 12:34:04 -0500 |
---|---|---|
committer | Robert Haas <rhaas@postgresql.org> | 2014-02-25 12:34:04 -0500 |
commit | dd1a3bccca241a998b4ebf39d67202698e5fa599 (patch) | |
tree | ac25477cab559d842e406a1f6ba878257c694dc4 /src/backend | |
parent | 278c94209b90b8e241f64ea4ce2d955b63b1f5d7 (diff) | |
download | postgresql-dd1a3bccca241a998b4ebf39d67202698e5fa599.tar.gz postgresql-dd1a3bccca241a998b4ebf39d67202698e5fa599.zip |
Show xid and xmin in pg_stat_activity and pg_stat_replication.
Christian Kruse, reviewed by Andres Freund and myself, with further
minor adjustments by me.
Diffstat (limited to 'src/backend')
-rw-r--r-- | src/backend/catalog/system_views.sql | 3 | ||||
-rw-r--r-- | src/backend/postmaster/pgstat.c | 50 | ||||
-rw-r--r-- | src/backend/storage/ipc/sinvaladt.c | 32 | ||||
-rw-r--r-- | src/backend/utils/adt/pgstatfuncs.c | 27 |
4 files changed, 96 insertions, 16 deletions
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql index a7c6a4e094b..04dfbb0ee54 100644 --- a/src/backend/catalog/system_views.sql +++ b/src/backend/catalog/system_views.sql @@ -586,6 +586,8 @@ CREATE VIEW pg_stat_activity AS S.state_change, S.waiting, S.state, + S.backend_xid, + s.backend_xmin, S.query FROM pg_database D, pg_stat_get_activity(NULL) AS S, pg_authid U WHERE S.datid = D.oid AND @@ -601,6 +603,7 @@ CREATE VIEW pg_stat_replication AS S.client_hostname, S.client_port, S.backend_start, + S.backend_xmin, W.state, W.sent_location, W.write_location, diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c index 305d1269124..06ea5880859 100644 --- a/src/backend/postmaster/pgstat.c +++ b/src/backend/postmaster/pgstat.c @@ -48,12 +48,14 @@ #include "postmaster/autovacuum.h" #include "postmaster/fork_process.h" #include "postmaster/postmaster.h" +#include "storage/proc.h" #include "storage/backendid.h" #include "storage/fd.h" #include "storage/ipc.h" #include "storage/latch.h" #include "storage/pg_shmem.h" #include "storage/procsignal.h" +#include "storage/sinvaladt.h" #include "utils/ascii.h" #include "utils/guc.h" #include "utils/memutils.h" @@ -213,7 +215,7 @@ typedef struct TwoPhasePgStatRecord */ static MemoryContext pgStatLocalContext = NULL; static HTAB *pgStatDBHash = NULL; -static PgBackendStatus *localBackendStatusTable = NULL; +static LocalPgBackendStatus *localBackendStatusTable = NULL; static int localNumBackends = 0; /* @@ -2306,6 +2308,28 @@ pgstat_fetch_stat_beentry(int beid) if (beid < 1 || beid > localNumBackends) return NULL; + return &localBackendStatusTable[beid - 1].backendStatus; +} + + +/* ---------- + * pgstat_fetch_stat_local_beentry() - + * + * Like pgstat_fetch_stat_beentry() but with locally computed addtions (like + * xid and xmin values of the backend) + * + * NB: caller is responsible for a check if the user is permitted to see + * this info (especially the querystring). + * ---------- + */ +LocalPgBackendStatus * +pgstat_fetch_stat_local_beentry(int beid) +{ + pgstat_read_current_status(); + + if (beid < 1 || beid > localNumBackends) + return NULL; + return &localBackendStatusTable[beid - 1]; } @@ -2783,8 +2807,8 @@ static void pgstat_read_current_status(void) { volatile PgBackendStatus *beentry; - PgBackendStatus *localtable; - PgBackendStatus *localentry; + LocalPgBackendStatus *localtable; + LocalPgBackendStatus *localentry; char *localappname, *localactivity; int i; @@ -2795,9 +2819,9 @@ pgstat_read_current_status(void) pgstat_setup_memcxt(); - localtable = (PgBackendStatus *) + localtable = (LocalPgBackendStatus *) MemoryContextAlloc(pgStatLocalContext, - sizeof(PgBackendStatus) * MaxBackends); + sizeof(LocalPgBackendStatus) * MaxBackends); localappname = (char *) MemoryContextAlloc(pgStatLocalContext, NAMEDATALEN * MaxBackends); @@ -2821,19 +2845,19 @@ pgstat_read_current_status(void) { int save_changecount = beentry->st_changecount; - localentry->st_procpid = beentry->st_procpid; - if (localentry->st_procpid > 0) + localentry->backendStatus.st_procpid = beentry->st_procpid; + if (localentry->backendStatus.st_procpid > 0) { - memcpy(localentry, (char *) beentry, sizeof(PgBackendStatus)); + memcpy(&localentry->backendStatus, (char *) beentry, sizeof(PgBackendStatus)); /* * strcpy is safe even if the string is modified concurrently, * because there's always a \0 at the end of the buffer. */ strcpy(localappname, (char *) beentry->st_appname); - localentry->st_appname = localappname; + localentry->backendStatus.st_appname = localappname; strcpy(localactivity, (char *) beentry->st_activity); - localentry->st_activity = localactivity; + localentry->backendStatus.st_activity = localactivity; } if (save_changecount == beentry->st_changecount && @@ -2846,8 +2870,12 @@ pgstat_read_current_status(void) beentry++; /* Only valid entries get included into the local array */ - if (localentry->st_procpid > 0) + if (localentry->backendStatus.st_procpid > 0) { + BackendIdGetTransactionIds(i, + &localentry->backend_xid, + &localentry->backend_xmin); + localentry++; localappname += NAMEDATALEN; localactivity += pgstat_track_activity_query_size; diff --git a/src/backend/storage/ipc/sinvaladt.c b/src/backend/storage/ipc/sinvaladt.c index e7c3fb2f548..e6805d96b1c 100644 --- a/src/backend/storage/ipc/sinvaladt.c +++ b/src/backend/storage/ipc/sinvaladt.c @@ -25,6 +25,7 @@ #include "storage/shmem.h" #include "storage/sinvaladt.h" #include "storage/spin.h" +#include "access/transam.h" /* @@ -401,6 +402,37 @@ BackendIdGetProc(int backendID) } /* + * BackendIdGetTransactionIds + * Get the xid and xmin of the backend. The result may be out of date + * arbitrarily quickly, so the caller must be careful about how this + * information is used. + */ +void +BackendIdGetTransactionIds(int backendID, TransactionId *xid, TransactionId *xmin) +{ + ProcState *stateP; + SISeg *segP = shmInvalBuffer; + PGXACT *xact; + + *xid = InvalidTransactionId; + *xmin = InvalidTransactionId; + + /* Need to lock out additions/removals of backends */ + LWLockAcquire(SInvalWriteLock, LW_SHARED); + + if (backendID > 0 && backendID <= segP->lastBackend) + { + stateP = &segP->procState[backendID - 1]; + xact = &ProcGlobal->allPgXact[stateP->proc->pgprocno]; + + *xid = xact->xid; + *xmin = xact->xmin; + } + + LWLockRelease(SInvalWriteLock); +} + +/* * SIInsertDataEntries * Add new invalidation message(s) to the buffer. */ diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c index a4f31cfc7fc..140704f97ca 100644 --- a/src/backend/utils/adt/pgstatfuncs.c +++ b/src/backend/utils/adt/pgstatfuncs.c @@ -536,7 +536,7 @@ pg_stat_get_activity(PG_FUNCTION_ARGS) oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); - tupdesc = CreateTemplateTupleDesc(14, false); + tupdesc = CreateTemplateTupleDesc(16, false); TupleDescInitEntry(tupdesc, (AttrNumber) 1, "datid", OIDOID, -1, 0); TupleDescInitEntry(tupdesc, (AttrNumber) 2, "pid", @@ -565,6 +565,10 @@ pg_stat_get_activity(PG_FUNCTION_ARGS) TEXTOID, -1, 0); TupleDescInitEntry(tupdesc, (AttrNumber) 14, "client_port", INT4OID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 15, "backend_xid", + XIDOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 16, "backend_xmin", + XIDOID, -1, 0); funcctx->tuple_desc = BlessTupleDesc(tupdesc); @@ -616,9 +620,10 @@ pg_stat_get_activity(PG_FUNCTION_ARGS) if (funcctx->call_cntr < funcctx->max_calls) { /* for each row */ - Datum values[14]; - bool nulls[14]; + Datum values[16]; + bool nulls[16]; HeapTuple tuple; + LocalPgBackendStatus *local_beentry; PgBackendStatus *beentry; MemSet(values, 0, sizeof(values)); @@ -627,12 +632,14 @@ pg_stat_get_activity(PG_FUNCTION_ARGS) if (*(int *) (funcctx->user_fctx) > 0) { /* Get specific pid slot */ - beentry = pgstat_fetch_stat_beentry(*(int *) (funcctx->user_fctx)); + local_beentry = pgstat_fetch_stat_local_beentry(*(int *) (funcctx->user_fctx)); + beentry = &local_beentry->backendStatus; } else { /* Get the next one in the list */ - beentry = pgstat_fetch_stat_beentry(funcctx->call_cntr + 1); /* 1-based index */ + local_beentry = pgstat_fetch_stat_local_beentry(funcctx->call_cntr + 1); /* 1-based index */ + beentry = &local_beentry->backendStatus; } if (!beentry) { @@ -657,6 +664,16 @@ pg_stat_get_activity(PG_FUNCTION_ARGS) else 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); + else + nulls[15] = true; + /* Values only available to same user or superuser */ if (superuser() || beentry->st_userid == GetUserId()) { |