PostgreSQL Source Code git master
Loading...
Searching...
No Matches
multixact.h File Reference
#include "access/transam.h"
#include "access/xlogreader.h"
#include "lib/stringinfo.h"
#include "storage/sync.h"
Include dependency graph for multixact.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  MultiXactMember
 
struct  xl_multixact_create
 
struct  xl_multixact_truncate
 

Macros

#define InvalidMultiXactId   ((MultiXactId) 0)
 
#define FirstMultiXactId   ((MultiXactId) 1)
 
#define MaxMultiXactId   ((MultiXactId) 0xFFFFFFFF)
 
#define MultiXactIdIsValid(multi)   ((multi) != InvalidMultiXactId)
 
#define MaxMultiXactStatus   MultiXactStatusUpdate
 
#define ISUPDATE_from_mxstatus(status)    ((status) > MultiXactStatusForUpdate)
 
#define XLOG_MULTIXACT_ZERO_OFF_PAGE   0x00
 
#define XLOG_MULTIXACT_ZERO_MEM_PAGE   0x10
 
#define XLOG_MULTIXACT_CREATE_ID   0x20
 
#define XLOG_MULTIXACT_TRUNCATE_ID   0x30
 
#define SizeOfMultiXactCreate   (offsetof(xl_multixact_create, members))
 
#define SizeOfMultiXactTruncate   (sizeof(xl_multixact_truncate))
 

Typedefs

typedef struct MultiXactMember MultiXactMember
 
typedef struct xl_multixact_create xl_multixact_create
 
typedef struct xl_multixact_truncate xl_multixact_truncate
 

Enumerations

enum  MultiXactStatus {
  MultiXactStatusForKeyShare = 0x00 , MultiXactStatusForShare = 0x01 , MultiXactStatusForNoKeyUpdate = 0x02 , MultiXactStatusForUpdate = 0x03 ,
  MultiXactStatusNoKeyUpdate = 0x04 , MultiXactStatusUpdate = 0x05
}
 

Functions

MultiXactId MultiXactIdCreate (TransactionId xid1, MultiXactStatus status1, TransactionId xid2, MultiXactStatus status2)
 
MultiXactId MultiXactIdExpand (MultiXactId multi, TransactionId xid, MultiXactStatus status)
 
MultiXactId MultiXactIdCreateFromMembers (int nmembers, MultiXactMember *members)
 
MultiXactId ReadNextMultiXactId (void)
 
void ReadMultiXactIdRange (MultiXactId *oldest, MultiXactId *next)
 
bool MultiXactIdIsRunning (MultiXactId multi, bool isLockOnly)
 
void MultiXactIdSetOldestMember (void)
 
int GetMultiXactIdMembers (MultiXactId multi, MultiXactMember **members, bool from_pgupgrade, bool isLockOnly)
 
void GetMultiXactInfo (uint32 *multixacts, MultiXactOffset *nextOffset, MultiXactId *oldestMultiXactId, MultiXactOffset *oldestOffset)
 
bool MultiXactIdPrecedes (MultiXactId multi1, MultiXactId multi2)
 
bool MultiXactIdPrecedesOrEquals (MultiXactId multi1, MultiXactId multi2)
 
int multixactoffsetssyncfiletag (const FileTag *ftag, char *path)
 
int multixactmemberssyncfiletag (const FileTag *ftag, char *path)
 
void AtEOXact_MultiXact (void)
 
void AtPrepare_MultiXact (void)
 
void PostPrepare_MultiXact (FullTransactionId fxid)
 
Size MultiXactShmemSize (void)
 
void MultiXactShmemInit (void)
 
void BootStrapMultiXact (void)
 
void StartupMultiXact (void)
 
void TrimMultiXact (void)
 
void SetMultiXactIdLimit (MultiXactId oldest_datminmxid, Oid oldest_datoid)
 
void MultiXactGetCheckptMulti (bool is_shutdown, MultiXactId *nextMulti, MultiXactOffset *nextMultiOffset, MultiXactId *oldestMulti, Oid *oldestMultiDB)
 
void CheckPointMultiXact (void)
 
MultiXactId GetOldestMultiXactId (void)
 
void TruncateMultiXact (MultiXactId newOldestMulti, Oid newOldestMultiDB)
 
void MultiXactSetNextMXact (MultiXactId nextMulti, MultiXactOffset nextMultiOffset)
 
void MultiXactAdvanceNextMXact (MultiXactId minMulti, MultiXactOffset minMultiOffset)
 
void MultiXactAdvanceOldest (MultiXactId oldestMulti, Oid oldestMultiDB)
 
int MultiXactMemberFreezeThreshold (void)
 
void multixact_twophase_recover (FullTransactionId fxid, uint16 info, void *recdata, uint32 len)
 
void multixact_twophase_postcommit (FullTransactionId fxid, uint16 info, void *recdata, uint32 len)
 
void multixact_twophase_postabort (FullTransactionId fxid, uint16 info, void *recdata, uint32 len)
 
void multixact_redo (XLogReaderState *record)
 
void multixact_desc (StringInfo buf, XLogReaderState *record)
 
const charmultixact_identify (uint8 info)
 
charmxid_to_string (MultiXactId multi, int nmembers, MultiXactMember *members)
 
charmxstatus_to_string (MultiXactStatus status)
 

Macro Definition Documentation

◆ FirstMultiXactId

#define FirstMultiXactId   ((MultiXactId) 1)

Definition at line 26 of file multixact.h.

◆ InvalidMultiXactId

#define InvalidMultiXactId   ((MultiXactId) 0)

Definition at line 25 of file multixact.h.

◆ ISUPDATE_from_mxstatus

#define ISUPDATE_from_mxstatus (   status)     ((status) > MultiXactStatusForUpdate)

Definition at line 51 of file multixact.h.

55{
56 TransactionId xid;
57 MultiXactStatus status;
59
60
61/* ----------------
62 * multixact-related XLOG entries
63 * ----------------
64 */
65
66#define XLOG_MULTIXACT_ZERO_OFF_PAGE 0x00
67#define XLOG_MULTIXACT_ZERO_MEM_PAGE 0x10
68#define XLOG_MULTIXACT_CREATE_ID 0x20
69#define XLOG_MULTIXACT_TRUNCATE_ID 0x30
70
71typedef struct xl_multixact_create
72{
73 MultiXactId mid; /* new MultiXact's ID */
74 MultiXactOffset moff; /* its starting offset in members file */
75 int32 nmembers; /* number of member XIDs */
78
79#define SizeOfMultiXactCreate (offsetof(xl_multixact_create, members))
80
81typedef struct xl_multixact_truncate
82{
84
85 /* truncate multixact offsets older than this */
87
88 /* truncate multixact members older than this */
91
92#define SizeOfMultiXactTruncate (sizeof(xl_multixact_truncate))
93
94
99 MultiXactStatus status);
100extern MultiXactId MultiXactIdCreateFromMembers(int nmembers,
101 MultiXactMember *members);
102
105extern bool MultiXactIdIsRunning(MultiXactId multi, bool isLockOnly);
106extern void MultiXactIdSetOldestMember(void);
107extern int GetMultiXactIdMembers(MultiXactId multi, MultiXactMember **members,
108 bool from_pgupgrade, bool isLockOnly);
109extern void GetMultiXactInfo(uint32 *multixacts, MultiXactOffset *nextOffset,
110 MultiXactId *oldestMultiXactId,
111 MultiXactOffset *oldestOffset);
115
116extern int multixactoffsetssyncfiletag(const FileTag *ftag, char *path);
117extern int multixactmemberssyncfiletag(const FileTag *ftag, char *path);
118
119extern void AtEOXact_MultiXact(void);
120extern void AtPrepare_MultiXact(void);
122
123extern Size MultiXactShmemSize(void);
124extern void MultiXactShmemInit(void);
125extern void BootStrapMultiXact(void);
126extern void StartupMultiXact(void);
127extern void TrimMultiXact(void);
130extern void MultiXactGetCheckptMulti(bool is_shutdown,
131 MultiXactId *nextMulti,
132 MultiXactOffset *nextMultiOffset,
133 MultiXactId *oldestMulti,
134 Oid *oldestMultiDB);
135extern void CheckPointMultiXact(void);
139extern void MultiXactSetNextMXact(MultiXactId nextMulti,
140 MultiXactOffset nextMultiOffset);
143extern void MultiXactAdvanceOldest(MultiXactId oldestMulti, Oid oldestMultiDB);
144extern int MultiXactMemberFreezeThreshold(void);
145
147 void *recdata, uint32 len);
149 void *recdata, uint32 len);
151 void *recdata, uint32 len);
152
153extern void multixact_redo(XLogReaderState *record);
154extern void multixact_desc(StringInfo buf, XLogReaderState *record);
155extern const char *multixact_identify(uint8 info);
156extern char *mxid_to_string(MultiXactId multi, int nmembers,
157 MultiXactMember *members);
158extern char *mxstatus_to_string(MultiXactStatus status);
159
160#endif /* MULTIXACT_H */
static int32 next
Definition blutils.c:225
uint8_t uint8
Definition c.h:586
TransactionId MultiXactId
Definition c.h:718
#define FLEXIBLE_ARRAY_MEMBER
Definition c.h:522
uint64 MultiXactOffset
Definition c.h:720
int32_t int32
Definition c.h:584
uint16_t uint16
Definition c.h:587
uint32_t uint32
Definition c.h:588
uint32 TransactionId
Definition c.h:708
size_t Size
Definition c.h:661
void MultiXactShmemInit(void)
Definition multixact.c:1773
MultiXactId MultiXactIdExpand(MultiXactId multi, TransactionId xid, MultiXactStatus status)
Definition multixact.c:390
void ReadMultiXactIdRange(MultiXactId *oldest, MultiXactId *next)
Definition multixact.c:675
bool MultiXactIdPrecedes(MultiXactId multi1, MultiXactId multi2)
Definition multixact.c:2818
char * mxstatus_to_string(MultiXactStatus status)
Definition multixact.c:1552
void multixact_redo(XLogReaderState *record)
Definition multixact.c:2868
MultiXactStatus
Definition multixact.h:37
void multixact_twophase_postcommit(FullTransactionId fxid, uint16 info, void *recdata, uint32 len)
Definition multixact.c:1718
int multixactoffsetssyncfiletag(const FileTag *ftag, char *path)
Definition multixact.c:2965
void PostPrepare_MultiXact(FullTransactionId fxid)
Definition multixact.c:1648
void MultiXactSetNextMXact(MultiXactId nextMulti, MultiXactOffset nextMultiOffset)
Definition multixact.c:2041
void AtPrepare_MultiXact(void)
Definition multixact.c:1634
bool MultiXactIdPrecedesOrEquals(MultiXactId multi1, MultiXactId multi2)
Definition multixact.c:2832
void MultiXactAdvanceOldest(MultiXactId oldestMulti, Oid oldestMultiDB)
Definition multixact.c:2240
void GetMultiXactInfo(uint32 *multixacts, MultiXactOffset *nextOffset, MultiXactId *oldestMultiXactId, MultiXactOffset *oldestOffset)
Definition multixact.c:2520
bool MultiXactIdIsRunning(MultiXactId multi, bool isLockOnly)
Definition multixact.c:501
void MultiXactIdSetOldestMember(void)
Definition multixact.c:575
void multixact_desc(StringInfo buf, XLogReaderState *record)
Definition mxactdesc.c:50
Size MultiXactShmemSize(void)
Definition multixact.c:1761
void MultiXactGetCheckptMulti(bool is_shutdown, MultiXactId *nextMulti, MultiXactOffset *nextMultiOffset, MultiXactId *oldestMulti, Oid *oldestMultiDB)
Definition multixact.c:1995
int multixactmemberssyncfiletag(const FileTag *ftag, char *path)
Definition multixact.c:2974
MultiXactId GetOldestMultiXactId(void)
Definition multixact.c:2352
void CheckPointMultiXact(void)
Definition multixact.c:2017
MultiXactId MultiXactIdCreateFromMembers(int nmembers, MultiXactMember *members)
Definition multixact.c:694
void TrimMultiXact(void)
Definition multixact.c:1883
char * mxid_to_string(MultiXactId multi, int nmembers, MultiXactMember *members)
Definition multixact.c:1575
void multixact_twophase_postabort(FullTransactionId fxid, uint16 info, void *recdata, uint32 len)
Definition multixact.c:1733
int MultiXactMemberFreezeThreshold(void)
Definition multixact.c:2564
void MultiXactAdvanceNextMXact(MultiXactId minMulti, MultiXactOffset minMultiOffset)
Definition multixact.c:2213
MultiXactId ReadNextMultiXactId(void)
Definition multixact.c:658
void BootStrapMultiXact(void)
Definition multixact.c:1842
void multixact_twophase_recover(FullTransactionId fxid, uint16 info, void *recdata, uint32 len)
Definition multixact.c:1697
MultiXactId MultiXactIdCreate(TransactionId xid1, MultiXactStatus status1, TransactionId xid2, MultiXactStatus status2)
Definition multixact.c:337
void TruncateMultiXact(MultiXactId newOldestMulti, Oid newOldestMultiDB)
Definition multixact.c:2652
const char * multixact_identify(uint8 info)
Definition mxactdesc.c:83
void AtEOXact_MultiXact(void)
Definition multixact.c:1606
void StartupMultiXact(void)
Definition multixact.c:1858
void SetMultiXactIdLimit(MultiXactId oldest_datminmxid, Oid oldest_datoid)
Definition multixact.c:2063
int GetMultiXactIdMembers(MultiXactId multi, MultiXactMember **members, bool from_pgupgrade, bool isLockOnly)
Definition multixact.c:1151
const void size_t len
static char buf[DEFAULT_XLOG_SEG_SIZE]
unsigned int Oid
static int fb(int x)
Definition sync.h:51
MultiXactId mid
Definition multixact.h:74
MultiXactMember members[FLEXIBLE_ARRAY_MEMBER]
Definition multixact.h:77
MultiXactOffset moff
Definition multixact.h:75
MultiXactOffset oldestOffset
Definition multixact.h:90
MultiXactId oldestMulti
Definition multixact.h:87

