Re: IPC/MultixactCreation on the Standby server
Heikki Linnakangas <hlinnaka@iki.fi>
From: Heikki Linnakangas <hlinnaka@iki.fi>
To: Ivan Bykov <i.bykov@modernsys.ru>, pgsql-hackers@lists.postgresql.org, Álvaro Herrera <alvherre@kurilemu.de>
Cc: Andrey Borodin <x4mmm@yandex-team.ru>,
Kirill Reshke <reshkekirill@gmail.com>
Date: 2025-11-25T09:57:39Z
Lists: pgsql-hackers
This approach makes a lot of sense to me. I think there's one more case that this fixes: If someone uses "pg_resetwal -m ..." to advance nextMulti, that's yet another case where the last multixid becomes unreadable because we haven't set the next mxid's offset in the SLRU yet. People shouldn't be running pg_resetwal unnecessarily, but the docs for pg_resetwal include instructions on how to determine a safe value for nextMulti. You will in fact lose the last multixid if you follow the instructions, so it's not as safe as it sounds. This patch fixes that issue too. Álvaro, are you planning to commit this? I've been looking at this code lately for the 64-bit mxoffsets patch, so I could also pick it up if you'd like. > @@ -1383,7 +1417,10 @@ GetMultiXactIdMembers(MultiXactId multi, MultiXactMember **members, > * 1. This multixact may be the latest one created, in which case there is > * no next one to look at. In this case the nextOffset value we just > * saved is the correct endpoint. > + * TODO: how does it work on Standby? MultiXactState->nextMXact does not seem to be up-to date. > + * nextMXact and nextOffset are in sync, so nothing bad can happen, but nextMXact seems mostly random. That's scary. AFAICS MultiXactState->nextMXact should be up-to-date in hot standby mode. Are we missing MultiXactAdvanceNextMXact() calls somewhere, or what's going on? The case 1. is still valid, you can indeed just look at the saved nextOffset. But now the next offset should also be set on the SLRU, except right after upgrading to a version that has this patch. So I guess we still need to have this special case to deal with upgrades. > * > + * THIS IS NOT POSSIBLE ANYMORE, KEEP IT FOR HISTORIC REASONS. > * 2. The next multixact may still be in process of being filled in: that > * is, another process may have done GetNewMultiXactId but not yet written > * the offset entry for that ID. In that scenario, it is guaranteed that This comment needs to be cleaned up to explain how all this works now... > @@ -1138,8 +1168,13 @@ GetNewMultiXactId(int nmembers, MultiXactOffset *offset) > result = FirstMultiXactId; > } > > - /* Make sure there is room for the MXID in the file. */ > - ExtendMultiXactOffset(result); > + /* > + * Make sure there is room for the MXID and next offset in the file. > + * We might overflow to the next segment, but we don't need to handle > + * FirstMultiXactId specifically, because ExtendMultiXactOffset handles > + * both cases well: 0 offset and FirstMultiXactId would create segment. > + */ > + ExtendMultiXactOffset(MultiXactState->nextMXact + 1); > > /* > * Reserve the members space, similarly to above. Also, be careful not to Does this create the file correctly, if you upgrade the binary to a new version that contains this patch, and nextMXact was at a segment boundary before the upgrade? > @@ -2487,10 +2509,11 @@ ExtendMultiXactOffset(MultiXactId multi) > > /* > * No work except at first MultiXactId of a page. But beware: just after > - * wraparound, the first MultiXactId of page zero is FirstMultiXactId. > + * wraparound, the first MultiXactId of page zero is FirstMultiXactId, > + * make sure we are not in that case. > */ > - if (MultiXactIdToOffsetEntry(multi) != 0 && > - multi != FirstMultiXactId) > + Assert(multi != FirstMultiXactId); > + if (MultiXactIdToOffsetEntry(multi) != 0) > return; > > pageno = MultiXactIdToOffsetPage(multi); I don't quite understand this change. I guess the point is that the caller now never calls this with FirstMultiXactId, but it feels a bit weird to assert and rely on that here. I didn't look at the test changes yet. - Heikki
Commits
Same data as JSON:
GET /api/v1/messages/:b64id/commits
the thread's linked commits as JSON, with link sources.
API reference →
-
Fix test to work with non-8kB block sizes
- 7c2061bdfba7 19 (unreleased) landed
-
Fix setting next multixid's offset at offset wraparound
- 48969555447f 14.21 landed
- b9a02b9780bc 15.16 landed
- 4d689a17693e 16.12 landed
- cad40cec24f3 17.8 landed
- 02ba5e3be4f3 18.2 landed
- 4d936c3fff1a 19 (unreleased) landed
-
Add test for multixid wraparound
- 7b81be9b4267 19 (unreleased) landed
-
Set next multixid's offset when creating a new multixid
- 81416e1016dd 14.21 landed
- 8cfb174a61eb 15.16 landed
- 635166913078 16.12 landed
- 8ba61bc06386 17.8 landed
- e46041fd973c 18.2 landed
- 789d65364cde 19 (unreleased) landed
-
psql: Improve tab completion for large objects.
- 14ee8e640300 19 (unreleased) cited
-
Refactor some repetitive SLRU code
- c61678551699 19 (unreleased) cited
-
Transaction IDs wrap around, per my proposal of 13-Aug-01. More
- bc7d37a525c0 7.2.1 cited