diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c index 12b74da41de..5b452c613aa 100644 --- a/src/backend/storage/ipc/procarray.c +++ b/src/backend/storage/ipc/procarray.c @@ -1920,20 +1920,21 @@ GetOldestActiveTransactionId(void) Assert(!RecoveryInProgress()); - LWLockAcquire(ProcArrayLock, LW_SHARED); - /* - * It's okay to read nextXid without acquiring XidGenLock because (1) we - * assume TransactionIds can be read atomically and (2) we don't care if - * we get a slightly stale value. It can't be very stale anyway, because - * the LWLockAcquire above will have done any necessary memory - * interlocking. + * Read nextXid, as the upper bound of what's still active. + * + * Reading a TransactionId is atomic, but we must grab the lock to make + * sure that all XIDs < nextXid are already present in the proc array (or + * have already completed), when we spin over it. */ + LWLockAcquire(XidGenLock, LW_SHARED); oldestRunningXid = ShmemVariableCache->nextXid; + LWLockRelease(XidGenLock); /* * Spin over procArray collecting all xids and subxids. */ + LWLockAcquire(ProcArrayLock, LW_SHARED); for (index = 0; index < arrayP->numProcs; index++) { int pgprocno = arrayP->pgprocnos[index]; @@ -1955,7 +1956,6 @@ GetOldestActiveTransactionId(void) * smaller than oldestRunningXid */ } - LWLockRelease(ProcArrayLock); return oldestRunningXid;