◆ MaxMultiXactId

#define MaxMultiXactId   ((MultiXactId) 0xFFFFFFFF)

Definition at line 27 of file multixact.h.

◆ MaxMultiXactStatus

#define MaxMultiXactStatus   MultiXactStatusUpdate

Definition at line 48 of file multixact.h.

◆ MultiXactIdIsValid

#define MultiXactIdIsValid (   multi)    ((multi) != InvalidMultiXactId)

Definition at line 29 of file multixact.h.

◆ SizeOfMultiXactCreate

#define SizeOfMultiXactCreate   (offsetof(xl_multixact_create, members))

Definition at line 80 of file multixact.h.

◆ SizeOfMultiXactTruncate

#define SizeOfMultiXactTruncate   (sizeof(xl_multixact_truncate))

Definition at line 93 of file multixact.h.

◆ XLOG_MULTIXACT_CREATE_ID

#define XLOG_MULTIXACT_CREATE_ID   0x20

Definition at line 69 of file multixact.h.

◆ XLOG_MULTIXACT_TRUNCATE_ID

#define XLOG_MULTIXACT_TRUNCATE_ID   0x30

Definition at line 70 of file multixact.h.

◆ XLOG_MULTIXACT_ZERO_MEM_PAGE

#define XLOG_MULTIXACT_ZERO_MEM_PAGE   0x10

Definition at line 68 of file multixact.h.

◆ XLOG_MULTIXACT_ZERO_OFF_PAGE

#define XLOG_MULTIXACT_ZERO_OFF_PAGE   0x00

Definition at line 67 of file multixact.h.

Typedef Documentation

◆ MultiXactMember

◆ xl_multixact_create

◆ xl_multixact_truncate

Enumeration Type Documentation

◆ MultiXactStatus

Enumerator
MultiXactStatusForKeyShare 
MultiXactStatusForShare 
MultiXactStatusForNoKeyUpdate 
MultiXactStatusForUpdate 
MultiXactStatusNoKeyUpdate 
MultiXactStatusUpdate 

Definition at line 36 of file multixact.h.

37{
42 /* an update that doesn't touch "key" columns */
44 /* other updates, and delete */
@ MultiXactStatusForShare
Definition multixact.h:39
@ MultiXactStatusForNoKeyUpdate
Definition multixact.h:40
@ MultiXactStatusNoKeyUpdate
Definition multixact.h:43
@ MultiXactStatusUpdate
Definition multixact.h:45
@ MultiXactStatusForUpdate
Definition multixact.h:41
@ MultiXactStatusForKeyShare
Definition multixact.h:38

Function Documentation

◆ AtEOXact_MultiXact()

void AtEOXact_MultiXact ( void  )
extern

Definition at line 1606 of file multixact.c.

1607{
1608 /*
1609 * Reset our OldestMemberMXactId and OldestVisibleMXactId values, both of
1610 * which should only be valid while within a transaction.
1611 *
1612 * We assume that storing a MultiXactId is atomic and so we need not take
1613 * MultiXactGenLock to do this.
1614 */
1617
1618 /*
1619 * Discard the local MultiXactId cache. Since MXactContext was created as
1620 * a child of TopTransactionContext, we needn't delete it explicitly.
1621 */
1624}
static void dclist_init(dclist_head *head)
Definition ilist.h:671
static MultiXactId * MyOldestVisibleMXactIdSlot(void)
Definition multixact.c:253
static MemoryContext MXactContext
Definition multixact.c:286
static dclist_head MXactCache
Definition multixact.c:285
static MultiXactId * MyOldestMemberMXactIdSlot(void)
Definition multixact.c:225
#define InvalidMultiXactId
Definition multixact.h:25

References dclist_init(), fb(), InvalidMultiXactId, MXactCache, MXactContext, MyOldestMemberMXactIdSlot(), and MyOldestVisibleMXactIdSlot().

Referenced by AbortTransaction(), CommitTransaction(), and test_read_multixact().

◆ AtPrepare_MultiXact()

void AtPrepare_MultiXact ( void  )
extern

Definition at line 1634 of file multixact.c.

1635{
1637
1640 &myOldestMember, sizeof(MultiXactId));
1641}
#define MultiXactIdIsValid(multi)
Definition multixact.h:29
void RegisterTwoPhaseRecord(TwoPhaseRmgrId rmid, uint16 info, const void *data, uint32 len)
Definition twophase.c:1273
#define TWOPHASE_RM_MULTIXACT_ID

References fb(), MultiXactIdIsValid, MyOldestMemberMXactIdSlot(), RegisterTwoPhaseRecord(), and TWOPHASE_RM_MULTIXACT_ID.

Referenced by PrepareTransaction().

◆ BootStrapMultiXact()

void BootStrapMultiXact ( void  )
extern

Definition at line 1842 of file multixact.c.

1843{
1844 /* Zero the initial pages and flush them to disk */
1847}
#define MultiXactMemberCtl
Definition multixact.c:120
#define MultiXactOffsetCtl
Definition multixact.c:119
void SimpleLruZeroAndWritePage(SlruCtl ctl, int64 pageno)
Definition slru.c:445

References MultiXactMemberCtl, MultiXactOffsetCtl, and SimpleLruZeroAndWritePage().

Referenced by BootStrapXLOG().

◆ CheckPointMultiXact()

void CheckPointMultiXact ( void  )
extern

Definition at line 2017 of file multixact.c.

2018{
2020
2021 /*
2022 * Write dirty MultiXact pages to disk. This may result in sync requests
2023 * queued for later handling by ProcessSyncRequests(), as part of the
2024 * checkpoint.
2025 */
2028
2030}
void SimpleLruWriteAll(SlruCtl ctl, bool allow_redirtied)
Definition slru.c:1348

References fb(), MultiXactMemberCtl, MultiXactOffsetCtl, and SimpleLruWriteAll().

Referenced by CheckPointGuts().

◆ GetMultiXactIdMembers()

int GetMultiXactIdMembers ( MultiXactId  multi,
MultiXactMember **  members,
bool  from_pgupgrade,
bool  isLockOnly 
)
extern

Definition at line 1151 of file multixact.c.

