Re: An improvement of ProcessTwoPhaseBuffer logic
Michael Paquier <michael@paquier.xyz>
From: Michael Paquier <michael@paquier.xyz>
To: Noah Misch <noah@leadboat.com>
Cc: Vitaly Davydov <v.davydov@postgrespro.ru>, pgsql-hackers <pgsql-hackers@postgresql.org>
Date: 2025-01-16T07:50:09Z
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 →
-
Integrate FullTransactionIds deeper into two-phase code
- 62a17a92833d 19 (unreleased) landed
-
Merge copies of converting an XID to a FullTransactionId.
- 1587f7b9fc1a 17.3 landed
- 81772a495ec9 18.0 landed
-
Revert recent changes related to handling of 2PC files at recovery
- 4d6d7bdc0642 13.19 landed
- 060f9f5ea537 14.16 landed
- 42c900d31e57 15.11 landed
- 4d72357c40ee 16.7 landed
- d1bf86a62211 17.3 landed
- a6c70f68cdeb 18.0 landed
-
Fix failures with incorrect epoch handling for 2PC files at recovery
- c3de0f9eed38 17.3 landed
- 7e125b20eed6 18.0 landed
Attachments
- v2-0001-Fix-twophase.c-XID-epoch-tracking.patch (text/x-diff) patch v2-0001
- v2-0002-Integrate-deeper-FullTransactionIds-into-twophase.patch (text/x-diff) patch v2-0002
On Wed, Jan 15, 2025 at 05:00:51PM -0800, Noah Misch wrote: > I agree with accepting +4 bytes in GlobalTransactionData. Let's just bite the bullet and do that on HEAD and v17, then, integrating deeper FullTransactionIds into the internals of twophase.c. > I think "using the current epoch" is wrong for half of the nextFullXid values > having epoch > 0. For example, nextFullId==2^32 is in epoch 1, but all the > allowable XIDs are in epoch 0. (I mean "allowable" in the sense of > AssertTransactionIdInAllowableRange().) From then until we assign another > 2^31 XIDs, epochs 0 and 1 are both expected in XID values. After 2^31 XID > assignments, every allowable XID be in epoch 1. Hence, twophase.c would need > two-epoch logic like we have in widen_snapshot_xid() and XLogRecGetFullXid(). > Is that right? (I wrote this in a hurry, so this email may have more than the > standard level of errors.) Before commit 7e125b2, twophase also had that > logic. I didn't work out the user-visible consequences of that logic's new > absence here, but I bet on twophase recovery breakage. Similar problem here > (up to two epochs are acceptable, not just one): > > + /* Discard files from past epochs */ > + if (EpochFromFullTransactionId(fxid) < EpochFromFullTransactionId(nextXid)) Oops, you're right. Your suggestion to unify all that in a single routine is an excellent idea. Missed the bits in xid8funcs.c. > I wrote the attached half-baked patch to fix those, but I tend to think it's > better to use FullTransactionId as many places as possible in twophase.c. > (We'd still need to convert XIDs that we read from xl_xact_prepare records, > along the lines of XLogRecGetFullXid().) How do you see it? I'm all for integrating more FullTransactionIds now that these reflect in the file names, and do a deeper cut. As far as I understand, the most important point of the logic is to detect and discard the future files first in restoreTwoPhaseData() -> ProcessTwoPhaseBuffer() when scanning the contents of pg_twophase at the beginning of recovery. Once this filtering is done, it should be safe to use your FullTransactionIdFromAllowableAt() when doing the fxid <-> xid transitions between the records and the files on disk flushed by a restartpoint which store an XID, and the shmem state of GlobalTransactionData with a fxid. With the additions attached, FullTransactionIdFromAllowableAt() gets down from 8 to 6 calls in twophase.c. The change related to MarkAsPreparingGuts() seems optional, though. I am trying to figure out how to write a regression test to trigger this error, lacking a bit of time today. That's going to require more trickery with pg_resetwal to make that cheap, or something like that.. Attached are some suggestions, as of a 0002 that applies on top of your 0001. XLogRecGetFullXid() is used nowhere. This could be removed, perhaps, or not? -- Michael