Re: Recovering from detoast-related catcache invalidations
Noah Misch <noah@leadboat.com>
From: Noah Misch <noah@leadboat.com>
To: Heikki Linnakangas <hlinnaka@iki.fi>
Cc: Tom Lane <tgl@sss.pgh.pa.us>, Xiaoran Wang <fanfuxiaoran@gmail.com>, pgsql-hackers@lists.postgresql.org, Andres Freund <andres@anarazel.de>
Date: 2025-01-07T21:56:53Z
Lists: pgsql-hackers
Commits
Same data as JSON:
GET /api/v1/messages/:b64id/commits
the thread's linked commits as JSON, with link sources.
API reference →
-
Fix catcache invalidation of a list entry that's being built
- f217c410553d 13.19 landed
- 91fc447c21d3 16.7 landed
- 96e61b2792a5 17.3 landed
- fce17c3a53d6 14.16 landed
- ce7c406f0f8d 15.11 landed
- af8cd1639ab2 18.0 landed
-
Cope with inplace update making catcache stale during TOAST fetch.
- 7a21306aee0a 13.16 landed
- 11f3815d6af8 12.20 landed
- af73e37fa181 14.13 landed
- b08a4b6163eb 15.8 landed
- e4afd7153bd8 16.4 landed
- f9f47f0d93d1 17.0 landed
-
Add previous commit to .git-blame-ignore-revs.
- 36578fa04942 17.0 landed
-
Re-pgindent catcache.c after previous commit.
- d41358f4bbc8 15.6 landed
- d29a4fbacfb7 12.18 landed
- 96c019ffa3f8 17.0 landed
- 7ceeb57baddd 14.11 landed
- 56dcd71decb7 16.2 landed
- 475b3ea3c06b 13.14 landed
-
Cope with catcache entries becoming stale during detoasting.
- db122d426a2d 14.11 landed
- ad98fb14226a 17.0 landed
- 98e03f957436 13.14 landed
- 7e2561e1a258 16.2 landed
- 3b4d85cf159c 12.18 landed
- 2a46a0df4793 15.6 landed
On Tue, Dec 24, 2024 at 12:18:09AM +0200, Heikki Linnakangas wrote:
> On 14/12/2024 02:06, Heikki Linnakangas wrote:
> > Ok, I missed that. It does not handle the 2nd scenario though: If a new
> > catalog tuple is concurrently inserted that should be part of the list,
> > it is missed.
> > Attached is an injection point test case to reproduce that. If you
> > change the test so that the function's body is shorter, so that it's not
> > toasted, the test passes.
Nice discovery.
> I'm thinking of the attached to fix this. It changes the strategy for
> detecting concurrent cache invalidations. Instead of the "recheck" mechanism
> that was introduced in commit ad98fb1422, keep a stack of "build
> in-progress" entries, and CatCacheInvalidate() invalidate those
> "in-progress" entries in addition to the actual CatCTup and CatCList
> entries.
>
> My first attempt was to insert the CatCTup or CatCList entry to the catcache
> before starting to build it, marked with a flag to indicate that the entry
> isn't fully built yet. But when I started to write that it got pretty
> invasive, and it felt easier to add another structure to hold the
> in-progress entries instead.
That's similar to how relcache has been doing it (in_progress_list). I see no
problem applying that technique here.
> not sure I want to
> commit the test with the injection point, but it's useful now to demonstrate
> the bug.)
I'd err on the side of including it. Apart from some copied comments, the
test looks ready.
On Wed, Dec 25, 2024 at 11:27:38AM +0200, Heikki Linnakangas wrote:
> +++ b/src/test/modules/test_misc/t/007_bugs.pl
test_misc/t/007_bugs.pl could be home to almost anything. How about naming it
007_catcache_inval.pl?
> @@ -744,6 +770,13 @@ ResetCatalogCache(CatCache *cache)
> #endif
> }
> }
> +
> + /* Also invalidate any entries that are being built */
> + for (CatCCreating *e = catcache_creating_stack; e != NULL; e = e->next)
> + {
> + if (e->cache == cache)
> + e->dead = true;
> + }
> }
With debug_discard_caches=1, "make check" hangs early with some INSERT using
100% CPU. The new test file does likewise. I bet this needs a special case
to short-circuit debug_discard_caches, like RelationCacheInvalidate() has.
> @@ -1665,6 +1698,8 @@ SearchCatCacheList(CatCache *cache,
> HeapTuple ntp;
> MemoryContext oldcxt;
> int i;
> + volatile CatCCreating creating_list;
You could drop the volatile by copying catcache_creating_stack to an
additional var that you reference after longjmp, instead of referencing
creating_list.next after longjmp. Likewise for the instance of volatile in
CatalogCacheCreateEntry().
https://pubs.opengroup.org/onlinepubs/9799919799/functions/longjmp.html has
the rules. Using volatile is fine, though.
> + bool first_iter = true;
This is okay as non-volatile, but it could just as easily move inside the
PG_TRY.
> @@ -2076,38 +2118,33 @@ CatalogCacheCreateEntry(CatCache *cache, HeapTuple ntp, SysScanDesc scandesc,
> + PG_TRY();
> {
> - matches = equalTuple(before, ntp);
> - heap_freetuple(before);
> + dtp = toast_flatten_tuple(ntp, cache->cc_tupdesc);
gcc 4.8.5 warns:
catcache.c: In function ‘CatalogCacheCreateEntry’:
catcache.c:2159:29: warning: ‘dtp’ may be used uninitialized in this function [-Wmaybe-uninitialized]
ct->tuple.t_tableOid = dtp->t_tableOid;
I remember some commit of a gcc 4.x warning fix in a recent year, and we do
have buildfarm representation. Consider silencing it.
The rest looks good. Thanks.