1153{
1154 int64 pageno;
1156 int entryno;
1157 int slotno;
1159 MultiXactOffset offset;
1161 int length;
1163 MultiXactId nextMXact;
1164 MultiXactMember *ptr;
1165 LWLock *lock;
1166
1167 debug_elog3(DEBUG2, "GetMembers: asked for %u", multi);
1168
1169 if (!MultiXactIdIsValid(multi) || from_pgupgrade)
1170 {
1171 *members = NULL;
1172 return -1;
1173 }
1174
1175 /* See if the MultiXactId is in the local cache */
1176 length = mXactCacheGetById(multi, members);
1177 if (length >= 0)
1178 {
1179 debug_elog3(DEBUG2, "GetMembers: found %s in the cache",
1180 mxid_to_string(multi, length, *members));
1181 return length;
1182 }
1183
1184 /* Set our OldestVisibleMXactId[] entry if we didn't already */
1186
1187 /*
1188 * If we know the multi is used only for locking and not for updates, then
1189 * we can skip checking if the value is older than our oldest visible
1190 * multi. It cannot possibly still be running.
1191 */
1192 if (isLockOnly &&
1194 {
1195 debug_elog2(DEBUG2, "GetMembers: a locker-only multi is too old");
1196 *members = NULL;
1197 return -1;
1198 }
1199
1200 /*
1201 * We check known limits on MultiXact before resorting to the SLRU area.
1202 *
1203 * An ID older than MultiXactState->oldestMultiXactId cannot possibly be
1204 * useful; it has already been removed, or will be removed shortly, by
1205 * truncation. If one is passed, an error is raised.
1206 *
1207 * Also, an ID >= nextMXact shouldn't ever be seen here; if it is seen, it
1208 * implies undetected ID wraparound has occurred. This raises a hard
1209 * error.
1210 *
1211 * Shared lock is enough here since we aren't modifying any global state.
1212 * Acquire it just long enough to grab the current counter values.
1213 */
1215
1217 nextMXact = MultiXactState->nextMXact;
1218
1220
1221 if (MultiXactIdPrecedes(multi, oldestMXact))
1222 ereport(ERROR,
1224 errmsg("MultiXactId %u does no longer exist -- apparent wraparound",
1225 multi)));
1226
1227 if (!MultiXactIdPrecedes(multi, nextMXact))
1228 ereport(ERROR,
1230 errmsg("MultiXactId %u has not been created yet -- apparent wraparound",
1231 multi)));
1232
1233 /*
1234 * Find out the offset at which we need to start reading MultiXactMembers
1235 * and the number of members in the multixact. We determine the latter as
1236 * the difference between this multixact's starting offset and the next
1237 * one's.
1238 */
1239 pageno = MultiXactIdToOffsetPage(multi);
1241
1242 /* Acquire the bank lock for the page we need. */
1245
1246 /* read this multi's offset */
1247 slotno = SimpleLruReadPage(MultiXactOffsetCtl, pageno, true, multi);
1248 offptr = (MultiXactOffset *) MultiXactOffsetCtl->shared->page_buffer[slotno];
1249 offptr += entryno;
1250 offset = *offptr;
1251
1252 if (offset == 0)
1253 ereport(ERROR,
1255 errmsg("MultiXact %u has invalid offset", multi)));
1256
1257 /* read next multi's offset */
1258 {
1260
1261 /* handle wraparound if needed */
1262 tmpMXact = NextMultiXactId(multi);
1263
1264 prev_pageno = pageno;
1265
1268
1269 if (pageno != prev_pageno)
1270 {
1271 LWLock *newlock;
1272
1273 /*
1274 * Since we're going to access a different SLRU page, if this page
1275 * falls under a different bank, release the old bank's lock and
1276 * acquire the lock of the new bank.
1277 */
1279 if (newlock != lock)
1280 {
1281 LWLockRelease(lock);
1283 lock = newlock;
1284 }
1286 }
1287
1288 offptr = (MultiXactOffset *) MultiXactOffsetCtl->shared->page_buffer[slotno];
1289 offptr += entryno;
1291 }
1292
1293 LWLockRelease(lock);
1294 lock = NULL;
1295
1296 /* Sanity check the next offset */
1297 if (nextMXOffset == 0)
1298 ereport(ERROR,
1300 errmsg("MultiXact %u has invalid next offset", multi)));
1301 if (nextMXOffset == offset)
1302 ereport(ERROR,
1304 errmsg("MultiXact %u with offset (%" PRIu64 ") has zero members",
1305 multi, offset)));
1306 if (nextMXOffset < offset)
1307 ereport(ERROR,
1309 errmsg("MultiXact %u has offset (%" PRIu64 ") greater than its next offset (%" PRIu64 ")",
1310 multi, offset, nextMXOffset)));
1311 if (nextMXOffset - offset > INT32_MAX)
1312 ereport(ERROR,
1314 errmsg("MultiXact %u has too many members (%" PRIu64 ")",
1315 multi, nextMXOffset - offset)));
1316 length = nextMXOffset - offset;
1317
1318 /* read the members */
1319 ptr = (MultiXactMember *) palloc(length * sizeof(MultiXactMember));
1320 prev_pageno = -1;
1321 for (int i = 0; i < length; i++, offset++)
1322 {
1325 int flagsoff;
1326 int bshift;
1327 int memberoff;
1328
1329 pageno = MXOffsetToMemberPage(offset);
1331
1332 if (pageno != prev_pageno)
1333 {
1334 LWLock *newlock;
1335
1336 /*
1337 * Since we're going to access a different SLRU page, if this page
1338 * falls under a different bank, release the old bank's lock and
1339 * acquire the lock of the new bank.
1340 */
1342 if (newlock != lock)
1343 {
1344 if (lock)
1345 LWLockRelease(lock);
1347 lock = newlock;
1348 }
1349
1350 slotno = SimpleLruReadPage(MultiXactMemberCtl, pageno, true, multi);
1351 prev_pageno = pageno;
1352 }
1353
1355 (MultiXactMemberCtl->shared->page_buffer[slotno] + memberoff);
1357
1360 flagsptr = (uint32 *) (MultiXactMemberCtl->shared->page_buffer[slotno] + flagsoff);
1361
1362 ptr[i].xid = *xactptr;
1364 }
1365
1366 LWLockRelease(lock);
1367
1368 /*
1369 * Copy the result into the local cache.
1370 */
1371 mXactCachePut(multi, length, ptr);
1372
1373 debug_elog3(DEBUG2, "GetMembers: no cache for %s",
1374 mxid_to_string(multi, length, ptr));
1375 *members = ptr;
1376 return length;
1377}
#define Assert(condition)
Definition c.h:915
int64_t int64
Definition c.h:585
int errcode(int sqlerrcode)
Definition elog.c:874
#define DEBUG2
Definition elog.h:29
#define ERROR
Definition elog.h:39
#define ereport(elevel,...)
Definition elog.h:150
int i
Definition isn.c:77
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition lwlock.c:1177
void LWLockRelease(LWLock *lock)
Definition lwlock.c:1794
@ LW_SHARED
Definition lwlock.h:113
@ LW_EXCLUSIVE
Definition lwlock.h:112
void * palloc(Size size)
Definition mcxt.c:1387
static int mXactCacheGetById(MultiXactId multi, MultiXactMember **members)
Definition multixact.c:1460
bool MultiXactIdPrecedes(MultiXactId multi1, MultiXactId multi2)
Definition multixact.c:2818
static void MultiXactIdSetOldestVisible(void)
Definition multixact.c:625
static void mXactCachePut(MultiXactId multi, int nmembers, MultiXactMember *members)
Definition multixact.c:1507
static MultiXactId NextMultiXactId(MultiXactId multi)
Definition multixact.c:102
#define debug_elog3(a, b, c)
Definition multixact.c:296
char * mxid_to_string(MultiXactId multi, int nmembers, MultiXactMember *members)
Definition multixact.c:1575
static MultiXactStateData * MultiXactState
Definition multixact.c:219
#define debug_elog2(a, b)
Definition multixact.c:295
static int MXOffsetToFlagsBitShift(MultiXactOffset32 offset)
#define MXACT_MEMBER_XACT_BITMASK
static int64 MXOffsetToMemberPage(MultiXactOffset32 offset)
static int MXOffsetToMemberOffset(MultiXactOffset32 offset)
static int MultiXactIdToOffsetEntry(MultiXactId multi)
static int64 MultiXactIdToOffsetPage(MultiXactId multi)
static int MXOffsetToFlagsOffset(MultiXactOffset32 offset)
static char * errmsg
#define ERRCODE_DATA_CORRUPTED
int SimpleLruReadPage(SlruCtl ctl, int64 pageno, bool write_ok, TransactionId xid)
Definition slru.c:528
static LWLock * SimpleLruGetBankLock(SlruCtl ctl, int64 pageno)
Definition slru.h:160
TransactionId xid
Definition multixact.h:57
MultiXactStatus status
Definition multixact.h:58
MultiXactId nextMXact
Definition multixact.c:132
MultiXactId oldestMultiXactId
Definition multixact.c:145
#define TransactionIdIsValid(xid)
Definition transam.h:41

References Assert, DEBUG2, debug_elog2, debug_elog3, ereport, errcode(), ERRCODE_DATA_CORRUPTED, errmsg, ERROR, fb(), i, LW_EXCLUSIVE, LW_SHARED, LWLockAcquire(), LWLockRelease(), MultiXactIdIsValid, MultiXactIdPrecedes(), MultiXactIdSetOldestVisible(), MultiXactIdToOffsetEntry(), MultiXactIdToOffsetPage(), MultiXactMemberCtl, MultiXactOffsetCtl, MultiXactState, MXACT_MEMBER_XACT_BITMASK, mXactCacheGetById(), mXactCachePut(), mxid_to_string(), MXOffsetToFlagsBitShift(), MXOffsetToFlagsOffset(), MXOffsetToMemberOffset(), MXOffsetToMemberPage(), MyOldestVisibleMXactIdSlot(), NextMultiXactId(), MultiXactStateData::nextMXact, MultiXactStateData::oldestMultiXactId, palloc(), SimpleLruGetBankLock(), SimpleLruReadPage(), MultiXactMember::status, TransactionIdIsValid, and MultiXactMember::xid.

Referenced by Do_MultiXactIdWait(), DoesMultiXactIdConflict(), FreezeMultiXactId(), GetMultiXactIdHintBits(), heap_lock_tuple(), heap_lock_updated_tuple_rec(), heap_tuple_should_freeze(), MultiXactIdExpand(), MultiXactIdGetUpdateXid(), MultiXactIdIsRunning(), pg_get_multixact_members(), pgrowlocks(), and test_read_multixact().

◆ GetMultiXactInfo()

void GetMultiXactInfo ( uint32 multixacts,
MultiXactOffset nextOffset,
MultiXactId oldestMultiXactId,
MultiXactOffset oldestOffset 
)
extern

◆ GetOldestMultiXactId()

MultiXactId GetOldestMultiXactId ( void  )
extern

Definition at line 2352 of file multixact.c.

2353{
2355
2356 /*
2357 * This is the oldest valid value among all the OldestMemberMXactId[] and
2358 * OldestVisibleMXactId[] entries, or nextMXact if none are valid.
2359 */
2362 for (int i = 0; i < NumMemberSlots; i++)
2363 {
2365
2370 }
2371 for (int i = 0; i < NumVisibleSlots; i++)
2372 {
2374
2379 }
2380
2382
2383 return oldestMXact;
2384}
#define NumMemberSlots
Definition multixact.c:215
static MultiXactId * OldestVisibleMXactId
Definition multixact.c:221
static MultiXactId * OldestMemberMXactId
Definition multixact.c:220
#define NumVisibleSlots
Definition multixact.c:216

References fb(), i, LW_SHARED, LWLockAcquire(), LWLockRelease(), MultiXactIdIsValid, MultiXactIdPrecedes(), MultiXactState, MultiXactStateData::nextMXact, NumMemberSlots, NumVisibleSlots, OldestMemberMXactId, and OldestVisibleMXactId.

Referenced by heapam_relation_set_new_filelocator(), vac_update_datfrozenxid(), and vacuum_get_cutoffs().

◆ multixact_desc()

void multixact_desc ( StringInfo  buf,
XLogReaderState record 
)
extern

Definition at line 50 of file mxactdesc.c.

