Skip to content

Commit 256a5c7

Browse files
Maxim OrlovCommitfest Bot
authored andcommitted
Add pg_upgarde for 64 bit multixact offsets
Author: Maxim Orlov <[email protected]> Author: Heikki Linnakangas <[email protected]>
1 parent cbe201e commit 256a5c7

File tree

12 files changed

+830
-62
lines changed

12 files changed

+830
-62
lines changed

src/backend/access/transam/multixact.c

Lines changed: 0 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1829,48 +1829,6 @@ BootStrapMultiXact(void)
18291829
SimpleLruZeroAndWritePage(MultiXactMemberCtl, 0);
18301830
}
18311831

1832-
/*
1833-
* MaybeExtendOffsetSlru
1834-
* Extend the offsets SLRU area, if necessary
1835-
*
1836-
* After a binary upgrade from <= 9.2, the pg_multixact/offsets SLRU area might
1837-
* contain files that are shorter than necessary; this would occur if the old
1838-
* installation had used multixacts beyond the first page (files cannot be
1839-
* copied, because the on-disk representation is different). pg_upgrade would
1840-
* update pg_control to set the next offset value to be at that position, so
1841-
* that tuples marked as locked by such MultiXacts would be seen as visible
1842-
* without having to consult multixact. However, trying to create and use a
1843-
* new MultiXactId would result in an error because the page on which the new
1844-
* value would reside does not exist. This routine is in charge of creating
1845-
* such pages.
1846-
*/
1847-
static void
1848-
MaybeExtendOffsetSlru(void)
1849-
{
1850-
int64 pageno;
1851-
LWLock *lock;
1852-
1853-
pageno = MultiXactIdToOffsetPage(MultiXactState->nextMXact);
1854-
lock = SimpleLruGetBankLock(MultiXactOffsetCtl, pageno);
1855-
1856-
LWLockAcquire(lock, LW_EXCLUSIVE);
1857-
1858-
if (!SimpleLruDoesPhysicalPageExist(MultiXactOffsetCtl, pageno))
1859-
{
1860-
int slotno;
1861-
1862-
/*
1863-
* Fortunately for us, SimpleLruWritePage is already prepared to deal
1864-
* with creating a new segment file even if the page we're writing is
1865-
* not the first in it, so this is enough.
1866-
*/
1867-
slotno = SimpleLruZeroPage(MultiXactOffsetCtl, pageno);
1868-
SimpleLruWritePage(MultiXactOffsetCtl, slotno);
1869-
}
1870-
1871-
LWLockRelease(lock);
1872-
}
1873-
18741832
/*
18751833
* This must be called ONCE during postmaster or standalone-backend startup.
18761834
*
@@ -2063,20 +2021,6 @@ MultiXactSetNextMXact(MultiXactId nextMulti,
20632021
MultiXactState->nextMXact = nextMulti;
20642022
MultiXactState->nextOffset = nextMultiOffset;
20652023
LWLockRelease(MultiXactGenLock);
2066-
2067-
/*
2068-
* During a binary upgrade, make sure that the offsets SLRU is large
2069-
* enough to contain the next value that would be created.
2070-
*
2071-
* We need to do this pretty early during the first startup in binary
2072-
* upgrade mode: before StartupMultiXact() in fact, because this routine
2073-
* is called even before that by StartupXLOG(). And we can't do it
2074-
* earlier than at this point, because during that first call of this
2075-
* routine we determine the MultiXactState->nextMXact value that
2076-
* MaybeExtendOffsetSlru needs.
2077-
*/
2078-
if (IsBinaryUpgrade)
2079-
MaybeExtendOffsetSlru();
20802024
}
20812025

