Re: Vacuum ERRORs out considering freezing dead tuples from before OldestXmin
Heikki Linnakangas <hlinnaka@iki.fi>
From: Heikki Linnakangas <hlinnaka@iki.fi>
To: Melanie Plageman <melanieplageman@gmail.com>
Cc: Pg Hackers <pgsql-hackers@postgresql.org>,
Andres Freund <andres@anarazel.de>, Noah Misch <noah@leadboat.com>,
Peter Geoghegan <pg@bowt.ie>
Date: 2024-06-24T08:27:42Z
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 →
-
Test that vacuum removes tuples older than OldestXmin
- 2c0bc4765741 17.6 landed
- 303ba0573ce6 18.0 landed
- 80c34692e8e6 17.0 landed
- aa607980aee0 18.0 landed
-
Lower minimum maintenance_work_mem to 64kB
- 2eda3df9ad53 17.0 landed
- bbf668d66fbf 18.0 landed
-
Add accidentally omitted test to meson build file
- 9d198f4d3e3b 16.4 landed
-
Use DELETE instead of UPDATE to speed up vacuum test
- 924a08b76f5d 14.13 landed
- 9744fe24118b 15.8 landed
- 571e0ee40ebd 16.4 landed
-
Revert "Test that vacuum removes tuples older than OldestXmin"
- efcbb76efe40 18.0 landed
- 1a3e90948b50 17.0 landed
-
Ensure vacuum removes all visibly dead tuples older than OldestXmin
- fd4f12df5e46 17.0 landed
- 83c39a1f7f3f 18.0 landed
On 21/06/2024 03:02, Peter Geoghegan wrote: > On Thu, Jun 20, 2024 at 7:42 PM Melanie Plageman > <melanieplageman@gmail.com> wrote: >> If vacuum fails to remove a tuple with xmax older than >> VacuumCutoffs->OldestXmin and younger than >> GlobalVisState->maybe_needed, it will ERROR out when determining >> whether or not to freeze the tuple with "cannot freeze committed >> xmax". >> >> In back branches starting with 14, failing to remove tuples older than >> OldestXmin during pruning caused vacuum to infinitely loop in >> lazy_scan_prune(), as investigated on this [1] thread. > > This is a great summary. +1 >> We can fix this by always removing tuples considered dead before >> VacuumCutoffs->OldestXmin. This is okay even if a reconnected standby >> has a transaction that sees that tuple as alive, because it will >> simply wait to replay the removal until it would be correct to do so >> or recovery conflict handling will cancel the transaction that sees >> the tuple as alive and allow replay to continue. > > I think that this is the right general approach. +1 >> The repro forces a round of index vacuuming after the standby >> reconnects and before pruning a dead tuple whose xmax is older than >> OldestXmin. >> >> At the end of the round of index vacuuming, _bt_pendingfsm_finalize() >> calls GetOldestNonRemovableTransactionId(), thereby updating the >> backend's GlobalVisState and moving maybe_needed backwards. > > Right. I saw details exactly consistent with this when I used GDB > against a production instance. > > I'm glad that you were able to come up with a repro that involves > exactly the same basic elements, including index page deletion. Would it be possible to make it robust so that we could always run it with "make check"? This seems like an important corner case to regression test. -- Heikki Linnakangas Neon (https://neon.tech)