51{
52 char *rec = XLogRecGetData(record);
53 uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
54
55 if (info == XLOG_MULTIXACT_ZERO_OFF_PAGE ||
57 {
58 int64 pageno;
59
60 memcpy(&pageno, rec, sizeof(pageno));
61 appendStringInfo(buf, "%" PRId64, pageno);
62 }
63 else if (info == XLOG_MULTIXACT_CREATE_ID)
64 {
66 int i;
67
68 appendStringInfo(buf, "%u offset %" PRIu64 " nmembers %d: ", xlrec->mid,
69 xlrec->moff, xlrec->nmembers);
70 for (i = 0; i < xlrec->nmembers; i++)
71 out_member(buf, &xlrec->members[i]);
72 }
73 else if (info == XLOG_MULTIXACT_TRUNCATE_ID)
74 {
76
77 appendStringInfo(buf, "oldestMulti %u, oldestOffset %" PRIu64,
78 xlrec->oldestMulti, xlrec->oldestOffset);
79 }
80}
#define XLOG_MULTIXACT_ZERO_MEM_PAGE
Definition multixact.h:68
#define XLOG_MULTIXACT_ZERO_OFF_PAGE
Definition multixact.h:67
#define XLOG_MULTIXACT_TRUNCATE_ID
Definition multixact.h:70
#define XLOG_MULTIXACT_CREATE_ID
Definition multixact.h:69
static void out_member(StringInfo buf, MultiXactMember *member)
Definition mxactdesc.c:20
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition stringinfo.c:145
#define XLogRecGetInfo(decoder)
Definition xlogreader.h:409
#define XLogRecGetData(decoder)
Definition xlogreader.h:414

References appendStringInfo(), buf, fb(), i, out_member(), XLOG_MULTIXACT_CREATE_ID, XLOG_MULTIXACT_TRUNCATE_ID, XLOG_MULTIXACT_ZERO_MEM_PAGE, XLOG_MULTIXACT_ZERO_OFF_PAGE, XLogRecGetData, and XLogRecGetInfo.

◆ multixact_identify()

const char * multixact_identify ( uint8  info)
extern

Definition at line 83 of file mxactdesc.c.

84{
85 const char *id = NULL;
86
87 switch (info & ~XLR_INFO_MASK)
88 {
90 id = "ZERO_OFF_PAGE";
91 break;
93 id = "ZERO_MEM_PAGE";
94 break;
96 id = "CREATE_ID";
97 break;
99 id = "TRUNCATE_ID";
100 break;
101 }
102
103 return id;
104}
#define XLR_INFO_MASK
Definition xlogrecord.h:62

References fb(), XLOG_MULTIXACT_CREATE_ID, XLOG_MULTIXACT_TRUNCATE_ID, XLOG_MULTIXACT_ZERO_MEM_PAGE, XLOG_MULTIXACT_ZERO_OFF_PAGE, and XLR_INFO_MASK.

◆ multixact_redo()

void multixact_redo ( XLogReaderState record)
extern

Definition at line 2868 of file multixact.c.

2869{
2870 uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
2871
2872 /* Backup blocks are not used in multixact records */
2874
2875 if (info == XLOG_MULTIXACT_ZERO_OFF_PAGE)
2876 {
2877 int64 pageno;
2878
2879 memcpy(&pageno, XLogRecGetData(record), sizeof(pageno));
2881 }
2882 else if (info == XLOG_MULTIXACT_ZERO_MEM_PAGE)
2883 {
2884 int64 pageno;
2885
2886 memcpy(&pageno, XLogRecGetData(record), sizeof(pageno));
2888 }
2889 else if (info == XLOG_MULTIXACT_CREATE_ID)
2890 {
2894 int i;
2895
2896 /* Store the data back into the SLRU files */
2897 RecordNewMultiXact(xlrec->mid, xlrec->moff, xlrec->nmembers,
2898 xlrec->members);
2899
2900 /* Make sure nextMXact/nextOffset are beyond what this record has */
2902 xlrec->moff + xlrec->nmembers);
2903
2904 /*
2905 * Make sure nextXid is beyond any XID mentioned in the record. This
2906 * should be unnecessary, since any XID found here ought to have other
2907 * evidence in the XLOG, but let's be safe.
2908 */
2909 max_xid = XLogRecGetXid(record);
2910 for (i = 0; i < xlrec->nmembers; i++)
2911 {
2912 if (TransactionIdPrecedes(max_xid, xlrec->members[i].xid))
2913 max_xid = xlrec->members[i].xid;
2914 }
2915
2917 }
2918 else if (info == XLOG_MULTIXACT_TRUNCATE_ID)
2919 {
2921 int64 pageno;
2922
2923 memcpy(&xlrec, XLogRecGetData(record),
2925
2926 elog(DEBUG1, "replaying multixact truncation: "
2927 "oldestMulti %u (offsets segment %" PRIx64 "), "
2928 "oldestOffset %" PRIu64 " (members segment %" PRIx64 ")",
2929 xlrec.oldestMulti,
2930 MultiXactIdToOffsetSegment(xlrec.oldestMulti),
2931 xlrec.oldestOffset,
2932 MXOffsetToMemberSegment(xlrec.oldestOffset));
2933
2934 /* should not be required, but more than cheap enough */
2936
2937 /*
2938 * Advance the horizon values, so they're current at the end of
2939 * recovery.
2940 */
2941 SetMultiXactIdLimit(xlrec.oldestMulti, xlrec.oldestMultiDB);
2942
2943 PerformMembersTruncation(xlrec.oldestOffset);
2944
2945 /*
2946 * During XLOG replay, latest_page_number isn't necessarily set up
2947 * yet; insert a suitable value to bypass the sanity test in
2948 * SimpleLruTruncate.
2949 */
2950 pageno = MultiXactIdToOffsetPage(xlrec.oldestMulti);
2951 pg_atomic_write_u64(&MultiXactOffsetCtl->shared->latest_page_number,
2952 pageno);
2953 PerformOffsetsTruncation(xlrec.oldestMulti);
2954
2956 }
2957 else
2958 elog(PANIC, "multixact_redo: unknown op code %u", info);
2959}
static void pg_atomic_write_u64(volatile pg_atomic_uint64 *ptr, uint64 val)
Definition atomics.h:485
#define PANIC
Definition elog.h:42
#define DEBUG1
Definition elog.h:30
#define elog(elevel,...)
Definition elog.h:226
static void PerformOffsetsTruncation(MultiXactId newOldestMulti)
Definition multixact.c:2627
static void RecordNewMultiXact(MultiXactId multi, MultiXactOffset offset, int nmembers, MultiXactMember *members)
Definition multixact.c:795
static void PerformMembersTruncation(MultiXactOffset newOldestOffset)
Definition multixact.c:2617
void MultiXactAdvanceNextMXact(MultiXactId minMulti, MultiXactOffset minMultiOffset)
Definition multixact.c:2213
void SetMultiXactIdLimit(MultiXactId oldest_datminmxid, Oid oldest_datoid)
Definition multixact.c:2063
#define SizeOfMultiXactTruncate
Definition multixact.h:93
static int64 MultiXactIdToOffsetSegment(MultiXactId multi)
static int64 MXOffsetToMemberSegment(MultiXactOffset offset)
static bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition transam.h:263
void AdvanceNextFullTransactionIdPastXid(TransactionId xid)
Definition varsup.c:304
#define XLogRecGetXid(decoder)
Definition xlogreader.h:411
#define XLogRecHasAnyBlockRefs(decoder)
Definition xlogreader.h:416

References AdvanceNextFullTransactionIdPastXid(), Assert, DEBUG1, elog, fb(), i, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MultiXactAdvanceNextMXact(), MultiXactIdToOffsetPage(), MultiXactIdToOffsetSegment(), MultiXactMemberCtl, MultiXactOffsetCtl, MXOffsetToMemberSegment(), NextMultiXactId(), PANIC, PerformMembersTruncation(), PerformOffsetsTruncation(), pg_atomic_write_u64(), RecordNewMultiXact(), SetMultiXactIdLimit(), SimpleLruZeroAndWritePage(), SizeOfMultiXactTruncate, TransactionIdPrecedes(), XLOG_MULTIXACT_CREATE_ID, XLOG_MULTIXACT_TRUNCATE_ID, XLOG_MULTIXACT_ZERO_MEM_PAGE, XLOG_MULTIXACT_ZERO_OFF_PAGE, XLogRecGetData, XLogRecGetInfo, XLogRecGetXid, and XLogRecHasAnyBlockRefs.

◆ multixact_twophase_postabort()

void multixact_twophase_postabort ( FullTransactionId  fxid,
uint16  info,
void recdata,
uint32  len 
)
extern

Definition at line 1733 of file multixact.c.

1735{
1737}
void multixact_twophase_postcommit(FullTransactionId fxid, uint16 info, void *recdata, uint32 len)
Definition multixact.c:1718

References fb(), len, and multixact_twophase_postcommit().

◆ multixact_twophase_postcommit()

void multixact_twophase_postcommit ( FullTransactionId  fxid,
uint16  info,
void recdata,
uint32  len 
)
extern

Definition at line 1718 of file multixact.c.

1720{
1722
1723 Assert(len == sizeof(MultiXactId));
1724
1726}
static MultiXactId * PreparedXactOldestMemberMXactIdSlot(ProcNumber procno)
Definition multixact.c:237
int ProcNumber
Definition procnumber.h:24
ProcNumber TwoPhaseGetDummyProcNumber(FullTransactionId fxid, bool lock_held)
Definition twophase.c:910

References Assert, fb(), InvalidMultiXactId, len, PreparedXactOldestMemberMXactIdSlot(), and TwoPhaseGetDummyProcNumber().

Referenced by multixact_twophase_postabort().

◆ multixact_twophase_recover()

void multixact_twophase_recover ( FullTransactionId  fxid,
uint16  info,
void recdata,
uint32  len 
)
extern

Definition at line 1697 of file multixact.c.

1699{
1702
1703 /*
1704 * Get the oldest member XID from the state file record, and set it in the
1705 * OldestMemberMXactId slot reserved for this prepared transaction.
1706 */
1707 Assert(len == sizeof(MultiXactId));
1709
1711}

References Assert, fb(), len, PreparedXactOldestMemberMXactIdSlot(), and TwoPhaseGetDummyProcNumber().

◆ MultiXactAdvanceNextMXact()

void MultiXactAdvanceNextMXact ( MultiXactId  minMulti,
MultiXactOffset  minMultiOffset 
)
extern

◆ MultiXactAdvanceOldest()

void MultiXactAdvanceOldest ( MultiXactId  oldestMulti,
Oid  oldestMultiDB 
)
extern

Definition at line 2240 of file multixact.c.

2241{
2243
2245 SetMultiXactIdLimit(oldestMulti, oldestMultiDB);
2246}
bool InRecovery
Definition xlogutils.c:50

References Assert, InRecovery, MultiXactIdPrecedes(), MultiXactState, MultiXactStateData::oldestMultiXactId, and SetMultiXactIdLimit().

Referenced by xlog_redo().

◆ MultiXactGetCheckptMulti()

void MultiXactGetCheckptMulti ( bool  is_shutdown,
MultiXactId nextMulti,
MultiXactOffset nextMultiOffset,
MultiXactId oldestMulti,
Oid oldestMultiDB 
)
extern

Definition at line 1995 of file multixact.c.

2000{
2002 *nextMulti = MultiXactState->nextMXact;
2003 *nextMultiOffset = MultiXactState->nextOffset;
2004 *oldestMulti = MultiXactState->oldestMultiXactId;
2005 *oldestMultiDB = MultiXactState->oldestMultiXactDB;
2007
2009 "MultiXact: checkpoint is nextMulti %u, nextOffset %" PRIu64 ", oldestMulti %u in DB %u",
2010 *nextMulti, *nextMultiOffset, *oldestMulti, *oldestMultiDB);
2011}
#define debug_elog6(a, b, c, d, e, f)
Definition multixact.c:299

References DEBUG2, debug_elog6, fb(), LW_SHARED, LWLockAcquire(), LWLockRelease(), MultiXactState, MultiXactStateData::nextMXact, MultiXactStateData::nextOffset, MultiXactStateData::oldestMultiXactDB, and MultiXactStateData::oldestMultiXactId.

Referenced by CreateCheckPoint().

◆ MultiXactIdCreate()

MultiXactId MultiXactIdCreate ( TransactionId  xid1,
MultiXactStatus  status1,
TransactionId  xid2,
MultiXactStatus  status2 
)
extern

