diff options
| author | Tom Lane <tgl@sss.pgh.pa.us> | 2002-05-24 18:57:57 +0000 |
|---|---|---|
| committer | Tom Lane <tgl@sss.pgh.pa.us> | 2002-05-24 18:57:57 +0000 |
| commit | 3f4d48802271126b1343289a9d2267ff1ed3788a (patch) | |
| tree | b8c7507719ba240834e28cfbb56e2badff118b7e /src/backend/storage/ipc/sinval.c | |
| parent | 2f2d05763d1c55c7998c0d7030659e3db6f60183 (diff) | |
| download | postgresql-3f4d48802271126b1343289a9d2267ff1ed3788a.tar.gz | |
Mark index entries "killed" when they are no longer visible to any
transaction, so as to avoid returning them out of the index AM. Saves
repeated heap_fetch operations on frequently-updated rows. Also detect
queries on unique keys (equality to all columns of a unique index), and
don't bother continuing scan once we have found first match.
Killing is implemented in the btree and hash AMs, but not yet in rtree
or gist, because there isn't an equally convenient place to do it in
those AMs (the outer amgetnext routine can't do it without re-pinning
the index page).
Did some small cleanup on APIs of HeapTupleSatisfies, heap_fetch, and
index_insert to make this a little easier.
Diffstat (limited to 'src/backend/storage/ipc/sinval.c')
| -rw-r--r-- | src/backend/storage/ipc/sinval.c | 43 |
1 files changed, 35 insertions, 8 deletions
diff --git a/src/backend/storage/ipc/sinval.c b/src/backend/storage/ipc/sinval.c index a32c8ae703..6415271bea 100644 --- a/src/backend/storage/ipc/sinval.c +++ b/src/backend/storage/ipc/sinval.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/storage/ipc/sinval.c,v 1.46 2002/05/21 22:05:55 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/ipc/sinval.c,v 1.47 2002/05/24 18:57:56 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -297,6 +297,10 @@ GetOldestXmin(bool allDbs) * it is considered running or not. * This ensures that the set of transactions seen as "running" by the * current xact will not change after it takes the snapshot. + * + * Also, we compute the current global xmin (oldest xmin across all running + * transactions) and save it in RecentGlobalXmin. This is the same + * computation done by GetOldestXmin(TRUE). *---------- */ Snapshot @@ -305,6 +309,9 @@ GetSnapshotData(bool serializable) Snapshot snapshot = (Snapshot) malloc(sizeof(SnapshotData)); SISeg *segP = shmInvalBuffer; ProcState *stateP = segP->procState; + TransactionId xmin; + TransactionId xmax; + TransactionId globalxmin; int index; int count = 0; @@ -321,7 +328,7 @@ GetSnapshotData(bool serializable) if (snapshot->xip == NULL) elog(ERROR, "Memory exhausted in GetSnapshotData"); - snapshot->xmin = GetCurrentTransactionId(); + globalxmin = xmin = GetCurrentTransactionId(); /* * If we are going to set MyProc->xmin then we'd better get exclusive @@ -356,7 +363,7 @@ GetSnapshotData(bool serializable) *-------------------- */ - snapshot->xmax = ReadNewTransactionId(); + xmax = ReadNewTransactionId(); for (index = 0; index < segP->lastBackend; index++) { @@ -374,28 +381,48 @@ GetSnapshotData(bool serializable) * running a transaction, and xacts started since we read the * next transaction ID. There's no need to store XIDs above * what we got from ReadNewTransactionId, since we'll treat - * them as running anyway. + * them as running anyway. We also assume that such xacts can't + * compute an xmin older than ours, so they needn't be considered + * in computing globalxmin. */ if (proc == MyProc || !TransactionIdIsNormal(xid) || - TransactionIdFollowsOrEquals(xid, snapshot->xmax)) + TransactionIdFollowsOrEquals(xid, xmax)) continue; - if (TransactionIdPrecedes(xid, snapshot->xmin)) - snapshot->xmin = xid; + if (TransactionIdPrecedes(xid, xmin)) + xmin = xid; snapshot->xip[count] = xid; count++; + + /* Update globalxmin to be the smallest valid xmin */ + xid = proc->xmin; + if (TransactionIdIsNormal(xid)) + if (TransactionIdPrecedes(xid, globalxmin)) + globalxmin = xid; } } if (serializable) - MyProc->xmin = snapshot->xmin; + MyProc->xmin = xmin; LWLockRelease(SInvalLock); /* Serializable snapshot must be computed before any other... */ Assert(TransactionIdIsValid(MyProc->xmin)); + /* + * Update globalxmin to include actual process xids. This is a slightly + * different way of computing it than GetOldestXmin uses, but should give + * the same result. + */ + if (TransactionIdPrecedes(xmin, globalxmin)) + globalxmin = xmin; + + RecentGlobalXmin = globalxmin; + + snapshot->xmin = xmin; + snapshot->xmax = xmax; snapshot->xcnt = count; snapshot->curcid = GetCurrentCommandId(); |
