69 #define UINT32_ACCESS_ONCE(var) ((uint32)(*((volatile uint32 *)&(var))))
310 #ifdef XIDCACHE_DEBUG
313 static long xc_by_recent_xmin = 0;
314 static long xc_by_known_xact = 0;
315 static long xc_by_my_xact = 0;
316 static long xc_by_latest_xid = 0;
317 static long xc_by_main_xid = 0;
318 static long xc_by_child_xid = 0;
319 static long xc_by_known_assigned = 0;
320 static long xc_no_overflow = 0;
321 static long xc_slow_answer = 0;
323 #define xc_by_recent_xmin_inc() (xc_by_recent_xmin++)
324 #define xc_by_known_xact_inc() (xc_by_known_xact++)
325 #define xc_by_my_xact_inc() (xc_by_my_xact++)
326 #define xc_by_latest_xid_inc() (xc_by_latest_xid++)
327 #define xc_by_main_xid_inc() (xc_by_main_xid++)
328 #define xc_by_child_xid_inc() (xc_by_child_xid++)
329 #define xc_by_known_assigned_inc() (xc_by_known_assigned++)
330 #define xc_no_overflow_inc() (xc_no_overflow++)
331 #define xc_slow_answer_inc() (xc_slow_answer++)
333 static void DisplayXidCache(
void);
336 #define xc_by_recent_xmin_inc() ((void) 0)
337 #define xc_by_known_xact_inc() ((void) 0)
338 #define xc_by_my_xact_inc() ((void) 0)
339 #define xc_by_latest_xid_inc() ((void) 0)
340 #define xc_by_main_xid_inc() ((void) 0)
341 #define xc_by_child_xid_inc() ((void) 0)
342 #define xc_by_known_assigned_inc() ((void) 0)
343 #define xc_no_overflow_inc() ((void) 0)
344 #define xc_slow_answer_inc() ((void) 0)
350 bool exclusive_lock);
382 #define PROCARRAY_MAXPROCS (MaxBackends + max_prepared_xacts)
400 #define TOTAL_MAX_CACHED_SUBXIDS \
401 ((PGPROC_MAX_CACHED_SUBXIDS + 1) * PROCARRAY_MAXPROCS)
487 (
errcode(ERRCODE_TOO_MANY_CONNECTIONS),
488 errmsg(
"sorry, too many clients already")));
571 #ifdef XIDCACHE_DEBUG
583 Assert(myoff >= 0 && myoff < arrayP->numProcs);
613 movecount = arrayP->
numProcs - myoff - 1;
840 while (extraWaits-- > 0)
1113 "recovery snapshots are now enabled");
1117 "recovery snapshot waiting for non-overflowed snapshot or "
1118 "until oldest active xid on standby is at least %u (now %u)",
1172 xids[nxids++] = xid;
1180 elog(
ERROR,
"KnownAssignedXids is not empty");
1199 for (
i = 0;
i < nxids;
i++)
1204 "found duplicated transaction %u for KnownAssignedXids insertion",
1288 "recovery snapshot waiting for non-overflowed snapshot or "
1289 "until oldest active xid on standby is at least %u (now %u)",
1330 for (
i = 0;
i < nsubxids;
i++)
1445 (
errcode(ERRCODE_OUT_OF_MEMORY),
1446 errmsg(
"out of memory")));
1458 latestCompletedXid =
1470 for (
int pgxactoff = 0; pgxactoff < numProcs; pgxactoff++)
1478 if (pgxactoff == mypgxactoff)
1507 pxids = other_subxidstates[pgxactoff].
count;
1509 pgprocno = arrayP->
pgprocnos[pgxactoff];
1511 for (
j = pxids - 1;
j >= 0;
j--)
1531 if (other_subxidstates[pgxactoff].overflowed)
1532 xids[nxids++] = pxid;
1617 bool result =
false;
1959 rel->
rd_rel->relkind == RELKIND_RELATION ||
1960 rel->
rd_rel->relkind == RELKIND_MATVIEW ||
1961 rel->
rd_rel->relkind == RELKIND_TOASTVALUE);
2078 uint64 curXactCompletionCount;
2118 snapshot->
copied =
false;
2167 bool suboverflowed =
false;
2172 uint64 curXactCompletionCount;
2177 Assert(snapshot != NULL);
2190 if (snapshot->
xip == NULL)
2198 if (snapshot->
xip == NULL)
2200 (
errcode(ERRCODE_OUT_OF_MEMORY),
2201 errmsg(
"out of memory")));
2205 if (snapshot->
subxip == NULL)
2207 (
errcode(ERRCODE_OUT_OF_MEMORY),
2208 errmsg(
"out of memory")));
2225 myxid = other_xids[mypgxactoff];
2257 for (
int pgxactoff = 0; pgxactoff < numProcs; pgxactoff++)
2277 if (pgxactoff == mypgxactoff)
2300 statusFlags = allStatusFlags[pgxactoff];
2328 if (subxidStates[pgxactoff].overflowed)
2329 suboverflowed =
true;
2332 int nsubxids = subxidStates[pgxactoff].
count;
2336 int pgprocno = pgprocnos[pgxactoff];
2341 memcpy(snapshot->
subxip + subcount,
2344 subcount += nsubxids;
2385 suboverflowed =
true;
2425 def_vis_xid = def_vis_xid_data;
2485 snapshot->
xmin = xmin;
2486 snapshot->
xmax = xmax;
2487 snapshot->
xcnt = count;
2500 snapshot->
copied =
false;
2521 bool result =
false;
2599 bool result =
false;
2697 if (CurrentRunningXacts->
xids == NULL)
2704 if (CurrentRunningXacts->
xids == NULL)
2706 (
errcode(ERRCODE_OUT_OF_MEMORY),
2707 errmsg(
"out of memory")));
2710 xids = CurrentRunningXacts->
xids;
2712 count = subcount = 0;
2713 suboverflowed =
false;
2722 latestCompletedXid =
2750 oldestRunningXid = xid;
2753 suboverflowed =
true;
2763 xids[count++] = xid;
2793 subcount += nsubxids;
2813 CurrentRunningXacts->
xcnt = count - subcount;
2814 CurrentRunningXacts->
subxcnt = subcount;
2826 return CurrentRunningXacts;
2880 oldestRunningXid = xid;
2890 return oldestRunningXid;
2960 if (!recovery_in_progress)
2978 oldestSafeXid = xid;
2984 return oldestSafeXid;
3034 vxids[count++] = vxid;
3056 bool result =
false;
3077 for (
i = 0;
i < nvxids;
i++)
3139 if (proc->
pid == pid)
3177 if (other_xids[
index] == xid)
3232 bool allDbs,
int excludeVacuum,
3255 if (excludeVacuum & statusFlags)
3277 vxids[count++] = vxid;
3342 (
errcode(ERRCODE_OUT_OF_MEMORY),
3343 errmsg(
"out of memory")));
3378 vxids[count++] = vxid;
3405 bool conflictPending)
3499 return count >= min;
3624 if (proc->
roleId == roleid)
3661 #define MAXAUTOVACPIDS 10
3666 for (tries = 0; tries < 50; tries++)
3674 *nbackends = *nprepared = 0;
3698 autovac_pids[nautovacs++] = proc->
pid;
3714 (
void)
kill(autovac_pids[
index], SIGTERM);
3764 (
errcode(ERRCODE_OBJECT_IN_USE),
3765 errmsg(
"database \"%s\" is being used by prepared transactions",
3768 "There are %d prepared transactions using the database.",
3796 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
3797 errmsg(
"permission denied to terminate process"),
3798 errdetail(
"Only roles with the %s attribute may terminate processes of roles with the %s attribute.",
3799 "SUPERUSER",
"SUPERUSER")));
3805 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
3806 errmsg(
"permission denied to terminate process"),
3807 errdetail(
"Only roles with privileges of the role whose process is being terminated or with privileges of the \"%s\" role may terminate this process.",
3808 "pg_signal_backend")));
3830 (void)
kill(-pid, SIGTERM);
3832 (void)
kill(pid, SIGTERM);
3848 bool already_locked)
3852 if (!already_locked)
3858 if (!already_locked)
3861 elog(
DEBUG1,
"xmin required by slots: data %u, catalog %u",
3862 xmin, catalog_xmin);
3880 if (catalog_xmin != NULL)
3926 for (
i = nxids - 1;
i >= 0;
i--)
3936 mysubxidstat->
count--;
3949 if (j < 0 && !MyProc->subxidStatus.overflowed)
3950 elog(
WARNING,
"did not find subXID %u in MyProc", anxid);
3959 mysubxidstat->
count--;
3965 if (j < 0 && !MyProc->subxidStatus.overflowed)
3966 elog(
WARNING,
"did not find subXID %u in MyProc", xid);
3977 #ifdef XIDCACHE_DEBUG
3983 DisplayXidCache(
void)
3986 "XidCache: xmin: %ld, known: %ld, myxact: %ld, latest: %ld, mainxid: %ld, childxid: %ld, knownassigned: %ld, nooflo: %ld, slow: %ld\n",
3993 xc_by_known_assigned,
4062 state->definitely_needed))
4201 return state->maybe_needed;
4266 + (
int32) (xid - rel_xid));
4370 Assert(next_expected_xid == xid);
4585 static unsigned int transactionEndsCounter;
4589 #define KAX_COMPRESS_FREQUENCY 128
4590 #define KAX_COMPRESS_IDLE_INTERVAL 1000
4598 nelements = head - tail;
4629 if (nelements < 2 * pArray->numKnownAssignedXids)
4639 if (lastCompressTs != 0)
4659 for (
i = tail;
i < head;
i++)
4693 bool exclusive_lock)
4709 if (to_xid >= from_xid)
4710 nxids = to_xid - from_xid + 1;
4714 next_xid = from_xid;
4729 Assert(head >= 0 && head <= pArray->maxKnownAssignedXids);
4730 Assert(tail >= 0 && tail < pArray->maxKnownAssignedXids);
4741 elog(
ERROR,
"out-of-order XID insertion in KnownAssignedXids");
4758 elog(
ERROR,
"too many KnownAssignedXids");
4762 next_xid = from_xid;
4763 for (
i = 0;
i < nxids;
i++)
4780 if (!exclusive_lock)
4803 int result_index = -1;
4821 while (first <= last)
4826 mid_index = (first + last) / 2;
4831 result_index = mid_index;
4835 last = mid_index - 1;
4837 first = mid_index + 1;
4840 if (result_index < 0)
4857 if (result_index == tail)
4931 for (
i = 0;
i < nsubxids;
i++)
4970 for (
i = tail;
i < head;
i++)
4993 for (
i = tail;
i < head;
i++)
5057 for (
i = tail;
i < head;
i++)
5081 xarray[count++] = knownXid;
5107 for (
i = tail;
i < head;
i++)
5142 for (
i = tail;
i < head;
i++)
5151 elog(trace_level,
"%d KnownAssignedXids (num=%d tail=%d head=%d) %s",
bool has_privs_of_role(Oid member, Oid role)
static bool pg_atomic_compare_exchange_u32(volatile pg_atomic_uint32 *ptr, uint32 *expected, uint32 newval)
#define pg_read_barrier()
#define pg_write_barrier()
static void pg_atomic_write_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
static uint32 pg_atomic_read_u32(volatile pg_atomic_uint32 *ptr)
static uint32 pg_atomic_exchange_u32(volatile pg_atomic_uint32 *ptr, uint32 newval)
TimestampTz GetCurrentTimestamp(void)
#define PG_USED_FOR_ASSERTS_ONLY
#define FLEXIBLE_ARRAY_MEMBER
#define OidIsValid(objectId)
bool IsCatalogRelation(Relation relation)
char * get_database_name(Oid dbid)
elog(ERROR, "%s: %s", p2, msg)
int errdetail(const char *fmt,...)
int errdetail_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
int trace_recovery(int trace_level)
#define ereport(elevel,...)
Assert(fmt[strlen(fmt) - 1] !='\n')
List * lappend_int(List *list, int datum)
#define VirtualTransactionIdIsValid(vxid)
#define InvalidLocalTransactionId
#define VirtualTransactionIdEquals(vxid1, vxid2)
#define GET_VXID_FROM_PGPROC(vxid, proc)
bool LWLockHeldByMe(LWLock *lock)
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
bool LWLockHeldByMeInMode(LWLock *lock, LWLockMode mode)
void LWLockRelease(LWLock *lock)
bool LWLockConditionalAcquire(LWLock *lock, LWLockMode mode)
void pfree(void *pointer)
#define AmStartupProcess()
#define IsBootstrapProcessingMode()
#define CHECK_FOR_INTERRUPTS()
static bool pg_lfind32(uint32 key, uint32 *base, uint32 nelem)
#define qsort(a, b, c, d)
void PGSemaphoreUnlock(PGSemaphore sema)
void PGSemaphoreLock(PGSemaphore sema)
#define PROC_IN_LOGICAL_DECODING
#define NUM_AUXILIARY_PROCS
#define PROC_AFFECTS_ALL_HORIZONS
#define PROC_VACUUM_STATE_MASK
#define PROC_IS_AUTOVACUUM
@ KAX_STARTUP_PROCESS_IDLE
static GlobalVisState GlobalVisDataRels
bool GlobalVisTestIsRemovableFullXid(GlobalVisState *state, FullTransactionId fxid)
TransactionId GetOldestNonRemovableTransactionId(Relation rel)
VirtualTransactionId * GetVirtualXIDsDelayingChkpt(int *nvxids, int type)
#define TOTAL_MAX_CACHED_SUBXIDS
static GlobalVisState GlobalVisSharedRels
void ProcArrayGetReplicationSlotXmin(TransactionId *xmin, TransactionId *catalog_xmin)
static GlobalVisState GlobalVisCatalogRels
bool GlobalVisTestIsRemovableXid(GlobalVisState *state, TransactionId xid)
bool GlobalVisCheckRemovableFullXid(Relation rel, FullTransactionId fxid)
static void KnownAssignedXidsCompress(KAXCompressReason reason, bool haveLock)
pid_t SignalVirtualTransaction(VirtualTransactionId vxid, ProcSignalReason sigmode, bool conflictPending)
Size ProcArrayShmemSize(void)
TransactionId GetOldestSafeDecodingTransactionId(bool catalogOnly)
void XidCacheRemoveRunningXids(TransactionId xid, int nxids, const TransactionId *xids, TransactionId latestXid)
bool TransactionIdIsActive(TransactionId xid)
static FullTransactionId FullXidRelativeTo(FullTransactionId rel, TransactionId xid)
bool MinimumActiveBackends(int min)
void TerminateOtherDBBackends(Oid databaseId)
#define xc_no_overflow_inc()
static TransactionId standbySnapshotPendingXmin
void ExpireAllKnownAssignedTransactionIds(void)
#define UINT32_ACCESS_ONCE(var)
VirtualTransactionId * GetConflictingVirtualXIDs(TransactionId limitXmin, Oid dbOid)
RunningTransactions GetRunningTransactionData(void)
TransactionId GetOldestActiveTransactionId(void)
static void KnownAssignedXidsRemoveTree(TransactionId xid, int nsubxids, TransactionId *subxids)
static int KnownAssignedXidsGetAndSetXmin(TransactionId *xarray, TransactionId *xmin, TransactionId xmax)
#define xc_by_recent_xmin_inc()
void ProcArrayEndTransaction(PGPROC *proc, TransactionId latestXid)
void RecordKnownAssignedTransactionIds(TransactionId xid)
static int KnownAssignedXidsGet(TransactionId *xarray, TransactionId xmax)
TransactionId GetOldestTransactionIdConsideredRunning(void)
static TransactionId latestObservedXid
static ProcArrayStruct * procArray
int GetMaxSnapshotSubxidCount(void)
int CountDBConnections(Oid databaseid)
static GlobalVisState GlobalVisTempRels
#define xc_by_my_xact_inc()
#define xc_by_known_assigned_inc()
struct ProcArrayStruct ProcArrayStruct
void CancelDBBackends(Oid databaseid, ProcSignalReason sigmode, bool conflictPending)
#define PROCARRAY_MAXPROCS
void GetReplicationHorizons(TransactionId *xmin, TransactionId *catalog_xmin)
static bool GlobalVisTestShouldUpdate(GlobalVisState *state)
static void ProcArrayEndTransactionInternal(PGPROC *proc, TransactionId latestXid)
static void KnownAssignedXidsRemovePreceding(TransactionId removeXid)
void ProcArrayAdd(PGPROC *proc)
struct ComputeXidHorizonsResult ComputeXidHorizonsResult
TransactionId GlobalVisTestNonRemovableHorizon(GlobalVisState *state)
static TransactionId * KnownAssignedXids
#define xc_by_child_xid_inc()
pid_t CancelVirtualTransaction(VirtualTransactionId vxid, ProcSignalReason sigmode)
Snapshot GetSnapshotData(Snapshot snapshot)
static bool * KnownAssignedXidsValid
bool HaveVirtualXIDsDelayingChkpt(VirtualTransactionId *vxids, int nvxids, int type)
static void KnownAssignedXidsRemove(TransactionId xid)
void KnownAssignedTransactionIdsIdleMaintenance(void)
static void GlobalVisUpdateApply(ComputeXidHorizonsResult *horizons)
int GetMaxSnapshotXidCount(void)
GlobalVisState * GlobalVisTestFor(Relation rel)
int CountDBBackends(Oid databaseid)
bool GlobalVisCheckRemovableXid(Relation rel, TransactionId xid)
bool ProcArrayInstallRestoredXmin(TransactionId xmin, PGPROC *proc)
#define KAX_COMPRESS_FREQUENCY
void CreateSharedProcArray(void)
static TransactionId KnownAssignedXidsGetOldestXmin(void)
void ProcArrayApplyRecoveryInfo(RunningTransactions running)
void ProcArrayClearTransaction(PGPROC *proc)
VirtualTransactionId * GetCurrentVirtualXIDs(TransactionId limitXmin, bool excludeXmin0, bool allDbs, int excludeVacuum, int *nvxids)
int CountUserBackends(Oid roleid)
PGPROC * BackendPidGetProc(int pid)
static TransactionId ComputeXidHorizonsResultLastXmin
static void GlobalVisUpdate(void)
#define xc_slow_answer_inc()
static void KnownAssignedXidsDisplay(int trace_level)
#define xc_by_main_xid_inc()
PGPROC * BackendPidGetProcWithLock(int pid)
static void MaintainLatestCompletedXidRecovery(TransactionId latestXid)
static void ComputeXidHorizons(ComputeXidHorizonsResult *h)
void ProcArrayApplyXidAssignment(TransactionId topxid, int nsubxids, TransactionId *subxids)
static bool KnownAssignedXidExists(TransactionId xid)
bool CountOtherDBBackends(Oid databaseId, int *nbackends, int *nprepared)
int BackendXidGetPid(TransactionId xid)
#define xc_by_latest_xid_inc()
bool IsBackendPid(int pid)
#define xc_by_known_xact_inc()
static bool KnownAssignedXidsSearch(TransactionId xid, bool remove)
static void KnownAssignedXidsReset(void)
FullTransactionId GlobalVisTestNonRemovableFullHorizon(GlobalVisState *state)
static GlobalVisHorizonKind GlobalVisHorizonKindForRel(Relation rel)
void ProcArraySetReplicationSlotXmin(TransactionId xmin, TransactionId catalog_xmin, bool already_locked)
void ProcArrayInitRecovery(TransactionId initializedUptoXID)
void ProcArrayRemove(PGPROC *proc, TransactionId latestXid)
#define KAX_COMPRESS_IDLE_INTERVAL
static void MaintainLatestCompletedXid(TransactionId latestXid)
static void ProcArrayGroupClearXid(PGPROC *proc, TransactionId latestXid)
void ExpireTreeKnownAssignedTransactionIds(TransactionId xid, int nsubxids, TransactionId *subxids, TransactionId max_xid)
static TransactionId cachedXidIsNotInProgress
bool ProcArrayInstallImportedXmin(TransactionId xmin, VirtualTransactionId *sourcevxid)
static bool GetSnapshotDataReuse(Snapshot snapshot)
static void KnownAssignedXidsAdd(TransactionId from_xid, TransactionId to_xid, bool exclusive_lock)
bool TransactionIdIsInProgress(TransactionId xid)
void ExpireOldKnownAssignedTransactionIds(TransactionId xid)
int SendProcSignal(pid_t pid, ProcSignalReason reason, BackendId backendId)
#define RELATION_IS_LOCAL(relation)
#define RelationIsAccessibleInLogicalDecoding(relation)
Size add_size(Size s1, Size s2)
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Size mul_size(Size s1, Size s2)
void pg_usleep(long microsec)
TransactionId TransactionXmin
void StandbyReleaseOldLocks(TransactionId oldxid)
void appendStringInfo(StringInfo str, const char *fmt,...)
void initStringInfo(StringInfo str)
TransactionId slot_catalog_xmin
TransactionId data_oldest_nonremovable
TransactionId temp_oldest_nonremovable
TransactionId shared_oldest_nonremovable
TransactionId oldest_considered_running
FullTransactionId latest_completed
TransactionId catalog_oldest_nonremovable
TransactionId shared_oldest_nonremovable_raw
FullTransactionId definitely_needed
FullTransactionId maybe_needed
bool procArrayGroupMember
pg_atomic_uint32 procArrayGroupNext
bool recoveryConflictPending
XidCacheStatus subxidStatus
TransactionId procArrayGroupMemberXid
XidCacheStatus * subxidStates
pg_atomic_uint32 procArrayGroupFirst
TransactionId replication_slot_xmin
TransactionId replication_slot_catalog_xmin
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
TransactionId lastOverflowedXid
int tailKnownAssignedXids
int headKnownAssignedXids
TransactionId oldestRunningXid
TransactionId latestCompletedXid
uint64 snapXactCompletionCount
FullTransactionId nextXid
uint64 xactCompletionCount
FullTransactionId latestCompletedXid
LocalTransactionId localTransactionId
TransactionId xids[PGPROC_MAX_CACHED_SUBXIDS]
void SubTransSetParent(TransactionId xid, TransactionId parent)
TransactionId SubTransGetTopmostTransaction(TransactionId xid)
void ExtendSUBTRANS(TransactionId newestXact)
bool superuser_arg(Oid roleid)
TransactionId TransactionIdLatest(TransactionId mainxid, int nxids, const TransactionId *xids)
bool TransactionIdDidCommit(TransactionId transactionId)
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
bool TransactionIdPrecedesOrEquals(TransactionId id1, TransactionId id2)
bool TransactionIdDidAbort(TransactionId transactionId)
bool TransactionIdFollows(TransactionId id1, TransactionId id2)
bool TransactionIdFollowsOrEquals(TransactionId id1, TransactionId id2)
#define FullTransactionIdIsNormal(x)
static FullTransactionId FullTransactionIdNewer(FullTransactionId a, FullTransactionId b)
#define TransactionIdRetreat(dest)
#define InvalidTransactionId