98#define MULTIXACT_MEMBER_LOW_THRESHOLD UINT64CONST(2000000000)
99#define MULTIXACT_MEMBER_HIGH_THRESHOLD UINT64CONST(4000000000)
119#define MultiXactOffsetCtl (&MultiXactOffsetCtlData)
120#define MultiXactMemberCtl (&MultiXactMemberCtlData)
215#define NumMemberSlots (MaxBackends + max_prepared_xacts)
216#define NumVisibleSlots MaxBackends
284#define MAX_CACHE_ENTRIES 256
288#ifdef MULTIXACT_DEBUG
289#define debug_elog2(a,b) elog(a,b)
290#define debug_elog3(a,b,c) elog(a,b,c)
291#define debug_elog4(a,b,c,d) elog(a,b,c,d)
292#define debug_elog5(a,b,c,d,e) elog(a,b,c,d,e)
293#define debug_elog6(a,b,c,d,e,f) elog(a,b,c,d,e,f)
295#define debug_elog2(a,b)
296#define debug_elog3(a,b,c)
297#define debug_elog4(a,b,c,d)
298#define debug_elog5(a,b,c,d,e)
299#define debug_elog6(a,b,c,d,e,f)
449 for (
i = 0;
i < nmembers;
i++)
452 (members[
i].status == status))
476 for (
i = 0,
j = 0;
i < nmembers;
i++)
538 for (
i = 0;
i < nmembers;
i++)
553 for (
i = 0;
i < nmembers;
i++)
735 for (
i = 0;
i < nmembers;
i++)
740 elog(
ERROR,
"new multixact has more than one updating member: %s",
769 xlrec.nmembers = nmembers;
877 next_offset = offset + nmembers;
878 if (next_offset == 0)
893 for (
int i = 0;
i < nmembers;
i++, offset++)
977 elog(
ERROR,
"cannot assign MultiXactIds during recovery");
1029 errmsg(
"database is not accepting commands that assign new MultiXactIds to avoid wraparound data loss in database \"%s\"",
1031 errhint(
"Execute a database-wide VACUUM in that database.\n"
1032 "You might also need to commit or roll back old prepared transactions, or drop stale replication slots.")));
1036 errmsg(
"database is not accepting commands that assign new MultiXactIds to avoid wraparound data loss in database with OID %u",
1038 errhint(
"Execute a database-wide VACUUM in that database.\n"
1039 "You might also need to commit or roll back old prepared transactions, or drop stale replication slots.")));
1057 (
errmsg_plural(
"database \"%s\" must be vacuumed before %u more MultiXactId is used",
1058 "database \"%s\" must be vacuumed before %u more MultiXactIds are used",
1059 multiWrapLimit - result,
1061 multiWrapLimit - result),
1062 errdetail(
"Approximately %.2f%% of MultiXactIds are available for use.",
1063 (
double) (multiWrapLimit - result) / (
MaxMultiXactId / 2) * 100),
1064 errhint(
"Execute a database-wide VACUUM in that database.\n"
1065 "You might also need to commit or roll back old prepared transactions, or drop stale replication slots.")));
1068 (
errmsg_plural(
"database with OID %u must be vacuumed before %u more MultiXactId is used",
1069 "database with OID %u must be vacuumed before %u more MultiXactIds are used",
1070 multiWrapLimit - result,
1072 multiWrapLimit - result),
1073 errdetail(
"Approximately %.2f%% of MultiXactIds are available for use.",
1074 (
double) (multiWrapLimit - result) / (
MaxMultiXactId / 2) * 100),
1075 errhint(
"Execute a database-wide VACUUM in that database.\n"
1076 "You might also need to commit or roll back old prepared transactions, or drop stale replication slots.")));
1102 if (nextOffset + nmembers < nextOffset)
1105 errmsg(
"MultiXact members would wrap around")));
1106 *offset = nextOffset;
1234 errmsg(
"MultiXactId %u does no longer exist -- apparent wraparound",
1240 errmsg(
"MultiXactId %u has not been created yet -- apparent wraparound",
1265 errmsg(
"MultiXact %u has invalid offset", multi)));
1310 errmsg(
"MultiXact %u has invalid next offset", multi)));
1314 errmsg(
"MultiXact %u with offset (%" PRIu64 ") has zero members",
1319 errmsg(
"MultiXact %u has offset (%" PRIu64 ") greater than its next offset (%" PRIu64 ")",
1324 errmsg(
"MultiXact %u has too many members (%" PRIu64 ")",
1331 for (
int i = 0;
i < length;
i++, offset++)
1454 return entry->
multi;
1482 if (entry->
multi == multi)
1530 "MultiXact cache context",
1539 entry->
multi = multi;
1572 return "fornokeyupd";
1580 elog(
ERROR,
"unrecognized multixact status %d", status);
1600 for (
i = 1;
i < nmembers;
i++)
2023 "MultiXact: checkpoint is nextMulti %u, nextOffset %" PRIu64 ", oldestMulti %u in DB %u",
2024 *nextMulti, *nextMultiOffset, *oldestMulti, *oldestMultiDB);
2060 nextMulti, nextMultiOffset);
2100 multiStopLimit = multiWrapLimit - 3000000;
2114 multiWarnLimit = multiWrapLimit - 100000000;
2143 (
errmsg_internal(
"MultiXactId wrap limit is %u, limited by database with OID %u",
2198 (
errmsg_plural(
"database \"%s\" must be vacuumed before %u more MultiXactId is used",
2199 "database \"%s\" must be vacuumed before %u more MultiXactIds are used",
2203 errdetail(
"Approximately %.2f%% of MultiXactIds are available for use.",
2205 errhint(
"To avoid MultiXactId assignment failures, execute a database-wide VACUUM in that database.\n"
2206 "You might also need to commit or roll back old prepared transactions, or drop stale replication slots.")));
2209 (
errmsg_plural(
"database with OID %u must be vacuumed before %u more MultiXactId is used",
2210 "database with OID %u must be vacuumed before %u more MultiXactIds are used",
2214 errdetail(
"Approximately %.2f%% of MultiXactIds are available for use.",
2216 errhint(
"To avoid MultiXactId assignment failures, execute a database-wide VACUUM in that database.\n"
2217 "You might also need to commit or roll back old prepared transactions, or drop stale replication slots.")));
2317 while (nmembers > 0)
2438 if (oldestMultiXactId == nextMXact)
2444 oldestOffset = nextOffset;
2470 (
errmsg(
"MultiXact member truncation is disabled because oldest checkpointed MultiXact %u does not exist on disk",
2471 oldestMultiXactId)));
2595 members = nextOffset - oldestOffset;
2718 (
errmsg(
"cannot truncate up to MultiXact %u because it does not exist on disk, skipping truncation",
2735 (
errmsg(
"cannot truncate up to MultiXact %u because it has invalid offset, skipping truncation",
2741 elog(
DEBUG1,
"performing multixact truncation: "
2742 "oldestMulti %u (offsets segment %" PRIx64 "), "
2743 "oldestOffset %" PRIu64 " (members segment %" PRIx64 ")",
2843 return errdetail(
"Could not access member of multixact %u at offset %" PRIu64 ".",
2846 return errdetail(
"Could not access multixact member at offset %" PRIu64 ".",
2894 xlrec.oldestMulti = oldestMulti;
2895 xlrec.oldestOffset = oldestOffset;
2949 for (
i = 0;
i <
xlrec->nmembers;
i++)
2965 elog(
DEBUG1,
"replaying multixact truncation: "
2966 "oldestMulti %u (offsets segment %" PRIx64 "), "
2967 "oldestOffset %" PRIu64 " (members segment %" PRIx64 ")",
2997 elog(
PANIC,
"multixact_redo: unknown op code %u", info);
static void pg_atomic_write_u64(volatile pg_atomic_uint64 *ptr, uint64 val)
int autovacuum_multixact_freeze_max_age
#define Assert(condition)
TransactionId MultiXactId
#define FLEXIBLE_ARRAY_MEMBER
#define MemSet(start, val, len)
int errcode(int sqlerrcode)
int errhint(const char *fmt,...) pg_attribute_printf(1
int errdetail(const char *fmt,...) pg_attribute_printf(1
int int errmsg_internal(const char *fmt,...) pg_attribute_printf(1
int int int errmsg_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...) pg_attribute_printf(1
#define ereport(elevel,...)
#define palloc_array(type, count)
Datum difference(PG_FUNCTION_ARGS)
int multixact_offset_buffers
int multixact_member_buffers
#define dclist_container(type, membername, ptr)
static uint32 dclist_count(const dclist_head *head)
static void dclist_move_head(dclist_head *head, dlist_node *node)
static dlist_node * dclist_tail_node(dclist_head *head)
static void dclist_delete_from(dclist_head *head, dlist_node *node)
#define DCLIST_STATIC_INIT(name)
static void dclist_push_head(dclist_head *head, dlist_node *node)
static void dclist_init(dclist_head *head)
#define dclist_foreach(iter, lhead)
#define INJECTION_POINT_CACHED(name, arg)
#define INJECTION_POINT_LOAD(name)
char * get_database_name(Oid dbid)
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
void LWLockRelease(LWLock *lock)
char * MemoryContextStrdup(MemoryContext context, const char *string)
void * MemoryContextAlloc(MemoryContext context, Size size)
MemoryContext TopTransactionContext
void pfree(void *pointer)
MemoryContext TopMemoryContext
#define AllocSetContextCreate
#define ALLOCSET_SMALL_SIZES
#define START_CRIT_SECTION()
#define END_CRIT_SECTION()
static MultiXactId PreviousMultiXactId(MultiXactId multi)
static SlruCtlData MultiXactOffsetCtlData
void MultiXactShmemInit(void)
static bool MultiXactMemberPagePrecedes(int64 page1, int64 page2)
static MultiXactId GetNewMultiXactId(int nmembers, MultiXactOffset *offset)
static int mXactCacheGetById(MultiXactId multi, MultiXactMember **members)
MultiXactId MultiXactIdExpand(MultiXactId multi, TransactionId xid, MultiXactStatus status)
static void ExtendMultiXactMember(MultiXactOffset offset, int nmembers)
void ReadMultiXactIdRange(MultiXactId *oldest, MultiXactId *next)
static MultiXactId * MyOldestVisibleMXactIdSlot(void)
bool MultiXactIdPrecedes(MultiXactId multi1, MultiXactId multi2)
char * mxstatus_to_string(MultiXactStatus status)
void multixact_redo(XLogReaderState *record)
static void PerformOffsetsTruncation(MultiXactId newOldestMulti)
void multixact_twophase_postcommit(FullTransactionId fxid, uint16 info, void *recdata, uint32 len)
#define debug_elog5(a, b, c, d, e)
static void MultiXactIdSetOldestVisible(void)
int multixactoffsetssyncfiletag(const FileTag *ftag, char *path)
static bool find_multixact_start(MultiXactId multi, MultiXactOffset *result)
void PostPrepare_MultiXact(FullTransactionId fxid)
void MultiXactSetNextMXact(MultiXactId nextMulti, MultiXactOffset nextMultiOffset)
#define MultiXactMemberCtl
static void WriteMTruncateXlogRec(Oid oldestMultiDB, MultiXactId endTruncOff, MultiXactOffset endTruncMemb)
void AtPrepare_MultiXact(void)
bool MultiXactIdPrecedesOrEquals(MultiXactId multi1, MultiXactId multi2)
void MultiXactAdvanceOldest(MultiXactId oldestMulti, Oid oldestMultiDB)
static void mXactCachePut(MultiXactId multi, int nmembers, MultiXactMember *members)
void GetMultiXactInfo(uint32 *multixacts, MultiXactOffset *nextOffset, MultiXactId *oldestMultiXactId, MultiXactOffset *oldestOffset)
bool MultiXactIdIsRunning(MultiXactId multi, bool isLockOnly)
void MultiXactIdSetOldestMember(void)
#define MULTIXACT_MEMBER_LOW_THRESHOLD
static MemoryContext MXactContext
static MultiXactId * OldestVisibleMXactId
static int mxactMemberComparator(const void *arg1, const void *arg2)
static void ExtendMultiXactOffset(MultiXactId multi)
Size MultiXactShmemSize(void)
#define MultiXactOffsetCtl
void MultiXactGetCheckptMulti(bool is_shutdown, MultiXactId *nextMulti, MultiXactOffset *nextMultiOffset, MultiXactId *oldestMulti, Oid *oldestMultiDB)
static void RecordNewMultiXact(MultiXactId multi, MultiXactOffset offset, int nmembers, MultiXactMember *members)
int multixactmemberssyncfiletag(const FileTag *ftag, char *path)
#define MAX_CACHE_ENTRIES
static MultiXactId NextMultiXactId(MultiXactId multi)
MultiXactId GetOldestMultiXactId(void)
void CheckPointMultiXact(void)
static int MultiXactOffsetIoErrorDetail(const void *opaque_data)
static MultiXactId * PreparedXactOldestMemberMXactIdSlot(ProcNumber procno)
MultiXactId MultiXactIdCreateFromMembers(int nmembers, MultiXactMember *members)
static Size MultiXactSharedStateShmemSize(void)
static MultiXactId mXactCacheGetBySet(int nmembers, MultiXactMember *members)
static dclist_head MXactCache
#define debug_elog3(a, b, c)
char * mxid_to_string(MultiXactId multi, int nmembers, MultiXactMember *members)
#define debug_elog4(a, b, c, d)
void multixact_twophase_postabort(FullTransactionId fxid, uint16 info, void *recdata, uint32 len)
static void PerformMembersTruncation(MultiXactOffset newOldestOffset)
static bool MultiXactOffsetPagePrecedes(int64 page1, int64 page2)
static MultiXactId * MyOldestMemberMXactIdSlot(void)
int MultiXactMemberFreezeThreshold(void)
static void SetOldestOffset(void)
void MultiXactAdvanceNextMXact(MultiXactId minMulti, MultiXactOffset minMultiOffset)
static MultiXactId * OldestMemberMXactId
static MultiXactStateData * MultiXactState
MultiXactId ReadNextMultiXactId(void)
void BootStrapMultiXact(void)
#define debug_elog6(a, b, c, d, e, f)
void multixact_twophase_recover(FullTransactionId fxid, uint16 info, void *recdata, uint32 len)
static int MultiXactMemberIoErrorDetail(const void *opaque_data)
MultiXactId MultiXactIdCreate(TransactionId xid1, MultiXactStatus status1, TransactionId xid2, MultiXactStatus status2)
void TruncateMultiXact(MultiXactId newOldestMulti, Oid newOldestMultiDB)
bool check_multixact_offset_buffers(int *newval, void **extra, GucSource source)
bool check_multixact_member_buffers(int *newval, void **extra, GucSource source)
void AtEOXact_MultiXact(void)
#define MULTIXACT_MEMBER_HIGH_THRESHOLD
static SlruCtlData MultiXactMemberCtlData
#define debug_elog2(a, b)
void StartupMultiXact(void)
void SetMultiXactIdLimit(MultiXactId oldest_datminmxid, Oid oldest_datoid)
int GetMultiXactIdMembers(MultiXactId multi, MultiXactMember **members, bool from_pgupgrade, bool isLockOnly)
#define MultiXactIdIsValid(multi)
#define XLOG_MULTIXACT_ZERO_MEM_PAGE
#define XLOG_MULTIXACT_ZERO_OFF_PAGE
@ MultiXactStatusForShare
@ MultiXactStatusForNoKeyUpdate
@ MultiXactStatusNoKeyUpdate
@ MultiXactStatusForUpdate
@ MultiXactStatusForKeyShare
#define ISUPDATE_from_mxstatus(status)
#define InvalidMultiXactId
#define XLOG_MULTIXACT_TRUNCATE_ID
#define SizeOfMultiXactCreate
#define SizeOfMultiXactTruncate
#define XLOG_MULTIXACT_CREATE_ID
static int64 MultiXactIdToOffsetSegment(MultiXactId multi)
static int64 MXOffsetToMemberSegment(MultiXactOffset offset)
#define MXACT_MEMBER_BITS_PER_XACT
static int MXOffsetToFlagsBitShift(MultiXactOffset32 offset)
#define MXACT_MEMBER_XACT_BITMASK
static int64 MXOffsetToMemberPage(MultiXactOffset32 offset)
#define MULTIXACT_OFFSETS_PER_PAGE
static int MXOffsetToMemberOffset(MultiXactOffset32 offset)
static int MultiXactIdToOffsetEntry(MultiXactId multi)
static int64 MultiXactIdToOffsetPage(MultiXactId multi)
#define MULTIXACT_MEMBERS_PER_PAGE
static int MXOffsetToFlagsOffset(MultiXactOffset32 offset)
#define ERRCODE_DATA_CORRUPTED
static rewind_source * source
static char buf[DEFAULT_XLOG_SEG_SIZE]
void SendPostmasterSignal(PMSignalReason reason)
@ PMSIGNAL_START_AUTOVAC_LAUNCHER
#define qsort(a, b, c, d)
#define FIRST_PREPARED_XACT_PROC_NUMBER
#define DELAY_CHKPT_START
bool TransactionIdIsInProgress(TransactionId xid)
Size add_size(Size s1, Size s2)
Size mul_size(Size s1, Size s2)
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
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)
void SimpleLruWriteAll(SlruCtl ctl, bool allow_redirtied)
int SimpleLruReadPage(SlruCtl ctl, int64 pageno, bool write_ok, const void *opaque_data)
bool SimpleLruDoesPhysicalPageExist(SlruCtl ctl, int64 pageno)
int SlruSyncFileTag(SlruCtl ctl, const FileTag *ftag, char *path)
int SimpleLruZeroPage(SlruCtl ctl, int64 pageno)
void SimpleLruZeroAndWritePage(SlruCtl ctl, int64 pageno)
void SimpleLruTruncate(SlruCtl ctl, int64 cutoffPage)
int SimpleLruReadPage_ReadOnly(SlruCtl ctl, int64 pageno, const void *opaque_data)
Size SimpleLruShmemSize(int nslots, int nlsns)
bool check_slru_buffers(const char *name, int *newval)
static LWLock * SimpleLruGetBankLock(SlruCtl ctl, int64 pageno)
#define SlruPagePrecedesUnitTests(ctl, per_page)
void appendStringInfo(StringInfo str, const char *fmt,...)
void appendStringInfoChar(StringInfo str, char ch)
void initStringInfo(StringInfo str)
MultiXactId multiWrapLimit
MultiXactId multiStopLimit
MultiXactId multiWarnLimit
MultiXactId multiVacLimit
MultiXactOffset nextOffset
MultiXactId oldestMultiXactId
MultiXactId perBackendXactIds[FLEXIBLE_ARRAY_MEMBER]
MultiXactOffset oldestOffset
MultiXactMember members[FLEXIBLE_ARRAY_MEMBER]
@ SYNC_HANDLER_MULTIXACT_MEMBER
@ SYNC_HANDLER_MULTIXACT_OFFSET
bool TransactionIdDidCommit(TransactionId transactionId)
#define TransactionIdEquals(id1, id2)
#define TransactionIdIsValid(xid)
static bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
ProcNumber TwoPhaseGetDummyProcNumber(FullTransactionId fxid, bool lock_held)
void RegisterTwoPhaseRecord(TwoPhaseRmgrId rmid, uint16 info, const void *data, uint32 len)
#define TWOPHASE_RM_MULTIXACT_ID
void AdvanceNextFullTransactionIdPastXid(TransactionId xid)
bool IsTransactionState(void)
bool TransactionIdIsCurrentTransactionId(TransactionId xid)
bool RecoveryInProgress(void)
void XLogFlush(XLogRecPtr record)
XLogRecPtr XLogSimpleInsertInt64(RmgrId rmid, uint8 info, int64 value)
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
void XLogRegisterData(const void *data, uint32 len)
void XLogBeginInsert(void)
#define XLogRecGetInfo(decoder)
#define XLogRecGetData(decoder)
#define XLogRecGetXid(decoder)
#define XLogRecHasAnyBlockRefs(decoder)