3 * Backend status reporting infrastructure.
5 * Copyright (c) 2001-2025, PostgreSQL Global Development Group
9 * src/backend/utils/activity/backend_status.c
28 * Total number of backends including auxiliary
30 * We reserve a slot for each possible PGPROC entry, including aux processes.
31 * (But not including PGPROC entries reserved for prepared xacts; they are not
35 #define NumBackendStatSlots (MaxBackends + NUM_AUXILIARY_PROCS)
46/* exposed so that backend_progress.c can access it */
63/* Status for backends including auxiliary */
66/* Total number of backends including auxiliary */
78 * Report shared-memory space needed by BackendStatusShmemInit.
85 /* BackendStatusArray: */
87 /* BackendAppnameBuffer: */
90 /* BackendClientHostnameBuffer: */
93 /* BackendActivityBuffer: */
97 /* BackendSslStatusBuffer: */
102 /* BackendGssStatusBuffer: */
110 * Initialize the shared status array and several string buffers
111 * during postmaster startup.
121 /* Create or attach to the shared array */
129 * We're the first - initialize.
134 /* Create or attach to the shared appname buffer */
143 /* Initialize st_appname pointers. */
152 /* Create or attach to the shared client hostname buffer */
161 /* Initialize st_clienthostname pointers. */
170 /* Create or attach to the shared activity buffer */
182 /* Initialize st_activity pointers. */
192 /* Create or attach to the shared SSL status buffer */
201 MemSet(BackendSslStatusBuffer, 0, size);
203 /* Initialize st_sslstatus pointers. */
204 ptr = BackendSslStatusBuffer;
214 /* Create or attach to the shared GSSAPI status buffer */
223 MemSet(BackendGssStatusBuffer, 0, size);
225 /* Initialize st_gssstatus pointers. */
226 ptr = BackendGssStatusBuffer;
237 * Initialize pgstats backend activity state, and set up our on-proc-exit
238 * hook. Called from InitPostgres and AuxiliaryProcessMain. MyProcNumber must
239 * be set, but we must not have started any transaction yet (since the exit
240 * hook must run after the last transaction exit).
242 * NOTE: MyDatabaseId isn't set yet; so the shutdown hook has to be careful.
247 /* Initialize MyBEEntry */
252 /* Set up a process-exit hook to clean up */
258 * pgstat_bestart_initial() -
260 * Initialize this backend's entry in the PgBackendStatus array. Called
261 * from InitPostgres and AuxiliaryProcessMain.
263 * Clears out a new pgstat entry, initializing it to suitable defaults and
264 * reporting STATE_STARTING. Backends should continue filling in any
265 * transport security details as needed with pgstat_bestart_security(), and
266 * must finally exit STATE_STARTING by calling pgstat_bestart_final().
275 /* pgstats state must be initialized from pgstat_beinit() */
279 * To minimize the time spent modifying the PgBackendStatus entry, and
280 * avoid risk of errors inside the critical section, we first copy the
281 * shared-memory struct to a local variable, then modify the data in the
282 * local variable, then copy the local variable back to shared memory.
283 * Only the last step has to be inside the critical section.
285 * Most of the data we copy from shared memory is just going to be
286 * overwritten, but the struct's not so large that it's worth the
287 * maintenance hassle to copy only the needful fields.
294 * Now fill in all the fields of lbeentry, except for strings that are
295 * out-of-line data. Those have to be handled separately, below.
307 * We may not have a MyProcPort (eg, if this is the autovacuum process).
308 * If so, use all-zeroes client address, which is dealt with specially in
309 * pg_stat_get_backend_client_addr and pg_stat_get_backend_client_port.
327 * we don't zero st_progress_param here to save cycles; nobody should
328 * examine it until st_progress_command has been set to something other
329 * than PROGRESS_COMMAND_INVALID
333 * We're ready to enter the critical section that fills the shared-memory
334 * status entry. We follow the protocol of bumping st_changecount before
335 * and after; and make sure it's even afterwards. We use a volatile
336 * pointer here to ensure the compiler doesn't try to get cute.
340 /* make sure we'll memcpy the same st_changecount back */
348 * We can write the out-of-line strings and structs using the pointers
349 * that are in lbeentry; this saves some de-volatilizing messiness.
358 /* Also make sure the last byte in each string area is always 0 */
363 /* These structs can just start from zeroes each time */
375 * pgstat_bestart_security() -
377 * Fill in SSL and GSS information for the pgstat entry. This is the second
378 * optional step taken when filling a backend's entry, not required for
379 * auxiliary processes.
381 * This should only be called from backends with a MyProcPort.
399 /* pgstats state must be initialized from pgstat_beinit() */
405 memset(&lsslstatus, 0,
sizeof(lsslstatus));
421 memset(&lgssstatus, 0,
sizeof(lgssstatus));
437 * Update my status entry, following the protocol of bumping
438 * st_changecount before and after. We use a volatile pointer here to
439 * ensure the compiler doesn't try to get cute.
457 * pgstat_bestart_final() -
459 * Finalizes the state of this backend's entry by filling in the user and
460 * database IDs, clearing STATE_STARTING, and reporting the application_name.
462 * We must be inside a transaction if this is not an auxiliary process, as
463 * we may need to do encoding conversion.
472 /* pgstats state must be initialized from pgstat_beinit() */
475 /* We have userid for client-backends, wal-sender and bgworker processes */
484 * Update my status entry, following the protocol of bumping
485 * st_changecount before and after. We use a volatile pointer here to
486 * ensure the compiler doesn't try to get cute.
496 /* Create the backend statistics entry */
500 /* Update app name to current GUC setting */
506 * Clear out our entry in the PgBackendStatus array.
514 * Clear my status entry, following the protocol of bumping st_changecount
515 * before and after. We use a volatile pointer here to ensure the
516 * compiler doesn't try to get cute.
524 /* so that functions can check if backend_status.c is up via MyBEEntry */
529 * Discard any data collected in the current transaction. Any subsequent
530 * request will cause new snapshots to be read.
532 * This is also invoked during transaction commit or abort to discard the
533 * no-longer-wanted snapshot.
538 /* Release memory, if any was allocated */
545 /* Reset variables */
555 "Backend Status Snapshot",
561 * pgstat_report_activity() -
563 * Called from tcop/postgres.c to report what the backend is actually doing
564 * (but note cmd_str can be NULL for certain cases).
566 * All updates of the status entry follow the protocol of bumping
567 * st_changecount before and after. We use a volatile pointer here to
568 * ensure the compiler doesn't try to get cute.
579 TRACE_POSTGRESQL_STATEMENT_STATUS(cmd_str);
591 * track_activities is disabled, but we last reported a
592 * non-disabled state. As our final update, change the state and
593 * clear fields we will not be updating anymore.
600 /* st_xact_start_timestamp and wait_event_info are also disabled */
611 * To minimize the time spent modifying the entry, and avoid risk of
612 * errors inside the critical section, fetch all the needed data first.
618 * Compute length of to-be-stored string unaware of multi-byte
619 * characters. For speed reasons that'll get corrected on read, rather
620 * than computed every write.
627 * If the state has changed from "active" or "idle in transaction",
628 * calculate the duration.
651 * Now update the status entry
659 * If a new query is started, we reset the query identifier as it'll only
660 * be known after parse analysis, to avoid reporting last query's
680 * pgstat_report_query_id() -
682 * Called to update top-level query identifier.
691 * if track_activities is disabled, st_query_id should already have been
698 * We only report the top-level query identifiers. The stored query_id is
699 * reset when a backend calls pgstat_report_activity(STATE_RUNNING), or
700 * with an explicit call to this function using the force flag. If the
701 * saved query identifier is not zero it means that it's not a top-level
702 * command, so ignore the one provided unless it's an explicit call to
703 * reset the identifier.
709 * Update my status entry, following the protocol of bumping
710 * st_changecount before and after. We use a volatile pointer here to
711 * ensure the compiler doesn't try to get cute.
719 * pgstat_report_plan_id() -
721 * Called to update top-level plan identifier.
730 * if track_activities is disabled, st_plan_id should already have been
737 * We only report the top-level plan identifiers. The stored plan_id is
738 * reset when a backend calls pgstat_report_activity(STATE_RUNNING), or
739 * with an explicit call to this function using the force flag. If the
740 * saved plan identifier is not zero it means that it's not a top-level
741 * command, so ignore the one provided unless it's an explicit call to
742 * reset the identifier.
748 * Update my status entry, following the protocol of bumping
749 * st_changecount before and after. We use a volatile pointer here to
750 * ensure the compiler doesn't try to get cute.
758 * pgstat_report_appname() -
760 * Called to update our application name.
772 /* This should be unnecessary if GUC did its job, but be safe */
776 * Update my status entry, following the protocol of bumping
777 * st_changecount before and after. We use a volatile pointer here to
778 * ensure the compiler doesn't try to get cute.
789 * Report current transaction start timestamp as the specified value.
790 * Zero means there is no active transaction.
801 * Update my status entry, following the protocol of bumping
802 * st_changecount before and after. We use a volatile pointer here to
803 * ensure the compiler doesn't try to get cute.
813 * pgstat_read_current_status() -
815 * Copy the current contents of the PgBackendStatus array to local memory,
816 * if not already done in this transaction.
826 *localclienthostname,
837 return;
/* already done */
842 * Allocate storage for local copy of state data. We can presume that
843 * none of these requests overflow size_t, because we already calculated
844 * the same values using mul_size during shmem setup. However, with
845 * probably-silly values of pgstat_track_activity_query_size and
846 * max_connections, the localactivity buffer could exceed 1GB, so use
847 * "huge" allocation for that one.
852 localappname = (
char *)
855 localclienthostname = (
char *)
858 localactivity = (
char *)
876 localentry = localtable;
880 * Follow the protocol of retrying if st_changecount changes while we
881 * copy the entry, or if it's odd. (The check for odd is needed to
882 * cover the case where we are able to completely copy the entry while
883 * the source backend is between increment steps.) We use a volatile
884 * pointer here to ensure the compiler doesn't try to get cute.
888 int before_changecount;
889 int after_changecount;
894 /* Skip all the data-copying work if entry is not in use */
900 * For each PgBackendStatus field that is a pointer, copy the
901 * pointed-to data, then adjust the local copy of the pointer
902 * field to point at the local copy of the data.
904 * strcpy is safe even if the string is modified concurrently,
905 * because there's always a 0円 at the end of the buffer.
935 /* Make sure we can break out of loop if stuck... */
939 /* Only valid entries get included into the local array */
943 * The BackendStatusArray index is exactly the ProcNumber of the
944 * source backend. Note that this means localBackendStatusTable
945 * is in order by proc_number. pgstat_get_beentry_by_proc_number()
971 /* Set the pointer only after completion of a valid table */
977 * pgstat_get_backend_current_activity() -
979 * Return a string representing the current activity of the backend with
980 * the specified PID. This looks directly at the BackendStatusArray,
981 * and so will provide current information regardless of the age of our
982 * transaction's snapshot of the status array.
984 * It is the caller's responsibility to invoke this only for backends whose
985 * state is expected to remain stable while the result is in use. The
986 * only current use is in deadlock reporting, where we can expect that
987 * the target backend is blocked on a lock. (There are corner cases
988 * where the target's wait could get aborted while we are looking at it,
989 * but the very worst consequence is to return a pointer to a string
990 * that's been changed, so we won't worry too much.)
992 * Note: return strings for special cases match pg_stat_get_backend_activity.
1005 * Although we expect the target backend's entry to be stable, that
1006 * doesn't imply that anyone else's is. To avoid identifying the
1007 * wrong backend, while we check for a match to the desired PID we
1008 * must follow the protocol of retrying if st_changecount changes
1009 * while we examine the entry, or if it's odd. (This might be
1010 * unnecessary, since fetching or storing an int is almost certainly
1011 * atomic, but let's play it safe.) We use a volatile pointer here to
1012 * ensure the compiler doesn't try to get cute.
1019 int before_changecount;
1020 int after_changecount;
1032 /* Make sure we can break out of loop if stuck... */
1038 /* Now it is safe to use the non-volatile pointer */
1040 return "<insufficient privilege>";
1042 return "<command string not enabled>";
1045 /* this'll leak a bit of memory, but that seems acceptable */
1053 /* If we get here, caller is in error ... */
1054 return "<backend information not available>";
1058 * pgstat_get_crashed_backend_activity() -
1060 * Return a string representing the current activity of the backend with
1061 * the specified PID. Like the function above, but reads shared memory with
1062 * the expectation that it may be corrupt. On success, copy the string
1063 * into the "buffer" argument and return that pointer. On failure,
1066 * This function is only intended to be used by the postmaster to report the
1067 * query that crashed a backend. In particular, no attempt is made to
1068 * follow the correct concurrency protocol when accessing the
1069 * BackendStatusArray. But that's OK, in the worst case we'll return a
1070 * corrupted message. We also must take care not to trip on ereport(ERROR).
1082 * We probably shouldn't get here before shared memory has been set up,
1092 /* Read pointer just once, so it can't change after validation */
1094 const char *activity_last;
1097 * We mustn't access activity string before we verify that it
1098 * falls within the BackendActivityBuffer. To make sure that the
1099 * entire string including its ending is contained within the
1100 * buffer, subtract one activity length from the buffer size.
1106 activity > activity_last)
1109 /* If no string available, no point in a report */
1110 if (activity[0] ==
'0円')
1114 * Copy only ASCII-safe characters so we don't run into encoding
1115 * problems when reporting the message; and be sure not to run off
1116 * the end of memory. As only ASCII characters are reported, it
1117 * doesn't seem necessary to perform multibyte aware clipping.
1133 * pgstat_get_my_query_id() -
1135 * Return current backend's query identifier.
1144 * There's no need for a lock around pgstat_begin_read_activity /
1145 * pgstat_end_read_activity here as it's only called from
1146 * pg_stat_get_activity which is already protected, or from the same
1147 * backend which means that there won't be concurrent writes.
1153 * pgstat_get_my_plan_id() -
1155 * Return current backend's plan identifier.
1163 /* No need for a lock, for roughly the same reasons as above. */
1168 * pgstat_get_backend_type_by_proc_number() -
1170 * Return the type of the backend with the specified ProcNumber. This looks
1171 * directly at the BackendStatusArray, so the return value may be out of date.
1172 * The only current use of this function is in pg_signal_backend(), which is
1173 * inherently racy, so we don't worry too much about this.
1175 * It is the caller's responsibility to use this wisely; at minimum, callers
1176 * should ensure that procNumber is valid and perform the required permissions
1186 * We bypass the changecount mechanism since fetching and storing an int
1187 * is almost certainly atomic.
1195 * Comparison function for bsearch() on an array of LocalPgBackendStatus.
1196 * The proc_number field is used to compare the arguments.
1209 * pgstat_get_beentry_by_proc_number() -
1211 * Support function for the SQL-callable pgstat* functions. Returns
1212 * our local copy of the current-activity entry for one backend,
1213 * or NULL if the given beid doesn't identify any known session.
1215 * The argument is the ProcNumber of the desired session
1216 * (note that this is unlike pgstat_get_local_beentry_by_index()).
1218 * NB: caller is responsible for a check if the user is permitted to see
1219 * this info (especially the querystring).
1235 * pgstat_get_local_beentry_by_proc_number() -
1237 * Like pgstat_get_beentry_by_proc_number() but with locally computed additions
1238 * (like xid and xmin values of the backend)
1240 * The argument is the ProcNumber of the desired session
1241 * (note that this is unlike pgstat_get_local_beentry_by_index()).
1243 * NB: caller is responsible for checking if the user is permitted to see this
1244 * info (especially the querystring).
1255 * Since the localBackendStatusTable is in order by proc_number, we can
1256 * use bsearch() to search it efficiently.
1258 key.proc_number = procNumber;
1265 * pgstat_get_local_beentry_by_index() -
1267 * Like pgstat_get_beentry_by_proc_number() but with locally computed
1268 * additions (like xid and xmin values of the backend)
1270 * The idx argument is a 1-based index in the localBackendStatusTable
1271 * (note that this is unlike pgstat_get_beentry_by_proc_number()).
1272 * Returns NULL if the argument is out of range (no current caller does that).
1274 * NB: caller is responsible for a check if the user is permitted to see
1275 * this info (especially the querystring).
1291 * pgstat_fetch_stat_numbackends() -
1293 * Support function for the SQL-callable pgstat* functions. Returns
1294 * the number of sessions known in the localBackendStatusTable, i.e.
1295 * the maximum 1-based index to pass to pgstat_get_local_beentry_by_index().
1307 * Convert a potentially unsafely truncated activity string (see
1308 * PgBackendStatus.st_activity_raw's documentation) into a correctly truncated
1311 * The returned string is allocated in the caller's memory context and may be
1322 * Some callers, like pgstat_get_backend_current_activity(), do not
1323 * guarantee that the buffer isn't concurrently modified. We try to take
1324 * care that the buffer is always terminated by a NUL byte regardless, but
1325 * let's still be paranoid about the string's length. In those cases the
1326 * underlying buffer is guaranteed to be pgstat_track_activity_query_size
1331 /* now double-guaranteed to be NUL terminated */
1332 rawlen = strlen(activity);
1335 * All supported server-encodings make it possible to determine the length
1336 * of a multi-byte character from its first byte (this is not the case for
1337 * client encodings, see GB18030). As st_activity is always stored using
1338 * server encoding, this allows us to perform multi-byte aware truncation,
1339 * even if the string earlier was truncated in the middle of a multi-byte
Datum idx(PG_FUNCTION_ARGS)
void ascii_safe_strlcpy(char *dest, const char *src, size_t destsiz)
void TimestampDifference(TimestampTz start_time, TimestampTz stop_time, long *secs, int *microsecs)
TimestampTz GetCurrentTimestamp(void)
@ PROGRESS_COMMAND_INVALID
#define NumBackendStatSlots
int pgstat_fetch_stat_numbackends(void)
PgBackendStatus * MyBEEntry
LocalPgBackendStatus * pgstat_get_local_beentry_by_proc_number(ProcNumber procNumber)
void pgstat_clear_backend_activity_snapshot(void)
static LocalPgBackendStatus * localBackendStatusTable
void pgstat_bestart_security(void)
static int localNumBackends
void pgstat_bestart_initial(void)
static void pgstat_beshutdown_hook(int code, Datum arg)
void pgstat_report_query_id(int64 query_id, bool force)
static char * BackendClientHostnameBuffer
static int cmp_lbestatus(const void *a, const void *b)
bool pgstat_track_activities
char * pgstat_clip_activity(const char *raw_activity)
static MemoryContext backendStatusSnapContext
int64 pgstat_get_my_query_id(void)
const char * pgstat_get_crashed_backend_activity(int pid, char *buffer, int buflen)
static char * BackendActivityBuffer
void BackendStatusShmemInit(void)
static void pgstat_setup_backend_status_context(void)
LocalPgBackendStatus * pgstat_get_local_beentry_by_index(int idx)
static char * BackendAppnameBuffer
void pgstat_report_activity(BackendState state, const char *cmd_str)
BackendType pgstat_get_backend_type_by_proc_number(ProcNumber procNumber)
void pgstat_report_xact_timestamp(TimestampTz tstamp)
void pgstat_report_plan_id(int64 plan_id, bool force)
PgBackendStatus * pgstat_get_beentry_by_proc_number(ProcNumber procNumber)
static PgBackendStatus * BackendStatusArray
int64 pgstat_get_my_plan_id(void)
void pgstat_bestart_final(void)
Size BackendStatusShmemSize(void)
void pgstat_report_appname(const char *appname)
static Size BackendActivityBufferSize
const char * pgstat_get_backend_current_activity(int pid, bool checkUser)
static void pgstat_read_current_status(void)
int pgstat_track_activity_query_size
@ STATE_IDLEINTRANSACTION_ABORTED
@ STATE_IDLEINTRANSACTION
#define pgstat_read_activity_complete(before_changecount, after_changecount)
#define PGSTAT_END_WRITE_ACTIVITY(beentry)
#define PGSTAT_BEGIN_WRITE_ACTIVITY(beentry)
#define pgstat_end_read_activity(beentry, after_changecount)
#define pgstat_begin_read_activity(beentry, before_changecount)
bool be_gssapi_get_auth(Port *port)
bool be_gssapi_get_enc(Port *port)
const char * be_gssapi_get_princ(Port *port)
bool be_gssapi_get_delegation(Port *port)
const char * be_tls_get_version(Port *port)
int be_tls_get_cipher_bits(Port *port)
const char * be_tls_get_cipher(Port *port)
void be_tls_get_peer_serial(Port *port, char *ptr, size_t len)
void be_tls_get_peer_issuer_name(Port *port, char *ptr, size_t len)
void be_tls_get_peer_subject_name(Port *port, char *ptr, size_t len)
#define unvolatize(underlying_type, expr)
#define MemSet(start, val, len)
TimestampTz MyStartTimestamp
Assert(PointerIsAligned(start, uint64))
void on_shmem_exit(pg_on_exit_callback function, Datum arg)
int pg_mbcliplen(const char *mbstr, int len, int limit)
static int cliplen(const char *str, int len, int limit)
void * MemoryContextAlloc(MemoryContext context, Size size)
MemoryContext TopMemoryContext
char * pnstrdup(const char *in, Size len)
void * MemoryContextAllocHuge(MemoryContext context, Size size)
void MemoryContextDelete(MemoryContext context)
#define AllocSetContextCreate
#define ALLOCSET_SMALL_SIZES
#define CHECK_FOR_INTERRUPTS()
Oid GetSessionUserId(void)
BackendType MyBackendType
#define pgstat_count_conn_txn_idle_time(n)
#define pgstat_count_conn_active_time(n)
void pgstat_create_backend(ProcNumber procnum)
bool pgstat_tracks_backend_bktype(BackendType bktype)
size_t strlcpy(char *dst, const char *src, size_t siz)
void ProcNumberGetTransactionIds(ProcNumber procNumber, TransactionId *xid, TransactionId *xmin, int *nsubxid, bool *overflowed)
#define INVALID_PROC_NUMBER
Size add_size(Size s1, Size s2)
Size mul_size(Size s1, Size s2)
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
TransactionId backend_xid
PgBackendStatus backendStatus
int backend_subxact_count
TransactionId backend_xmin
bool backend_subxact_overflowed
char gss_princ[NAMEDATALEN]
char ssl_version[NAMEDATALEN]
char ssl_cipher[NAMEDATALEN]
char ssl_client_dn[NAMEDATALEN]
char ssl_client_serial[NAMEDATALEN]
char ssl_issuer_dn[NAMEDATALEN]
BackendType st_backendType
TimestampTz st_state_start_timestamp
TimestampTz st_proc_start_timestamp
PgBackendGSSStatus * st_gssstatus
TimestampTz st_activity_start_timestamp
ProgressCommandType st_progress_command
PgBackendSSLStatus * st_sslstatus
TimestampTz st_xact_start_timestamp
Oid st_progress_command_target
TimestampTz GetCurrentStatementStartTimestamp(void)