Definition at line 337 of file multixact.c.

339{
341 MultiXactMember members[2];
342
345
347
348 /* MultiXactIdSetOldestMember() must have been called already. */
350
351 /*
352 * Note: unlike MultiXactIdExpand, we don't bother to check that both XIDs
353 * are still running. In typical usage, xid2 will be our own XID and the
354 * caller just did a check on xid1, so it'd be wasted effort.
355 */
356
357 members[0].xid = xid1;
358 members[0].status = status1;
359 members[1].xid = xid2;
360 members[1].status = status2;
361
363
364 debug_elog3(DEBUG2, "Create: %s",
365 mxid_to_string(newMulti, 2, members));
366
367 return newMulti;
368}
MultiXactId MultiXactIdCreateFromMembers(int nmembers, MultiXactMember *members)
Definition multixact.c:694
#define TransactionIdEquals(id1, id2)
Definition transam.h:43

References Assert, DEBUG2, debug_elog3, fb(), MultiXactIdCreateFromMembers(), MultiXactIdIsValid, mxid_to_string(), MyOldestMemberMXactIdSlot(), MultiXactMember::status, TransactionIdEquals, TransactionIdIsValid, and MultiXactMember::xid.

Referenced by compute_new_xmax_infomask(), and test_create_multixact().

◆ MultiXactIdCreateFromMembers()

MultiXactId MultiXactIdCreateFromMembers ( int  nmembers,
MultiXactMember members 
)
extern

Definition at line 694 of file multixact.c.

695{
696 MultiXactId multi;
697 MultiXactOffset offset;
699
700 debug_elog3(DEBUG2, "Create: %s",
701 mxid_to_string(InvalidMultiXactId, nmembers, members));
702
703 /*
704 * See if the same set of members already exists in our cache; if so, just
705 * re-use that MultiXactId. (Note: it might seem that looking in our
706 * cache is insufficient, and we ought to search disk to see if a
707 * duplicate definition already exists. But since we only ever create
708 * MultiXacts containing our own XID, in most cases any such MultiXacts
709 * were in fact created by us, and so will be in our cache. There are
710 * corner cases where someone else added us to a MultiXact without our
711 * knowledge, but it's not worth checking for.)
712 */
713 multi = mXactCacheGetBySet(nmembers, members);
714 if (MultiXactIdIsValid(multi))
715 {
716 debug_elog2(DEBUG2, "Create: in cache!");
717 return multi;
718 }
719
720 /* Verify that there is a single update Xid among the given members. */
721 {
722 int i;
723 bool has_update = false;
724
725 for (i = 0; i < nmembers; i++)
726 {
727 if (ISUPDATE_from_mxstatus(members[i].status))
728 {
729 if (has_update)
730 elog(ERROR, "new multixact has more than one updating member: %s",
731 mxid_to_string(InvalidMultiXactId, nmembers, members));
732 has_update = true;
733 }
734 }
735 }
736
737 /* Load the injection point before entering the critical section */
738 INJECTION_POINT_LOAD("multixact-create-from-members");
739
740 /*
741 * Assign the MXID and offsets range to use, and make sure there is space
742 * in the OFFSETs and MEMBERs files. NB: this routine does
743 * START_CRIT_SECTION().
744 *
745 * Note: unlike MultiXactIdCreate and MultiXactIdExpand, we do not check
746 * that we've called MultiXactIdSetOldestMember here. This is because
747 * this routine is used in some places to create new MultiXactIds of which
748 * the current backend is not a member, notably during freezing of multis
749 * in vacuum. During vacuum, in particular, it would be unacceptable to
750 * keep OldestMulti set, in case it runs for long.
751 */
752 multi = GetNewMultiXactId(nmembers, &offset);
753
754 INJECTION_POINT_CACHED("multixact-create-from-members", NULL);
755
756 /* Make an XLOG entry describing the new MXID. */
757 xlrec.mid = multi;
758 xlrec.moff = offset;
759 xlrec.nmembers = nmembers;
760
761 /*
762 * XXX Note: there's a lot of padding space in MultiXactMember. We could
763 * find a more compact representation of this Xlog record -- perhaps all
764 * the status flags in one XLogRecData, then all the xids in another one?
765 * Not clear that it's worth the trouble though.
766 */
769 XLogRegisterData(members, nmembers * sizeof(MultiXactMember));
770
772
773 /* Now enter the information into the OFFSETs and MEMBERs logs */
774 RecordNewMultiXact(multi, offset, nmembers, members);
775
776 /* Done with critical section */
778
779 /* Store the new MultiXactId in the local cache, too */
780 mXactCachePut(multi, nmembers, members);
781
782 debug_elog2(DEBUG2, "Create: all done");
783
784 return multi;
785}
#define INJECTION_POINT_CACHED(name, arg)
#define INJECTION_POINT_LOAD(name)
#define END_CRIT_SECTION()
Definition miscadmin.h:152
static MultiXactId GetNewMultiXactId(int nmembers, MultiXactOffset *offset)
Definition multixact.c:962
static MultiXactId mXactCacheGetBySet(int nmembers, MultiXactMember *members)
Definition multixact.c:1417
#define ISUPDATE_from_mxstatus(status)
Definition multixact.h:51
#define SizeOfMultiXactCreate
Definition multixact.h:80
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition xloginsert.c:478
void XLogRegisterData(const void *data, uint32 len)
Definition xloginsert.c:368
void XLogBeginInsert(void)
Definition xloginsert.c:152

References DEBUG2, debug_elog2, debug_elog3, elog, END_CRIT_SECTION, ERROR, fb(), GetNewMultiXactId(), i, INJECTION_POINT_CACHED, INJECTION_POINT_LOAD, InvalidMultiXactId, ISUPDATE_from_mxstatus, MultiXactIdIsValid, mXactCacheGetBySet(), mXactCachePut(), mxid_to_string(), RecordNewMultiXact(), SizeOfMultiXactCreate, XLOG_MULTIXACT_CREATE_ID, XLogBeginInsert(), XLogInsert(), and XLogRegisterData().

Referenced by FreezeMultiXactId(), MultiXactIdCreate(), and MultiXactIdExpand().

◆ MultiXactIdExpand()

MultiXactId MultiXactIdExpand ( MultiXactId  multi,
TransactionId  xid,
MultiXactStatus  status 
)
extern

Definition at line 390 of file multixact.c.

391{
393 MultiXactMember *members;
395 int nmembers;
396 int i;
397 int j;
398
401
402 /* MultiXactIdSetOldestMember() must have been called already. */
404
405 debug_elog5(DEBUG2, "Expand: received multi %u, xid %u status %s",
406 multi, xid, mxstatus_to_string(status));
407
408 /*
409 * Note: we don't allow for old multis here. The reason is that the only
410 * caller of this function does a check that the multixact is no longer
411 * running.
412 */
413 nmembers = GetMultiXactIdMembers(multi, &members, false, false);
414
415 if (nmembers < 0)
416 {
417 MultiXactMember member;
418
419 /*
420 * The MultiXactId is obsolete. This can only happen if all the
421 * MultiXactId members stop running between the caller checking and
422 * passing it to us. It would be better to return that fact to the
423 * caller, but it would complicate the API and it's unlikely to happen
424 * too often, so just deal with it by creating a singleton MultiXact.
425 */
426 member.xid = xid;
427 member.status = status;
429
430 debug_elog4(DEBUG2, "Expand: %u has no members, create singleton %u",
431 multi, newMulti);
432 return newMulti;
433 }
434
435 /*
436 * If the TransactionId is already a member of the MultiXactId with the
437 * same status, just return the existing MultiXactId.
438 */
439 for (i = 0; i < nmembers; i++)
440 {
441 if (TransactionIdEquals(members[i].xid, xid) &&
442 (members[i].status == status))
443 {
444 debug_elog4(DEBUG2, "Expand: %u is already a member of %u",
445 xid, multi);
446 pfree(members);
447 return multi;
448 }
449 }
450
451 /*
452 * Determine which of the members of the MultiXactId are still of
453 * interest. This is any running transaction, and also any transaction
454 * that grabbed something stronger than just a lock and was committed. (An
455 * update that aborted is of no interest here; and having more than one
456 * update Xid in a multixact would cause errors elsewhere.)
457 *
458 * Removing dead members is not just an optimization: freezing of tuples
459 * whose Xmax are multis depends on this behavior.
460 *
461 * Note we have the same race condition here as above: j could be 0 at the
462 * end of the loop.
463 */
464 newMembers = palloc_array(MultiXactMember, nmembers + 1);
465
466 for (i = 0, j = 0; i < nmembers; i++)
467 {
468 if (TransactionIdIsInProgress(members[i].xid) ||
469 (ISUPDATE_from_mxstatus(members[i].status) &&
470 TransactionIdDidCommit(members[i].xid)))
471 {
472 newMembers[j].xid = members[i].xid;
473 newMembers[j++].status = members[i].status;
474 }
475 }
476
477 newMembers[j].xid = xid;
478 newMembers[j++].status = status;
480
481 pfree(members);
483
484 debug_elog3(DEBUG2, "Expand: returning new multi %u", newMulti);
485
486 return newMulti;
487}
#define palloc_array(type, count)
Definition fe_memutils.h:76
int j
Definition isn.c:78
void pfree(void *pointer)
Definition mcxt.c:1616
char * mxstatus_to_string(MultiXactStatus status)
Definition multixact.c:1552
#define debug_elog5(a, b, c, d, e)
Definition multixact.c:298
#define debug_elog4(a, b, c, d)
Definition multixact.c:297
int GetMultiXactIdMembers(MultiXactId multi, MultiXactMember **members, bool from_pgupgrade, bool isLockOnly)
Definition multixact.c:1151
bool TransactionIdIsInProgress(TransactionId xid)
Definition procarray.c:1401
bool TransactionIdDidCommit(TransactionId transactionId)
Definition transam.c:126

References Assert, DEBUG2, debug_elog3, debug_elog4, debug_elog5, fb(), GetMultiXactIdMembers(), i, ISUPDATE_from_mxstatus, j, MultiXactIdCreateFromMembers(), MultiXactIdIsValid, mxstatus_to_string(), MyOldestMemberMXactIdSlot(), palloc_array, pfree(), MultiXactMember::status, TransactionIdDidCommit(), TransactionIdEquals, TransactionIdIsInProgress(), TransactionIdIsValid, and MultiXactMember::xid.

Referenced by compute_new_xmax_infomask().

◆ MultiXactIdIsRunning()

bool MultiXactIdIsRunning ( MultiXactId  multi,
bool  isLockOnly 
)
extern

Definition at line 501 of file multixact.c.

