diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml index e930731b162..9856968997e 100644 --- a/doc/src/sgml/monitoring.sgml +++ b/doc/src/sgml/monitoring.sgml @@ -620,8 +620,8 @@ postgres 27093 0.0 0.0 30096 2752 ? Ss 11:34 0:00 postgres: ser backend_start timestamp with time zone - Time when this process was started, i.e., when the - client connected to the server + Time when this process was started. For client backends, + this is the time the client connected to the server. @@ -797,6 +797,17 @@ postgres 27093 0.0 0.0 30096 2752 ? Ss 11:34 0:00 postgres: ser . + + backend_type + text + Type of current backend. Possible types are + autovacuum launcher, autovacuum worker, + background worker, background writer, + client backend, checkpointer, + startup, walreceiver, + walsender and walwriter. + + diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c index 6cfce4f8ddb..d8efdb5ed3d 100644 --- a/src/backend/bootstrap/bootstrap.c +++ b/src/backend/bootstrap/bootstrap.c @@ -387,6 +387,10 @@ AuxiliaryProcessMain(int argc, char *argv[]) /* finish setting up bufmgr.c */ InitBufferPoolBackend(); + /* Initialize backend status information */ + pgstat_initialize(); + pgstat_bestart(); + /* register a before-shutdown callback for LWLock cleanup */ before_shmem_exit(ShutdownAuxiliaryProcess, 0); } diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql index d8b762ee3fb..d357c8b8fdb 100644 --- a/src/backend/catalog/system_views.sql +++ b/src/backend/catalog/system_views.sql @@ -716,7 +716,8 @@ CREATE VIEW pg_stat_activity AS S.state, S.backend_xid, s.backend_xmin, - S.query + S.query, + S.backend_type FROM pg_stat_get_activity(NULL) AS S LEFT JOIN pg_database AS D ON (S.datid = D.oid) LEFT JOIN pg_authid AS U ON (S.usesysid = U.oid); diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c index b704788eb5a..869afd4c4a5 100644 --- a/src/backend/postmaster/pgstat.c +++ b/src/backend/postmaster/pgstat.c @@ -50,6 +50,7 @@ #include "postmaster/autovacuum.h" #include "postmaster/fork_process.h" #include "postmaster/postmaster.h" +#include "replication/walsender.h" #include "storage/backendid.h" #include "storage/dsm.h" #include "storage/fd.h" @@ -102,6 +103,18 @@ #define PGSTAT_FUNCTION_HASH_SIZE 512 +/* ---------- + * Total number of backends including auxiliary + * + * We reserve a slot for each possible BackendId, plus one for each + * possible auxiliary process type. (This scheme assumes there is not + * more than one of any auxiliary process type at a time.) MaxBackends + * includes autovacuum workers and background workers as well. + * ---------- + */ +#define NumBackendStatSlots (MaxBackends + NUM_AUXPROCTYPES) + + /* ---------- * GUC parameters * ---------- @@ -212,7 +225,11 @@ typedef struct TwoPhasePgStatRecord */ static MemoryContext pgStatLocalContext = NULL; static HTAB *pgStatDBHash = NULL; + +/* Status for backends including auxiliary */ static LocalPgBackendStatus *localBackendStatusTable = NULL; + +/* Total number of backends including auxiliary */ static int localNumBackends = 0; /* @@ -2505,20 +2522,20 @@ BackendStatusShmemSize(void) Size size; /* BackendStatusArray: */ - size = mul_size(sizeof(PgBackendStatus), MaxBackends); + size = mul_size(sizeof(PgBackendStatus), NumBackendStatSlots); /* BackendAppnameBuffer: */ size = add_size(size, - mul_size(NAMEDATALEN, MaxBackends)); + mul_size(NAMEDATALEN, NumBackendStatSlots)); /* BackendClientHostnameBuffer: */ size = add_size(size, - mul_size(NAMEDATALEN, MaxBackends)); + mul_size(NAMEDATALEN, NumBackendStatSlots)); /* BackendActivityBuffer: */ size = add_size(size, - mul_size(pgstat_track_activity_query_size, MaxBackends)); + mul_size(pgstat_track_activity_query_size, NumBackendStatSlots)); #ifdef USE_SSL /* BackendSslStatusBuffer: */ size = add_size(size, - mul_size(sizeof(PgBackendSSLStatus), MaxBackends)); + mul_size(sizeof(PgBackendSSLStatus), NumBackendStatSlots)); #endif return size; } @@ -2536,7 +2553,7 @@ CreateSharedBackendStatus(void) char *buffer; /* Create or attach to the shared array */ - size = mul_size(sizeof(PgBackendStatus), MaxBackends); + size = mul_size(sizeof(PgBackendStatus), NumBackendStatSlots); BackendStatusArray = (PgBackendStatus *) ShmemInitStruct("Backend Status Array", size, &found); @@ -2559,7 +2576,7 @@ CreateSharedBackendStatus(void) /* Initialize st_appname pointers. */ buffer = BackendAppnameBuffer; - for (i = 0; i < MaxBackends; i++) + for (i = 0; i < NumBackendStatSlots; i++) { BackendStatusArray[i].st_appname = buffer; buffer += NAMEDATALEN; @@ -2577,7 +2594,7 @@ CreateSharedBackendStatus(void) /* Initialize st_clienthostname pointers. */ buffer = BackendClientHostnameBuffer; - for (i = 0; i < MaxBackends; i++) + for (i = 0; i < NumBackendStatSlots; i++) { BackendStatusArray[i].st_clienthostname = buffer; buffer += NAMEDATALEN; @@ -2586,7 +2603,7 @@ CreateSharedBackendStatus(void) /* Create or attach to the shared activity buffer */ BackendActivityBufferSize = mul_size(pgstat_track_activity_query_size, - MaxBackends); + NumBackendStatSlots); BackendActivityBuffer = (char *) ShmemInitStruct("Backend Activity Buffer", BackendActivityBufferSize, @@ -2598,7 +2615,7 @@ CreateSharedBackendStatus(void) /* Initialize st_activity pointers. */ buffer = BackendActivityBuffer; - for (i = 0; i < MaxBackends; i++) + for (i = 0; i < NumBackendStatSlots; i++) { BackendStatusArray[i].st_activity = buffer; buffer += pgstat_track_activity_query_size; @@ -2607,7 +2624,7 @@ CreateSharedBackendStatus(void) #ifdef USE_SSL /* Create or attach to the shared SSL status buffer */ - size = mul_size(sizeof(PgBackendSSLStatus), MaxBackends); + size = mul_size(sizeof(PgBackendSSLStatus), NumBackendStatSlots); BackendSslStatusBuffer = (PgBackendSSLStatus *) ShmemInitStruct("Backend SSL Status Buffer", size, &found); @@ -2619,7 +2636,7 @@ CreateSharedBackendStatus(void) /* Initialize st_sslstatus pointers. */ ptr = BackendSslStatusBuffer; - for (i = 0; i < MaxBackends; i++) + for (i = 0; i < NumBackendStatSlots; i++) { BackendStatusArray[i].st_sslstatus = ptr; ptr++; @@ -2633,7 +2650,8 @@ CreateSharedBackendStatus(void) * pgstat_initialize() - * * Initialize pgstats state, and set up our on-proc-exit hook. - * Called from InitPostgres. MyBackendId must be set, + * Called from InitPostgres and AuxiliaryProcessMain. For auxiliary process, + * MyBackendId is invalid. Otherwise, MyBackendId must be set, * but we must not have started any transaction yet (since the * exit hook must run after the last transaction exit). * NOTE: MyDatabaseId isn't set yet; so the shutdown hook has to be careful. @@ -2643,8 +2661,26 @@ void pgstat_initialize(void) { /* Initialize MyBEEntry */ - Assert(MyBackendId >= 1 && MyBackendId <= MaxBackends); - MyBEEntry = &BackendStatusArray[MyBackendId - 1]; + if (MyBackendId != InvalidBackendId) + { + Assert(MyBackendId >= 1 && MyBackendId <= MaxBackends); + MyBEEntry = &BackendStatusArray[MyBackendId - 1]; + } + else + { + /* Must be an auxiliary process */ + Assert(MyAuxProcType != NotAnAuxProcess); + + /* + * Assign the MyBEEntry for an auxiliary process. Since it doesn't + * have a BackendId, the slot is statically allocated based on the + * auxiliary process type (MyAuxProcType). Backends use slots indexed + * in the range from 1 to MaxBackends (inclusive), so we use + * MaxBackends + AuxBackendType + 1 as the index of the slot for an + * auxiliary process. + */ + MyBEEntry = &BackendStatusArray[MaxBackends + MyAuxProcType]; + } /* Set up a process-exit hook to clean up */ on_shmem_exit(pgstat_beshutdown_hook, 0); @@ -2655,15 +2691,16 @@ pgstat_initialize(void) * * Initialize this backend's entry in the PgBackendStatus array. * Called from InitPostgres. - * MyDatabaseId, session userid, and application_name must be set - * (hence, this cannot be combined with pgstat_initialize). + * + * Apart from auxiliary processes, MyBackendId, MyDatabaseId, + * session userid, and application_name must be set for a + * backend (hence, this cannot be combined with pgstat_initialize). * ---------- */ void pgstat_bestart(void) { TimestampTz proc_start_timestamp; - Oid userid; SockAddr clientaddr; volatile PgBackendStatus *beentry; @@ -2678,7 +2715,6 @@ pgstat_bestart(void) proc_start_timestamp = MyProcPort->SessionStartTime; else proc_start_timestamp = GetCurrentTimestamp(); - userid = GetSessionUserId(); /* * We may not have a MyProcPort (eg, if this is the autovacuum process). @@ -2697,6 +2733,66 @@ pgstat_bestart(void) * cute. */ beentry = MyBEEntry; + + /* pgstats state must be initialized from pgstat_initialize() */ + Assert(beentry != NULL); + + if (MyBackendId != InvalidBackendId) + { + if (IsAutoVacuumLauncherProcess()) + { + /* Autovacuum Launcher */ + beentry->st_backendType = B_AUTOVAC_LAUNCHER; + } + else if (IsAutoVacuumWorkerProcess()) + { + /* Autovacuum Worker */ + beentry->st_backendType = B_AUTOVAC_WORKER; + } + else if (am_walsender) + { + /* Wal sender */ + beentry->st_backendType = B_WAL_SENDER; + } + else if (IsBackgroundWorker) + { + /* bgworker */ + beentry->st_backendType = B_BG_WORKER; + } + else + { + /* client-backend */ + beentry->st_backendType = B_BACKEND; + } + } + else + { + /* Must be an auxiliary process */ + Assert(MyAuxProcType != NotAnAuxProcess); + switch (MyAuxProcType) + { + case StartupProcess: + beentry->st_backendType = B_STARTUP; + break; + case BgWriterProcess: + beentry->st_backendType = B_BG_WRITER; + break; + case CheckpointerProcess: + beentry->st_backendType = B_CHECKPOINTER; + break; + case WalWriterProcess: + beentry->st_backendType = B_WAL_WRITER; + break; + case WalReceiverProcess: + beentry->st_backendType = B_WAL_RECEIVER; + break; + default: + elog(FATAL, "unrecognized process type: %d", + (int) MyAuxProcType); + proc_exit(1); + } + } + do { pgstat_increment_changecount_before(beentry); @@ -2708,7 +2804,15 @@ pgstat_bestart(void) beentry->st_state_start_timestamp = 0; beentry->st_xact_start_timestamp = 0; beentry->st_databaseid = MyDatabaseId; - beentry->st_userid = userid; + + /* We have userid for client-backends, wal-sender and bgworker processes */ + if (beentry->st_backendType == B_BACKEND + || beentry->st_backendType == B_WAL_SENDER + || beentry->st_backendType == B_BG_WORKER) + beentry->st_userid = GetSessionUserId(); + else + beentry->st_userid = InvalidOid; + beentry->st_clientaddr = clientaddr; if (MyProcPort && MyProcPort->remote_hostname) strlcpy(beentry->st_clienthostname, MyProcPort->remote_hostname, @@ -3046,24 +3150,24 @@ pgstat_read_current_status(void) localtable = (LocalPgBackendStatus *) MemoryContextAlloc(pgStatLocalContext, - sizeof(LocalPgBackendStatus) * MaxBackends); + sizeof(LocalPgBackendStatus) * NumBackendStatSlots); localappname = (char *) MemoryContextAlloc(pgStatLocalContext, - NAMEDATALEN * MaxBackends); + NAMEDATALEN * NumBackendStatSlots); localactivity = (char *) MemoryContextAlloc(pgStatLocalContext, - pgstat_track_activity_query_size * MaxBackends); + pgstat_track_activity_query_size * NumBackendStatSlots); #ifdef USE_SSL localsslstatus = (PgBackendSSLStatus *) MemoryContextAlloc(pgStatLocalContext, - sizeof(PgBackendSSLStatus) * MaxBackends); + sizeof(PgBackendSSLStatus) * NumBackendStatSlots); #endif localNumBackends = 0; beentry = BackendStatusArray; localentry = localtable; - for (i = 1; i <= MaxBackends; i++) + for (i = 1; i <= NumBackendStatSlots; i++) { /* * Follow the protocol of retrying if st_changecount changes while we @@ -3829,7 +3933,47 @@ pgstat_get_crashed_backend_activity(int pid, char *buffer, int buflen) return NULL; } +const char * +pgstat_get_backend_desc(BackendType backendType) +{ + const char *backendDesc = "unknown process type"; + switch (backendType) + { + case B_AUTOVAC_LAUNCHER: + backendDesc = "autovacuum launcher"; + break; + case B_AUTOVAC_WORKER: + backendDesc = "autovacuum worker"; + break; + case B_BACKEND: + backendDesc = "client backend"; + break; + case B_BG_WORKER: + backendDesc = "background worker"; + break; + case B_BG_WRITER: + backendDesc = "background writer"; + break; + case B_CHECKPOINTER: + backendDesc = "checkpointer"; + break; + case B_STARTUP: + backendDesc = "startup"; + break; + case B_WAL_RECEIVER: + backendDesc = "walreceiver"; + break; + case B_WAL_SENDER: + backendDesc = "walsender"; + break; + case B_WAL_WRITER: + backendDesc = "walwriter"; + break; + } + + return backendDesc; +} /* ------------------------------------------------------------ * Local support functions follow * ------------------------------------------------------------ diff --git a/src/backend/postmaster/startup.c b/src/backend/postmaster/startup.c index b172b5e5d78..b6232524750 100644 --- a/src/backend/postmaster/startup.c +++ b/src/backend/postmaster/startup.c @@ -25,6 +25,7 @@ #include "access/xlog.h" #include "libpq/pqsignal.h" #include "miscadmin.h" +#include "pgstat.h" #include "postmaster/startup.h" #include "storage/ipc.h" #include "storage/latch.h" diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c index 040ad7b7371..cfc3fba1b7d 100644 --- a/src/backend/replication/walsender.c +++ b/src/backend/replication/walsender.c @@ -2011,8 +2011,8 @@ WalSndLoop(WalSndSendDataCallback send_data) last_reply_timestamp = GetCurrentTimestamp(); waiting_for_ping_response = false; - /* Report to pgstat that this process is a WAL sender */ - pgstat_report_activity(STATE_RUNNING, "walsender"); + /* Report to pgstat that this process is running */ + pgstat_report_activity(STATE_RUNNING, NULL); /* * Loop until we reach the end of this timeline or the client requests to diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 8f467bef504..3e716b1c6c7 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -941,6 +941,33 @@ AuxiliaryProcKill(int code, Datum arg) SpinLockRelease(ProcStructLock); } +/* + * AuxiliaryPidGetProc -- get PGPROC for an auxiliary process + * given its PID + * + * Returns NULL if not found. + */ +PGPROC * +AuxiliaryPidGetProc(int pid) +{ + PGPROC *result = NULL; + int index; + + if (pid == 0) /* never match dummy PGPROCs */ + return NULL; + + for (index = 0; index < NUM_AUXILIARY_PROCS; index++) + { + PGPROC *proc = &AuxiliaryProcs[index]; + + if (proc->pid == pid) + { + result = proc; + break; + } + } + return result; +} /* * ProcQueue package: routines for putting processes to sleep diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c index a987d0d6214..dd2b924d0af 100644 --- a/src/backend/utils/adt/pgstatfuncs.c +++ b/src/backend/utils/adt/pgstatfuncs.c @@ -20,6 +20,7 @@ #include "funcapi.h" #include "miscadmin.h" #include "pgstat.h" +#include "postmaster/postmaster.h" #include "storage/proc.h" #include "storage/procarray.h" #include "utils/acl.h" @@ -538,7 +539,7 @@ pg_stat_get_progress_info(PG_FUNCTION_ARGS) Datum pg_stat_get_activity(PG_FUNCTION_ARGS) { -#define PG_STAT_GET_ACTIVITY_COLS 23 +#define PG_STAT_GET_ACTIVITY_COLS 24 int num_backends = pgstat_fetch_stat_numbackends(); int curr_backend; int pid = PG_ARGISNULL(0) ? -1 : PG_GETARG_INT32(0); @@ -582,8 +583,8 @@ pg_stat_get_activity(PG_FUNCTION_ARGS) LocalPgBackendStatus *local_beentry; PgBackendStatus *beentry; PGPROC *proc; - const char *wait_event_type; - const char *wait_event; + const char *wait_event_type = NULL; + const char *wait_event = NULL; MemSet(values, 0, sizeof(values)); MemSet(nulls, 0, sizeof(nulls)); @@ -615,9 +616,18 @@ pg_stat_get_activity(PG_FUNCTION_ARGS) continue; /* Values available to all callers */ - values[0] = ObjectIdGetDatum(beentry->st_databaseid); + if (beentry->st_databaseid != InvalidOid) + values[0] = ObjectIdGetDatum(beentry->st_databaseid); + else + nulls[0] = true; + values[1] = Int32GetDatum(beentry->st_procpid); - values[2] = ObjectIdGetDatum(beentry->st_userid); + + if (beentry->st_userid != InvalidOid) + values[2] = ObjectIdGetDatum(beentry->st_userid); + else + nulls[2] = true; + if (beentry->st_appname) values[3] = CStringGetTextDatum(beentry->st_appname); else @@ -635,17 +645,17 @@ pg_stat_get_activity(PG_FUNCTION_ARGS) if (beentry->st_ssl) { - 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); + values[18] = BoolGetDatum(true); /* ssl */ + values[19] = CStringGetTextDatum(beentry->st_sslstatus->ssl_version); + values[20] = CStringGetTextDatum(beentry->st_sslstatus->ssl_cipher); + values[21] = Int32GetDatum(beentry->st_sslstatus->ssl_bits); + values[22] = BoolGetDatum(beentry->st_sslstatus->ssl_compression); + values[23] = CStringGetTextDatum(beentry->st_sslstatus->ssl_clientdn); } else { - values[17] = BoolGetDatum(false); /* ssl */ - nulls[18] = nulls[19] = nulls[20] = nulls[21] = nulls[22] = true; + values[18] = BoolGetDatum(false); /* ssl */ + nulls[19] = nulls[20] = nulls[21] = nulls[22] = nulls[23] = true; } /* Values only available to role member */ @@ -690,10 +700,24 @@ pg_stat_get_activity(PG_FUNCTION_ARGS) wait_event = pgstat_get_wait_event(raw_wait_event); } - else + else if (beentry->st_backendType != B_BACKEND) { - wait_event_type = NULL; - wait_event = NULL; + /* + * For an auxiliary process, retrieve process info from + * AuxiliaryProcs stored in shared-memory. + */ + proc = AuxiliaryPidGetProc(beentry->st_procpid); + + if (proc != NULL) + { + uint32 raw_wait_event; + + raw_wait_event = + UINT32_ACCESS_ONCE(proc->wait_event_info); + wait_event_type = + pgstat_get_wait_event_type(raw_wait_event); + wait_event = pgstat_get_wait_event(raw_wait_event); + } } if (wait_event_type) @@ -793,6 +817,9 @@ pg_stat_get_activity(PG_FUNCTION_ARGS) nulls[14] = true; } } + /* Add backend type */ + values[17] = + CStringGetTextDatum(pgstat_get_backend_desc(beentry->st_backendType)); } else { @@ -808,6 +835,7 @@ pg_stat_get_activity(PG_FUNCTION_ARGS) nulls[12] = true; nulls[13] = true; nulls[14] = true; + nulls[17] = true; } tuplestore_putvalues(tupstore, tupdesc, values, nulls); diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c index 9f938f2d270..b8b4a06350c 100644 --- a/src/backend/utils/init/postinit.c +++ b/src/backend/utils/init/postinit.c @@ -665,7 +665,12 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username, /* The autovacuum launcher is done here */ if (IsAutoVacuumLauncherProcess()) + { + /* report this backend in the PgBackendStatus array */ + pgstat_bestart(); + return; + } /* * Start a new transaction here before first access to db, and get a @@ -874,7 +879,10 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username, * transaction we started before returning. */ if (!bootstrap) + { + pgstat_bestart(); CommitTransactionCommand(); + } return; } diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index b8fa18ae2ea..fc374d79c8b 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 201703242 +#define CATALOG_VERSION_NO 201703261 #endif diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index ee67459c32e..79f9b9012e2 100644 --- a/src/include/catalog/pg_proc.h +++ b/src/include/catalog/pg_proc.h @@ -2811,7 +2811,7 @@ 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 f t t s r 0 0 23 "" _null_ _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 f t s r 1 0 2249 "23" "{23,26,23,26,25,25,25,25,25,1184,1184,1184,1184,869,25,23,28,28,16,25,25,23,16,25}" "{i,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}" "{pid,datid,pid,usesysid,application_name,state,query,wait_event_type,wait_event,xact_start,query_start,backend_start,state_change,client_addr,client_hostname,client_port,backend_xid,backend_xmin,ssl,sslversion,sslcipher,sslbits,sslcompression,sslclientdn}" _null_ _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 f t s r 1 0 2249 "23" "{23,26,23,26,25,25,25,25,25,1184,1184,1184,1184,869,25,23,28,28,25,16,25,25,23,16,25}" "{i,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}" "{pid,datid,pid,usesysid,application_name,state,query,wait_event_type,wait_event,xact_start,query_start,backend_start,state_change,client_addr,client_hostname,client_port,backend_xid,backend_xmin,backend_type,ssl,sslversion,sslcipher,sslbits,sslcompression,sslclientdn}" _null_ _null_ pg_stat_get_activity _null_ _null_ _null_ )); DESCR("statistics: information about currently active backends"); DATA(insert OID = 3318 ( pg_stat_get_progress_info PGNSP PGUID 12 1 100 0 0 f f f f t t s r 1 0 2249 "25" "{25,23,26,26,20,20,20,20,20,20,20,20,20,20}" "{i,o,o,o,o,o,o,o,o,o,o,o,o,o}" "{cmdtype,pid,datid,relid,param1,param2,param3,param4,param5,param6,param7,param8,param9,param10}" _null_ _null_ pg_stat_get_progress_info _null_ _null_ _null_ )); DESCR("statistics: information about progress of backends running maintenance command"); diff --git a/src/include/pgstat.h b/src/include/pgstat.h index 201562521f7..e29397f25b8 100644 --- a/src/include/pgstat.h +++ b/src/include/pgstat.h @@ -695,6 +695,25 @@ typedef struct PgStat_GlobalStats } PgStat_GlobalStats; +/* ---------- + * Backend types + * ---------- + */ +typedef enum BackendType +{ + B_AUTOVAC_LAUNCHER, + B_AUTOVAC_WORKER, + B_BACKEND, + B_BG_WORKER, + B_BG_WRITER, + B_CHECKPOINTER, + B_STARTUP, + B_WAL_RECEIVER, + B_WAL_SENDER, + B_WAL_WRITER +} BackendType; + + /* ---------- * Backend states * ---------- @@ -927,6 +946,9 @@ typedef struct PgBackendSSLStatus * showing its current activity. (The structs are allocated according to * BackendId, but that is not critical.) Note that the collector process * has no involvement in, or even access to, these structs. + * + * Each auxiliary process also maintains a PgBackendStatus struct in shared + * memory. * ---------- */ typedef struct PgBackendStatus @@ -951,6 +973,9 @@ typedef struct PgBackendStatus /* The entry is valid iff st_procpid > 0, unused if st_procpid == 0 */ int st_procpid; + /* Type of backends */ + BackendType st_backendType; + /* Times when current backend, transaction, and activity started */ TimestampTz st_proc_start_timestamp; TimestampTz st_xact_start_timestamp; @@ -1149,6 +1174,7 @@ extern const char *pgstat_get_wait_event_type(uint32 wait_event_info); extern const char *pgstat_get_backend_current_activity(int pid, bool checkUser); extern const char *pgstat_get_crashed_backend_activity(int pid, char *buffer, int buflen); +extern const char *pgstat_get_backend_desc(BackendType backendType); extern void pgstat_progress_start_command(ProgressCommandType cmdtype, Oid relid); diff --git a/src/include/storage/proc.h b/src/include/storage/proc.h index 1b345faa2dc..1a125d83f40 100644 --- a/src/include/storage/proc.h +++ b/src/include/storage/proc.h @@ -272,7 +272,6 @@ extern PGPROC *PreparedXactProcs; */ #define NUM_AUXILIARY_PROCS 4 - /* configurable options */ extern int DeadlockTimeout; extern int StatementTimeout; @@ -309,6 +308,8 @@ extern void LockErrorCleanup(void); extern void ProcWaitForSignal(uint32 wait_event_info); extern void ProcSendSignal(int pid); +extern PGPROC *AuxiliaryPidGetProc(int pid); + extern void BecomeLockGroupLeader(void); extern bool BecomeLockGroupMember(PGPROC *leader, int pid); diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out index e8f8726c537..71121c86634 100644 --- a/src/test/regress/expected/rules.out +++ b/src/test/regress/expected/rules.out @@ -1727,8 +1727,9 @@ pg_stat_activity| SELECT s.datid, s.state, s.backend_xid, s.backend_xmin, - s.query - FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, ssl, sslversion, sslcipher, sslbits, sslcompression, sslclientdn) + s.query, + s.backend_type + FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, sslcompression, sslclientdn) LEFT JOIN pg_database d ON ((s.datid = d.oid))) LEFT JOIN pg_authid u ON ((s.usesysid = u.oid))); pg_stat_all_indexes| SELECT c.oid AS relid, @@ -1859,7 +1860,7 @@ pg_stat_replication| SELECT s.pid, w.replay_lag, w.sync_priority, w.sync_state - FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, ssl, sslversion, sslcipher, sslbits, sslcompression, sslclientdn) + FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, sslcompression, sslclientdn) JOIN pg_stat_get_wal_senders() w(pid, state, sent_location, write_location, flush_location, replay_location, write_lag, flush_lag, replay_lag, sync_priority, sync_state) ON ((s.pid = w.pid))) LEFT JOIN pg_authid u ON ((s.usesysid = u.oid))); pg_stat_ssl| SELECT s.pid, @@ -1869,7 +1870,7 @@ pg_stat_ssl| SELECT s.pid, s.sslbits AS bits, s.sslcompression AS compression, s.sslclientdn AS clientdn - FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, ssl, sslversion, sslcipher, sslbits, sslcompression, sslclientdn); + FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, sslcompression, sslclientdn); pg_stat_subscription| SELECT su.oid AS subid, su.subname, st.pid,