Expose some information about backend subxact status.

A new function pg_stat_get_backend_subxact() can be used to get
information about the number of subtransactions in the cache of
a particular backend and whether that cache has overflowed. This
can be useful for tracking down performance problems that can
result from overflowed snapshots.

Dilip Kumar, reviewed by Zhihong Yu, Nikolay Samokhvalov,
Justin Pryzby, Nathan Bossart, Ashutosh Sharma, Julien
Rouhaud. Additional design comments from Andres Freund,
Tom Lane, Bruce Momjian, and David G. Johnston.

Discussion: http://postgr.es/m/CAFiTN-ut0uwkRJDQJeDPXpVyTWD46m3gt3JDToE02hTfONEN=Q@mail.gmail.com
This commit is contained in:
Robert Haas 2022-12-19 14:43:09 -05:00
parent 7122f9d543
commit 10ea0f924a
8 changed files with 90 additions and 7 deletions

View File

@ -5671,6 +5671,24 @@ FROM pg_stat_get_backend_idset() AS backendid;
</para></entry>
</row>
<row>
<entry role="func_table_entry"><para role="func_signature">
<indexterm>
<primary>pg_stat_get_backend_subxact</primary>
</indexterm>
<function>pg_stat_get_backend_subxact</function> ( <type>integer</type> )
<returnvalue>record</returnvalue>
</para>
<para>
Returns a record of information about the subtransactions of the
backend with the specified ID.
The fields returned are <parameter>subxact_count</parameter>, which
is the number of subtransactions in the backend's subtransaction cache,
and <parameter>subxact_overflow</parameter>, which indicates whether
the backend's subtransaction cache is overflowed or not.
</para></entry>
</row>
<row>
<entry role="func_table_entry"><para role="func_signature">
<indexterm>

View File

@ -404,17 +404,20 @@ 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.
* Get the xid, xmin, nsubxid and overflow status 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)
BackendIdGetTransactionIds(int backendID, TransactionId *xid,
TransactionId *xmin, int *nsubxid, bool *overflowed)
{
SISeg *segP = shmInvalBuffer;
*xid = InvalidTransactionId;
*xmin = InvalidTransactionId;
*nsubxid = 0;
*overflowed = false;
/* Need to lock out additions/removals of backends */
LWLockAcquire(SInvalWriteLock, LW_SHARED);
@ -428,6 +431,8 @@ BackendIdGetTransactionIds(int backendID, TransactionId *xid, TransactionId *xmi
{
*xid = proc->xid;
*xmin = proc->xmin;
*nsubxid = proc->subxidStatus.count;
*overflowed = proc->subxidStatus.overflowed;
}
}

View File

@ -855,7 +855,9 @@ pgstat_read_current_status(void)
localentry->backend_id = i;
BackendIdGetTransactionIds(i,
&localentry->backend_xid,
&localentry->backend_xmin);
&localentry->backend_xmin,
&localentry->backend_subxact_count,
&localentry->backend_subxact_overflowed);
localentry++;
localappname += NAMEDATALEN;

View File

@ -687,6 +687,44 @@ pg_stat_get_backend_userid(PG_FUNCTION_ARGS)
PG_RETURN_OID(beentry->st_userid);
}
Datum
pg_stat_get_backend_subxact(PG_FUNCTION_ARGS)
{
#define PG_STAT_GET_SUBXACT_COLS 2
TupleDesc tupdesc;
Datum values[PG_STAT_GET_SUBXACT_COLS];
bool nulls[PG_STAT_GET_SUBXACT_COLS];
int32 beid = PG_GETARG_INT32(0);
LocalPgBackendStatus *local_beentry;
/* Initialise values and NULL flags arrays */
MemSet(values, 0, sizeof(values));
MemSet(nulls, 0, sizeof(nulls));
/* Initialise attributes information in the tuple descriptor */
tupdesc = CreateTemplateTupleDesc(PG_STAT_GET_SUBXACT_COLS);
TupleDescInitEntry(tupdesc, (AttrNumber) 1, "subxact_count",
INT4OID, -1, 0);
TupleDescInitEntry(tupdesc, (AttrNumber) 2, "subxact_overflow",
BOOLOID, -1, 0);
BlessTupleDesc(tupdesc);
if ((local_beentry = pgstat_fetch_stat_local_beentry(beid)) != NULL)
{
/* Fill values and NULLs */
values[0] = Int32GetDatum(local_beentry->backend_subxact_count);
values[1] = BoolGetDatum(local_beentry->backend_subxact_overflowed);
}
else
{
nulls[0] = true;
nulls[1] = true;
}
/* Returns the record as Datum */
PG_RETURN_DATUM(HeapTupleGetDatum(heap_form_tuple(tupdesc, values, nulls)));
}
Datum
pg_stat_get_backend_activity(PG_FUNCTION_ARGS)

View File

@ -57,6 +57,6 @@
*/
/* yyyymmddN */
#define CATALOG_VERSION_NO 202212131
#define CATALOG_VERSION_NO 202212191
#endif

View File

@ -5441,6 +5441,13 @@
proname => 'pg_stat_get_backend_dbid', provolatile => 's', proparallel => 'r',
prorettype => 'oid', proargtypes => 'int4',
prosrc => 'pg_stat_get_backend_dbid' },
{ oid => '6107', descr => 'statistics: get subtransaction status of backend',
proname => 'pg_stat_get_backend_subxact', provolatile => 's', proparallel => 'r',
prorettype => 'record', proargtypes => 'int4',
proallargtypes => '{int4,int4,bool}',
proargmodes => '{i,o,o}',
proargnames => '{bid,subxact_count,subxact_overflowed}',
prosrc => 'pg_stat_get_backend_subxact' },
{ oid => '1939', descr => 'statistics: user ID of backend',
proname => 'pg_stat_get_backend_userid', provolatile => 's',
proparallel => 'r', prorettype => 'oid', proargtypes => 'int4',

View File

@ -32,7 +32,9 @@ extern Size SInvalShmemSize(void);
extern void CreateSharedInvalidationState(void);
extern void SharedInvalBackendInit(bool sendOnly);
extern PGPROC *BackendIdGetProc(int backendID);
extern void BackendIdGetTransactionIds(int backendID, TransactionId *xid, TransactionId *xmin);
extern void BackendIdGetTransactionIds(int backendID, TransactionId *xid,
TransactionId *xmin, int *nsubxid,
bool *overflowed);
extern void SIInsertDataEntries(const SharedInvalidationMessage *data, int n);
extern int SIGetDataEntries(SharedInvalidationMessage *data, int datasize);

View File

@ -266,6 +266,17 @@ typedef struct LocalPgBackendStatus
* not.
*/
TransactionId backend_xmin;
/*
* Number of cached subtransactions in the current session.
*/
int backend_subxact_count;
/*
* The number of subtransactions in the current session exceeded the cached
* subtransaction limit.
*/
bool backend_subxact_overflowed;
} LocalPgBackendStatus;