mirror of
https://github.com/postgres/postgres.git
synced 2025-05-01 01:04:50 +03:00
Restore lock level to update statusFlags
Reverts 27838981be9d (some comments are kept). Per discussion, it does not seem safe to relax the lock level used for this; in order for it to be safe, there would have to be memory barriers between the point we set the flag and the point we set the trasaction Xid, which perhaps would not be so bad; but there would also have to be barriers at the readers' side, which from a performance perspective might be bad. Now maybe this analysis is wrong and it *is* safe for some reason, but proof of that is not trivial. Discussion: https://postgr.es/m/20201118190928.vnztes7c2sldu43a@alap3.anarazel.de
This commit is contained in:
parent
9fbc3f318d
commit
dcfff74fb1
@ -1712,13 +1712,6 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params)
|
|||||||
/* Begin a transaction for vacuuming this relation */
|
/* Begin a transaction for vacuuming this relation */
|
||||||
StartTransactionCommand();
|
StartTransactionCommand();
|
||||||
|
|
||||||
/*
|
|
||||||
* Need to acquire a snapshot to prevent pg_subtrans from being truncated,
|
|
||||||
* cutoff xids in local memory wrapping around, and to have updated xmin
|
|
||||||
* horizons.
|
|
||||||
*/
|
|
||||||
PushActiveSnapshot(GetTransactionSnapshot());
|
|
||||||
|
|
||||||
if (!(params->options & VACOPT_FULL))
|
if (!(params->options & VACOPT_FULL))
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -1739,9 +1732,11 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params)
|
|||||||
* Note: these flags remain set until CommitTransaction or
|
* Note: these flags remain set until CommitTransaction or
|
||||||
* AbortTransaction. We don't want to clear them until we reset
|
* AbortTransaction. We don't want to clear them until we reset
|
||||||
* MyProc->xid/xmin, otherwise GetOldestNonRemovableTransactionId()
|
* MyProc->xid/xmin, otherwise GetOldestNonRemovableTransactionId()
|
||||||
* might appear to go backwards, which is probably Not Good.
|
* might appear to go backwards, which is probably Not Good. (We also
|
||||||
|
* set PROC_IN_VACUUM *before* taking our own snapshot, so that our
|
||||||
|
* xmin doesn't become visible ahead of setting the flag.)
|
||||||
*/
|
*/
|
||||||
LWLockAcquire(ProcArrayLock, LW_SHARED);
|
LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
|
||||||
MyProc->statusFlags |= PROC_IN_VACUUM;
|
MyProc->statusFlags |= PROC_IN_VACUUM;
|
||||||
if (params->is_wraparound)
|
if (params->is_wraparound)
|
||||||
MyProc->statusFlags |= PROC_VACUUM_FOR_WRAPAROUND;
|
MyProc->statusFlags |= PROC_VACUUM_FOR_WRAPAROUND;
|
||||||
@ -1749,6 +1744,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params)
|
|||||||
LWLockRelease(ProcArrayLock);
|
LWLockRelease(ProcArrayLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Need to acquire a snapshot to prevent pg_subtrans from being truncated,
|
||||||
|
* cutoff xids in local memory wrapping around, and to have updated xmin
|
||||||
|
* horizons.
|
||||||
|
*/
|
||||||
|
PushActiveSnapshot(GetTransactionSnapshot());
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check for user-requested abort. Note we want this to be inside a
|
* Check for user-requested abort. Note we want this to be inside a
|
||||||
* transaction, so xact.c doesn't issue useless WARNING.
|
* transaction, so xact.c doesn't issue useless WARNING.
|
||||||
|
@ -181,7 +181,7 @@ StartupDecodingContext(List *output_plugin_options,
|
|||||||
*/
|
*/
|
||||||
if (!IsTransactionOrTransactionBlock())
|
if (!IsTransactionOrTransactionBlock())
|
||||||
{
|
{
|
||||||
LWLockAcquire(ProcArrayLock, LW_SHARED);
|
LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
|
||||||
MyProc->statusFlags |= PROC_IN_LOGICAL_DECODING;
|
MyProc->statusFlags |= PROC_IN_LOGICAL_DECODING;
|
||||||
ProcGlobal->statusFlags[MyProc->pgxactoff] = MyProc->statusFlags;
|
ProcGlobal->statusFlags[MyProc->pgxactoff] = MyProc->statusFlags;
|
||||||
LWLockRelease(ProcArrayLock);
|
LWLockRelease(ProcArrayLock);
|
||||||
|
@ -662,10 +662,8 @@ ProcArrayEndTransaction(PGPROC *proc, TransactionId latestXid)
|
|||||||
/* avoid unnecessarily dirtying shared cachelines */
|
/* avoid unnecessarily dirtying shared cachelines */
|
||||||
if (proc->statusFlags & PROC_VACUUM_STATE_MASK)
|
if (proc->statusFlags & PROC_VACUUM_STATE_MASK)
|
||||||
{
|
{
|
||||||
/* Only safe to change my own flags with just share lock */
|
|
||||||
Assert(proc == MyProc);
|
|
||||||
Assert(!LWLockHeldByMe(ProcArrayLock));
|
Assert(!LWLockHeldByMe(ProcArrayLock));
|
||||||
LWLockAcquire(ProcArrayLock, LW_SHARED);
|
LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
|
||||||
Assert(proc->statusFlags == ProcGlobal->statusFlags[proc->pgxactoff]);
|
Assert(proc->statusFlags == ProcGlobal->statusFlags[proc->pgxactoff]);
|
||||||
proc->statusFlags &= ~PROC_VACUUM_STATE_MASK;
|
proc->statusFlags &= ~PROC_VACUUM_STATE_MASK;
|
||||||
ProcGlobal->statusFlags[proc->pgxactoff] = proc->statusFlags;
|
ProcGlobal->statusFlags[proc->pgxactoff] = proc->statusFlags;
|
||||||
@ -685,8 +683,8 @@ ProcArrayEndTransactionInternal(PGPROC *proc, TransactionId latestXid)
|
|||||||
size_t pgxactoff = proc->pgxactoff;
|
size_t pgxactoff = proc->pgxactoff;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Note: we need exclusive lock here because we're going to
|
* Note: we need exclusive lock here because we're going to change other
|
||||||
* change other processes' PGPROC entries.
|
* processes' PGPROC entries.
|
||||||
*/
|
*/
|
||||||
Assert(LWLockHeldByMeInMode(ProcArrayLock, LW_EXCLUSIVE));
|
Assert(LWLockHeldByMeInMode(ProcArrayLock, LW_EXCLUSIVE));
|
||||||
Assert(TransactionIdIsValid(ProcGlobal->xids[pgxactoff]));
|
Assert(TransactionIdIsValid(ProcGlobal->xids[pgxactoff]));
|
||||||
|
@ -102,9 +102,9 @@ typedef enum
|
|||||||
* but its myProcLocks[] lists are valid.
|
* but its myProcLocks[] lists are valid.
|
||||||
*
|
*
|
||||||
* We allow many fields of this struct to be accessed without locks, such as
|
* We allow many fields of this struct to be accessed without locks, such as
|
||||||
* statusFlags or delayChkpt. However, keep in mind that writing mirrored ones
|
* delayChkpt and isBackgroundWorker. However, keep in mind that writing
|
||||||
* (see below) requires holding ProcArrayLock or XidGenLock in at least shared
|
* mirrored ones (see below) requires holding ProcArrayLock or XidGenLock in
|
||||||
* mode, so that pgxactoff does not change concurrently.
|
* at least shared mode, so that pgxactoff does not change concurrently.
|
||||||
*
|
*
|
||||||
* Mirrored fields:
|
* Mirrored fields:
|
||||||
*
|
*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user