diff options
author | Alvaro Herrera <alvherre@alvh.no-ip.org> | 2020-11-18 13:24:22 -0300 |
---|---|---|
committer | Alvaro Herrera <alvherre@alvh.no-ip.org> | 2020-11-18 13:24:22 -0300 |
commit | 27838981be9de35d54ffcdc6cc06b5d5ea9e0cee (patch) | |
tree | 436d056002452e160108f1799cce4e6217b1c790 /src/backend/storage/ipc/procarray.c | |
parent | 2cccb627f10d5dd4c21806fa251e4fb61eadd28c (diff) | |
download | postgresql-27838981be9de35d54ffcdc6cc06b5d5ea9e0cee.tar.gz postgresql-27838981be9de35d54ffcdc6cc06b5d5ea9e0cee.zip |
Relax lock level for setting PGPROC->statusFlags
We don't actually need a lock to set PGPROC->statusFlags itself; what we
do need is a shared lock on either XidGenLock or ProcArrayLock in order to
ensure MyProc->pgxactoff keeps still while we modify the mirror array in
ProcGlobal->statusFlags. Some places were using an exclusive lock for
that, which is excessive. Relax those to use shared lock only.
procarray.c has a couple of places with somewhat brittle assumptions
about PGPROC changes: ProcArrayEndTransaction uses only shared lock, so
it's permissible to change MyProc only. On the other hand,
ProcArrayEndTransactionInternal also changes other procs, so it must
hold exclusive lock. Add asserts to ensure those assumptions continue
to hold.
Author: Álvaro Herrera <alvherre@alvh.no-ip.org>
Reviewed-by: Michael Paquier <michael@paquier.xyz>
Discussion: https://postgr.es/m/20201117155501.GA13805@alvherre.pgsql
Diffstat (limited to 'src/backend/storage/ipc/procarray.c')
-rw-r--r-- | src/backend/storage/ipc/procarray.c | 8 |
1 files changed, 7 insertions, 1 deletions
diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c index e2cb6e990d1..94edb24b22d 100644 --- a/src/backend/storage/ipc/procarray.c +++ b/src/backend/storage/ipc/procarray.c @@ -662,6 +662,8 @@ ProcArrayEndTransaction(PGPROC *proc, TransactionId latestXid) /* avoid unnecessarily dirtying shared cachelines */ if (proc->statusFlags & PROC_VACUUM_STATE_MASK) { + /* Only safe to change my own flags with just share lock */ + Assert(proc == MyProc); Assert(!LWLockHeldByMe(ProcArrayLock)); LWLockAcquire(ProcArrayLock, LW_SHARED); Assert(proc->statusFlags == ProcGlobal->statusFlags[proc->pgxactoff]); @@ -682,7 +684,11 @@ ProcArrayEndTransactionInternal(PGPROC *proc, TransactionId latestXid) { size_t pgxactoff = proc->pgxactoff; - Assert(LWLockHeldByMe(ProcArrayLock)); + /* + * Note: we need exclusive lock here because we're going to + * change other processes' PGPROC entries. + */ + Assert(LWLockHeldByMeInMode(ProcArrayLock, LW_EXCLUSIVE)); Assert(TransactionIdIsValid(ProcGlobal->xids[pgxactoff])); Assert(ProcGlobal->xids[pgxactoff] == proc->xid); |