diff options
Diffstat (limited to 'src/backend/storage/ipc/procarray.c')
-rw-r--r-- | src/backend/storage/ipc/procarray.c | 271 |
1 files changed, 183 insertions, 88 deletions
diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c index 185f581c8b6..0bf20a49375 100644 --- a/src/backend/storage/ipc/procarray.c +++ b/src/backend/storage/ipc/procarray.c @@ -9,8 +9,9 @@ * one is as a means of determining the set of currently running transactions. * * Because of various subtle race conditions it is critical that a backend - * hold the correct locks while setting or clearing its MyPgXact->xid field. - * See notes in src/backend/access/transam/README. + * hold the correct locks while setting or clearing its xid (in + * ProcGlobal->xids[]/MyProc->xid). See notes in + * src/backend/access/transam/README. * * The process arrays now also include structures representing prepared * transactions. The xid and subxids fields of these are valid, as are the @@ -436,7 +437,9 @@ ProcArrayAdd(PGPROC *proc) ProcArrayStruct *arrayP = procArray; int index; + /* See ProcGlobal comment explaining why both locks are held */ LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE); + LWLockAcquire(XidGenLock, LW_EXCLUSIVE); if (arrayP->numProcs >= arrayP->maxProcs) { @@ -445,7 +448,6 @@ ProcArrayAdd(PGPROC *proc) * fixed supply of PGPROC structs too, and so we should have failed * earlier.) */ - LWLockRelease(ProcArrayLock); ereport(FATAL, (errcode(ERRCODE_TOO_MANY_CONNECTIONS), errmsg("sorry, too many clients already"))); @@ -471,10 +473,25 @@ ProcArrayAdd(PGPROC *proc) } memmove(&arrayP->pgprocnos[index + 1], &arrayP->pgprocnos[index], - (arrayP->numProcs - index) * sizeof(int)); + (arrayP->numProcs - index) * sizeof(*arrayP->pgprocnos)); + memmove(&ProcGlobal->xids[index + 1], &ProcGlobal->xids[index], + (arrayP->numProcs - index) * sizeof(*ProcGlobal->xids)); + arrayP->pgprocnos[index] = proc->pgprocno; + ProcGlobal->xids[index] = proc->xid; + arrayP->numProcs++; + for (; index < arrayP->numProcs; index++) + { + allProcs[arrayP->pgprocnos[index]].pgxactoff = index; + } + + /* + * Release in reversed acquisition order, to reduce frequency of having to + * wait for XidGenLock while holding ProcArrayLock. + */ + LWLockRelease(XidGenLock); LWLockRelease(ProcArrayLock); } @@ -500,36 +517,58 @@ ProcArrayRemove(PGPROC *proc, TransactionId latestXid) DisplayXidCache(); #endif + /* See ProcGlobal comment explaining why both locks are held */ LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE); + LWLockAcquire(XidGenLock, LW_EXCLUSIVE); + + Assert(ProcGlobal->allProcs[arrayP->pgprocnos[proc->pgxactoff]].pgxactoff == proc->pgxactoff); if (TransactionIdIsValid(latestXid)) { - Assert(TransactionIdIsValid(allPgXact[proc->pgprocno].xid)); + Assert(TransactionIdIsValid(ProcGlobal->xids[proc->pgxactoff])); /* Advance global latestCompletedXid while holding the lock */ MaintainLatestCompletedXid(latestXid); + + ProcGlobal->xids[proc->pgxactoff] = 0; } else { /* Shouldn't be trying to remove a live transaction here */ - Assert(!TransactionIdIsValid(allPgXact[proc->pgprocno].xid)); + Assert(!TransactionIdIsValid(ProcGlobal->xids[proc->pgxactoff])); } + Assert(TransactionIdIsValid(ProcGlobal->xids[proc->pgxactoff] == 0)); + for (index = 0; index < arrayP->numProcs; index++) { if (arrayP->pgprocnos[index] == proc->pgprocno) { /* Keep the PGPROC array sorted. See notes above */ memmove(&arrayP->pgprocnos[index], &arrayP->pgprocnos[index + 1], - (arrayP->numProcs - index - 1) * sizeof(int)); + (arrayP->numProcs - index - 1) * sizeof(*arrayP->pgprocnos)); + memmove(&ProcGlobal->xids[index], &ProcGlobal->xids[index + 1], + (arrayP->numProcs - index - 1) * sizeof(*ProcGlobal->xids)); + arrayP->pgprocnos[arrayP->numProcs - 1] = -1; /* for debugging */ arrayP->numProcs--; + + /* adjust for removed PGPROC */ + for (; index < arrayP->numProcs; index++) + allProcs[arrayP->pgprocnos[index]].pgxactoff--; + + /* + * Release in reversed acquisition order, to reduce frequency of + * having to wait for XidGenLock while holding ProcArrayLock. + */ + LWLockRelease(XidGenLock); LWLockRelease(ProcArrayLock); return; } } /* Oops */ + LWLockRelease(XidGenLock); LWLockRelease(ProcArrayLock); elog(LOG, "failed to find proc %p in ProcArray", proc); @@ -562,7 +601,7 @@ ProcArrayEndTransaction(PGPROC *proc, TransactionId latestXid) * else is taking a snapshot. See discussion in * src/backend/access/transam/README. */ - Assert(TransactionIdIsValid(allPgXact[proc->pgprocno].xid)); + Assert(TransactionIdIsValid(proc->xid)); /* * If we can immediately acquire ProcArrayLock, we clear our own XID @@ -584,7 +623,7 @@ ProcArrayEndTransaction(PGPROC *proc, TransactionId latestXid) * anyone else's calculation of a snapshot. We might change their * estimate of global xmin, but that's OK. */ - Assert(!TransactionIdIsValid(allPgXact[proc->pgprocno].xid)); + Assert(!TransactionIdIsValid(proc->xid)); proc->lxid = InvalidLocalTransactionId; /* must be cleared with xid/xmin: */ @@ -607,7 +646,13 @@ static inline void ProcArrayEndTransactionInternal(PGPROC *proc, PGXACT *pgxact, TransactionId latestXid) { - pgxact->xid = InvalidTransactionId; + size_t pgxactoff = proc->pgxactoff; + + Assert(TransactionIdIsValid(ProcGlobal->xids[pgxactoff])); + Assert(ProcGlobal->xids[pgxactoff] == proc->xid); + + ProcGlobal->xids[pgxactoff] = InvalidTransactionId; + proc->xid = InvalidTransactionId; proc->lxid = InvalidLocalTransactionId; /* must be cleared with xid/xmin: */ pgxact->vacuumFlags &= ~PROC_VACUUM_STATE_MASK; @@ -643,7 +688,7 @@ ProcArrayGroupClearXid(PGPROC *proc, TransactionId latestXid) uint32 wakeidx; /* We should definitely have an XID to clear. */ - Assert(TransactionIdIsValid(allPgXact[proc->pgprocno].xid)); + Assert(TransactionIdIsValid(proc->xid)); /* Add ourselves to the list of processes needing a group XID clear. */ proc->procArrayGroupMember = true; @@ -748,20 +793,28 @@ ProcArrayGroupClearXid(PGPROC *proc, TransactionId latestXid) * This is used after successfully preparing a 2-phase transaction. We are * not actually reporting the transaction's XID as no longer running --- it * will still appear as running because the 2PC's gxact is in the ProcArray - * too. We just have to clear out our own PGXACT. + * too. We just have to clear out our own PGPROC. */ void ProcArrayClearTransaction(PGPROC *proc) { PGXACT *pgxact = &allPgXact[proc->pgprocno]; + size_t pgxactoff; /* - * We can skip locking ProcArrayLock here, because this action does not - * actually change anyone's view of the set of running XIDs: our entry is - * duplicate with the gxact that has already been inserted into the - * ProcArray. + * We can skip locking ProcArrayLock exclusively here, because this action + * does not actually change anyone's view of the set of running XIDs: our + * entry is duplicate with the gxact that has already been inserted into + * the ProcArray. But need it in shared mode for pgproc->pgxactoff to stay + * the same. */ - pgxact->xid = InvalidTransactionId; + LWLockAcquire(ProcArrayLock, LW_SHARED); + + pgxactoff = proc->pgxactoff; + + ProcGlobal->xids[pgxactoff] = InvalidTransactionId; + proc->xid = InvalidTransactionId; + proc->lxid = InvalidLocalTransactionId; proc->xmin = InvalidTransactionId; proc->recoveryConflictPending = false; @@ -773,6 +826,8 @@ ProcArrayClearTransaction(PGPROC *proc) /* Clear the subtransaction-XID cache too */ pgxact->nxids = 0; pgxact->overflowed = false; + + LWLockRelease(ProcArrayLock); } /* @@ -1167,7 +1222,7 @@ ProcArrayApplyXidAssignment(TransactionId topxid, * there are four possibilities for finding a running transaction: * * 1. The given Xid is a main transaction Id. We will find this out cheaply - * by looking at the PGXACT struct for each backend. + * by looking at ProcGlobal->xids. * * 2. The given Xid is one of the cached subxact Xids in the PGPROC array. * We can find this out cheaply too. @@ -1176,26 +1231,28 @@ ProcArrayApplyXidAssignment(TransactionId topxid, * if the Xid is running on the primary. * * 4. Search the SubTrans tree to find the Xid's topmost parent, and then see - * if that is running according to PGXACT or KnownAssignedXids. This is the - * slowest way, but sadly it has to be done always if the others failed, - * unless we see that the cached subxact sets are complete (none have + * if that is running according to ProcGlobal->xids[] or KnownAssignedXids. + * This is the slowest way, but sadly it has to be done always if the others + * failed, unless we see that the cached subxact sets are complete (none have * overflowed). * * ProcArrayLock has to be held while we do 1, 2, 3. If we save the top Xids * while doing 1 and 3, we can release the ProcArrayLock while we do 4. * This buys back some concurrency (and we can't retrieve the main Xids from - * PGXACT again anyway; see GetNewTransactionId). + * ProcGlobal->xids[] again anyway; see GetNewTransactionId). */ bool TransactionIdIsInProgress(TransactionId xid) { static TransactionId *xids = NULL; + static TransactionId *other_xids; int nxids = 0; ProcArrayStruct *arrayP = procArray; TransactionId topxid; TransactionId latestCompletedXid; - int i, - j; + int mypgxactoff; + size_t numProcs; + int j; /* * Don't bother checking a transaction older than RecentXmin; it could not @@ -1250,6 +1307,8 @@ TransactionIdIsInProgress(TransactionId xid) errmsg("out of memory"))); } + other_xids = ProcGlobal->xids; + LWLockAcquire(ProcArrayLock, LW_SHARED); /* @@ -1266,20 +1325,22 @@ TransactionIdIsInProgress(TransactionId xid) } /* No shortcuts, gotta grovel through the array */ - for (i = 0; i < arrayP->numProcs; i++) + mypgxactoff = MyProc->pgxactoff; + numProcs = arrayP->numProcs; + for (size_t pgxactoff = 0; pgxactoff < numProcs; pgxactoff++) { - int pgprocno = arrayP->pgprocnos[i]; - PGPROC *proc = &allProcs[pgprocno]; - PGXACT *pgxact = &allPgXact[pgprocno]; + int pgprocno; + PGXACT *pgxact; + PGPROC *proc; TransactionId pxid; int pxids; - /* Ignore my own proc --- dealt with it above */ - if (proc == MyProc) + /* Ignore ourselves --- dealt with it above */ + if (pgxactoff == mypgxactoff) continue; /* Fetch xid just once - see GetNewTransactionId */ - pxid = UINT32_ACCESS_ONCE(pgxact->xid); + pxid = UINT32_ACCESS_ONCE(other_xids[pgxactoff]); if (!TransactionIdIsValid(pxid)) continue; @@ -1304,8 +1365,12 @@ TransactionIdIsInProgress(TransactionId xid) /* * Step 2: check the cached child-Xids arrays */ + pgprocno = arrayP->pgprocnos[pgxactoff]; + pgxact = &allPgXact[pgprocno]; pxids = pgxact->nxids; pg_read_barrier(); /* pairs with barrier in GetNewTransactionId() */ + pgprocno = arrayP->pgprocnos[pgxactoff]; + proc = &allProcs[pgprocno]; for (j = pxids - 1; j >= 0; j--) { /* Fetch xid just once - see GetNewTransactionId */ @@ -1336,7 +1401,7 @@ TransactionIdIsInProgress(TransactionId xid) */ if (RecoveryInProgress()) { - /* none of the PGXACT entries should have XIDs in hot standby mode */ + /* none of the PGPROC entries should have XIDs in hot standby mode */ Assert(nxids == 0); if (KnownAssignedXidExists(xid)) @@ -1391,7 +1456,7 @@ TransactionIdIsInProgress(TransactionId xid) Assert(TransactionIdIsValid(topxid)); if (!TransactionIdEquals(topxid, xid)) { - for (i = 0; i < nxids; i++) + for (int i = 0; i < nxids; i++) { if (TransactionIdEquals(xids[i], topxid)) return true; @@ -1414,6 +1479,7 @@ TransactionIdIsActive(TransactionId xid) { bool result = false; ProcArrayStruct *arrayP = procArray; + TransactionId *other_xids = ProcGlobal->xids; int i; /* @@ -1429,11 +1495,10 @@ TransactionIdIsActive(TransactionId xid) { int pgprocno = arrayP->pgprocnos[i]; PGPROC *proc = &allProcs[pgprocno]; - PGXACT *pgxact = &allPgXact[pgprocno]; TransactionId pxid; /* Fetch xid just once - see GetNewTransactionId */ - pxid = UINT32_ACCESS_ONCE(pgxact->xid); + pxid = UINT32_ACCESS_ONCE(other_xids[i]); if (!TransactionIdIsValid(pxid)) continue; @@ -1519,6 +1584,7 @@ ComputeXidHorizons(ComputeXidHorizonsResult *h) ProcArrayStruct *arrayP = procArray; TransactionId kaxmin; bool in_recovery = RecoveryInProgress(); + TransactionId *other_xids = ProcGlobal->xids; /* inferred after ProcArrayLock is released */ h->catalog_oldest_nonremovable = InvalidTransactionId; @@ -1562,7 +1628,7 @@ ComputeXidHorizons(ComputeXidHorizonsResult *h) TransactionId xmin; /* Fetch xid just once - see GetNewTransactionId */ - xid = UINT32_ACCESS_ONCE(pgxact->xid); + xid = UINT32_ACCESS_ONCE(other_xids[pgprocno]); xmin = UINT32_ACCESS_ONCE(proc->xmin); /* @@ -1852,14 +1918,17 @@ Snapshot GetSnapshotData(Snapshot snapshot) { ProcArrayStruct *arrayP = procArray; + TransactionId *other_xids = ProcGlobal->xids; TransactionId xmin; TransactionId xmax; - int index; - int count = 0; + size_t count = 0; int subcount = 0; bool suboverflowed = false; FullTransactionId latest_completed; TransactionId oldestxid; + int mypgxactoff; + TransactionId myxid; + TransactionId replication_slot_xmin = InvalidTransactionId; TransactionId replication_slot_catalog_xmin = InvalidTransactionId; @@ -1904,6 +1973,10 @@ GetSnapshotData(Snapshot snapshot) LWLockAcquire(ProcArrayLock, LW_SHARED); latest_completed = ShmemVariableCache->latestCompletedXid; + mypgxactoff = MyProc->pgxactoff; + myxid = other_xids[mypgxactoff]; + Assert(myxid == MyProc->xid); + oldestxid = ShmemVariableCache->oldestXid; /* xmax is always latestCompletedXid + 1 */ @@ -1914,57 +1987,79 @@ GetSnapshotData(Snapshot snapshot) /* initialize xmin calculation with xmax */ xmin = xmax; + /* take own xid into account, saves a check inside the loop */ + if (TransactionIdIsNormal(myxid) && NormalTransactionIdPrecedes(myxid, xmin)) + xmin = myxid; + snapshot->takenDuringRecovery = RecoveryInProgress(); if (!snapshot->takenDuringRecovery) { + size_t numProcs = arrayP->numProcs; + TransactionId *xip = snapshot->xip; int *pgprocnos = arrayP->pgprocnos; - int numProcs; /* - * Spin over procArray checking xid, xmin, and subxids. The goal is - * to gather all active xids, find the lowest xmin, and try to record - * subxids. + * First collect set of pgxactoff/xids that need to be included in the + * snapshot. */ - numProcs = arrayP->numProcs; - for (index = 0; index < numProcs; index++) + for (size_t pgxactoff = 0; pgxactoff < numProcs; pgxactoff++) { - int pgprocno = pgprocnos[index]; - PGXACT *pgxact = &allPgXact[pgprocno]; - TransactionId xid; + /* Fetch xid just once - see GetNewTransactionId */ + TransactionId xid = UINT32_ACCESS_ONCE(other_xids[pgxactoff]); + int pgprocno; + PGXACT *pgxact; + uint8 vacuumFlags; + + Assert(allProcs[arrayP->pgprocnos[pgxactoff]].pgxactoff == pgxactoff); /* - * Skip over backends doing logical decoding which manages xmin - * separately (check below) and ones running LAZY VACUUM. + * If the transaction has no XID assigned, we can skip it; it + * won't have sub-XIDs either. */ - if (pgxact->vacuumFlags & - (PROC_IN_LOGICAL_DECODING | PROC_IN_VACUUM)) + if (likely(xid == InvalidTransactionId)) continue; - /* Fetch xid just once - see GetNewTransactionId */ - xid = UINT32_ACCESS_ONCE(pgxact->xid); + /* + * We don't include our own XIDs (if any) in the snapshot. It + * needs to be includeded in the xmin computation, but we did so + * outside the loop. + */ + if (pgxactoff == mypgxactoff) + continue; /* - * If the transaction has no XID assigned, we can skip it; it - * won't have sub-XIDs either. If the XID is >= xmax, we can also - * skip it; such transactions will be treated as running anyway - * (and any sub-XIDs will also be >= xmax). + * The only way we are able to get here with a non-normal xid + * is during bootstrap - with this backend using + * BootstrapTransactionId. But the above test should filter + * that out. */ - if (!TransactionIdIsNormal(xid) - || !NormalTransactionIdPrecedes(xid, xmax)) + Assert(TransactionIdIsNormal(xid)); + + /* + * If the XID is >= xmax, we can skip it; such transactions will + * be treated as running anyway (and any sub-XIDs will also be >= + * xmax). + */ + if (!NormalTransactionIdPrecedes(xid, xmax)) continue; + pgprocno = pgprocnos[pgxactoff]; + pgxact = &allPgXact[pgprocno]; + vacuumFlags = pgxact->vacuumFlags; + /* - * We don't include our own XIDs (if any) in the snapshot, but we - * must include them in xmin. + * Skip over backends doing logical decoding which manages xmin + * separately (check below) and ones running LAZY VACUUM. */ + if (vacuumFlags & (PROC_IN_LOGICAL_DECODING | PROC_IN_VACUUM)) + continue; + if (NormalTransactionIdPrecedes(xid, xmin)) xmin = xid; - if (pgxact == MyPgXact) - continue; /* Add XID to snapshot. */ - snapshot->xip[count++] = xid; + xip[count++] = xid; /* * Save subtransaction XIDs if possible (if we've already @@ -1987,9 +2082,9 @@ GetSnapshotData(Snapshot snapshot) suboverflowed = true; else { - int nxids = pgxact->nxids; + int nsubxids = pgxact->nxids; - if (nxids > 0) + if (nsubxids > 0) { PGPROC *proc = &allProcs[pgprocno]; @@ -1997,8 +2092,8 @@ GetSnapshotData(Snapshot snapshot) memcpy(snapshot->subxip + subcount, (void *) proc->subxids.xids, - nxids * sizeof(TransactionId)); - subcount += nxids; + nsubxids * sizeof(TransactionId)); + subcount += nsubxids; } } } @@ -2130,6 +2225,7 @@ GetSnapshotData(Snapshot snapshot) } RecentXmin = xmin; + Assert(TransactionIdPrecedesOrEquals(TransactionXmin, RecentXmin)); snapshot->xmin = xmin; snapshot->xmax = xmax; @@ -2292,7 +2388,7 @@ ProcArrayInstallRestoredXmin(TransactionId xmin, PGPROC *proc) * GetRunningTransactionData -- returns information about running transactions. * * Similar to GetSnapshotData but returns more information. We include - * all PGXACTs with an assigned TransactionId, even VACUUM processes and + * all PGPROCs with an assigned TransactionId, even VACUUM processes and * prepared transactions. * * We acquire XidGenLock and ProcArrayLock, but the caller is responsible for @@ -2307,7 +2403,7 @@ ProcArrayInstallRestoredXmin(TransactionId xmin, PGPROC *proc) * This is never executed during recovery so there is no need to look at * KnownAssignedXids. * - * Dummy PGXACTs from prepared transaction are included, meaning that this + * Dummy PGPROCs from prepared transaction are included, meaning that this * may return entries with duplicated TransactionId values coming from * transaction finishing to prepare. Nothing is done about duplicated * entries here to not hold on ProcArrayLock more than necessary. @@ -2326,6 +2422,7 @@ GetRunningTransactionData(void) static RunningTransactionsData CurrentRunningXactsData; ProcArrayStruct *arrayP = procArray; + TransactionId *other_xids = ProcGlobal->xids; RunningTransactions CurrentRunningXacts = &CurrentRunningXactsData; TransactionId latestCompletedXid; TransactionId oldestRunningXid; @@ -2386,7 +2483,7 @@ GetRunningTransactionData(void) TransactionId xid; /* Fetch xid just once - see GetNewTransactionId */ - xid = UINT32_ACCESS_ONCE(pgxact->xid); + xid = UINT32_ACCESS_ONCE(other_xids[index]); /* * We don't need to store transactions that don't have a TransactionId @@ -2483,7 +2580,7 @@ GetRunningTransactionData(void) * GetOldestActiveTransactionId() * * Similar to GetSnapshotData but returns just oldestActiveXid. We include - * all PGXACTs with an assigned TransactionId, even VACUUM processes. + * all PGPROCs with an assigned TransactionId, even VACUUM processes. * We look at all databases, though there is no need to include WALSender * since this has no effect on hot standby conflicts. * @@ -2498,6 +2595,7 @@ TransactionId GetOldestActiveTransactionId(void) { ProcArrayStruct *arrayP = procArray; + TransactionId *other_xids = ProcGlobal->xids; TransactionId oldestRunningXid; int index; @@ -2520,12 +2618,10 @@ GetOldestActiveTransactionId(void) LWLockAcquire(ProcArrayLock, LW_SHARED); for (index = 0; index < arrayP->numProcs; index++) { - int pgprocno = arrayP->pgprocnos[index]; - PGXACT *pgxact = &allPgXact[pgprocno]; TransactionId xid; /* Fetch xid just once - see GetNewTransactionId */ - xid = UINT32_ACCESS_ONCE(pgxact->xid); + xid = UINT32_ACCESS_ONCE(other_xids[index]); if (!TransactionIdIsNormal(xid)) continue; @@ -2603,8 +2699,8 @@ GetOldestSafeDecodingTransactionId(bool catalogOnly) * If we're not in recovery, we walk over the procarray and collect the * lowest xid. Since we're called with ProcArrayLock held and have * acquired XidGenLock, no entries can vanish concurrently, since - * PGXACT->xid is only set with XidGenLock held and only cleared with - * ProcArrayLock held. + * ProcGlobal->xids[i] is only set with XidGenLock held and only cleared + * with ProcArrayLock held. * * In recovery we can't lower the safe value besides what we've computed * above, so we'll have to wait a bit longer there. We unfortunately can @@ -2613,17 +2709,17 @@ GetOldestSafeDecodingTransactionId(bool catalogOnly) */ if (!recovery_in_progress) { + TransactionId *other_xids = ProcGlobal->xids; + /* - * Spin over procArray collecting all min(PGXACT->xid) + * Spin over procArray collecting min(ProcGlobal->xids[i]) */ for (index = 0; index < arrayP->numProcs; index++) { - int pgprocno = arrayP->pgprocnos[index]; - PGXACT *pgxact = &allPgXact[pgprocno]; TransactionId xid; /* Fetch xid just once - see GetNewTransactionId */ - xid = UINT32_ACCESS_ONCE(pgxact->xid); + xid = UINT32_ACCESS_ONCE(other_xids[index]); if (!TransactionIdIsNormal(xid)) continue; @@ -2811,6 +2907,7 @@ BackendXidGetPid(TransactionId xid) { int result = 0; ProcArrayStruct *arrayP = procArray; + TransactionId *other_xids = ProcGlobal->xids; int index; if (xid == InvalidTransactionId) /* never match invalid xid */ @@ -2822,9 +2919,8 @@ BackendXidGetPid(TransactionId xid) { int pgprocno = arrayP->pgprocnos[index]; PGPROC *proc = &allProcs[pgprocno]; - PGXACT *pgxact = &allPgXact[pgprocno]; - if (pgxact->xid == xid) + if (other_xids[index] == xid) { result = proc->pid; break; @@ -3104,7 +3200,6 @@ MinimumActiveBackends(int min) { int pgprocno = arrayP->pgprocnos[index]; PGPROC *proc = &allProcs[pgprocno]; - PGXACT *pgxact = &allPgXact[pgprocno]; /* * Since we're not holding a lock, need to be prepared to deal with @@ -3121,7 +3216,7 @@ MinimumActiveBackends(int min) continue; /* do not count deleted entries */ if (proc == MyProc) continue; /* do not count myself */ - if (pgxact->xid == InvalidTransactionId) + if (proc->xid == InvalidTransactionId) continue; /* do not count if no XID assigned */ if (proc->pid == 0) continue; /* do not count prepared xacts */ @@ -3547,8 +3642,8 @@ XidCacheRemoveRunningXids(TransactionId xid, * * Note that we do not have to be careful about memory ordering of our own * reads wrt. GetNewTransactionId() here - only this process can modify - * relevant fields of MyProc/MyPgXact. But we do have to be careful about - * our own writes being well ordered. + * relevant fields of MyProc/ProcGlobal->xids[]. But we do have to be + * careful about our own writes being well ordered. */ LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE); @@ -3906,7 +4001,7 @@ FullXidRelativeTo(FullTransactionId rel, TransactionId xid) * In Hot Standby mode, we maintain a list of transactions that are (or were) * running on the primary at the current point in WAL. These XIDs must be * treated as running by standby transactions, even though they are not in - * the standby server's PGXACT array. + * the standby server's PGPROC array. * * We record all XIDs that we know have been assigned. That includes all the * XIDs seen in WAL records, plus all unobserved XIDs that we can deduce have |