mirror of
https://github.com/postgres/postgres.git
synced 2025-11-10 17:42:29 +03:00
Split the shared-memory array of PGPROC pointers out of the sinval
communication structure, and make it its own module with its own lock. This should reduce contention at least a little, and it definitely makes the code seem cleaner. Per my recent proposal.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
$PostgreSQL: pgsql/src/backend/access/transam/README,v 1.2 2004/09/16 16:58:26 tgl Exp $
|
||||
$PostgreSQL: pgsql/src/backend/access/transam/README,v 1.3 2005/05/19 21:35:45 tgl Exp $
|
||||
|
||||
The Transaction System
|
||||
----------------------
|
||||
@@ -246,7 +246,7 @@ but since we allow arbitrary nesting of subtransactions, we can't fit all Xids
|
||||
in shared memory, so we have to store them on disk. Note, however, that for
|
||||
each transaction we keep a "cache" of Xids that are known to be part of the
|
||||
transaction tree, so we can skip looking at pg_subtrans unless we know the
|
||||
cache has been overflowed. See storage/ipc/sinval.c for the gory details.
|
||||
cache has been overflowed. See storage/ipc/procarray.c for the gory details.
|
||||
|
||||
slru.c is the supporting mechanism for both pg_clog and pg_subtrans. It
|
||||
implements the LRU policy for in-memory buffer pages. The high-level routines
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/backend/access/transam/multixact.c,v 1.3 2005/05/07 18:14:25 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/transam/multixact.c,v 1.4 2005/05/19 21:35:45 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -44,7 +44,7 @@
|
||||
#include "utils/memutils.h"
|
||||
#include "storage/backendid.h"
|
||||
#include "storage/lmgr.h"
|
||||
#include "storage/sinval.h"
|
||||
#include "storage/procarray.h"
|
||||
|
||||
|
||||
/*
|
||||
@@ -383,8 +383,8 @@ MultiXactIdIsRunning(MultiXactId multi)
|
||||
}
|
||||
|
||||
/*
|
||||
* This could be made better by having a special entry point in sinval.c,
|
||||
* walking the PGPROC array only once for the whole array. But in most
|
||||
* This could be made faster by having another entry point in procarray.c,
|
||||
* walking the PGPROC array only once for all the members. But in most
|
||||
* cases nmembers should be small enough that it doesn't much matter.
|
||||
*/
|
||||
for (i = 0; i < nmembers; i++)
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/backend/access/transam/subtrans.c,v 1.7 2004/12/31 21:59:29 pgsql Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/transam/subtrans.c,v 1.8 2005/05/19 21:35:45 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -30,7 +30,6 @@
|
||||
|
||||
#include "access/slru.h"
|
||||
#include "access/subtrans.h"
|
||||
#include "storage/sinval.h"
|
||||
#include "utils/tqual.h"
|
||||
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* Copyright (c) 2000-2005, PostgreSQL Global Development Group
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/transam/varsup.c,v 1.63 2005/04/13 18:54:56 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/transam/varsup.c,v 1.64 2005/05/19 21:35:45 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -107,7 +107,7 @@ GetNewTransactionId(bool isSubXact)
|
||||
* nextXid are already present in PGPROC. Else we have a race
|
||||
* condition.
|
||||
*
|
||||
* XXX by storing xid into MyProc without acquiring SInvalLock, we are
|
||||
* XXX by storing xid into MyProc without acquiring ProcArrayLock, we are
|
||||
* relying on fetch/store of an xid to be atomic, else other backends
|
||||
* might see a partially-set xid here. But holding both locks at once
|
||||
* would be a nasty concurrency hit (and in fact could cause a
|
||||
@@ -120,8 +120,7 @@ GetNewTransactionId(bool isSubXact)
|
||||
*
|
||||
* A solution to the atomic-store problem would be to give each PGPROC
|
||||
* its own spinlock used only for fetching/storing that PGPROC's xid
|
||||
* and related fields. (SInvalLock would then mean primarily that
|
||||
* PGPROCs couldn't be added/removed while holding the lock.)
|
||||
* and related fields.
|
||||
*
|
||||
* If there's no room to fit a subtransaction XID into PGPROC, set the
|
||||
* cache-overflowed flag instead. This forces readers to look in
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.200 2005/04/28 21:47:10 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.201 2005/05/19 21:35:45 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -34,7 +34,7 @@
|
||||
#include "miscadmin.h"
|
||||
#include "storage/fd.h"
|
||||
#include "storage/proc.h"
|
||||
#include "storage/sinval.h"
|
||||
#include "storage/procarray.h"
|
||||
#include "storage/smgr.h"
|
||||
#include "utils/flatfiles.h"
|
||||
#include "utils/guc.h"
|
||||
@@ -1503,16 +1503,18 @@ CommitTransaction(void)
|
||||
* this must be done _before_ releasing locks we hold and _after_
|
||||
* RecordTransactionCommit.
|
||||
*
|
||||
* LWLockAcquire(SInvalLock) is required: UPDATE with xid 0 is blocked by
|
||||
* xid 1' UPDATE, xid 1 is doing commit while xid 2 gets snapshot - if
|
||||
* xid 2' GetSnapshotData sees xid 1 as running then it must see xid 0
|
||||
* as running as well or it will see two tuple versions - one deleted
|
||||
* by xid 1 and one inserted by xid 0. See notes in GetSnapshotData.
|
||||
* LWLockAcquire(ProcArrayLock) is required; consider this example:
|
||||
* UPDATE with xid 0 is blocked by xid 1's UPDATE.
|
||||
* xid 1 is doing commit while xid 2 gets snapshot.
|
||||
* If xid 2's GetSnapshotData sees xid 1 as running then it must see
|
||||
* xid 0 as running as well, or it will be able to see two tuple versions
|
||||
* - one deleted by xid 1 and one inserted by xid 0. See notes in
|
||||
* GetSnapshotData.
|
||||
*/
|
||||
if (MyProc != NULL)
|
||||
{
|
||||
/* Lock SInvalLock because that's what GetSnapshotData uses. */
|
||||
LWLockAcquire(SInvalLock, LW_EXCLUSIVE);
|
||||
/* Lock ProcArrayLock because that's what GetSnapshotData uses. */
|
||||
LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
|
||||
MyProc->xid = InvalidTransactionId;
|
||||
MyProc->xmin = InvalidTransactionId;
|
||||
|
||||
@@ -1520,7 +1522,7 @@ CommitTransaction(void)
|
||||
MyProc->subxids.nxids = 0;
|
||||
MyProc->subxids.overflowed = false;
|
||||
|
||||
LWLockRelease(SInvalLock);
|
||||
LWLockRelease(ProcArrayLock);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1688,8 +1690,8 @@ AbortTransaction(void)
|
||||
*/
|
||||
if (MyProc != NULL)
|
||||
{
|
||||
/* Lock SInvalLock because that's what GetSnapshotData uses. */
|
||||
LWLockAcquire(SInvalLock, LW_EXCLUSIVE);
|
||||
/* Lock ProcArrayLock because that's what GetSnapshotData uses. */
|
||||
LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
|
||||
MyProc->xid = InvalidTransactionId;
|
||||
MyProc->xmin = InvalidTransactionId;
|
||||
|
||||
@@ -1697,7 +1699,7 @@ AbortTransaction(void)
|
||||
MyProc->subxids.nxids = 0;
|
||||
MyProc->subxids.overflowed = false;
|
||||
|
||||
LWLockRelease(SInvalLock);
|
||||
LWLockRelease(ProcArrayLock);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.191 2005/05/10 22:27:29 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.192 2005/05/19 21:35:45 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -38,7 +38,7 @@
|
||||
#include "storage/lwlock.h"
|
||||
#include "storage/pmsignal.h"
|
||||
#include "storage/proc.h"
|
||||
#include "storage/sinval.h"
|
||||
#include "storage/procarray.h"
|
||||
#include "storage/spin.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/guc.h"
|
||||
@@ -776,7 +776,7 @@ begin:;
|
||||
if (MyLastRecPtr.xrecoff == 0 && !no_tran)
|
||||
{
|
||||
/*
|
||||
* We do not acquire SInvalLock here because of possible deadlock.
|
||||
* We do not acquire ProcArrayLock here because of possible deadlock.
|
||||
* Anyone who wants to inspect other procs' logRec must acquire
|
||||
* WALInsertLock, instead. A better solution would be a per-PROC
|
||||
* spinlock, but no time for that before 7.2 --- tgl 12/19/01.
|
||||
@@ -4887,11 +4887,11 @@ CreateCheckPoint(bool shutdown, bool force)
|
||||
* commits after REDO point).
|
||||
*
|
||||
* XXX temporarily ifdef'd out to avoid three-way deadlock condition:
|
||||
* GetUndoRecPtr needs to grab SInvalLock to ensure that it is looking
|
||||
* at a stable set of proc records, but grabbing SInvalLock while
|
||||
* GetUndoRecPtr needs to grab ProcArrayLock to ensure that it is looking
|
||||
* at a stable set of proc records, but grabbing ProcArrayLock while
|
||||
* holding WALInsertLock is no good. GetNewTransactionId may cause a
|
||||
* WAL record to be written while holding XidGenLock, and
|
||||
* GetSnapshotData needs to get XidGenLock while holding SInvalLock,
|
||||
* GetSnapshotData needs to get XidGenLock while holding ProcArrayLock,
|
||||
* so there's a risk of deadlock. Need to find a better solution. See
|
||||
* pgsql-hackers discussion of 17-Dec-01.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user