Use actual backend IDs in pg_stat_get_backend_subxact().
authorNathan Bossart <[email protected]>
Wed, 30 Aug 2023 21:47:20 +0000 (14:47 -0700)
committerNathan Bossart <[email protected]>
Wed, 30 Aug 2023 21:47:20 +0000 (14:47 -0700)
Unlike the other pg_stat_get_backend* functions,
pg_stat_get_backend_subxact() looks up the backend entry by using
its integer argument as a 1-based index in an internal array.  The
other functions look for the entry with the matching session
backend ID.  These numbers often match, but that isn't reliably
true.

This commit resolves this discrepancy by introducing
pgstat_get_local_beentry_by_backend_id() and using it in
pg_stat_get_backend_subxact().  We cannot use
pgstat_get_beentry_by_backend_id() because it returns a
PgBackendStatus, which lacks the locally computed additions
available in LocalPgBackendStatus that are required by
pg_stat_get_backend_subxact().

Author: Ian Barwick
Reviewed-by: Sami Imseih, Michael Paquier, Robert Haas
Discussion: https://postgr.es/m/CAB8KJ%3Dj-ACb3H4L9a_b3ZG3iCYDW5aEu3WsPAzkm2S7JzS1Few%40mail.gmail.com
Backpatch-through: 16

src/backend/utils/activity/backend_status.c
src/backend/utils/adt/pgstatfuncs.c
src/include/utils/backend_status.h

index a4860b10fc69283db3a3ceb4caf4a08197ff201b..722c5acf38dc6755b191c92d3bb9340e910f7920 100644 (file)
@@ -1088,9 +1088,33 @@ cmp_lbestatus(const void *a, const void *b)
  */
 PgBackendStatus *
 pgstat_get_beentry_by_backend_id(BackendId beid)
+{
+   LocalPgBackendStatus *ret = pgstat_get_local_beentry_by_backend_id(beid);
+
+   if (ret)
+       return &ret->backendStatus;
+
+   return NULL;
+}
+
+
+/* ----------
+ * pgstat_get_local_beentry_by_backend_id() -
+ *
+ * Like pgstat_get_beentry_by_backend_id() but with locally computed additions
+ * (like xid and xmin values of the backend)
+ *
+ * The beid argument is the BackendId of the desired session
+ * (note that this is unlike pgstat_get_local_beentry_by_index()).
+ *
+ * NB: caller is responsible for checking if the user is permitted to see this
+ * info (especially the querystring).
+ * ----------
+ */
+LocalPgBackendStatus *
+pgstat_get_local_beentry_by_backend_id(BackendId beid)
 {
    LocalPgBackendStatus key;
-   LocalPgBackendStatus *ret;
 
    pgstat_read_current_status();
 
@@ -1099,14 +1123,8 @@ pgstat_get_beentry_by_backend_id(BackendId beid)
     * bsearch() to search it efficiently.
     */
    key.backend_id = beid;
-   ret = (LocalPgBackendStatus *) bsearch(&key, localBackendStatusTable,
-                                          localNumBackends,
-                                          sizeof(LocalPgBackendStatus),
-                                          cmp_lbestatus);
-   if (ret)
-       return &ret->backendStatus;
-
-   return NULL;
+   return bsearch(&key, localBackendStatusTable, localNumBackends,
+                  sizeof(LocalPgBackendStatus), cmp_lbestatus);
 }
 
 
index 49cc887b97beaad7c81b13f9eeed8c0d470bd7d4..dd5094a2d45a9b59907c000423f5cbdca3a626bd 100644 (file)
@@ -727,7 +727,7 @@ pg_stat_get_backend_subxact(PG_FUNCTION_ARGS)
 
    BlessTupleDesc(tupdesc);
 
-   if ((local_beentry = pgstat_get_local_beentry_by_index(beid)) != NULL)
+   if ((local_beentry = pgstat_get_local_beentry_by_backend_id(beid)) != NULL)
    {
        /* Fill values and NULLs */
        values[0] = Int32GetDatum(local_beentry->backend_subxact_count);
index 1718ff7ce6602b0dd8d34ed22c93ed3d75d6fdca..d51c840dafbeff3a36bf46b686b0475c8ff9a405 100644 (file)
@@ -334,6 +334,7 @@ extern uint64 pgstat_get_my_query_id(void);
  */
 extern int pgstat_fetch_stat_numbackends(void);
 extern PgBackendStatus *pgstat_get_beentry_by_backend_id(BackendId beid);
+extern LocalPgBackendStatus *pgstat_get_local_beentry_by_backend_id(BackendId beid);
 extern LocalPgBackendStatus *pgstat_get_local_beentry_by_index(int idx);
 extern char *pgstat_clip_activity(const char *raw_activity);