20822026
/*

src/bin/pg_upgrade/Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,14 @@ OBJS = \
1818
file.o \
1919
function.o \
2020
info.o \
21+
multixact_new.o \
22+
multixact_old.o \
2123
option.o \
2224
parallel.o \
2325
pg_upgrade.o \
2426
relfilenumber.o \
2527
server.o \
28+
slru_io.o \
2629
tablespace.o \
2730
task.o \
2831
util.o \

src/bin/pg_upgrade/meson.build

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,14 @@ pg_upgrade_sources = files(
88
'file.c',
99
'function.c',
1010
'info.c',
11+
'multixact_new.c',
12+
'multixact_old.c',
1113
'option.c',
1214
'parallel.c',
1315
'pg_upgrade.c',
1416
'relfilenumber.c',
1517
'server.c',
18+
'slru_io.c',
1619
'tablespace.c',
1720
'task.c',
1821
'util.c',

src/bin/pg_upgrade/multixact_new.c

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
/*
2+
* multixact_new.c
3+
*
4+
* Functions to write multixacts in the v19 format with 64-bit
5+
* MultiXactOffsets
6+
*
7+
* Copyright (c) 2025, PostgreSQL Global Development Group
8+
* src/bin/pg_upgrade/multixact_new.c
9+
*/
10+
11+
#include "postgres_fe.h"
12+
13+
#include "access/multixact.h"
14+
#include "access/multixact_internal.h"
15+
16+
#include "multixact_new.h"
17+
18+
MultiXactWriter *
19+
AllocMultiXactWrite(const char *pgdata, MultiXactId firstMulti,
20+
MultiXactOffset firstOffset)
21+
{
22+
MultiXactWriter *state = pg_malloc(sizeof(*state));
23+
char dir[MAXPGPATH] = {0};
24+
25+
pg_sprintf(dir, "%s/pg_multixact/offsets", pgdata);
26+
state->offset = AllocSlruWrite(dir, false);
27+
SlruWriteSwitchPage(state->offset, MultiXactIdToOffsetPage(firstMulti));
28+
29+
pg_sprintf(dir, "%s/pg_multixact/members", pgdata);
30+
state->members = AllocSlruWrite(dir, true /* use long segment names */ );
31+
SlruWriteSwitchPage(state->members, MXOffsetToMemberPage(firstOffset));
32+
33+
return state;
34+
}
35+
36+
/*
37+
* Write a new multixact with members.
38+
*
39+
* Simplified version of the correspoding server function, hence the name.
40+
*/
41+
void
42+
RecordNewMultiXact(MultiXactWriter *state, MultiXactOffset offset,
43+
MultiXactId multi, int nmembers, MultiXactMember *members)
44+
{
45+
int64 pageno;
46+
int64 prev_pageno;
47+
int entryno;
48+
char *buf;
49+
MultiXactOffset *offptr;
50+
51+
pageno = MultiXactIdToOffsetPage(multi);
52+
entryno = MultiXactIdToOffsetEntry(multi);
53+
54+
/* Store the offset */
55+
buf = SlruWriteSwitchPage(state->offset, pageno);
56+
offptr = (MultiXactOffset *) buf;
57+
offptr[entryno] = offset;
58+
59+
/* Store the members */
60+
prev_pageno = -1;
61+
for (int i = 0; i < nmembers; i++, offset++)
62+
{
63+
TransactionId *memberptr;
64+
uint32 *flagsptr;
65+
uint32 flagsval;
66+
int bshift;
67+
int flagsoff;
68+
int memberoff;
69+
70+
Assert(members[i].status <= MultiXactStatusUpdate);
71+
72+
pageno = MXOffsetToMemberPage(offset);
73+
memberoff = MXOffsetToMemberOffset(offset);
74+
flagsoff = MXOffsetToFlagsOffset(offset);
75+
bshift = MXOffsetToFlagsBitShift(offset);
76+
77+
if (pageno != prev_pageno)
78+
{
79+
buf = SlruWriteSwitchPage(state->members, pageno);
80+
prev_pageno = pageno;
81+
}
82+
83+
memberptr = (TransactionId *) (buf + memberoff);
84+
85+
*memberptr = members[i].xid;
86+
87+
flagsptr = (uint32 *) (buf + flagsoff);
88+
89+
flagsval = *flagsptr;
90+
flagsval &= ~(((1 << MXACT_MEMBER_BITS_PER_XACT) - 1) << bshift);
91+
flagsval |= (members[i].status << bshift);
92+
*flagsptr = flagsval;
93+
}
94+
}
95+
96+
void
97+
FreeMultiXactWrite(MultiXactWriter *state)
98+
{
99+
FreeSlruWrite(state->offset);
100+
FreeSlruWrite(state->members);
101+
102+
pfree(state);
103+
}

src/bin/pg_upgrade/multixact_new.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*
2+
* multixact_new.h
3+
*
4+
* Copyright (c) 2025, PostgreSQL Global Development Group
5+
* src/bin/pg_upgrade/multixact_new.h
6+
*/
7+
#include "access/multixact.h"
8+
9+
#include "slru_io.h"
10+
11+
typedef struct MultiXactWriter
12+
{
13+
SlruSegState *offset;
14+
SlruSegState *members;
15+
} MultiXactWriter;
16+
17+
extern MultiXactWriter *AllocMultiXactWrite(const char *pgdata,
18+
MultiXactId firstMulti,
19+
MultiXactOffset firstOffset);
20+
extern void RecordNewMultiXact(MultiXactWriter *state, MultiXactOffset offset,
21+
MultiXactId multi, int nmembers,
22+
MultiXactMember *members);
23+
extern void FreeMultiXactWrite(MultiXactWriter *writer);

0 commit comments

Comments
 (0)