Re: Fix bug in multixact Oldest*MXactId initialization and access
Heikki Linnakangas <hlinnaka@iki.fi>
From: Heikki Linnakangas <hlinnaka@iki.fi>
To: Sami Imseih <samimseih@gmail.com>
Cc: Yura Sokolov <y.sokolov@postgrespro.ru>,
"pgsql-hackers@lists.postgresql.org" <pgsql-hackers@lists.postgresql.org>,
Chao Li <li.evan.chao@gmail.com>
Date: 2026-02-28T09:22:03Z
Lists: pgsql-hackers
Attachments
- v2-0001-Fix-multixacts-OldestMemberMXactId-and-OldestVisi.patch (text/x-patch) patch v2-0001
(added back pgsql-hackers, I think you replied in private by accident)
On 28/02/2026 00:07, Sami Imseih wrote:
> 1/
>
> +MyOldestMemberMXactIdSlot(void)
> +{
> + Assert(MyProcNumber >= 0 && MyProcNumber < MaxBackends);
>
> It would be better to use NumVisibleSlots instead of MaxBackends in
> the second assert condition.
MaxBackends makes the assertion more strict. It verifies that we use one
of the slots reserved for regular backends, not prepared xacts. I'll add
a comment on that.
> 2/
>
> +static inline MultiXactId *
> +PreparedXactOldestMemberMXactIdSlot(ProcNumber procno)
> +{
> + Assert(procno >= FIRST_PREPARED_XACT_PROC_NUMBER);
> + Assert(procno - FIRST_PREPARED_XACT_PROC_NUMBER <
> + NumMemberSlots);
> + return &OldestMemberMXactId[procno -
> + FIRST_PREPARED_XACT_PROC_NUMBER];
> +}
>
> given
>
> +#define FIRST_PREPARED_XACT_PROC_NUMBER \
> + (MaxBackends + NUM_AUXILIARY_PROCS)
>
> let's say, MaxBackends = 100 and NUM_AUXILIARY_PROCS = 38, the
> first prepared transaction procno will be 138. The current math
> will return an index of 0 (138 - 138 = 0), but this corrupts
> backend slot 0.
Oof, you're right.
> Should we not account for NumVisibleSlots to skip
> over the regular backend slots?
>
> ```
> return &OldestMemberMXactId[NumVisibleSlots + (procno -
> FIRST_PREPARED_XACT_PROC_NUMBER)];
> ```
That's not quite right either. NumVisibleSlots has nothing to do with
the OldestMemberMXactId array, MaxBackends is the right offset here.
NumVisibleSlots == MaxBackends, but that's just a coincidence.
New version attached.
- Heikki
Commits
Same data as JSON:
GET /api/v1/messages/:b64id/commits
the thread's linked commits as JSON, with link sources.
API reference →
-
Add test for row-locking and multixids with prepared transactions
- 969576dab47b 17.10 landed
- fa3b328e6dc5 18.4 landed
- fe08113aefc9 19 (unreleased) landed
-
Skip prepared_xacts test if max_prepared_transactions < 2
- ffe53037dff7 14.23 landed
- a6b11ac4c42d 15.18 landed
- 65f5c451a3e1 16.14 landed
- 80d1d4ee06fd 17.10 landed
- 201436c19f40 18.4 landed
- 19615a44b3e6 19 (unreleased) landed
-
Fix OldestMemberMXactId and OldestVisibleMXactId array usage
- dcd9c06a4203 17.10 landed
- 0a50ef094382 18.4 landed
- ccae90abdbb6 19 (unreleased) landed
-
Redefine backend ID to be an index into the proc array
- ab355e3a88de 17.0 cited
-
Fix an old bug in multixact and two-phase commit. Prepared transactions can
- cd87b6f8a508 9.0.0 cited