pgstat: Split out relation stats handling from AtEO[Sub]Xact_PgStat() etc.

An upcoming patch will add additional work to these functions. To avoid the
functions getting too complicated / doing too many things at once, split out
sub-tasks into their own functions.

Author: Andres Freund <andres@anarazel.de>
Discussion: https://postgr.es/m/20210405092914.mmxqe7j56lsjfsej@alap3.anarazel.de
pull/70/head
Andres Freund 4 years ago
parent d3014fff4c
commit e1f958d759
  1. 191
      src/backend/postmaster/pgstat.c

@ -2374,43 +2374,19 @@ pgstat_update_heap_dead_tuples(Relation rel, int delta)
pgstat_info->t_counts.t_delta_dead_tuples -= delta; pgstat_info->t_counts.t_delta_dead_tuples -= delta;
} }
/*
/* ---------- * Perform relation stats specific end-of-transaction work. Helper for
* AtEOXact_PgStat * AtEOXact_PgStat.
* *
* Called from access/transam/xact.c at top-level transaction commit/abort. * Transfer transactional insert/update counts into the base tabstat entries.
* ---------- * We don't bother to free any of the transactional state, since it's all in
* TopTransactionContext and will go away anyway.
*/ */
void static void
AtEOXact_PgStat(bool isCommit, bool parallel) AtEOXact_PgStat_Relations(PgStat_SubXactStatus *xact_state, bool isCommit)
{ {
PgStat_SubXactStatus *xact_state;
/* Don't count parallel worker transaction stats */
if (!parallel)
{
/*
* Count transaction commit or abort. (We use counters, not just
* bools, in case the reporting message isn't sent right away.)
*/
if (isCommit)
pgStatXactCommit++;
else
pgStatXactRollback++;
}
/*
* Transfer transactional insert/update counts into the base tabstat
* entries. We don't bother to free any of the transactional state, since
* it's all in TopTransactionContext and will go away anyway.
*/
xact_state = pgStatXactStack;
if (xact_state != NULL)
{
PgStat_TableXactStatus *trans; PgStat_TableXactStatus *trans;
Assert(xact_state->nest_level == 1);
Assert(xact_state->prev == NULL);
for (trans = xact_state->first; trans != NULL; trans = trans->next) for (trans = xact_state->first; trans != NULL; trans = trans->next)
{ {
PgStat_TableStatus *tabstat; PgStat_TableStatus *tabstat;
@ -2455,38 +2431,66 @@ AtEOXact_PgStat(bool isCommit, bool parallel)
} }
tabstat->trans = NULL; tabstat->trans = NULL;
} }
} }
pgStatXactStack = NULL;
/* Make sure any stats snapshot is thrown away */ static void
pgstat_clear_snapshot(); AtEOXact_PgStat_Database(bool isCommit, bool parallel)
{
/* Don't count parallel worker transaction stats */
if (!parallel)
{
/*
* Count transaction commit or abort. (We use counters, not just
* bools, in case the reporting message isn't sent right away.)
*/
if (isCommit)
pgStatXactCommit++;
else
pgStatXactRollback++;
}
} }
/* ---------- /* ----------
* AtEOSubXact_PgStat * AtEOXact_PgStat
* *
* Called from access/transam/xact.c at subtransaction commit/abort. * Called from access/transam/xact.c at top-level transaction commit/abort.
* ---------- * ----------
*/ */
void void
AtEOSubXact_PgStat(bool isCommit, int nestDepth) AtEOXact_PgStat(bool isCommit, bool parallel)
{ {
PgStat_SubXactStatus *xact_state; PgStat_SubXactStatus *xact_state;
/* AtEOXact_PgStat_Database(isCommit, parallel);
/* handle transactional stats information */
xact_state = pgStatXactStack;
if (xact_state != NULL)
{
Assert(xact_state->nest_level == 1);
Assert(xact_state->prev == NULL);
AtEOXact_PgStat_Relations(xact_state, isCommit);
}
pgStatXactStack = NULL;
/* Make sure any stats snapshot is thrown away */
pgstat_clear_snapshot();
}
/*
* Perform relation stats specific end-of-sub-transaction work. Helper for
* AtEOSubXact_PgStat.
*
* Transfer transactional insert/update counts into the next higher * Transfer transactional insert/update counts into the next higher
* subtransaction state. * subtransaction state.
*/ */
xact_state = pgStatXactStack; static void
if (xact_state != NULL && AtEOSubXact_PgStat_Relations(PgStat_SubXactStatus *xact_state, bool isCommit, int nestDepth)
xact_state->nest_level >= nestDepth) {
{
PgStat_TableXactStatus *trans; PgStat_TableXactStatus *trans;
PgStat_TableXactStatus *next_trans; PgStat_TableXactStatus *next_trans;
/* delink xact_state from stack immediately to simplify reuse case */
pgStatXactStack = xact_state->prev;
for (trans = xact_state->first; trans != NULL; trans = next_trans) for (trans = xact_state->first; trans != NULL; trans = next_trans)
{ {
PgStat_TableStatus *tabstat; PgStat_TableStatus *tabstat;
@ -2495,6 +2499,7 @@ AtEOSubXact_PgStat(bool isCommit, int nestDepth)
Assert(trans->nest_level == nestDepth); Assert(trans->nest_level == nestDepth);
tabstat = trans->parent; tabstat = trans->parent;
Assert(tabstat->trans == trans); Assert(tabstat->trans == trans);
if (isCommit) if (isCommit)
{ {
if (trans->upper && trans->upper->nest_level == nestDepth - 1) if (trans->upper && trans->upper->nest_level == nestDepth - 1)
@ -2555,30 +2560,42 @@ AtEOSubXact_PgStat(bool isCommit, int nestDepth)
pfree(trans); pfree(trans);
} }
} }
pfree(xact_state);
}
} }
/* ----------
/* * AtEOSubXact_PgStat
* AtPrepare_PgStat
* Save the transactional stats state at 2PC transaction prepare.
* *
* In this phase we just generate 2PC records for all the pending * Called from access/transam/xact.c at subtransaction commit/abort.
* transaction-dependent stats work. * ----------
*/ */
void void
AtPrepare_PgStat(void) AtEOSubXact_PgStat(bool isCommit, int nestDepth)
{ {
PgStat_SubXactStatus *xact_state; PgStat_SubXactStatus *xact_state;
/* merge the sub-transaction's transactional stats into the parent */
xact_state = pgStatXactStack; xact_state = pgStatXactStack;
if (xact_state != NULL) if (xact_state != NULL &&
xact_state->nest_level >= nestDepth)
{ {
/* delink xact_state from stack immediately to simplify reuse case */
pgStatXactStack = xact_state->prev;
AtEOSubXact_PgStat_Relations(xact_state, isCommit, nestDepth);
pfree(xact_state);
}
}
/*
* Generate 2PC records for all the pending transaction-dependent relation
* stats.
*/
static void
AtPrepare_PgStat_Relations(PgStat_SubXactStatus *xact_state)
{
PgStat_TableXactStatus *trans; PgStat_TableXactStatus *trans;
Assert(xact_state->nest_level == 1);
Assert(xact_state->prev == NULL);
for (trans = xact_state->first; trans != NULL; trans = trans->next) for (trans = xact_state->first; trans != NULL; trans = trans->next)
{ {
PgStat_TableStatus *tabstat; PgStat_TableStatus *tabstat;
@ -2602,6 +2619,46 @@ AtPrepare_PgStat(void)
RegisterTwoPhaseRecord(TWOPHASE_RM_PGSTAT_ID, 0, RegisterTwoPhaseRecord(TWOPHASE_RM_PGSTAT_ID, 0,
&record, sizeof(TwoPhasePgStatRecord)); &record, sizeof(TwoPhasePgStatRecord));
} }
}
/*
* AtPrepare_PgStat
* Save the transactional stats state at 2PC transaction prepare.
*/
void
AtPrepare_PgStat(void)
{
PgStat_SubXactStatus *xact_state;
xact_state = pgStatXactStack;
if (xact_state != NULL)
{
Assert(xact_state->nest_level == 1);
Assert(xact_state->prev == NULL);
AtPrepare_PgStat_Relations(xact_state);
}
}
/*
* All we need do here is unlink the transaction stats state from the
* nontransactional state. The nontransactional action counts will be
* reported to the stats collector immediately, while the effects on
* live and dead tuple counts are preserved in the 2PC state file.
*
* Note: AtEOXact_PgStat_Relations is not called during PREPARE.
*/
static void
PostPrepare_PgStat_Relations(PgStat_SubXactStatus *xact_state)
{
PgStat_TableXactStatus *trans;
for (trans = xact_state->first; trans != NULL; trans = trans->next)
{
PgStat_TableStatus *tabstat;
tabstat = trans->parent;
tabstat->trans = NULL;
} }
} }
@ -2609,11 +2666,6 @@ AtPrepare_PgStat(void)
* PostPrepare_PgStat * PostPrepare_PgStat
* Clean up after successful PREPARE. * Clean up after successful PREPARE.
* *
* All we need do here is unlink the transaction stats state from the
* nontransactional state. The nontransactional action counts will be
* reported to the stats collector immediately, while the effects on live
* and dead tuple counts are preserved in the 2PC state file.
*
* Note: AtEOXact_PgStat is not called during PREPARE. * Note: AtEOXact_PgStat is not called during PREPARE.
*/ */
void void
@ -2628,15 +2680,10 @@ PostPrepare_PgStat(void)
xact_state = pgStatXactStack; xact_state = pgStatXactStack;
if (xact_state != NULL) if (xact_state != NULL)
{ {
PgStat_TableXactStatus *trans; Assert(xact_state->nest_level == 1);
Assert(xact_state->prev == NULL);
for (trans = xact_state->first; trans != NULL; trans = trans->next)
{
PgStat_TableStatus *tabstat;
tabstat = trans->parent; PostPrepare_PgStat_Relations(xact_state);
tabstat->trans = NULL;
}
} }
pgStatXactStack = NULL; pgStatXactStack = NULL;

Loading…
Cancel
Save