snapshot scalability: Move PGXACT->vacuumFlags to ProcGlobal->vacuumFlags.

Similar to the previous commit this increases the chance that data
frequently needed by GetSnapshotData() stays in l2 cache. As we now
take care to not unnecessarily write to ProcGlobal->vacuumFlags, there
should be very few modifications to the ProcGlobal->vacuumFlags array.

Author: Andres Freund <andres@anarazel.de>
Reviewed-By: Robert Haas <robertmhaas@gmail.com>
Reviewed-By: Thomas Munro <thomas.munro@gmail.com>
Reviewed-By: David Rowley <dgrowleyml@gmail.com>
Discussion: https://postgr.es/m/20200301083601.ews6hz5dduc3w2se@alap3.anarazel.de
This commit is contained in:
Andres Freund 2020-07-15 15:35:07 -07:00
parent 941697c3c1
commit 5788e258bb
9 changed files with 75 additions and 42 deletions

View File

@ -466,7 +466,7 @@ MarkAsPreparingGuts(GlobalTransaction gxact, TransactionId xid, const char *gid,
proc->xid = xid; proc->xid = xid;
Assert(proc->xmin == InvalidTransactionId); Assert(proc->xmin == InvalidTransactionId);
proc->delayChkpt = false; proc->delayChkpt = false;
pgxact->vacuumFlags = 0; proc->vacuumFlags = 0;
proc->pid = 0; proc->pid = 0;
proc->backendId = InvalidBackendId; proc->backendId = InvalidBackendId;
proc->databaseId = databaseid; proc->databaseId = databaseid;

View File

@ -1728,9 +1728,10 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params)
* might appear to go backwards, which is probably Not Good. * might appear to go backwards, which is probably Not Good.
*/ */
LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE); LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
MyPgXact->vacuumFlags |= PROC_IN_VACUUM; MyProc->vacuumFlags |= PROC_IN_VACUUM;
if (params->is_wraparound) if (params->is_wraparound)
MyPgXact->vacuumFlags |= PROC_VACUUM_FOR_WRAPAROUND; MyProc->vacuumFlags |= PROC_VACUUM_FOR_WRAPAROUND;
ProcGlobal->vacuumFlags[MyProc->pgxactoff] = MyProc->vacuumFlags;
LWLockRelease(ProcArrayLock); LWLockRelease(ProcArrayLock);
} }

View File

@ -2493,7 +2493,7 @@ do_autovacuum(void)
tab->at_datname, tab->at_nspname, tab->at_relname); tab->at_datname, tab->at_nspname, tab->at_relname);
EmitErrorReport(); EmitErrorReport();
/* this resets the PGXACT flags too */ /* this resets ProcGlobal->vacuumFlags[i] too */
AbortOutOfAnyTransaction(); AbortOutOfAnyTransaction();
FlushErrorState(); FlushErrorState();
MemoryContextResetAndDeleteChildren(PortalContext); MemoryContextResetAndDeleteChildren(PortalContext);
@ -2509,7 +2509,7 @@ do_autovacuum(void)
did_vacuum = true; did_vacuum = true;
/* the PGXACT flags are reset at the next end of transaction */ /* ProcGlobal->vacuumFlags[i] are reset at the next end of xact */
/* be tidy */ /* be tidy */
deleted: deleted:
@ -2686,7 +2686,7 @@ perform_work_item(AutoVacuumWorkItem *workitem)
cur_datname, cur_nspname, cur_relname); cur_datname, cur_nspname, cur_relname);
EmitErrorReport(); EmitErrorReport();
/* this resets the PGXACT flags too */ /* this resets ProcGlobal->vacuumFlags[i] too */
AbortOutOfAnyTransaction(); AbortOutOfAnyTransaction();
FlushErrorState(); FlushErrorState();
MemoryContextResetAndDeleteChildren(PortalContext); MemoryContextResetAndDeleteChildren(PortalContext);

View File