502{
503 MultiXactMember *members;
504 int nmembers;
505 int i;
506
507 debug_elog3(DEBUG2, "IsRunning %u?", multi);
508
509 /*
510 * "false" here means we assume our callers have checked that the given
511 * multi cannot possibly come from a pg_upgraded database.
512 */
513 nmembers = GetMultiXactIdMembers(multi, &members, false, isLockOnly);
514
515 if (nmembers <= 0)
516 {
517 debug_elog2(DEBUG2, "IsRunning: no members");
518 return false;
519 }
520
521 /*
522 * Checking for myself is cheap compared to looking in shared memory;
523 * return true if any live subtransaction of the current top-level
524 * transaction is a member.
525 *
526 * This is not needed for correctness, it's just a fast path.
527 */
528 for (i = 0; i < nmembers; i++)
529 {
530 if (TransactionIdIsCurrentTransactionId(members[i].xid))
531 {
532 debug_elog3(DEBUG2, "IsRunning: I (%d) am running!", i);
533 pfree(members);
534 return true;
535 }
536 }
537
538 /*
539 * This could be made faster by having another entry point in procarray.c,
540 * walking the PGPROC array only once for all the members. But in most
541 * cases nmembers should be small enough that it doesn't much matter.
542 */
543 for (i = 0; i < nmembers; i++)
544 {
545 if (TransactionIdIsInProgress(members[i].xid))
546 {
547 debug_elog4(DEBUG2, "IsRunning: member %d (%u) is running",
548 i, members[i].xid);
549 pfree(members);
550 return true;
551 }
552 }
553
554 pfree(members);
555
556 debug_elog3(DEBUG2, "IsRunning: %u is not running", multi);
557
558 return false;
559}
bool TransactionIdIsCurrentTransactionId(TransactionId xid)
Definition xact.c:943

References DEBUG2, debug_elog2, debug_elog3, debug_elog4, fb(), GetMultiXactIdMembers(), i, pfree(), TransactionIdIsCurrentTransactionId(), and TransactionIdIsInProgress().

Referenced by compute_new_xmax_infomask(), FreezeMultiXactId(), HeapTupleSatisfiesUpdate(), and HeapTupleSatisfiesVacuumHorizon().

◆ MultiXactIdPrecedes()

◆ MultiXactIdPrecedesOrEquals()

bool MultiXactIdPrecedesOrEquals ( MultiXactId  multi1,
MultiXactId  multi2 
)
extern

Definition at line 2832 of file multixact.c.

2833{
2834 int32 diff = (int32) (multi1 - multi2);
2835
2836 return (diff <= 0);
2837}

References fb().

Referenced by check_mxid_in_range(), heap_tuple_should_freeze(), heap_vacuum_rel(), TruncateMultiXact(), and vacuum_get_cutoffs().

◆ MultiXactIdSetOldestMember()

void MultiXactIdSetOldestMember ( void  )
extern

Definition at line 575 of file multixact.c.

576{
578 {
579 MultiXactId nextMXact;
580
581 /*
582 * You might think we don't need to acquire a lock here, since
583 * fetching and storing of TransactionIds is probably atomic, but in
584 * fact we do: suppose we pick up nextMXact and then lose the CPU for
585 * a long time. Someone else could advance nextMXact, and then
586 * another someone else could compute an OldestVisibleMXactId that
587 * would be after the value we are going to store when we get control
588 * back. Which would be wrong.
589 *
590 * Note that a shared lock is sufficient, because it's enough to stop
591 * someone from advancing nextMXact; and nobody else could be trying
592 * to write to our OldestMember entry, only reading (and we assume
593 * storing it is atomic.)
594 */
596
597 nextMXact = MultiXactState->nextMXact;
598
599 *MyOldestMemberMXactIdSlot() = nextMXact;
600
602
603 debug_elog4(DEBUG2, "MultiXact: setting OldestMember[%d] = %u",
604 MyProcNumber, nextMXact);
605 }
606}
ProcNumber MyProcNumber
Definition globals.c:90

References DEBUG2, debug_elog4, fb(), LW_SHARED, LWLockAcquire(), LWLockRelease(), MultiXactIdIsValid, MultiXactState, MyOldestMemberMXactIdSlot(), MyProcNumber, and MultiXactStateData::nextMXact.

Referenced by heap_delete(), heap_lock_tuple(), heap_lock_updated_tuple(), heap_update(), and test_create_multixact().

◆ MultiXactMemberFreezeThreshold()

int MultiXactMemberFreezeThreshold ( void  )
extern

Definition at line 2564 of file multixact.c.

2565{
2568 double fraction;
2569 int result;
2570 MultiXactId oldestMultiXactId;
2571 MultiXactOffset oldestOffset;
2572 MultiXactOffset nextOffset;
2573 uint64 members;
2574
2575 /* Read the current offsets and multixact usage. */
2576 GetMultiXactInfo(&multixacts, &nextOffset, &oldestMultiXactId, &oldestOffset);
2577 members = nextOffset - oldestOffset;
2578
2579 /* If member space utilization is low, no special action is required. */
2580 if (members <= MULTIXACT_MEMBER_LOW_THRESHOLD)
2582
2583 /*
2584 * Compute a target for relminmxid advancement. The number of multixacts
2585 * we try to eliminate from the system is based on how far we are past
2586 * MULTIXACT_MEMBER_LOW_THRESHOLD.
2587 *
2588 * The way this formula works is that when members is exactly at the low
2589 * threshold, fraction = 0.0, and we set freeze_max_age equal to
2590 * mxid_age(oldestMultiXactId). As members grows further, towards the
2591 * high threshold, fraction grows linearly from 0.0 to 1.0, and the result
2592 * shrinks from mxid_age(oldestMultiXactId) to 0. Beyond the high
2593 * threshold, fraction > 1.0 and the result is clamped to 0.
2594 */
2597
2598 /* fraction could be > 1.0, but lowest possible freeze age is zero */
2599 if (fraction >= 1.0)
2600 return 0;
2601
2603 result = multixacts - victim_multixacts;
2604
2605 /*
2606 * Clamp to autovacuum_multixact_freeze_max_age, so that we never make
2607 * autovacuum less aggressive than it would otherwise be.
2608 */
2610}
int autovacuum_multixact_freeze_max_age
Definition autovacuum.c:131
#define Min(x, y)
Definition c.h:1063
uint64_t uint64
Definition c.h:589
void GetMultiXactInfo(uint32 *multixacts, MultiXactOffset *nextOffset, MultiXactId *oldestMultiXactId, MultiXactOffset *oldestOffset)
Definition multixact.c:2520
#define MULTIXACT_MEMBER_LOW_THRESHOLD
Definition multixact.c:98
#define MULTIXACT_MEMBER_HIGH_THRESHOLD
Definition multixact.c:99

References autovacuum_multixact_freeze_max_age, fb(), GetMultiXactInfo(), Min, MULTIXACT_MEMBER_HIGH_THRESHOLD, and MULTIXACT_MEMBER_LOW_THRESHOLD.

Referenced by do_autovacuum(), do_start_worker(), and vacuum_get_cutoffs().

◆ multixactmemberssyncfiletag()

int multixactmemberssyncfiletag ( const FileTag ftag,
char path 
)
extern

Definition at line 2974 of file multixact.c.

2975{
2976 return SlruSyncFileTag(MultiXactMemberCtl, ftag, path);
2977}
int SlruSyncFileTag(SlruCtl ctl, const FileTag *ftag, char *path)
Definition slru.c:1857

References MultiXactMemberCtl, and SlruSyncFileTag().

◆ multixactoffsetssyncfiletag()

int multixactoffsetssyncfiletag ( const FileTag ftag,
char path 
)
extern

Definition at line 2965 of file multixact.c.

2966{
2967 return SlruSyncFileTag(MultiXactOffsetCtl, ftag, path);
2968}

References MultiXactOffsetCtl, and SlruSyncFileTag().

◆ MultiXactSetNextMXact()

void MultiXactSetNextMXact ( MultiXactId  nextMulti,
MultiXactOffset  nextMultiOffset 
)
extern

Definition at line 2041 of file multixact.c.

2043{
2044 Assert(MultiXactIdIsValid(nextMulti));
2045 debug_elog4(DEBUG2, "MultiXact: setting next multi to %u offset %" PRIu64,
2046 nextMulti, nextMultiOffset);
2047
2049 MultiXactState->nextMXact = nextMulti;
2050 MultiXactState->nextOffset = nextMultiOffset;
2052}

References Assert, DEBUG2, debug_elog4, fb(), LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MultiXactIdIsValid, MultiXactState, MultiXactStateData::nextMXact, and MultiXactStateData::nextOffset.

Referenced by BootStrapXLOG(), StartupXLOG(), and xlog_redo().

◆ MultiXactShmemInit()

void MultiXactShmemInit ( void  )
extern

Definition at line 1773 of file multixact.c.

1774{
1775 bool found;
1776
1777 debug_elog2(DEBUG2, "Shared Memory Init for MultiXact");
1778
1781
1783 "multixact_offset", multixact_offset_buffers, 0,
1784 "pg_multixact/offsets", LWTRANCHE_MULTIXACTOFFSET_BUFFER,
1787 false);
1790 "multixact_member", multixact_member_buffers, 0,
1791 "pg_multixact/members", LWTRANCHE_MULTIXACTMEMBER_BUFFER,
1794 true);
1795 /* doesn't call SimpleLruTruncate() or meet criteria for unit tests */
1796
1797 /* Initialize our shared state struct */
1798 MultiXactState = ShmemInitStruct("Shared MultiXact State",
1800 &found);
1801 if (!IsUnderPostmaster)
1802 {
1803 Assert(!found);
1804
1805 /* Make sure we zero out the per-backend state */
1807 }
1808 else
1809 Assert(found);
1810
1811 /*
1812 * Set up array pointers.
1813 */
1816}
#define MemSet(start, val, len)
Definition c.h:1079
int multixact_offset_buffers
Definition globals.c:163
bool IsUnderPostmaster
Definition globals.c:120
int multixact_member_buffers
Definition globals.c:162
static bool MultiXactMemberPagePrecedes(int64 page1, int64 page2)
Definition multixact.c:2806
static Size MultiXactSharedStateShmemSize(void)
Definition multixact.c:1748
static bool MultiXactOffsetPagePrecedes(int64 page1, int64 page2)
Definition multixact.c:2785
#define MULTIXACT_OFFSETS_PER_PAGE
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition shmem.c:378
void SimpleLruInit(SlruCtl ctl, const char *name, int nslots, int nlsns, const char *subdir, int buffer_tranche_id, int bank_tranche_id, SyncRequestHandler sync_handler, bool long_segment_names)
Definition slru.c:253
#define SlruPagePrecedesUnitTests(ctl, per_page)
Definition slru.h:185
MultiXactId perBackendXactIds[FLEXIBLE_ARRAY_MEMBER]
Definition multixact.c:209
@ SYNC_HANDLER_MULTIXACT_MEMBER
Definition sync.h:41
@ SYNC_HANDLER_MULTIXACT_OFFSET
Definition sync.h:40

References Assert, DEBUG2, debug_elog2, fb(), IsUnderPostmaster, MemSet, multixact_member_buffers, multixact_offset_buffers, MULTIXACT_OFFSETS_PER_PAGE, MultiXactMemberCtl, MultiXactMemberPagePrecedes(), MultiXactOffsetCtl, MultiXactOffsetPagePrecedes(), MultiXactSharedStateShmemSize(), MultiXactState, NumMemberSlots, OldestMemberMXactId, OldestVisibleMXactId, MultiXactStateData::perBackendXactIds, ShmemInitStruct(), SimpleLruInit(), SlruPagePrecedesUnitTests, SYNC_HANDLER_MULTIXACT_MEMBER, and SYNC_HANDLER_MULTIXACT_OFFSET.

