| From: | Yura Sokolov <y(dot)sokolov(at)postgrespro(dot)ru> |
|---|---|
| To: | "pgsql-hackers(at)lists(dot)postgresql(dot)org" <pgsql-hackers(at)lists(dot)postgresql(dot)org> |
| Cc: | Heikki Linnakangas <hlinnaka(at)iki(dot)fi>, Andres Freund <andres(at)anarazel(dot)de> |
| Subject: | Fix bug in multixact Oldest*MXactId initialization and access |
| Date: | 2026-02-24 17:35:18 |
| Message-ID: | 7acc94b0-ea82-4657-b1b0-77842cb7a60c@postgrespro.ru |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-hackers |
Good day.
multixact.c has bug in initialization and access of OldestMemberMXactId
(and partially OldestVisibleMXactId).
Size of this arrays is defined as:
#define MaxOldestSlot (MaxBackends + max_prepared_xacts)
assuming there are only backends and prepared transactions could hold
multixacts.
This assumption is correct. And in fact there were no bug when this formula
were introduced in 2009y [1], since these arrays were indexed but synthetic
dummy `dummyBackendId` field of `GlobalTransactionData` struct.
But in 2024y [2] field `dummyBackendId` were removed and pgprocno were used
instead.
But proc structs reserved for two phase commit are placed after auxiliary
procs, therefore writes to OldestMemberMXactId[dummy] starts to overwrites
slots of OldestVisibleMXactId.
Then PostgreSQL 18 increased NUM_AUXILIARY_PROCS due to reserve of workers
for AIO. And it is possible to make such test postgresql.conf with so
extremely low MaxBackend so writes to OldestMemberMXactId[dummy] overwrites
first entry of BufferDescriptors, which are allocated next in shared memory.
Patch in attach replaces direct accesses to this arrays with inline
functions which include asserts. And changes calculation of MaxOldestSlot
to include NUM_AUXILIARY_PROCS.
Certainly, it is not clearest patch possible:
- may be you will decide to not introduce inline functions,
- or will introduce separate inline function for each array,
- or will fix slot calculation to remove aux procs from account,
- or will revert deletion of dummyBackendId.
[1]
https://git.postgresql.org/gitweb/?p=postgresql.git;a=commitdiff;h=cd87b6f8a5084c070c3e56b07794be8fea33647d
[2]
https://git.postgresql.org/gitweb/?p=postgresql.git;a=commitdiff;h=ab355e3a88de745607f6dd4c21f0119b5c68f2ad
--
regards
Yura Sokolov aka funny-falcon
| Attachment | Content-Type | Size |
|---|---|---|
| v00-0001-Fix-multixacts-OldestMemberMXactId-and-OldestVis.patch | text/x-patch | 7.2 KB |
| From | Date | Subject | |
|---|---|---|---|
| Next Message | Álvaro Herrera | 2026-02-24 17:41:40 | Re: Cleaning up array_ref() and array_set() |
| Previous Message | Jacob Champion | 2026-02-24 17:27:52 | Re: pgsql: libpq: Grease the protocol by default |