@ -181,7 +181,8 @@ StartupDecodingContext(List *output_plugin_options,
if (!IsTransactionOrTransactionBlock()) if (!IsTransactionOrTransactionBlock())
{ {
LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE); LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
MyPgXact->vacuumFlags |= PROC_IN_LOGICAL_DECODING; MyProc->vacuumFlags |= PROC_IN_LOGICAL_DECODING;
ProcGlobal->vacuumFlags[MyProc->pgxactoff] = MyProc->vacuumFlags;
LWLockRelease(ProcArrayLock); LWLockRelease(ProcArrayLock);
} }

View File

@ -520,7 +520,8 @@ ReplicationSlotRelease(void)
/* might not have been set when we've been a plain slot */ /* might not have been set when we've been a plain slot */
LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE); LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
MyPgXact->vacuumFlags &= ~PROC_IN_LOGICAL_DECODING; MyProc->vacuumFlags &= ~PROC_IN_LOGICAL_DECODING;
ProcGlobal->vacuumFlags[MyProc->pgxactoff] = MyProc->vacuumFlags;
LWLockRelease(ProcArrayLock); LWLockRelease(ProcArrayLock);
} }

View File

@ -476,9 +476,12 @@ ProcArrayAdd(PGPROC *proc)
(arrayP->numProcs - index) * sizeof(*arrayP->pgprocnos)); (arrayP->numProcs - index) * sizeof(*arrayP->pgprocnos));
memmove(&ProcGlobal->xids[index + 1], &ProcGlobal->xids[index], memmove(&ProcGlobal->xids[index + 1], &ProcGlobal->xids[index],
(arrayP->numProcs - index) * sizeof(*ProcGlobal->xids)); (arrayP->numProcs - index) * sizeof(*ProcGlobal->xids));
memmove(&ProcGlobal->vacuumFlags[index + 1], &ProcGlobal->vacuumFlags[index],
(arrayP->numProcs - index) * sizeof(*ProcGlobal->vacuumFlags));
arrayP->pgprocnos[index] = proc->pgprocno; arrayP->pgprocnos[index] = proc->pgprocno;
ProcGlobal->xids[index] = proc->xid; ProcGlobal->xids[index] = proc->xid;
ProcGlobal->vacuumFlags[index] = proc->vacuumFlags;
arrayP->numProcs++; arrayP->numProcs++;
@ -539,6 +542,7 @@ ProcArrayRemove(PGPROC *proc, TransactionId latestXid)
} }
Assert(TransactionIdIsValid(ProcGlobal->xids[proc->pgxactoff] == 0)); Assert(TransactionIdIsValid(ProcGlobal->xids[proc->pgxactoff] == 0));
ProcGlobal->vacuumFlags[proc->pgxactoff] = 0;
for (index = 0; index < arrayP->numProcs; index++) for (index = 0; index < arrayP->numProcs; index++)
{ {
@ -549,6 +553,8 @@ ProcArrayRemove(PGPROC *proc, TransactionId latestXid)
(arrayP->numProcs - index - 1) * sizeof(*arrayP->pgprocnos)); (arrayP->numProcs - index - 1) * sizeof(*arrayP->pgprocnos));
memmove(&ProcGlobal->xids[index], &ProcGlobal->xids[index + 1], memmove(&ProcGlobal->xids[index], &ProcGlobal->xids[index + 1],
(arrayP->numProcs - index - 1) * sizeof(*ProcGlobal->xids)); (arrayP->numProcs - index - 1) * sizeof(*ProcGlobal->xids));
memmove(&ProcGlobal->vacuumFlags[index], &ProcGlobal->vacuumFlags[index + 1],
(arrayP->numProcs - index - 1) * sizeof(*ProcGlobal->vacuumFlags));
arrayP->pgprocnos[arrayP->numProcs - 1] = -1; /* for debugging */ arrayP->pgprocnos[arrayP->numProcs - 1] = -1; /* for debugging */
arrayP->numProcs--; arrayP->numProcs--;
@ -626,14 +632,24 @@ ProcArrayEndTransaction(PGPROC *proc, TransactionId latestXid)
Assert(!TransactionIdIsValid(proc->xid)); Assert(!TransactionIdIsValid(proc->xid));
proc->lxid = InvalidLocalTransactionId; proc->lxid = InvalidLocalTransactionId;
/* must be cleared with xid/xmin: */
pgxact->vacuumFlags &= ~PROC_VACUUM_STATE_MASK;
proc->xmin = InvalidTransactionId; proc->xmin = InvalidTransactionId;
proc->delayChkpt = false; /* be sure this is cleared in abort */ proc->delayChkpt = false; /* be sure this is cleared in abort */
proc->recoveryConflictPending = false; proc->recoveryConflictPending = false;
Assert(pgxact->nxids == 0); Assert(pgxact->nxids == 0);
Assert(pgxact->overflowed == false); Assert(pgxact->overflowed == false);
/* must be cleared with xid/xmin: */
/* avoid unnecessarily dirtying shared cachelines */
if (proc->vacuumFlags & PROC_VACUUM_STATE_MASK)
{
Assert(!LWLockHeldByMe(ProcArrayLock));
LWLockAcquire(ProcArrayLock, LW_SHARED);
Assert(proc->vacuumFlags == ProcGlobal->vacuumFlags[proc->pgxactoff]);
proc->vacuumFlags &= ~PROC_VACUUM_STATE_MASK;
ProcGlobal->vacuumFlags[proc->pgxactoff] = proc->vacuumFlags;
LWLockRelease(ProcArrayLock);
}
} }
} }
@ -654,12 +670,18 @@ ProcArrayEndTransactionInternal(PGPROC *proc, PGXACT *pgxact,
ProcGlobal->xids[pgxactoff] = InvalidTransactionId; ProcGlobal->xids[pgxactoff] = InvalidTransactionId;
proc->xid = InvalidTransactionId; proc->xid = InvalidTransactionId;
proc->lxid = InvalidLocalTransactionId; proc->lxid = InvalidLocalTransactionId;
/* must be cleared with xid/xmin: */
pgxact->vacuumFlags &= ~PROC_VACUUM_STATE_MASK;
proc->xmin = InvalidTransactionId; proc->xmin = InvalidTransactionId;
proc->delayChkpt = false; /* be sure this is cleared in abort */ proc->delayChkpt = false; /* be sure this is cleared in abort */
proc->recoveryConflictPending = false; proc->recoveryConflictPending = false;
/* must be cleared with xid/xmin: */
/* avoid unnecessarily dirtying shared cachelines */
if (proc->vacuumFlags & PROC_VACUUM_STATE_MASK)
{
proc->vacuumFlags &= ~PROC_VACUUM_STATE_MASK;
ProcGlobal->vacuumFlags[proc->pgxactoff] = proc->vacuumFlags;
}
/* Clear the subtransaction-XID cache too while holding the lock */ /* Clear the subtransaction-XID cache too while holding the lock */
pgxact->nxids = 0; pgxact->nxids = 0;
pgxact->overflowed = false; pgxact->overflowed = false;
@ -819,9 +841,8 @@ ProcArrayClearTransaction(PGPROC *proc)
proc->xmin = InvalidTransactionId; proc->xmin = InvalidTransactionId;
proc->recoveryConflictPending = false; proc->recoveryConflictPending = false;
/* redundant, but just in case */ Assert(!(proc->vacuumFlags & PROC_VACUUM_STATE_MASK));
pgxact->vacuumFlags &= ~PROC_VACUUM_STATE_MASK; Assert(!proc->delayChkpt);
proc->delayChkpt = false;
/* Clear the subtransaction-XID cache too */ /* Clear the subtransaction-XID cache too */
pgxact->nxids = 0; pgxact->nxids = 0;
@ -1623,7 +1644,7 @@ ComputeXidHorizons(ComputeXidHorizonsResult *h)
{ {
int pgprocno = arrayP->pgprocnos[index]; int pgprocno = arrayP->pgprocnos[index];
PGPROC *proc = &allProcs[pgprocno]; PGPROC *proc = &allProcs[pgprocno];
PGXACT *pgxact = &allPgXact[pgprocno]; int8 vacuumFlags = ProcGlobal->vacuumFlags[index];
TransactionId xid; TransactionId xid;
TransactionId xmin; TransactionId xmin;
@ -1640,8 +1661,8 @@ ComputeXidHorizons(ComputeXidHorizonsResult *h)
*/ */
xmin = TransactionIdOlder(xmin, xid); xmin = TransactionIdOlder(xmin, xid);
/* if neither is set, this proc doesn't influence the horizon */ /* if neither is set, this proc doesn't influence the horizon */
if (!TransactionIdIsValid(xmin)) if (!TransactionIdIsValid(xmin))
continue; continue;
/* /*
@ -1658,7 +1679,7 @@ ComputeXidHorizons(ComputeXidHorizonsResult *h)
* removed, as long as pg_subtrans is not truncated) or doing logical * removed, as long as pg_subtrans is not truncated) or doing logical
* decoding (which manages xmin separately, check below). * decoding (which manages xmin separately, check below).
*/ */
if (pgxact->vacuumFlags & (PROC_IN_VACUUM | PROC_IN_LOGICAL_DECODING)) if (vacuumFlags & (PROC_IN_VACUUM | PROC_IN_LOGICAL_DECODING))
continue; continue;
/* shared tables need to take backends in all database into account */ /* shared tables need to take backends in all database into account */
@ -1998,6 +2019,7 @@ GetSnapshotData(Snapshot snapshot)
size_t numProcs = arrayP->numProcs; size_t numProcs = arrayP->numProcs;
TransactionId *xip = snapshot->xip; TransactionId *xip = snapshot->xip;
int *pgprocnos = arrayP->pgprocnos; int *pgprocnos = arrayP->pgprocnos;
uint8 *allVacuumFlags = ProcGlobal->vacuumFlags;
/* /*
* First collect set of pgxactoff/xids that need to be included in the * First collect set of pgxactoff/xids that need to be included in the
@ -2007,8 +2029,6 @@ GetSnapshotData(Snapshot snapshot)
{ {
/* Fetch xid just once - see GetNewTransactionId */ /* Fetch xid just once - see GetNewTransactionId */
TransactionId xid = UINT32_ACCESS_ONCE(other_xids[pgxactoff]); TransactionId xid = UINT32_ACCESS_ONCE(other_xids[pgxactoff]);
int pgprocno;
PGXACT *pgxact;
uint8 vacuumFlags; uint8 vacuumFlags;
Assert(allProcs[arrayP->pgprocnos[pgxactoff]].pgxactoff == pgxactoff); Assert(allProcs[arrayP->pgprocnos[pgxactoff]].pgxactoff == pgxactoff);
@ -2044,14 +2064,11 @@ GetSnapshotData(Snapshot snapshot)
if (!NormalTransactionIdPrecedes(xid, xmax)) if (!NormalTransactionIdPrecedes(xid, xmax))
continue; continue;
pgprocno = pgprocnos[pgxactoff];
pgxact = &allPgXact[pgprocno];
vacuumFlags = pgxact->vacuumFlags;
/* /*
* Skip over backends doing logical decoding which manages xmin * Skip over backends doing logical decoding which manages xmin
* separately (check below) and ones running LAZY VACUUM. * separately (check below) and ones running LAZY VACUUM.
*/ */
vacuumFlags = allVacuumFlags[pgxactoff];
if (vacuumFlags & (PROC_IN_LOGICAL_DECODING | PROC_IN_VACUUM)) if (vacuumFlags & (PROC_IN_LOGICAL_DECODING | PROC_IN_VACUUM))
continue; continue;
@ -2078,6 +2095,9 @@ GetSnapshotData(Snapshot snapshot)
*/ */
if (!suboverflowed) if (!suboverflowed)
{ {
int pgprocno = pgprocnos[pgxactoff];
PGXACT *pgxact = &allPgXact[pgprocno];
if (pgxact->overflowed) if (pgxact->overflowed)
suboverflowed = true; suboverflowed = true;
else else
@ -2296,11 +2316,11 @@ ProcArrayInstallImportedXmin(TransactionId xmin,
{ {
int pgprocno = arrayP->pgprocnos[index]; int pgprocno = arrayP->pgprocnos[index];
PGPROC *proc = &allProcs[pgprocno]; PGPROC *proc = &allProcs[pgprocno];
PGXACT *pgxact = &allPgXact[pgprocno]; int vacuumFlags = ProcGlobal->vacuumFlags[index];
TransactionId xid; TransactionId xid;
/* Ignore procs running LAZY VACUUM */ /* Ignore procs running LAZY VACUUM */
if (pgxact->vacuumFlags & PROC_IN_VACUUM) if (vacuumFlags & PROC_IN_VACUUM)
continue; continue;
/* We are only interested in the specific virtual transaction. */ /* We are only interested in the specific virtual transaction. */
@ -2990,12 +3010,12 @@ GetCurrentVirtualXIDs(TransactionId limitXmin, bool excludeXmin0,
{ {
int pgprocno = arrayP->pgprocnos[index]; int pgprocno = arrayP->pgprocnos[index];
PGPROC *proc = &allProcs[pgprocno]; PGPROC *proc = &allProcs[pgprocno];
PGXACT *pgxact = &allPgXact[pgprocno]; uint8 vacuumFlags = ProcGlobal->vacuumFlags[index];
if (proc == MyProc) if (proc == MyProc)
continue; continue;
if (excludeVacuum & pgxact->vacuumFlags) if (excludeVacuum & vacuumFlags)
continue; continue;
if (allDbs || proc->databaseId == MyDatabaseId) if (allDbs || proc->databaseId == MyDatabaseId)
@ -3410,7 +3430,7 @@ CountOtherDBBackends(Oid databaseId, int *nbackends, int *nprepared)
{ {
int pgprocno = arrayP->pgprocnos[index]; int pgprocno = arrayP->pgprocnos[index];
PGPROC *proc = &allProcs[pgprocno]; PGPROC *proc = &allProcs[pgprocno];
PGXACT *pgxact = &allPgXact[pgprocno]; uint8 vacuumFlags = ProcGlobal->vacuumFlags[index];
if (proc->databaseId != databaseId) if (proc->databaseId != databaseId)
continue; continue;
@ -3424,7 +3444,7 @@ CountOtherDBBackends(Oid databaseId, int *nbackends, int *nprepared)
else else
{ {
(*nbackends)++; (*nbackends)++;
if ((pgxact->vacuumFlags & PROC_IS_AUTOVACUUM) && if ((vacuumFlags & PROC_IS_AUTOVACUUM) &&
nautovacs < MAXAUTOVACPIDS) nautovacs < MAXAUTOVACPIDS)
autovac_pids[nautovacs++] = proc->pid; autovac_pids[nautovacs++] = proc->pid;
} }

View File

@ -544,7 +544,6 @@ FindLockCycleRecurseMember(PGPROC *checkProc,
{ {
PGPROC *proc; PGPROC *proc;
LOCK *lock = checkProc->waitLock; LOCK *lock = checkProc->waitLock;
PGXACT *pgxact;
PROCLOCK *proclock; PROCLOCK *proclock;
SHM_QUEUE *procLocks; SHM_QUEUE *procLocks;
LockMethod lockMethodTable; LockMethod lockMethodTable;
@ -582,7 +581,6 @@ FindLockCycleRecurseMember(PGPROC *checkProc,
PGPROC *leader; PGPROC *leader;
proc = proclock->tag.myProc; proc = proclock->tag.myProc;
pgxact = &ProcGlobal->allPgXact[proc->pgprocno];
leader = proc->lockGroupLeader == NULL ? proc : proc->lockGroupLeader; leader = proc->lockGroupLeader == NULL ? proc : proc->lockGroupLeader;
/* A proc never blocks itself or any other lock group member */ /* A proc never blocks itself or any other lock group member */
@ -630,7 +628,7 @@ FindLockCycleRecurseMember(PGPROC *checkProc,
* ProcArrayLock. * ProcArrayLock.
*/ */
if (checkProc == MyProc && if (checkProc == MyProc &&
pgxact->vacuumFlags & PROC_IS_AUTOVACUUM) proc->vacuumFlags & PROC_IS_AUTOVACUUM)
blocking_autovacuum_proc = proc; blocking_autovacuum_proc = proc;
/* We're done looking at this proclock */ /* We're done looking at this proclock */

View File

@ -114,6 +114,7 @@ ProcGlobalShmemSize(void)
size = add_size(size, mul_size(NUM_AUXILIARY_PROCS, sizeof(PGXACT))); size = add_size(size, mul_size(NUM_AUXILIARY_PROCS, sizeof(PGXACT)));
size = add_size(size, mul_size(max_prepared_xacts, sizeof(PGXACT))); size = add_size(size, mul_size(max_prepared_xacts, sizeof(PGXACT)));
size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids))); size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids)));
size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->vacuumFlags)));
return size; return size;
} }
@ -223,6 +224,8 @@ InitProcGlobal(void)
ProcGlobal->xids = ProcGlobal->xids =
(TransactionId *) ShmemAlloc(TotalProcs * sizeof(*ProcGlobal->xids)); (TransactionId *) ShmemAlloc(TotalProcs * sizeof(*ProcGlobal->xids));
MemSet(ProcGlobal->xids, 0, TotalProcs * sizeof(*ProcGlobal->xids)); MemSet(ProcGlobal->xids, 0, TotalProcs * sizeof(*ProcGlobal->xids));
ProcGlobal->vacuumFlags = (uint8 *) ShmemAlloc(TotalProcs * sizeof(*ProcGlobal->vacuumFlags));
MemSet(ProcGlobal->vacuumFlags, 0, TotalProcs * sizeof(*ProcGlobal->vacuumFlags));
for (i = 0; i < TotalProcs; i++) for (i = 0; i < TotalProcs; i++)
{ {
@ -405,10 +408,10 @@ InitProcess(void)
MyProc->tempNamespaceId = InvalidOid; MyProc->tempNamespaceId = InvalidOid;
MyProc->isBackgroundWorker = IsBackgroundWorker; MyProc->isBackgroundWorker = IsBackgroundWorker;
MyProc->delayChkpt = false; MyProc->delayChkpt = false;
MyPgXact->vacuumFlags = 0; MyProc->vacuumFlags = 0;
/* NB -- autovac launcher intentionally does not set IS_AUTOVACUUM */ /* NB -- autovac launcher intentionally does not set IS_AUTOVACUUM */
if (IsAutoVacuumWorkerProcess()) if (IsAutoVacuumWorkerProcess())
MyPgXact->vacuumFlags |= PROC_IS_AUTOVACUUM; MyProc->vacuumFlags |= PROC_IS_AUTOVACUUM;
MyProc->lwWaiting = false; MyProc->lwWaiting = false;
MyProc->lwWaitMode = 0; MyProc->lwWaitMode = 0;
MyProc->waitLock = NULL; MyProc->waitLock = NULL;
@ -587,7 +590,7 @@ InitAuxiliaryProcess(void)
MyProc->tempNamespaceId = InvalidOid; MyProc->tempNamespaceId = InvalidOid;
MyProc->isBackgroundWorker = IsBackgroundWorker; MyProc->isBackgroundWorker = IsBackgroundWorker;
MyProc->delayChkpt = false; MyProc->delayChkpt = false;
MyPgXact->vacuumFlags = 0; MyProc->vacuumFlags = 0;
MyProc->lwWaiting = false; MyProc->lwWaiting = false;
MyProc->lwWaitMode = 0; MyProc->lwWaitMode = 0;
MyProc->waitLock = NULL; MyProc->waitLock = NULL;
@ -1323,7 +1326,7 @@ ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable)
if (deadlock_state == DS_BLOCKED_BY_AUTOVACUUM && allow_autovacuum_cancel) if (deadlock_state == DS_BLOCKED_BY_AUTOVACUUM && allow_autovacuum_cancel)
{ {
PGPROC *autovac = GetBlockingAutoVacuumPgproc(); PGPROC *autovac = GetBlockingAutoVacuumPgproc();
PGXACT *autovac_pgxact = &ProcGlobal->allPgXact[autovac->pgprocno]; uint8 vacuumFlags;
LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE); LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
@ -1331,8 +1334,9 @@ ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable)
* Only do it if the worker is not working to protect against Xid * Only do it if the worker is not working to protect against Xid
* wraparound. * wraparound.
*/ */
if ((autovac_pgxact->vacuumFlags & PROC_IS_AUTOVACUUM) && vacuumFlags = ProcGlobal->vacuumFlags[proc->pgxactoff];
!(autovac_pgxact->vacuumFlags & PROC_VACUUM_FOR_WRAPAROUND)) if ((vacuumFlags & PROC_IS_AUTOVACUUM) &&
!(vacuumFlags & PROC_VACUUM_FOR_WRAPAROUND))
{ {
int pid = autovac->pid; int pid = autovac->pid;
StringInfoData locktagbuf; StringInfoData locktagbuf;

View File

@ -41,7 +41,7 @@ struct XidCache
}; };
/* /*
* Flags for PGXACT->vacuumFlags * Flags for ProcGlobal->vacuumFlags[]
*/ */
#define PROC_IS_AUTOVACUUM 0x01 /* is it an autovac worker? */ #define PROC_IS_AUTOVACUUM 0x01 /* is it an autovac worker? */
#define PROC_IN_VACUUM 0x02 /* currently running lazy vacuum */ #define PROC_IN_VACUUM 0x02 /* currently running lazy vacuum */
@ -167,6 +167,9 @@ struct PGPROC
bool delayChkpt; /* true if this proc delays checkpoint start */ bool delayChkpt; /* true if this proc delays checkpoint start */
uint8 vacuumFlags; /* this backend's vacuum flags, see PROC_*
* above. mirrored in
* ProcGlobal->vacuumFlags[pgxactoff] */
/* /*
* Info to allow us to wait for synchronous replication, if needed. * Info to allow us to wait for synchronous replication, if needed.
* waitLSN is InvalidXLogRecPtr if not waiting; set only by user backend. * waitLSN is InvalidXLogRecPtr if not waiting; set only by user backend.
@ -244,7 +247,6 @@ extern PGDLLIMPORT struct PGXACT *MyPgXact;
*/ */
typedef struct PGXACT typedef struct PGXACT
{ {
uint8 vacuumFlags; /* vacuum-related flags, see above */
bool overflowed; bool overflowed;
uint8 nxids; uint8 nxids;
@ -314,6 +316,12 @@ typedef struct PROC_HDR
/* Array mirroring PGPROC.xid for each PGPROC currently in the procarray */ /* Array mirroring PGPROC.xid for each PGPROC currently in the procarray */
TransactionId *xids; TransactionId *xids;
/*
* Array mirroring PGPROC.vacuumFlags for each PGPROC currently in the
* procarray.
*/
uint8 *vacuumFlags;
/* Length of allProcs array */ /* Length of allProcs array */
uint32 allProcCount; uint32 allProcCount;
/* Head of list of free PGPROC structures */ /* Head of list of free PGPROC structures */