Referenced by CreateOrAttachShmemStructs().

◆ MultiXactShmemSize()

Size MultiXactShmemSize ( void  )
extern

Definition at line 1761 of file multixact.c.

1762{
1763 Size size;
1764
1768
1769 return size;
1770}
Size add_size(Size s1, Size s2)
Definition shmem.c:482
Size SimpleLruShmemSize(int nslots, int nlsns)
Definition slru.c:199

References add_size(), multixact_member_buffers, multixact_offset_buffers, MultiXactSharedStateShmemSize(), and SimpleLruShmemSize().

Referenced by CalculateShmemSize().

◆ mxid_to_string()

char * mxid_to_string ( MultiXactId  multi,
int  nmembers,
MultiXactMember members 
)
extern

Definition at line 1575 of file multixact.c.

1576{
1577 static char *str = NULL;
1579 int i;
1580
1581 if (str != NULL)
1582 pfree(str);
1583
1585
1586 appendStringInfo(&buf, "%u %d[%u (%s)", multi, nmembers, members[0].xid,
1587 mxstatus_to_string(members[0].status));
1588
1589 for (i = 1; i < nmembers; i++)
1590 appendStringInfo(&buf, ", %u (%s)", members[i].xid,
1591 mxstatus_to_string(members[i].status));
1592
1595 pfree(buf.data);
1596 return str;
1597}
const char * str
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition mcxt.c:1768
MemoryContext TopMemoryContext
Definition mcxt.c:166
void appendStringInfoChar(StringInfo str, char ch)
Definition stringinfo.c:242
void initStringInfo(StringInfo str)
Definition stringinfo.c:97

References appendStringInfo(), appendStringInfoChar(), buf, fb(), i, initStringInfo(), MemoryContextStrdup(), mxstatus_to_string(), pfree(), str, and TopMemoryContext.

Referenced by GetMultiXactIdMembers(), MultiXactIdCreate(), MultiXactIdCreateFromMembers(), mXactCacheGetById(), mXactCacheGetBySet(), and mXactCachePut().

◆ mxstatus_to_string()

char * mxstatus_to_string ( MultiXactStatus  status)
extern

Definition at line 1552 of file multixact.c.

1553{
1554 switch (status)
1555 {
1557 return "keysh";
1559 return "sh";
1561 return "fornokeyupd";
1563 return "forupd";
1565 return "nokeyupd";
1567 return "upd";
1568 default:
1569 elog(ERROR, "unrecognized multixact status %d", status);
1570 return "";
1571 }
1572}

References elog, ERROR, MultiXactStatusForKeyShare, MultiXactStatusForNoKeyUpdate, MultiXactStatusForShare, MultiXactStatusForUpdate, MultiXactStatusNoKeyUpdate, and MultiXactStatusUpdate.

Referenced by MultiXactIdExpand(), mxid_to_string(), and pg_get_multixact_members().

◆ PostPrepare_MultiXact()

void PostPrepare_MultiXact ( FullTransactionId  fxid)
extern

Definition at line 1648 of file multixact.c.

1649{
1651
1652 /*
1653 * Transfer our OldestMemberMXactId value to the slot reserved for the
1654 * prepared transaction.
1655 */
1658 {
1660
1661 /*
1662 * Even though storing MultiXactId is atomic, acquire lock to make
1663 * sure others see both changes, not just the reset of the slot of the
1664 * current backend. Using a volatile pointer might suffice, but this
1665 * isn't a hot spot.
1666 */
1668
1671
1673 }
1674
1675 /*
1676 * We don't need to transfer OldestVisibleMXactId value, because the
1677 * transaction is not going to be looking at any more multixacts once it's
1678 * prepared.
1679 *
1680 * We assume that storing a MultiXactId is atomic and so we need not take
1681 * MultiXactGenLock to do this.
1682 */
1684
1685 /*
1686 * Discard the local MultiXactId cache like in AtEOXact_MultiXact.
1687 */
1690}

References dclist_init(), fb(), InvalidMultiXactId, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MultiXactIdIsValid, MXactCache, MXactContext, MyOldestMemberMXactIdSlot(), MyOldestVisibleMXactIdSlot(), PreparedXactOldestMemberMXactIdSlot(), and TwoPhaseGetDummyProcNumber().

Referenced by PrepareTransaction().

◆ ReadMultiXactIdRange()

◆ ReadNextMultiXactId()

◆ SetMultiXactIdLimit()

void SetMultiXactIdLimit ( MultiXactId  oldest_datminmxid,
Oid  oldest_datoid 
)
extern

Definition at line 2063 of file multixact.c.

