Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 8b1dccd

Browse files
committedApr 7, 2022
pgstat: scaffolding for transactional stats creation / drop.
One problematic part of the current statistics collector design is that there is no reliable way of getting rid of statistics entries. Because of that pgstat_vacuum_stat() (called by [auto-]vacuum) matches all stats for the current database with the catalog contents and tries to drop now-superfluous entries. That's quite expensive. What's worse, it doesn't work on physical replicas, despite physical replicas collection statistics entries. This commit introduces infrastructure to create / drop statistics entries transactionally, together with the underlying catalog objects (functions, relations, subscriptions). pgstat_xact.c maintains a list of stats entries created / dropped transactionally in the current transaction. To ensure the removal of statistics entries is durable dropped statistics entries are included in commit / abort (and prepare) records, which also ensures that stats entries are dropped on standbys. Statistics entries created separately from creating the underlying catalog object (e.g. when stats were previously lost due to an immediate restart) are *not* WAL logged. However that can only happen outside of the transaction creating the catalog object, so it does not lead to "leaked" statistics entries. For this to work, functions creating / dropping functions / relations / subscriptions need to call into pgstat. For subscriptions this was already done when dropping subscriptions, via pgstat_report_subscription_drop() (now renamed to pgstat_drop_subscription()). This commit does not actually drop stats yet, it just provides the infrastructure. It is however a largely independent piece of infrastructure, so committing it separately makes sense. Bumps XLOG_PAGE_MAGIC. Author: Andres Freund <andres@anarazel.de> Reviewed-By: Thomas Munro <thomas.munro@gmail.com> Reviewed-By: Kyotaro Horiguchi <horikyota.ntt@gmail.com> Discussion: https://postgr.es/m/20220303021600.hs34ghqcw6zcokdh@alap3.anarazel.de
1 parent 8fb580a commit 8b1dccd

File tree

18 files changed

+524
-36
lines changed

18 files changed

+524
-36
lines changed
 

‎src/backend/access/rmgrdesc/xactdesc.c

+52
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,17 @@ ParseCommitRecord(uint8 info, xl_xact_commit *xlrec, xl_xact_parsed_commit *pars
8484
data += xl_relfilenodes->nrels * sizeof(RelFileNode);
8585
}
8686

87+
if (parsed->xinfo & XACT_XINFO_HAS_DROPPED_STATS)
88+
{
89+
xl_xact_stats_items *xl_drops = (xl_xact_stats_items *) data;
90+
91+
parsed->nstats = xl_drops->nitems;
92+
parsed->stats = xl_drops->items;
93+
94+
data += MinSizeOfXactStatsItems;
95+
data += xl_drops->nitems * sizeof(xl_xact_stats_item);
96+
}
97+
8798
if (parsed->xinfo & XACT_XINFO_HAS_INVALS)
8899
{
89100
xl_xact_invals *xl_invals = (xl_xact_invals *) data;
@@ -179,6 +190,17 @@ ParseAbortRecord(uint8 info, xl_xact_abort *xlrec, xl_xact_parsed_abort *parsed)
179190
data += xl_relfilenodes->nrels * sizeof(RelFileNode);
180191
}
181192

