TransactionXmin != MyProc->xmin
Heikki Linnakangas <hlinnaka@iki.fi>
From: Heikki Linnakangas <hlinnaka@iki.fi>
To: "pgsql-hackers@postgresql.org" <pgsql-hackers@postgresql.org>
Date: 2024-12-12T18:16:39Z
Lists: pgsql-hackers
Attachments
- subxid-truncation.spec (text/x-rpm-spec)
The comment in GetSnapshotData() defines transactionXmin like this: > TransactionXmin: the oldest xmin of any snapshot in use in the > current transaction (this is the same as MyProc->xmin). However, we don't update TransactionXmin when we update MyProc->xmin in SnapshotResetXmin(). So TransactionXmin can be older than MyProc->xmin. I browsed around to see if that might cause trouble, and found one such case: SubTransGetTopmostTransaction() uses TransactionXmin as the cut-off point so that it doesn't try to perform lookups of old XIDs that might've already been truncated away from pg_subtrans. When TransactionXmin is older than MyProc->xmin, then it might do that. The attached isolation test demonstrates that case and produces an error: ERROR: could not access status of transaction 17190290 DETAIL: Could not open file "pg_subtrans/0106": No such file or directory. A straightforward fix is to ensure that TransactionXmin is updated whenever MyProc->xmin is: diff --git a/src/backend/utils/time/snapmgr.c b/src/backend/utils/time/snapmgr.c index a1a0c2adeb6..f59830abd21 100644 --- a/src/backend/utils/time/snapmgr.c +++ b/src/backend/utils/time/snapmgr.c @@ -883,7 +883,7 @@ SnapshotResetXmin(void) pairingheap_first(&RegisteredSnapshots)); if (TransactionIdPrecedes(MyProc->xmin, minSnapshot->xmin)) - MyProc->xmin = minSnapshot->xmin; + MyProc->xmin = TransactionXmin = minSnapshot->xmin; } /* Anyone see a reason not to do that? There are a two other places where we set MyProc->xmin without updating TransactionXmin: 1. In ProcessStandbyHSFeedbackMessage(). AFAICS that's OK because walsender doesn't use TransactionXmin for anything. 2. In SnapBuildInitialSnapshot(). I suppose that's also OK because the TransactionXmin isn't used. I don't quite remember when that function might be called though. In any case, I propose that we set TransactionXmin in all of those cases as well, so that TransactionXmin is always the equal to MyProc->xmin. Maybe even rename it to MyProcXmin to make that more clear. -- Heikki Linnakangas Neon (https://neon.tech)
Commits
-
Update TransactionXmin when MyProc->xmin is updated
- 9c1afd3447ff 13.19 landed
- 41eafbb494c9 14.16 landed
- acd5c28db5d0 15.11 landed
- 9d8ab2c461d7 16.7 landed
- 7cfdb4d1e778 17.3 landed
- 578a7fe7b6f8 18.0 landed