mirror of
https://github.com/postgres/postgres.git
synced 2025-06-26 12:21:12 +03:00
Tune GetSnapshotData() during Hot Standby by avoiding loop
through normal backends. Makes code clearer also, since we avoid various Assert()s. Performance of snapshots taken during recovery no longer depends upon number of read-only backends.
This commit is contained in:
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.397 2010/04/16 08:58:16 heikki Exp $
|
* $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.398 2010/04/18 18:05:51 sriggs Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -6454,6 +6454,12 @@ CheckRecoveryConsistency(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
XLogConsistentState(void)
|
||||||
|
{
|
||||||
|
return reachedMinRecoveryPoint;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Is the system still in recovery?
|
* Is the system still in recovery?
|
||||||
*
|
*
|
||||||
|
@ -37,7 +37,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/storage/ipc/procarray.c,v 1.62 2010/04/06 10:50:57 sriggs Exp $
|
* $PostgreSQL: pgsql/src/backend/storage/ipc/procarray.c,v 1.63 2010/04/18 18:05:55 sriggs Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -1091,89 +1091,90 @@ GetSnapshotData(Snapshot snapshot)
|
|||||||
globalxmin = xmin = xmax;
|
globalxmin = xmin = xmax;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Spin over procArray checking xid, xmin, and subxids. The goal is to
|
* If in recovery get any known assigned xids.
|
||||||
* gather all active xids, find the lowest xmin, and try to record
|
|
||||||
* subxids.
|
|
||||||
*/
|
*/
|
||||||
for (index = 0; index < arrayP->numProcs; index++)
|
if (!snapshot->takenDuringRecovery)
|
||||||
{
|
{
|
||||||
volatile PGPROC *proc = arrayP->procs[index];
|
|
||||||
TransactionId xid;
|
|
||||||
|
|
||||||
/* Ignore procs running LAZY VACUUM */
|
|
||||||
if (proc->vacuumFlags & PROC_IN_VACUUM)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* Update globalxmin to be the smallest valid xmin */
|
|
||||||
xid = proc->xmin; /* fetch just once */
|
|
||||||
if (TransactionIdIsNormal(xid) &&
|
|
||||||
TransactionIdPrecedes(xid, globalxmin))
|
|
||||||
globalxmin = xid;
|
|
||||||
|
|
||||||
/* Fetch xid just once - see GetNewTransactionId */
|
|
||||||
xid = proc->xid;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the transaction has been assigned an xid < xmax we add it to the
|
* Spin over procArray checking xid, xmin, and subxids. The goal is to
|
||||||
* snapshot, and update xmin if necessary. There's no need to store
|
* gather all active xids, find the lowest xmin, and try to record
|
||||||
* XIDs >= xmax, since we'll treat them as running anyway. We don't
|
* subxids. During recovery no xids will be assigned, so all normal
|
||||||
* bother to examine their subxids either.
|
* backends can be ignored, nor are there any VACUUMs running. All
|
||||||
*
|
* prepared transaction xids are held in KnownAssignedXids, so these
|
||||||
* We don't include our own XID (if any) in the snapshot, but we must
|
* will be seen without needing to loop through procs here.
|
||||||
* include it into xmin.
|
|
||||||
*/
|
*/
|
||||||
if (TransactionIdIsNormal(xid))
|
for (index = 0; index < arrayP->numProcs; index++)
|
||||||
{
|
{
|
||||||
Assert(!snapshot->takenDuringRecovery);
|
volatile PGPROC *proc = arrayP->procs[index];
|
||||||
if (TransactionIdFollowsOrEquals(xid, xmax))
|
TransactionId xid;
|
||||||
|
|
||||||
|
/* Ignore procs running LAZY VACUUM */
|
||||||
|
if (proc->vacuumFlags & PROC_IN_VACUUM)
|
||||||
continue;
|
continue;
|
||||||
if (proc != MyProc)
|
|
||||||
snapshot->xip[count++] = xid;
|
|
||||||
if (TransactionIdPrecedes(xid, xmin))
|
|
||||||
xmin = xid;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/* Update globalxmin to be the smallest valid xmin */
|
||||||
* Save subtransaction XIDs if possible (if we've already overflowed,
|
xid = proc->xmin; /* fetch just once */
|
||||||
* there's no point). Note that the subxact XIDs must be later than
|
if (TransactionIdIsNormal(xid) &&
|
||||||
* their parent, so no need to check them against xmin. We could
|
TransactionIdPrecedes(xid, globalxmin))
|
||||||
* filter against xmax, but it seems better not to do that much work
|
globalxmin = xid;
|
||||||
* while holding the ProcArrayLock.
|
|
||||||
*
|
/* Fetch xid just once - see GetNewTransactionId */
|
||||||
* The other backend can add more subxids concurrently, but cannot
|
xid = proc->xid;
|
||||||
* remove any. Hence it's important to fetch nxids just once. Should
|
|
||||||
* be safe to use memcpy, though. (We needn't worry about missing any
|
/*
|
||||||
* xids added concurrently, because they must postdate xmax.)
|
* If the transaction has been assigned an xid < xmax we add it to the
|
||||||
*
|
* snapshot, and update xmin if necessary. There's no need to store
|
||||||
* Again, our own XIDs are not included in the snapshot.
|
* XIDs >= xmax, since we'll treat them as running anyway. We don't
|
||||||
*/
|
* bother to examine their subxids either.
|
||||||
if (!suboverflowed && proc != MyProc)
|
*
|
||||||
{
|
* We don't include our own XID (if any) in the snapshot, but we must
|
||||||
if (proc->subxids.overflowed)
|
* include it into xmin.
|
||||||
suboverflowed = true;
|
*/
|
||||||
else
|
if (TransactionIdIsNormal(xid))
|
||||||
{
|
{
|
||||||
int nxids = proc->subxids.nxids;
|
if (TransactionIdFollowsOrEquals(xid, xmax))
|
||||||
|
continue;
|
||||||
|
if (proc != MyProc)
|
||||||
|
snapshot->xip[count++] = xid;
|
||||||
|
if (TransactionIdPrecedes(xid, xmin))
|
||||||
|
xmin = xid;
|
||||||
|
}
|
||||||
|
|
||||||
if (nxids > 0)
|
/*
|
||||||
|
* Save subtransaction XIDs if possible (if we've already overflowed,
|
||||||
|
* there's no point). Note that the subxact XIDs must be later than
|
||||||
|
* their parent, so no need to check them against xmin. We could
|
||||||
|
* filter against xmax, but it seems better not to do that much work
|
||||||
|
* while holding the ProcArrayLock.
|
||||||
|
*
|
||||||
|
* The other backend can add more subxids concurrently, but cannot
|
||||||
|
* remove any. Hence it's important to fetch nxids just once. Should
|
||||||
|
* be safe to use memcpy, though. (We needn't worry about missing any
|
||||||
|
* xids added concurrently, because they must postdate xmax.)
|
||||||
|
*
|
||||||
|
* Again, our own XIDs are not included in the snapshot.
|
||||||
|
*/
|
||||||
|
if (!suboverflowed && proc != MyProc)
|
||||||
|
{
|
||||||
|
if (proc->subxids.overflowed)
|
||||||
|
suboverflowed = true;
|
||||||
|
else
|
||||||
{
|
{
|
||||||
Assert(!snapshot->takenDuringRecovery);
|
int nxids = proc->subxids.nxids;
|
||||||
memcpy(snapshot->subxip + subcount,
|
|
||||||
(void *) proc->subxids.xids,
|
if (nxids > 0)
|
||||||
nxids * sizeof(TransactionId));
|
{
|
||||||
subcount += nxids;
|
memcpy(snapshot->subxip + subcount,
|
||||||
|
(void *) proc->subxids.xids,
|
||||||
|
nxids * sizeof(TransactionId));
|
||||||
|
subcount += nxids;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
/*
|
|
||||||
* If in recovery get any known assigned xids.
|
|
||||||
*/
|
|
||||||
if (snapshot->takenDuringRecovery)
|
|
||||||
{
|
{
|
||||||
Assert(count == 0);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We store all xids directly into subxip[]. Here's why:
|
* We store all xids directly into subxip[]. Here's why:
|
||||||
*
|
*
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/access/xlog.h,v 1.106 2010/04/12 09:52:29 heikki Exp $
|
* $PostgreSQL: pgsql/src/include/access/xlog.h,v 1.107 2010/04/18 18:06:07 sriggs Exp $
|
||||||
*/
|
*/
|
||||||
#ifndef XLOG_H
|
#ifndef XLOG_H
|
||||||
#define XLOG_H
|
#define XLOG_H
|
||||||
@ -278,6 +278,7 @@ extern void xlog_desc(StringInfo buf, uint8 xl_info, char *rec);
|
|||||||
|
|
||||||
extern void issue_xlog_fsync(int fd, uint32 log, uint32 seg);
|
extern void issue_xlog_fsync(int fd, uint32 log, uint32 seg);
|
||||||
|
|
||||||
|
extern bool XLogConsistentState(void);
|
||||||
extern bool RecoveryInProgress(void);
|
extern bool RecoveryInProgress(void);
|
||||||
extern bool XLogInsertAllowed(void);
|
extern bool XLogInsertAllowed(void);
|
||||||
extern TimestampTz GetLatestXLogTime(void);
|
extern TimestampTz GetLatestXLogTime(void);
|
||||||
|
Reference in New Issue
Block a user