193+
if (parsed->xinfo & XACT_XINFO_HAS_DROPPED_STATS)
194+
{
195+
xl_xact_stats_items *xl_drops = (xl_xact_stats_items *) data;
196+
197+
parsed->nstats = xl_drops->nitems;
198+
parsed->stats = xl_drops->items;
199+
200+
data += MinSizeOfXactStatsItems;
201+
data += xl_drops->nitems * sizeof(xl_xact_stats_item);
202+
}
203+
182204
if (parsed->xinfo & XACT_XINFO_HAS_TWOPHASE)
183205
{
184206
xl_xact_twophase *xl_twophase = (xl_xact_twophase *) data;
@@ -244,6 +266,12 @@ ParsePrepareRecord(uint8 info, xl_xact_prepare *xlrec, xl_xact_parsed_prepare *p
244266
parsed->abortnodes = (RelFileNode *) bufptr;
245267
bufptr += MAXALIGN(xlrec->nabortrels * sizeof(RelFileNode));
246268

269+
parsed->stats = (xl_xact_stats_item *) bufptr;
270+
bufptr += MAXALIGN(xlrec->ncommitstats * sizeof(xl_xact_stats_item));
271+
272+
parsed->abortstats = (xl_xact_stats_item *) bufptr;
273+
bufptr += MAXALIGN(xlrec->nabortstats * sizeof(xl_xact_stats_item));
274+
247275
parsed->msgs = (SharedInvalidationMessage *) bufptr;
248276
bufptr += MAXALIGN(xlrec->ninvalmsgs * sizeof(SharedInvalidationMessage));
249277
}
@@ -280,6 +308,25 @@ xact_desc_subxacts(StringInfo buf, int nsubxacts, TransactionId *subxacts)
280308
}
281309
}
282310

