Re: UNDO with FILEOPS, and the FLUX table AM

From: Greg Burd <greg(at)burd(dot)me>
To: shihao zhong <zhong950419(at)gmail(dot)com>
Cc: pgsql-hackers(at)lists(dot)postgresql(dot)org, Manu <manuelreyesbravo(at)gmail(dot)com>, Matthias van de Meent <boekewurm+postgres(at)gmail(dot)com>, Hannu Krosing <hannuk(at)google(dot)com>
Subject: Re: UNDO with FILEOPS, and the FLUX table AM
Date: 2026-11-06 18:48:04
Message-ID: au4gW5tgz5R_r4HI@werk
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Hi Shihao, Manu, Matthias, Hannu,

v9 is attached, and it is smaller and more focused on purpose and as
requested. As I said on Oct 29, it is only the first three commits of
v8:

0001 cluster-wide UNDO engine (records in the WAL stream)
0002 transactional filesystem operations (FILEOPS) backed by UNDO
0003 route filesystem mutations through FILEOPS

The per-backend UNDO logs, the ATM and logical revert worker, the index
AM changes, the table AM hooks and FLUX are no longer in the series.
I'd like to go slowly: get agreement on the engine and on one user of
it, and only then bring the other pieces back, one at a time and each
with its own user, if the foundation is accepted and committed. If it
isn't, none of the rest should go in either.

On Sun, Oct 25, 2026 at 6:56 PM shihao zhong <zhong950419(at)gmail(dot)com> wrote:
> I think crash cleanup of orphaned relation files would be a good first
> user. It only needs undo at the end of recovery, so the first piece
> could be much smaller than 0001.
...
> I would guess that is under 1,000 lines of C. It could be two patches.

v9 is not that small, I wish it were. 0001-0003 add about 15,800 lines;
counting as you did (C outside the tests, no comments or blank lines)
that is about 5,800, 3,300 of them in 0001.

The user is FILEOPS rather than relation files: it is what makes CREATE
DATABASE, ALTER DATABASE SET TABLESPACE and CREATE/DROP TABLESPACE leave
nothing behind when they roll back or crash. Orphaned relation files
would be a second user of the same engine, and a natural next patch, but
I'd rather have the engine reviewed against one user before writing
another. If the consensus is that the first piece should be the smaller
design you sketched, I'm open to that; tell me and I'll cut 0001 down to
it.

What changed from v8's 0001-0003

- Rebased onto current master.

- Removed what only the set-aside commits used: an UNDO buffer manager
with no caller, two bufmgr.c functions, the index AMs' batching entry
points, per-backend fields in TransactionStateData, the nbtree/hash
UNDO rmgr IDs, a revert worker LWLock tranche, and stubs and getters
that had no caller even in v8. About 1,700 lines.

- Comments, log messages, the READMEs and the docs no longer describe the
ATM, a revert worker, per-backend UNDO, index_undo or FLUX. The UNDO
chapter (doc/src/sgml/undo.sgml) is rewritten around FILEOPS; v8's
version documented pg_stat_undo and index_undo, which do not exist in
0001-0003.

- Manu's Oct 26 review, as it applies without the revert worker. With no
ATM, a FILEOPS inverse that fails (a real EACCES, say) is tried once and
not retried. The startup undo phase used to count such a record as
applied and log "1 transactions rolled back"; it now counts failures and
ends with a WARNING saying how many records could not be applied
(0001, test_fileops/024). The inline-abort memory context fix, whose
test was in v8's nbtree commit, has test_fileops/023 instead. Manu, your
t/021 and t/022 test the revert worker, so they wait for it.

- Two fixes for Windows that v8 only had in later commits: undostats.c
no longer marks its built-in SQL functions with PG_FUNCTION_INFO_V1,
which MSVC rejected as a second declaration, and recovery/062 and 065
skip their file-mode checks there.

- recovery/065 now crashes the server before it closes the client. It
closed the client first, so the backend sometimes rolled the
transaction back online before the crash, which runs into the gap
below instead of testing the crash path.

Each commit message has a "Changes since v7" section with the details.

A known gap

An online ROLLBACK reverses FILEOPS changes in the backend, and no WAL
records that it did; redo of the abort record only drops the transaction
from UNDO tracking. So a physical standby keeps a change the primary
rolled back, and so does the primary after a crash, once the abort record
has reached disk. A crash before that is fine: the transaction is then a
loser and the startup undo phase reverses it. v8 closed this in 0005 by
carrying the inverses in the abort record, and that left with 0005. I'll
bring that into 0002 in the next version.

The CF entry is still 7389; I should probably re-title it.

best.

-greg

Attachment Content-Type Size
v9-0003-Route-filesystem-mutations-through-FILEOPS.patch text/x-patch 21.2 KB
v9-0002-Add-transactional-filesystem-operations-FILEOPS-back.patch text/x-patch 255.4 KB
v9-0001-Add-a-cluster-wide-UNDO-engine-with-records-in-the-W.patch text/x-patch 332.6 KB

In response to

Browse pgsql-hackers by date

  From Date Subject
Next Message Salma Elsayed 2026-11-06 18:52:53 Re: PoC: Simplify recovery after dropping a table by LOGGING the restore LSN
Previous Message Greg Burd 2026-11-06 18:42:44 Re: Tepid: selective index updates for heap relations