2064{
2065 MultiXactId multiVacLimit;
2066 MultiXactId multiWarnLimit;
2067 MultiXactId multiStopLimit;
2068 MultiXactId multiWrapLimit;
2070
2072
2073 /*
2074 * We pretend that a wrap will happen halfway through the multixact ID
2075 * space, but that's not really true, because multixacts wrap differently
2076 * from transaction IDs.
2077 */
2078 multiWrapLimit = oldest_datminmxid + (MaxMultiXactId >> 1);
2079 if (multiWrapLimit < FirstMultiXactId)
2080 multiWrapLimit += FirstMultiXactId;
2081
2082 /*
2083 * We'll refuse to continue assigning MultiXactIds once we get within 3M
2084 * multi of data loss. See SetTransactionIdLimit.
2085 */
2086 multiStopLimit = multiWrapLimit - 3000000;
2087 if (multiStopLimit < FirstMultiXactId)
2088 multiStopLimit -= FirstMultiXactId;
2089
2090 /*
2091 * We'll start complaining loudly when we get within 40M multis of data
2092 * loss. This is kind of arbitrary, but if you let your gas gauge get
2093 * down to 2% of full, would you be looking for the next gas station? We
2094 * need to be fairly liberal about this number because there are lots of
2095 * scenarios where most transactions are done by automatic clients that
2096 * won't pay attention to warnings. (No, we're not gonna make this
2097 * configurable. If you know enough to configure it, you know enough to
2098 * not get in this kind of trouble in the first place.)
2099 */
2100 multiWarnLimit = multiWrapLimit - 40000000;
2101 if (multiWarnLimit < FirstMultiXactId)
2102 multiWarnLimit -= FirstMultiXactId;
2103
2104 /*
2105 * We'll start trying to force autovacuums when oldest_datminmxid gets to
2106 * be more than autovacuum_multixact_freeze_max_age mxids old.
2107 *
2108 * Note: autovacuum_multixact_freeze_max_age is a PGC_POSTMASTER parameter
2109 * so that we don't have to worry about dealing with on-the-fly changes in
2110 * its value. See SetTransactionIdLimit.
2111 */
2113 if (multiVacLimit < FirstMultiXactId)
2114 multiVacLimit += FirstMultiXactId;
2115
2116 /* Grab lock for just long enough to set the new limit values */
2120 MultiXactState->multiVacLimit = multiVacLimit;
2121 MultiXactState->multiWarnLimit = multiWarnLimit;
2122 MultiXactState->multiStopLimit = multiStopLimit;
2123 MultiXactState->multiWrapLimit = multiWrapLimit;
2126
2127 /* Log the info */
2129 (errmsg_internal("MultiXactId wrap limit is %u, limited by database with OID %u",
2130 multiWrapLimit, oldest_datoid)));
2131
2132 /*
2133 * Computing the actual limits is only possible once the data directory is
2134 * in a consistent state. There's no need to compute the limits while
2135 * still replaying WAL - no decisions about new multis are made even
2136 * though multixact creations might be replayed. So we'll only do further
2137 * checks after TrimMultiXact() has been called.
2138 */
2140 return;
2141
2143
2144 /*
2145 * Offsets are 64-bits wide and never wrap around, so we don't need to
2146 * consider them for emergency autovacuum purposes. But now that we're in
2147 * a consistent state, determine MultiXactState->oldestOffset. It will be
2148 * used to adjust the freezing cutoff, to keep the offsets disk usage in
2149 * check.
2150 */
2152
2153 /*
2154 * If past the autovacuum force point, immediately signal an autovac
2155 * request. The reason for this is that autovac only processes one
2156 * database per invocation. Once it's finished cleaning up the oldest
2157 * database, it'll call here, and we'll signal the postmaster to start
2158 * another iteration immediately if there are still any old databases.
2159 */
2160 if (MultiXactIdPrecedes(multiVacLimit, curMulti) && IsUnderPostmaster)
2162
2163 /* Give an immediate warning if past the wrap warn point */
2164 if (MultiXactIdPrecedes(multiWarnLimit, curMulti))
2165 {
2166 char *oldest_datname;
2167
2168 /*
2169 * We can be called when not inside a transaction, for example during
2170 * StartupXLOG(). In such a case we cannot do database access, so we
2171 * must just report the oldest DB's OID.
2172 *
2173 * Note: it's also possible that get_database_name fails and returns
2174 * NULL, for example because the database just got dropped. We'll
2175 * still warn, even though the warning might now be unnecessary.
2176 */
2177 if (IsTransactionState())
2179 else
2181
2182 if (oldest_datname)
2184 (errmsg_plural("database \"%s\" must be vacuumed before %u more MultiXactId is used",
2185 "database \"%s\" must be vacuumed before %u more MultiXactIds are used",
2186 multiWrapLimit - curMulti,
2188 multiWrapLimit - curMulti),
2189 errhint("To avoid MultiXactId assignment failures, execute a database-wide VACUUM in that database.\n"
2190 "You might also need to commit or roll back old prepared transactions, or drop stale replication slots.")));
2191 else
2193 (errmsg_plural("database with OID %u must be vacuumed before %u more MultiXactId is used",
2194 "database with OID %u must be vacuumed before %u more MultiXactIds are used",
2195 multiWrapLimit - curMulti,
2197 multiWrapLimit - curMulti),
2198 errhint("To avoid MultiXactId assignment failures, execute a database-wide VACUUM in that database.\n"
2199 "You might also need to commit or roll back old prepared transactions, or drop stale replication slots.")));
2200 }
2201}
int errhint(const char *fmt,...) pg_attribute_printf(1
int int errmsg_internal(const char *fmt,...) pg_attribute_printf(1
#define WARNING
Definition elog.h:36
int int int errmsg_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...) pg_attribute_printf(1
char * get_database_name(Oid dbid)
Definition lsyscache.c:1310
static void SetOldestOffset(void)
Definition multixact.c:2391
#define FirstMultiXactId
Definition multixact.h:26
#define MaxMultiXactId
Definition multixact.h:27
void SendPostmasterSignal(PMSignalReason reason)
Definition pmsignal.c:165
@ PMSIGNAL_START_AUTOVAC_LAUNCHER
Definition pmsignal.h:39
MultiXactId multiWrapLimit
Definition multixact.c:158
MultiXactId multiStopLimit
Definition multixact.c:157
MultiXactId multiWarnLimit
Definition multixact.c:156
MultiXactId multiVacLimit
Definition multixact.c:155
bool IsTransactionState(void)
Definition xact.c:389

References Assert, autovacuum_multixact_freeze_max_age, DEBUG1, ereport, errhint(), errmsg_internal(), errmsg_plural(), fb(), MultiXactStateData::finishedStartup, FirstMultiXactId, get_database_name(), InRecovery, IsTransactionState(), IsUnderPostmaster, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MaxMultiXactId, MultiXactStateData::multiStopLimit, MultiXactStateData::multiVacLimit, MultiXactStateData::multiWarnLimit, MultiXactStateData::multiWrapLimit, MultiXactIdIsValid, MultiXactIdPrecedes(), MultiXactState, MultiXactStateData::nextMXact, MultiXactStateData::oldestMultiXactDB, MultiXactStateData::oldestMultiXactId, PMSIGNAL_START_AUTOVAC_LAUNCHER, SendPostmasterSignal(), SetOldestOffset(), and WARNING.

Referenced by BootStrapXLOG(), multixact_redo(), MultiXactAdvanceOldest(), StartupXLOG(), TrimMultiXact(), and vac_truncate_clog().

◆ StartupMultiXact()

void StartupMultiXact ( void  )
extern

Definition at line 1858 of file multixact.c.

1859{
1862 int64 pageno;
1863
1864 /*
1865 * Initialize offset's idea of the latest page number.
1866 */
1867 pageno = MultiXactIdToOffsetPage(multi);
1868 pg_atomic_write_u64(&MultiXactOffsetCtl->shared->latest_page_number,
1869 pageno);
1870
1871 /*
1872 * Initialize member's idea of the latest page number.
1873 */
1874 pageno = MXOffsetToMemberPage(offset);
1875 pg_atomic_write_u64(&MultiXactMemberCtl->shared->latest_page_number,
1876 pageno);
1877}

References MultiXactIdToOffsetPage(), MultiXactMemberCtl, MultiXactOffsetCtl, MultiXactState, MXOffsetToMemberPage(), MultiXactStateData::nextMXact, MultiXactStateData::nextOffset, and pg_atomic_write_u64().

Referenced by StartupXLOG().

◆ TrimMultiXact()

void TrimMultiXact ( void  )
extern

Definition at line 1883 of file multixact.c.

1884{
1885 MultiXactId nextMXact;
1886 MultiXactOffset offset;
1889 int64 pageno;
1890 int entryno;
1891 int flagsoff;
1892
1894 nextMXact = MultiXactState->nextMXact;
1895 offset = MultiXactState->nextOffset;
1899
1900 /* Clean up offsets state */
1901
1902 /*
1903 * (Re-)Initialize our idea of the latest page number for offsets.
1904 */
1905 pageno = MultiXactIdToOffsetPage(nextMXact);
1906 pg_atomic_write_u64(&MultiXactOffsetCtl->shared->latest_page_number,
1907 pageno);
1908
1909 /*
1910 * Set the offset of nextMXact on the offsets page. This is normally done
1911 * in RecordNewMultiXact() of the previous multixact, but let's be sure
1912 * the next page exists, if the nextMXact was reset with pg_resetwal for
1913 * example.
1914 *
1915 * Zero out the remainder of the page. See notes in TrimCLOG() for
1916 * background. Unlike CLOG, some WAL record covers every pg_multixact
1917 * SLRU mutation. Since, also unlike CLOG, we ignore the WAL rule "write
1918 * xlog before data," nextMXact successors may carry obsolete, nonzero
1919 * offset values.
1920 */
1921 entryno = MultiXactIdToOffsetEntry(nextMXact);
1922 {
1923 int slotno;
1926
1928 if (entryno == 0 || nextMXact == FirstMultiXactId)
1930 else
1931 slotno = SimpleLruReadPage(MultiXactOffsetCtl, pageno, true, nextMXact);
1932 offptr = (MultiXactOffset *) MultiXactOffsetCtl->shared->page_buffer[slotno];
1933 offptr += entryno;
1934
1935 *offptr = offset;
1936 if (entryno != 0 && (entryno + 1) * sizeof(MultiXactOffset) != BLCKSZ)
1937 MemSet(offptr + 1, 0, BLCKSZ - (entryno + 1) * sizeof(MultiXactOffset));
1938
1939 MultiXactOffsetCtl->shared->page_dirty[slotno] = true;
1940 LWLockRelease(lock);
1941 }
1942
1943 /*
1944 * And the same for members.
1945 *
1946 * (Re-)Initialize our idea of the latest page number for members.
1947 */
1948 pageno = MXOffsetToMemberPage(offset);
1949 pg_atomic_write_u64(&MultiXactMemberCtl->shared->latest_page_number,
1950 pageno);
1951
1952 /*
1953 * Zero out the remainder of the current members page. See notes in
1954 * TrimCLOG() for motivation.
1955 */
1957 if (flagsoff != 0)
1958 {
1959 int slotno;
1961 int memberoff;
1963
1966 slotno = SimpleLruReadPage(MultiXactMemberCtl, pageno, true, offset);
1967 xidptr = (TransactionId *)
1968 (MultiXactMemberCtl->shared->page_buffer[slotno] + memberoff);
1969
1971
1972 /*
1973 * Note: we don't need to zero out the flag bits in the remaining
1974 * members of the current group, because they are always reset before
1975 * writing.
1976 */
1977
1978 MultiXactMemberCtl->shared->page_dirty[slotno] = true;
1979 LWLockRelease(lock);
1980 }
1981
1982 /* signal that we're officially up */
1986
1987 /* Now compute how far away the next multixid wraparound is. */
1989}
int SimpleLruZeroPage(SlruCtl ctl, int64 pageno)
Definition slru.c:376

References fb(), MultiXactStateData::finishedStartup, FirstMultiXactId, LW_EXCLUSIVE, LW_SHARED, LWLockAcquire(), LWLockRelease(), MemSet, MultiXactIdToOffsetEntry(), MultiXactIdToOffsetPage(), MultiXactMemberCtl, MultiXactOffsetCtl, MultiXactState, MXOffsetToFlagsOffset(), MXOffsetToMemberOffset(), MXOffsetToMemberPage(), MultiXactStateData::nextMXact, MultiXactStateData::nextOffset, MultiXactStateData::oldestMultiXactDB, MultiXactStateData::oldestMultiXactId, pg_atomic_write_u64(), SetMultiXactIdLimit(), SimpleLruGetBankLock(), SimpleLruReadPage(), and SimpleLruZeroPage().

Referenced by StartupXLOG().

◆ TruncateMultiXact()

void TruncateMultiXact ( MultiXactId  newOldestMulti,
Oid  newOldestMultiDB 
)
extern

Definition at line 2652 of file multixact.c.

2653{
2654 MultiXactId oldestMulti;
2655 MultiXactId nextMulti;
2657 MultiXactOffset nextOffset;
2658
2662
2663 /*
2664 * We can only allow one truncation to happen at once. Otherwise parts of
2665 * members might vanish while we're doing lookups or similar. There's no
2666 * need to have an interlock with creating new multis or such, since those
2667 * are constrained by the limits (which only grow, never shrink).
2668 */
2670
2672 nextMulti = MultiXactState->nextMXact;
2673 nextOffset = MultiXactState->nextOffset;
2674 oldestMulti = MultiXactState->oldestMultiXactId;
2676
2677 /*
2678 * Make sure to only attempt truncation if there's values to truncate
2679 * away. In normal processing values shouldn't go backwards, but there's
2680 * some corner cases (due to bugs) where that's possible.
2681 */
2683 {
2685 return;
2686 }
2687
2688 /*
2689 * Compute up to where to truncate MultiXactMember. Lookup the
2690 * corresponding member offset for newOldestMulti for that.
2691 */
2692 if (newOldestMulti == nextMulti)
2693 {
2694 /* there are NO MultiXacts */
2695 newOldestOffset = nextOffset;
2696 }
2698 {
2699 ereport(LOG,
2700 (errmsg("cannot truncate up to MultiXact %u because it does not exist on disk, skipping truncation",
2701 newOldestMulti)));
2703 return;
2704 }
2705
2706 /*
2707 * On crash, MultiXactIdCreateFromMembers() can leave behind multixids
2708 * that were not yet written out and hence have zero offset on disk. If
2709 * such a multixid becomes oldestMulti, we won't be able to look up its
2710 * offset. That should be rare, so we don't try to do anything smart about
2711 * it. Just skip the truncation, and hope that by the next truncation
2712 * attempt, oldestMulti has advanced to a valid multixid.
2713 */
2714 if (newOldestOffset == 0)
2715 {
2716 ereport(LOG,
2717 (errmsg("cannot truncate up to MultiXact %u because it has invalid offset, skipping truncation",
2718 newOldestMulti)));
2720 return;
2721 }
2722
2723 elog(DEBUG1, "performing multixact truncation: "
2724 "oldestMulti %u (offsets segment %" PRIx64 "), "
2725 "oldestOffset %" PRIu64 " (members segment %" PRIx64 ")",
2730
2731 /*
2732 * Do truncation, and the WAL logging of the truncation, in a critical
2733 * section. That way offsets/members cannot get out of sync anymore, i.e.
2734 * once consistent the newOldestMulti will always exist in members, even
2735 * if we crashed in the wrong moment.
2736 */
2738
2739 /*
2740 * Prevent checkpoints from being scheduled concurrently. This is critical
2741 * because otherwise a truncation record might not be replayed after a
2742 * crash/basebackup, even though the state of the data directory would
2743 * require it.
2744 */
2747
2748 /* WAL log truncation */
2750
2751 /*
2752 * Update in-memory limits before performing the truncation, while inside
2753 * the critical section: Have to do it before truncation, to prevent
2754 * concurrent lookups of those values. Has to be inside the critical
2755 * section as otherwise a future call to this function would error out,
2756 * while looking up the oldest member in offsets, if our caller crashes
2757 * before updating the limits.
2758 */
2764
2765 /* First truncate members */
2767
2768 /* Then offsets */
2770
2772
2775}
#define LOG
Definition elog.h:31
#define START_CRIT_SECTION()
Definition miscadmin.h:150
static bool find_multixact_start(MultiXactId multi, MultiXactOffset *result)
Definition multixact.c:2477
static void WriteMTruncateXlogRec(Oid oldestMultiDB, MultiXactId endTruncOff, MultiXactOffset endTruncMemb)
Definition multixact.c:2847
bool MultiXactIdPrecedesOrEquals(MultiXactId multi1, MultiXactId multi2)
Definition multixact.c:2832
#define DELAY_CHKPT_START
Definition proc.h:136
PGPROC * MyProc
Definition proc.c:68
int delayChkptFlags
Definition proc.h:252
bool RecoveryInProgress(void)
Definition xlog.c:6444

References Assert, DEBUG1, DELAY_CHKPT_START, PGPROC::delayChkptFlags, elog, END_CRIT_SECTION, ereport, errmsg, fb(), find_multixact_start(), MultiXactStateData::finishedStartup, LOG, LW_EXCLUSIVE, LW_SHARED, LWLockAcquire(), LWLockRelease(), MultiXactIdIsValid, MultiXactIdPrecedesOrEquals(), MultiXactIdToOffsetSegment(), MultiXactState, MXOffsetToMemberSegment(), MyProc, MultiXactStateData::nextMXact, MultiXactStateData::nextOffset, MultiXactStateData::oldestMultiXactDB, MultiXactStateData::oldestMultiXactId, MultiXactStateData::oldestOffset, PerformMembersTruncation(), PerformOffsetsTruncation(), RecoveryInProgress(), START_CRIT_SECTION, and WriteMTruncateXlogRec().

Referenced by vac_truncate_clog().