311+
static void
312+
xact_desc_stats(StringInfo buf, const char *label,
313+
int ndropped, xl_xact_stats_item *dropped_stats)
314+
{
315+
int i;
316+
317+
if (ndropped > 0)
318+
{
319+
appendStringInfo(buf, "; %sdropped stats:", label);
320+
for (i = 0; i < ndropped; i++)
321+
{
322+
appendStringInfo(buf, " %u/%u/%u",
323+
dropped_stats[i].kind,
324+
dropped_stats[i].dboid,
325+
dropped_stats[i].objoid);
326+
}
327+
}
328+
}
329+
283330
static void
284331
xact_desc_commit(StringInfo buf, uint8 info, xl_xact_commit *xlrec, RepOriginId origin_id)
285332
{
@@ -295,6 +342,7 @@ xact_desc_commit(StringInfo buf, uint8 info, xl_xact_commit *xlrec, RepOriginId
295342

296343
xact_desc_relations(buf, "rels", parsed.nrels, parsed.xnodes);
297344
xact_desc_subxacts(buf, parsed.nsubxacts, parsed.subxacts);
345+
xact_desc_stats(buf, "", parsed.nstats, parsed.stats);
298346

299347
standby_desc_invalidations(buf, parsed.nmsgs, parsed.msgs, parsed.dbId,
300348
parsed.tsId,
@@ -338,6 +386,8 @@ xact_desc_abort(StringInfo buf, uint8 info, xl_xact_abort *xlrec, RepOriginId or
338386
LSN_FORMAT_ARGS(parsed.origin_lsn),
339387
timestamptz_to_str(parsed.origin_timestamp));
340388
}
389+
390+
xact_desc_stats(buf, "", parsed.nstats, parsed.stats);
341391
}
342392

343393
static void
@@ -353,6 +403,8 @@ xact_desc_prepare(StringInfo buf, uint8 info, xl_xact_prepare *xlrec, RepOriginI
353403
xact_desc_relations(buf, "rels(commit)", parsed.nrels, parsed.xnodes);
354404
xact_desc_relations(buf, "rels(abort)", parsed.nabortrels,
355405
parsed.abortnodes);
406+
xact_desc_stats(buf, "commit ", parsed.nstats, parsed.stats);
407+
xact_desc_stats(buf, "abort ", parsed.nabortstats, parsed.abortstats);
356408
xact_desc_subxacts(buf, parsed.nsubxacts, parsed.subxacts);
357409

358410
standby_desc_invalidations(buf, parsed.nmsgs, parsed.msgs, parsed.dbId,

‎src/backend/access/transam/twophase.c

+45
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,8 @@ static void RecordTransactionCommitPrepared(TransactionId xid,
205205
TransactionId *children,
206206
int nrels,
207207
RelFileNode *rels,
208+
int nstats,
209+
xl_xact_stats_item *stats,
208210
int ninvalmsgs,
209211
SharedInvalidationMessage *invalmsgs,
210212
bool initfileinval,
@@ -214,6 +216,8 @@ static void RecordTransactionAbortPrepared(TransactionId xid,
214216
TransactionId *children,
215217
int nrels,
216218
RelFileNode *rels,
219+
int nstats,
220+
xl_xact_stats_item *stats,
217221
const char *gid);
218222
static void ProcessRecords(char *bufptr, TransactionId xid,
219223
const TwoPhaseCallback callbacks[]);
@@ -1046,6 +1050,8 @@ StartPrepare(GlobalTransaction gxact)
10461050
TransactionId *children;
10471051
RelFileNode *commitrels;
10481052
RelFileNode *abortrels;
1053+
xl_xact_stats_item *abortstats = NULL;
1054+
xl_xact_stats_item *commitstats = NULL;
10491055
SharedInvalidationMessage *invalmsgs;
10501056

10511057
/* Initialize linked list */
@@ -1071,6 +1077,10 @@ StartPrepare(GlobalTransaction gxact)
10711077
hdr.nsubxacts = xactGetCommittedChildren(&children);
10721078
hdr.ncommitrels = smgrGetPendingDeletes(true, &commitrels);
10731079
hdr.nabortrels = smgrGetPendingDeletes(false, &abortrels);
1080+
hdr.ncommitstats =
1081+
pgstat_get_transactional_drops(true, &commitstats);
1082+
hdr.nabortstats =
1083+
pgstat_get_transactional_drops(false, &abortstats);
10741084
hdr.ninvalmsgs = xactGetCommittedInvalidationMessages(&invalmsgs,
10751085
&hdr.initfileinval);
10761086
hdr.gidlen = strlen(gxact->gid) + 1; /* Include '\0' */
@@ -1101,6 +1111,18 @@ StartPrepare(GlobalTransaction gxact)
11011111
save_state_data(abortrels, hdr.nabortrels * sizeof(RelFileNode));
11021112
pfree(abortrels);
11031113
}
1114+
if (hdr.ncommitstats > 0)
1115+
{
1116+
save_state_data(commitstats,
1117+
hdr.ncommitstats * sizeof(xl_xact_stats_item));
1118+
pfree(commitstats);
1119+
}
1120+
if (hdr.nabortstats > 0)
1121+
{
1122+
save_state_data(abortstats,
1123+
hdr.nabortstats * sizeof(xl_xact_stats_item));
1124+
pfree(abortstats);
1125+
}
11041126
if (hdr.ninvalmsgs > 0)
11051127
{
11061128
save_state_data(invalmsgs,
@@ -1472,6 +1494,8 @@ FinishPreparedTransaction(const char *gid, bool isCommit)
14721494
RelFileNode *abortrels;
14731495
RelFileNode *delrels;
14741496
int ndelrels;
1497+
xl_xact_stats_item *commitstats;
1498+
xl_xact_stats_item *abortstats;
14751499
SharedInvalidationMessage *invalmsgs;
14761500

14771501
/*
@@ -1506,6 +1530,10 @@ FinishPreparedTransaction(const char *gid, bool isCommit)
15061530
bufptr += MAXALIGN(hdr->ncommitrels * sizeof(RelFileNode));
15071531
abortrels = (RelFileNode *) bufptr;
15081532
bufptr += MAXALIGN(hdr->nabortrels * sizeof(RelFileNode));
1533+
commitstats = (xl_xact_stats_item*) bufptr;
1534+
bufptr += MAXALIGN(hdr->ncommitstats * sizeof(xl_xact_stats_item));
1535+
abortstats = (xl_xact_stats_item*) bufptr;
1536+
bufptr += MAXALIGN(hdr->nabortstats * sizeof(xl_xact_stats_item));
15091537
invalmsgs = (SharedInvalidationMessage *) bufptr;
15101538
bufptr += MAXALIGN(hdr->ninvalmsgs * sizeof(SharedInvalidationMessage));
15111539

@@ -1527,12 +1555,16 @@ FinishPreparedTransaction(const char *gid, bool isCommit)
15271555
RecordTransactionCommitPrepared(xid,
15281556
hdr->nsubxacts, children,
15291557
hdr->ncommitrels, commitrels,
1558+
hdr->ncommitstats,
1559+
commitstats,
15301560
hdr->ninvalmsgs, invalmsgs,
15311561
hdr->initfileinval, gid);
15321562
else
15331563
RecordTransactionAbortPrepared(xid,
15341564
hdr->nsubxacts, children,
15351565
hdr->nabortrels, abortrels,
1566+
hdr->nabortstats,
1567+
abortstats,
15361568
gid);
15371569

15381570
ProcArrayRemove(proc, latestXid);
@@ -1568,6 +1600,11 @@ FinishPreparedTransaction(const char *gid, bool isCommit)
15681600
/* Make sure files supposed to be dropped are dropped */
15691601
DropRelationFiles(delrels, ndelrels, false);
15701602

1603+
if (isCommit)
1604+
pgstat_execute_transactional_drops(hdr->ncommitstats, commitstats, false);
1605+
else
1606+
pgstat_execute_transactional_drops(hdr->nabortstats, abortstats, false);
1607+
15711608
/*
15721609
* Handle cache invalidation messages.
15731610
*
@@ -2066,6 +2103,8 @@ RecoverPreparedTransactions(void)
20662103
bufptr += MAXALIGN(hdr->nsubxacts * sizeof(TransactionId));
20672104
bufptr += MAXALIGN(hdr->ncommitrels * sizeof(RelFileNode));
20682105
bufptr += MAXALIGN(hdr->nabortrels * sizeof(RelFileNode));
2106+
bufptr += MAXALIGN(hdr->ncommitstats * sizeof(xl_xact_stats_item));
2107+
bufptr += MAXALIGN(hdr->nabortstats * sizeof(xl_xact_stats_item));
20692108
bufptr += MAXALIGN(hdr->ninvalmsgs * sizeof(SharedInvalidationMessage));
20702109

20712110
/*
@@ -2248,6 +2287,8 @@ RecordTransactionCommitPrepared(TransactionId xid,
22482287
TransactionId *children,
22492288
int nrels,
22502289
RelFileNode *rels,
2290+
int nstats,
2291+
xl_xact_stats_item *stats,
22512292
int ninvalmsgs,
22522293
SharedInvalidationMessage *invalmsgs,
22532294
bool initfileinval,
@@ -2277,6 +2318,7 @@ RecordTransactionCommitPrepared(TransactionId xid,
22772318
*/
22782319
recptr = XactLogCommitRecord(committs,
22792320
nchildren, children, nrels, rels,
2321+
nstats, stats,
22802322
ninvalmsgs, invalmsgs,
22812323
initfileinval,
22822324
MyXactFlags | XACT_FLAGS_ACQUIREDACCESSEXCLUSIVELOCK,
@@ -2343,6 +2385,8 @@ RecordTransactionAbortPrepared(TransactionId xid,
23432385
TransactionId *children,
23442386
int nrels,
23452387
RelFileNode *rels,
2388+
int nstats,
2389+
xl_xact_stats_item *stats,
23462390
const char *gid)
23472391
{
23482392
XLogRecPtr recptr;
@@ -2373,6 +2417,7 @@ RecordTransactionAbortPrepared(TransactionId xid,
23732417
recptr = XactLogAbortRecord(GetCurrentTimestamp(),
23742418
nchildren, children,
23752419
nrels, rels,
2420+
nstats, stats,
23762421
MyXactFlags | XACT_FLAGS_ACQUIREDACCESSEXCLUSIVELOCK,
23772422
xid, gid);
23782423

0 commit comments

Comments
 (0)