mirror of
https://github.com/postgres/postgres.git
synced 2025-05-01 01:04:50 +03:00
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:
parent
941697c3c1
commit
5788e258bb
@ -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;
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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 */
|
||||||
|
@ -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;
|
||||||
|
@ -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 */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user