Commit f009c316 authored by Tom Lane's avatar Tom Lane

Tweak code so that pg_subtrans is never consulted for XIDs older than

RecentXmin (== MyProc->xmin).  This ensures that it will be safe to
truncate pg_subtrans at RecentGlobalXmin, which should largely eliminate
any fear of bloat.  Along the way, eliminate SubTransXidsHaveCommonAncestor,
which isn't really needed and could not give a trustworthy result anyway
under the lookback restriction.
In an unrelated but nearby change, #ifdef out GetUndoRecPtr, which has
been dead code since 2001 and seems unlikely to ever be resurrected.
parent 37d937ea
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2003, 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/subtrans.c,v 1.1 2004/07/01 00:49:42 tgl Exp $ * $PostgreSQL: pgsql/src/backend/access/transam/subtrans.c,v 1.2 2004/08/22 02:41:57 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include "access/subtrans.h" #include "access/subtrans.h"
#include "miscadmin.h" #include "miscadmin.h"
#include "storage/lwlock.h" #include "storage/lwlock.h"
#include "utils/tqual.h"
/* /*
...@@ -113,6 +114,9 @@ SubTransGetParent(TransactionId xid) ...@@ -113,6 +114,9 @@ SubTransGetParent(TransactionId xid)
TransactionId *ptr; TransactionId *ptr;
TransactionId parent; TransactionId parent;
/* Can't ask about stuff that might not be around anymore */
Assert(TransactionIdFollowsOrEquals(xid, RecentXmin));
/* Bootstrap and frozen XIDs have no parent */ /* Bootstrap and frozen XIDs have no parent */
if (!TransactionIdIsNormal(xid)) if (!TransactionIdIsNormal(xid))
return InvalidTransactionId; return InvalidTransactionId;
...@@ -133,6 +137,13 @@ SubTransGetParent(TransactionId xid) ...@@ -133,6 +137,13 @@ SubTransGetParent(TransactionId xid)
* SubTransGetTopmostTransaction * SubTransGetTopmostTransaction
* *
* Returns the topmost transaction of the given transaction id. * Returns the topmost transaction of the given transaction id.
*
* Because we cannot look back further than RecentXmin, it is possible
* that this function will lie and return an intermediate subtransaction ID
* instead of the true topmost parent ID. This is OK, because in practice
* we only care about detecting whether the topmost parent is still running
* or is part of a current snapshot's list of still-running transactions.
* Therefore, any XID before RecentXmin is as good as any other.
*/ */
TransactionId TransactionId
SubTransGetTopmostTransaction(TransactionId xid) SubTransGetTopmostTransaction(TransactionId xid)
...@@ -140,9 +151,14 @@ SubTransGetTopmostTransaction(TransactionId xid) ...@@ -140,9 +151,14 @@ SubTransGetTopmostTransaction(TransactionId xid)
TransactionId parentXid = xid, TransactionId parentXid = xid,
previousXid = xid; previousXid = xid;
/* Can't ask about stuff that might not be around anymore */
Assert(TransactionIdFollowsOrEquals(xid, RecentXmin));
while (TransactionIdIsValid(parentXid)) while (TransactionIdIsValid(parentXid))
{ {
previousXid = parentXid; previousXid = parentXid;
if (TransactionIdPrecedes(parentXid, RecentXmin))
break;
parentXid = SubTransGetParent(parentXid); parentXid = SubTransGetParent(parentXid);
} }
...@@ -151,30 +167,6 @@ SubTransGetTopmostTransaction(TransactionId xid) ...@@ -151,30 +167,6 @@ SubTransGetTopmostTransaction(TransactionId xid)
return previousXid; return previousXid;
} }
/*
* SubTransXidsHaveCommonAncestor
*
* Returns true iff the Xids have a common ancestor
*/
bool
SubTransXidsHaveCommonAncestor(TransactionId xid1, TransactionId xid2)
{
if (TransactionIdEquals(xid1, xid2))
return true;
while (TransactionIdIsValid(xid1) && TransactionIdIsValid(xid2))
{
if (TransactionIdPrecedes(xid2, xid1))
xid1 = SubTransGetParent(xid1);
else
xid2 = SubTransGetParent(xid2);
if (TransactionIdEquals(xid1, xid2))
return true;
}
return false;
}
/* /*
* Initialization of shared memory for Subtrans * Initialization of shared memory for Subtrans
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/transam/transam.c,v 1.57 2004/07/01 00:49:42 tgl Exp $ * $PostgreSQL: pgsql/src/backend/access/transam/transam.c,v 1.58 2004/08/22 02:41:57 tgl Exp $
* *
* NOTES * NOTES
* This file contains the high level access-method interface to the * This file contains the high level access-method interface to the
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include "access/clog.h" #include "access/clog.h"
#include "access/subtrans.h" #include "access/subtrans.h"
#include "access/transam.h" #include "access/transam.h"
#include "utils/tqual.h"
/* ---------------- /* ----------------
...@@ -199,11 +200,15 @@ TransactionIdDidCommit(TransactionId transactionId) ...@@ -199,11 +200,15 @@ TransactionIdDidCommit(TransactionId transactionId)
/* /*
* If it's marked subcommitted, we have to check the parent recursively. * If it's marked subcommitted, we have to check the parent recursively.
* However, if it's older than RecentXmin, we can't look at pg_subtrans;
* instead assume that the parent crashed without cleaning up its children.
*/ */
if (xidstatus == TRANSACTION_STATUS_SUB_COMMITTED) if (xidstatus == TRANSACTION_STATUS_SUB_COMMITTED)
{ {
TransactionId parentXid; TransactionId parentXid;
if (TransactionIdPrecedes(transactionId, RecentXmin))
return false;
parentXid = SubTransGetParent(transactionId); parentXid = SubTransGetParent(transactionId);
Assert(TransactionIdIsValid(parentXid)); Assert(TransactionIdIsValid(parentXid));
return TransactionIdDidCommit(parentXid); return TransactionIdDidCommit(parentXid);
...@@ -243,24 +248,17 @@ TransactionIdDidAbort(TransactionId transactionId) ...@@ -243,24 +248,17 @@ TransactionIdDidAbort(TransactionId transactionId)
/* /*
* If it's marked subcommitted, we have to check the parent recursively. * If it's marked subcommitted, we have to check the parent recursively.
* * However, if it's older than RecentXmin, we can't look at pg_subtrans;
* If we detect that the parent has aborted, update pg_clog to show the * instead assume that the parent crashed without cleaning up its children.
* subtransaction as aborted. This is only needed when the parent
* crashed before either committing or aborting. We want to clean up
* pg_clog so future visitors don't need to make this check again.
*/ */
if (xidstatus == TRANSACTION_STATUS_SUB_COMMITTED) if (xidstatus == TRANSACTION_STATUS_SUB_COMMITTED)
{ {
TransactionId parentXid; TransactionId parentXid;
bool parentAborted;
if (TransactionIdPrecedes(transactionId, RecentXmin))
return true;
parentXid = SubTransGetParent(transactionId); parentXid = SubTransGetParent(transactionId);
parentAborted = TransactionIdDidAbort(parentXid); return TransactionIdDidAbort(parentXid);
if (parentAborted)
TransactionIdAbort(transactionId);
return parentAborted;
} }
/* /*
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/storage/ipc/sinval.c,v 1.68 2004/08/15 17:03:36 tgl Exp $ * $PostgreSQL: pgsql/src/backend/storage/ipc/sinval.c,v 1.69 2004/08/22 02:41:57 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -526,7 +526,7 @@ TransactionIdIsInProgress(TransactionId xid) ...@@ -526,7 +526,7 @@ TransactionIdIsInProgress(TransactionId xid)
/* /*
* Don't bother checking a very old transaction. * Don't bother checking a very old transaction.
*/ */
if (TransactionIdPrecedes(xid, RecentGlobalXmin)) if (TransactionIdPrecedes(xid, RecentXmin))
{ {
xc_by_recent_xmin_inc(); xc_by_recent_xmin_inc();
return false; return false;
...@@ -912,6 +912,7 @@ CountActiveBackends(void) ...@@ -912,6 +912,7 @@ CountActiveBackends(void)
return count; return count;
} }
#ifdef NOT_USED
/* /*
* GetUndoRecPtr -- returns oldest PGPROC->logRec. * GetUndoRecPtr -- returns oldest PGPROC->logRec.
*/ */
...@@ -947,6 +948,7 @@ GetUndoRecPtr(void) ...@@ -947,6 +948,7 @@ GetUndoRecPtr(void)
return (urec); return (urec);
} }
#endif /* NOT_USED */
/* /*
* BackendIdGetProc - given a BackendId, find its PGPROC structure * BackendIdGetProc - given a BackendId, find its PGPROC structure
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/storage/lmgr/lmgr.c,v 1.66 2004/07/28 14:23:29 tgl Exp $ * $PostgreSQL: pgsql/src/backend/storage/lmgr/lmgr.c,v 1.67 2004/08/22 02:41:57 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -345,7 +345,7 @@ XactLockTableWait(TransactionId xid) ...@@ -345,7 +345,7 @@ XactLockTableWait(TransactionId xid)
LOCKTAG tag; LOCKTAG tag;
TransactionId myxid = GetTopTransactionId(); TransactionId myxid = GetTopTransactionId();
Assert(!SubTransXidsHaveCommonAncestor(xid, myxid)); Assert(!TransactionIdEquals(xid, myxid));
MemSet(&tag, 0, sizeof(tag)); MemSet(&tag, 0, sizeof(tag));
tag.relId = XactLockTableId; tag.relId = XactLockTableId;
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/time/tqual.c,v 1.74 2004/07/28 14:23:30 tgl Exp $ * $PostgreSQL: pgsql/src/backend/utils/time/tqual.c,v 1.75 2004/08/22 02:41:57 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -933,8 +933,6 @@ HeapTupleSatisfiesVacuum(HeapTupleHeader tuple, TransactionId OldestXmin) ...@@ -933,8 +933,6 @@ HeapTupleSatisfiesVacuum(HeapTupleHeader tuple, TransactionId OldestXmin)
{ {
if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid */ if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid */
return HEAPTUPLE_INSERT_IN_PROGRESS; return HEAPTUPLE_INSERT_IN_PROGRESS;
Assert(SubTransXidsHaveCommonAncestor(HeapTupleHeaderGetXmin(tuple),
HeapTupleHeaderGetXmax(tuple)));
if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE) if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
return HEAPTUPLE_INSERT_IN_PROGRESS; return HEAPTUPLE_INSERT_IN_PROGRESS;
/* inserted and then deleted by same xact */ /* inserted and then deleted by same xact */
...@@ -1008,7 +1006,7 @@ HeapTupleSatisfiesVacuum(HeapTupleHeader tuple, TransactionId OldestXmin) ...@@ -1008,7 +1006,7 @@ HeapTupleSatisfiesVacuum(HeapTupleHeader tuple, TransactionId OldestXmin)
* Deleter committed, but check special cases. * Deleter committed, but check special cases.
*/ */
if (SubTransXidsHaveCommonAncestor(HeapTupleHeaderGetXmin(tuple), if (TransactionIdEquals(HeapTupleHeaderGetXmin(tuple),
HeapTupleHeaderGetXmax(tuple))) HeapTupleHeaderGetXmax(tuple)))
{ {
/* /*
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2003, 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/subtrans.h,v 1.1 2004/07/01 00:51:38 tgl Exp $ * $PostgreSQL: pgsql/src/include/access/subtrans.h,v 1.2 2004/08/22 02:41:58 tgl Exp $
*/ */
#ifndef SUBTRANS_H #ifndef SUBTRANS_H
#define SUBTRANS_H #define SUBTRANS_H
...@@ -20,7 +20,6 @@ ...@@ -20,7 +20,6 @@
extern void SubTransSetParent(TransactionId xid, TransactionId parent); extern void SubTransSetParent(TransactionId xid, TransactionId parent);
extern TransactionId SubTransGetParent(TransactionId xid); extern TransactionId SubTransGetParent(TransactionId xid);
extern TransactionId SubTransGetTopmostTransaction(TransactionId xid); extern TransactionId SubTransGetTopmostTransaction(TransactionId xid);
extern bool SubTransXidsHaveCommonAncestor(TransactionId xid1, TransactionId xid2);
extern int SUBTRANSShmemSize(void); extern int SUBTRANSShmemSize(void);
extern void SUBTRANSShmemInit(void); extern void SUBTRANSShmemInit(void);
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2003, 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.54 2004/07/21 22:31:25 tgl Exp $ * $PostgreSQL: pgsql/src/include/access/xlog.h,v 1.55 2004/08/22 02:41:58 tgl Exp $
*/ */
#ifndef XLOG_H #ifndef XLOG_H
#define XLOG_H #define XLOG_H
...@@ -135,9 +135,4 @@ extern void CreateCheckPoint(bool shutdown, bool force); ...@@ -135,9 +135,4 @@ extern void CreateCheckPoint(bool shutdown, bool force);
extern void XLogPutNextOid(Oid nextOid); extern void XLogPutNextOid(Oid nextOid);
extern XLogRecPtr GetRedoRecPtr(void); extern XLogRecPtr GetRedoRecPtr(void);
/* in storage/ipc/sinval.c, but don't want to declare in sinval.h because
* we'd have to include xlog.h into that ...
*/
extern XLogRecPtr GetUndoRecPtr(void);
#endif /* XLOG_H */ #endif /* XLOG_H */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment