Re: BUG #18146: Rows reappearing in Tables after Auto-Vacuum Failure in PostgreSQL on Windows
Robert Haas <robertmhaas@gmail.com>
From: Robert Haas <robertmhaas@gmail.com>
To: Thomas Munro <thomas.munro@gmail.com>
Cc: Michael Paquier <michael@paquier.xyz>, Tom Lane <tgl@sss.pgh.pa.us>, Laurenz Albe <laurenz.albe@cybertec.at>, rootcause000@gmail.com, pgsql-bugs@lists.postgresql.org
Date: 2023-10-23T15:06:42Z
Lists: pgsql-bugs
On Fri, Oct 20, 2023 at 1:17 AM Thomas Munro <thomas.munro@gmail.com> wrote: > > I take that back: there is a palloc() under RelationTruncate(). DNLGTM. > > Ooops, I should have quoted to the 0002 patch there. > > Hmm. We could teach md.c to do all its path manipulation in > MAXPGPATH-sized output buffers but that still wouldn't be enough > because it might decide to allocate more space for the array of > segments, and I'm not even sure where in PostgreSQL we guarantee that > everything that could appear here would fit in that. But that gives > me an idea. It feels like a bit of a dirty hack, which could perhaps > be made less dirty with some kind of function that includes the word > 'ensure' in its name, but I think we can make md.c promise not to > allocate anything before the next CFI with something like this: Ugh. AFAICS the problems are confined to smgrtruncate() and within that to the callback to smgr_truncate. As far as the rest of smgrtruncate() is concerned, it seems like DropRelationBuffers() and CacheInvalidateSmgr() are safe enough in a critical section, and the other code directly inside RelationTruncate() looks OK, too. But within mdtruncate(), we've got more than one problem, I think. mdnblocks() is a problem because of the reason that you mention, but register_dirty_segment() doesn't look totally safe either, because it can call RegisterSyncRequest() which, in a standalone backend, can call RememberSyncRequest(). In general, it seems like it would be a lot nicer if we were doing a lot less stuff inside the critical section here. So I think you're right that we need some refactoring. Maybe smgr_prepare_truncate() and smgr_execute_truncate() or something like that. I wonder if we could actually register the dirty segment in the "prepare" phase - is it bad if we register a dirty segment before actually dirtying it? And maybe even CacheInvalidateSmgr() could be done at that stage? It seems pretty clear that dropping the dirty buffers and actually truncating the relation on disk need to happen after we've entered the critical section, because if we fail after doing the former, we've thrown away dirty data in anticipation of performing an operation that didn't happen, and if we fail when attempting the latter, primaries and standbys diverge and the originally-reported bug on this thread happens. But we'd like to move as much other stuff as we can out of that critical section. -- Robert Haas EDB: http://www.enterprisedb.com
Commits
Same data as JSON:
GET /api/v1/messages/:b64id/commits
the thread's linked commits as JSON, with link sources.
API reference →
-
Fix C error reported by Oracle compiler.
- 417d41c658b3 13.19 landed
- 049c8cb9a239 14.16 landed
- 190054e61f5d 15.11 landed
- 9defaaa1da60 16.7 landed
- 45aef9f6bb0f 17.3 landed
-
Restore smgrtruncate() prototype in back-branches.
- a1d17a894731 13.19 landed
- f154f028d856 14.16 landed
- 3181befdca71 15.11 landed
- c957d7444fcc 16.7 landed
- 66aaabe7a18f 17.3 landed
-
Fix corruption when relation truncation fails.
- 2280912165d6 13.19 landed
- 23c743b645a5 14.16 landed
- fb540b6aa5ab 15.11 landed
- ba02d24bacbb 16.7 landed
- 0350b876b074 17.3 landed
- 38c579b08988 18.0 landed
-
RelationTruncate() must set DELAY_CHKPT_START.
- a501fe5a971e 15.11 landed
- ad5aa7bfd042 16.7 landed
- d4ffbf47b2d4 17.3 landed
- 1168acbca475 13.19 landed
- 7d0b91a28421 14.16 landed
- 75818b3afbf8 18.0 landed
-
WAL-log inplace update before revealing it to other sessions.
- 8e7e672cdaa6 18.0 cited
-
Fix bugs in MultiXact truncation
- b1ffe3ff0b7e 17.0 cited
-
Fix possible recovery trouble if TRUNCATE overlaps a checkpoint.
- 412ad7a55639 15.0 cited