Re: shared-memory based stats collector
Kyotaro Horiguchi <horikyota.ntt@gmail.com>
At Thu, 1 Apr 2021 19:44:25 -0700, Andres Freund <andres@anarazel.de> wrote in
> Hi,
>
> I spent quite a bit more time working on the patch. There's are large
> changes:
>
> - postmaster/pgstats.c (which is an incorrect location now that it's not
> a subprocess anymore) is split into utils/activity/pgstat.c and
> utils/activity/pgstat_kind.c. I don't love the _kind name, but I
> couldn't come up with anything better.
The place was not changed to keep footprint smaller. I agree that the
old place is not appropriate. pgstat_kind... How about changin
pgstat.c to pgstat_core.c and pgstat_kind.c to pgstat.c?
> - Implemented a new GUC, stats_fetch_consistency = {none, cache,
> snapshot}. I think the code overhead of it is pretty ok - most of the
> handling is entirely generalized.
Sounds good.
> - Most of the "per stats kind" handling is done in pgstat_kind.c. Nearly
> all the rest is done through an array with per-stats-kind information
> (extending what was already done with pgstat_sharedentsize etc).
>
> - There is no separate "pending stats" hash anymore. If there are
> pending stats, they are referenced from 'pgStatSharedRefHash' (which
> used to be the "lookup cache" hash). All the entries with pending
> stats are in double linked list pgStatPending.
Sounds reasonable. A bit silimar to TabStatusArray.. Pending stats and
shared stats share the same key so they are naturally consolidatable.
> - A stat's entry's lwlock, refcount, .. are moved into the dshash
> entry. There is no need for them to be separate anymore. Also allows
> to avoid doing some dsa lookups while holding dshash locks.
>
> - The dshash entries are not deleted until the refcount has reached
> 0. That's an important building block to avoid constantly re-creating
> stats when flushing pending stats for a dropped object.
Does that mean the entries for a dropped object is actually dropped by
the backend that has been flushd stats of the dropped object at exit?
Sounds nice.
> - The reference to the shared entry is established the first time stats
> for an object are reported. Together with the previous entry that
> avoids nearly all the avenues for re-creating already dropped stats
> (see below for the hole).
>
> - I addded a bunch of pg_regress style tests, and a larger amount of
> isolationtester tests. The latter are possibly due to a new
> pg_stat_force_next_flush() function, avoiding the need to wait until
> stats are submitted.
>
> - 2PC support for "precise" dropping of stats has been added, the
> collect_oids() based approach removed.
Cool!
> - lots of bugfixes, comments, etc...
Thanks for all of them.
> I know of one nontrivial issue that can lead to dropped stats being
> revived:
>
> Within a transaction, a functions can be called even when another
> transaction that dropped that function has already committed. I added a
> spec test reproducing the issue:
>
> # FIXME: this shows the bug that stats will be revived, because the
> # shared stats in s2 is only referenced *after* the DROP FUNCTION
> # committed. That's only possible because there is no locking (and
> # thus no stats invalidation) around function calls.
> permutation
> "s1_track_funcs_all" "s2_track_funcs_none"
> "s1_func_call" "s2_begin" "s2_func_call" "s1_func_drop" "s2_track_funcs_all" "s2_func_call" "s2_commit" "s2_ff" "s1_func_stats" "s2_func_stats"
>
> I think the best fix here would be to associate an xid with the dropped
> stats object, and only delete the dshash entry once there's no alive
> with a horizon from before that xid...
I'm not sure how we do that avoiding a full scan on dshash..
> There's also a second issue (stats for newly created objects surviving
> the transaction), but that's pretty simple to resolve.
>
> Here's all the gory details of my changes happening incrementally:
>
> https://github.com/anarazel/postgres/compare/master...shmstat
>
> I'll squash and split tomorrow. Too tired for today.
Thank you very much for all of your immense effort.
> I think this is starting to look a lot better than what we have now. But
> I'm getting less confident that it's realistic to get any of this into
> PG14, given the state of the release cycle.
>
>
>
> > I'm impressed that the way you resolved "who should load stats". Using
> > static shared memory area to hold the point to existing DSA memory
> > resolves the "first attacher problem". However somewhat doubtful
> > about the "who should write the stats file", I think it is reasonable
> > in general.
> >
> > But the current place of calling pgstat_write_stats() is a bit to
> > early. Checkpointer reports some stats *after* calling
> > ShutdownXLOG(). Perhaps we need to move it after pg_stat_report_*()
> > calls in HandleCheckpointerInterrupts().
>
> I now moved it into a before_shmem_exit(). I think that should avoid
> that problem?
I think so.
> > https://github.com/anarazel/postgres/commit/03824a236597c87c99d07aa14b9af9d6fe04dd37
> >
> > + * XXX: Why is this a good place to do this?
> >
> > Agreed. We don't need to so haste to clean up stats entries. We could
> > run that in pgstat_reporT_stat()?
>
> I've not changed that yet, but I had the same thought.
>
>
> > Agreed that it's better to move database stat entries to fixed
> > pointers.
>
> I actually ended up reverting that. My main motivation for it was that
> it was problematic that new pending database stats entries could be
> created at some random place in the hashtable. But with the linked list
> of pending entries that's not a problem anymore. And I found it
> nontrivial to manage the refcounts to the shared entry accurately this
> way.
>
> We could still add a cache for the two stats entries though...
Yeah.
> > > - consider removing PgStatTypes and replacing it with the oid of the
> > > table the type of stats reside in. So PGSTAT_TYPE_DB would be
> > > DatabaseRelationId, PGSTAT_TYPE_TABLE would be RelationRelationId, ...
> > >
> > > I think that'd make the system more cleanly extensible going forward?
> >
> > I'm not sure that works as expected. We already separated repliation
> > stats from the unified stats hash and pgstat_read/write_statsfile()
> > needs have the corresponding specific code path.
>
> I didn't quite go towards my proposal, but I think I got a lot closer
> towards not needing much extra code for additional types of stats. I
> even added an XXX to pgstat_read/write_statsfile() that show how they
> now could be made generic.
I'll check it.
> > > - the replication slot stuff isn't quite right in my branch
> >
> > Ah, yeah. As I mentioned above I think it should be in the unified
> > stats and should have a special means of shotcut. And the global
> > stats also should be the same.
>
> The problem is that I use indexes for addressing, but that they can
> change between restarts. I think we can fix that fairly easily, by
> mapping names to indices once, pgstat_restore_stats(). At the point we
> call pgstat_restore_stats() StartupReplicationSlots() already was
> executed, so we can just inquire at that point...
Does that mean the saved replslot stats is keyed by their names?
regards.
--
Kyotaro Horiguchi
NTT Open Source Software Center
Commits
-
Improve comment about dropped entries in pgstat.c
- a0ab20f16541 15.11 landed
- ec194b448cbc 16.7 landed
- bb93b33d7e39 17.3 landed
- 001a537b83ec 18.0 landed
-
Fix temporary memory leak in system table index scans
- 1acf10549e64 18.0 cited
-
pgstat: set timestamps of fixed-numbered stats after a crash.
- 5cd1c40b3ce9 15.0 landed
-
pgstat: Update docs to match the shared memory stats reality.
- b3abca68106d 15.0 landed
-
pgstat: Hide instability in stats.spec with -DCATCACHE_FORCE_RELEASE.
- d6c0db14836c 15.0 cited
-
pgstat: add/extend tests for resetting various kinds of stats.
- 5264add78478 15.0 landed
-
Add minimal tests for recovery conflict handling.
- 9f8a050f68dc 15.0 landed
-
pgstat: test stats interactions with physical replication.
- 53b9cd20d414 15.0 landed
-
pgstat: add tests for handling of restarts, including crashes.
- 16acf7f1aaea 15.0 landed
-
pgstat: add tests for transaction behaviour, 2PC, function stats.
- e349c95d3e91 15.0 landed
-
pgstat: add pg_stat_have_stats() test helper.
- ad401664b801 15.0 landed
-
pgstat: add pg_stat_force_next_flush(), use it to simplify tests.
- 0f96965c6581 15.0 landed
-
pgstat: move pgstat.c to utils/activity.
- fbfe6910eca0 15.0 landed
-
pgstat: store statistics in shared memory.
- 5891c7a8ed8f 15.0 landed
-
pgstat: remove stats_temp_directory.
- 6f0cf87872ab 15.0 landed
-
pgstat: rename STATS_COLLECTOR GUC group to STATS_CUMULATIVE.
- 1db4e5a4eeec 15.0 landed
-
pgstat: revise replication slot API in preparation for shared memory stats.
- e41aed674f35 15.0 landed
-
pgstat: scaffolding for transactional stats creation / drop.
- 8b1dccd37c71 15.0 landed
-
pgstat: introduce PgStat_Kind enum.
- 997afad89d12 15.0 landed
-
pgstat: prepare APIs used by pgstatfuncs for shared memory stats.
- 8fb580a35ce3 15.0 landed
-
pgstat: add pgstat_copy_relation_stats().
- 8ea7963fc741 15.0 landed
-
pgstat: rename some pgstat_send_* functions to pgstat_report_*.
- cc96373cf39b 15.0 landed
-
pgstat: stats collector references in comments.
- bdbd3d9064f9 15.0 landed
-
pgstat: move transactional code into pgstat_xact.c.
- ab62a642d52c 15.0 landed
-
dsm: allow use in single user mode.
- 46a2d2499a64 15.0 landed
-
dshash: revise sequential scan support.
- 909eebf27b9e 15.0 landed
-
pgstat: remove some superflous comments from pgstat.h.
- 55e566fc4bc8 15.0 landed
-
pgstat: reorder pgstat.[ch] contents.
- 315ae75e9b6d 15.0 landed
-
pgstat: split different types of stats into separate files.
- 13619598f108 15.0 landed
-
pgstat: introduce pgstat_relation_should_count().
- 8363102009d8 15.0 landed
-
pgstat: separate "xact level" handling out of relation specific functions.
- d4ba8b51c763 15.0 landed
-
pgstat: rename pgstat_initstats() to pgstat_relation_init().
- bff258a2732e 15.0 landed
-
pgstat: split out WAL handling from pgstat_{initialize,report_stat}.
- 78f9506b380f 15.0 landed
-
pgstat: run pgindent on pgstat.c/h.
- a3a75b982b5b 15.0 landed
-
pgstat: split relation, database handling out of pgstat_report_stat().
- 89c546c29489 15.0 landed
-
Move code around in StartupXLOG().
- be1c00ab13a7 15.0 cited
-
pgstat: Prepare to use mechanism for truncated rels also for droppped rels.
- 6b9501660c93 15.0 landed
-
pgstat: Split out relation stats handling from AtEO[Sub]Xact_PgStat() etc.
- e1f958d759ff 15.0 landed
-
pgstat: Schedule per-backend pgstat shutdown via before_shmem_exit().
- fb2c5028e635 15.0 landed
-
Schedule ShutdownXLOG() in single user mode using before_shmem_exit().
- a1bb3d5dbe6a 15.0 landed
-
Make parallel worker shutdown complete entirely via before_shmem_exit().
- fa91d4c91f28 15.0 landed
-
pgstat: Bring up pgstat in BaseInit() to fix uninitialized use of pgstat by AV.
- ee3f8d3d3aec 15.0 landed
-
pgstat: split reporting/fetching of bgwriter and checkpointer stats.
- 1bc8e7b0991c 15.0 landed
-
Split backend status and progress related functionality out of pgstat.c.
- e1025044cd4e 14.0 landed
-
Split wait event related code from pgstat.[ch] into wait_event.[ch].
- a333476b9251 14.0 landed
-
Make archiver process an auxiliary process.
- d75288fb27b8 14.0 landed
-
Force to send remaining WAL stats to the stats collector at walwriter exit.
- 33394ee6f243 14.0 cited
-
Add pg_stat_database counters for sessions and session time
- 960869da0803 14.0 cited
-
Collect statistics about SLRU caches
- 28cac71bd368 13.0 cited
-
Don't run atexit callbacks in quickdie signal handlers.
- 8e19a82640d3 12.0 cited
-
Create a "fast path" for acquiring weak relation locks.
- 3cba8999b343 9.2.0 cited