diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2001-08-25 18:52:43 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2001-08-25 18:52:43 +0000 |
commit | 2589735da08c4e597accb6eab5ae65b6339ee630 (patch) | |
tree | 829f7073292c6b55f86580863837441991638405 /src/backend/access/transam/transam.c | |
parent | 4699d81dc99ef1687e9396b57b0ed10f42699792 (diff) | |
download | postgresql-2589735da08c4e597accb6eab5ae65b6339ee630.tar.gz postgresql-2589735da08c4e597accb6eab5ae65b6339ee630.zip |
Replace implementation of pg_log as a relation accessed through the
buffer manager with 'pg_clog', a specialized access method modeled
on pg_xlog. This simplifies startup (don't need to play games to
open pg_log; among other things, OverrideTransactionSystem goes away),
should improve performance a little, and opens the door to recycling
commit log space by removing no-longer-needed segments of the commit
log. Actual recycling is not there yet, but I felt I should commit
this part separately since it'd still be useful if we chose not to
do transaction ID wraparound.
Diffstat (limited to 'src/backend/access/transam/transam.c')
-rw-r--r-- | src/backend/access/transam/transam.c | 320 |
1 files changed, 42 insertions, 278 deletions
diff --git a/src/backend/access/transam/transam.c b/src/backend/access/transam/transam.c index 65718b4cae9..3364ed66337 100644 --- a/src/backend/access/transam/transam.c +++ b/src/backend/access/transam/transam.c @@ -1,14 +1,14 @@ /*------------------------------------------------------------------------- * * transam.c - * postgres transaction log/time interface routines + * postgres transaction log interface routines * * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/transam/transam.c,v 1.46 2001/08/23 23:06:37 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/transam/transam.c,v 1.47 2001/08/25 18:52:41 tgl Exp $ * * NOTES * This file contains the high level access-method interface to the @@ -19,76 +19,27 @@ #include "postgres.h" -#include "access/heapam.h" +#include "access/clog.h" #include "access/transam.h" -#include "catalog/catname.h" -#include "miscadmin.h" -static int RecoveryCheckingEnabled(void); -static void TransRecover(Relation logRelation); static bool TransactionLogTest(TransactionId transactionId, XidStatus status); static void TransactionLogUpdate(TransactionId transactionId, XidStatus status); /* ---------------- - * global variables holding pointers to relations used - * by the transaction system. These are initialized by - * InitializeTransactionLog(). - * ---------------- - */ - -Relation LogRelation = (Relation) NULL; - -/* ---------------- * Single-item cache for results of TransactionLogTest. * ---------------- */ static TransactionId cachedTestXid = InvalidTransactionId; static XidStatus cachedTestXidStatus; -/* ---------------- - * transaction recovery state variables - * - * When the transaction system is initialized, we may - * need to do recovery checking. This decision is decided - * by the postmaster or the user by supplying the backend - * with a special flag. In general, we want to do recovery - * checking whenever we are running without a postmaster - * or when the number of backends running under the postmaster - * goes from zero to one. -cim 3/21/90 - * ---------------- - */ -static int RecoveryCheckingEnableState = 0; - -/* ---------------- - * recovery checking accessors - * ---------------- - */ -static int -RecoveryCheckingEnabled(void) -{ - return RecoveryCheckingEnableState; -} - -#ifdef NOT_USED -static void -SetRecoveryCheckingEnabled(bool state) -{ - RecoveryCheckingEnableState = (state == true); -} - -#endif /* ---------------------------------------------------------------- * postgres log access method interface * * TransactionLogTest * TransactionLogUpdate - * ======== - * these functions do work for the interface - * functions - they search/retrieve and append/update - * information in the log and time relations. * ---------------------------------------------------------------- */ @@ -102,59 +53,42 @@ static bool /* true/false: does transaction id have TransactionLogTest(TransactionId transactionId, /* transaction id to test */ XidStatus status) /* transaction status */ { - BlockNumber blockNumber; XidStatus xidstatus; /* recorded status of xid */ - bool fail = false; /* success/failure */ - - /* - * during initialization consider all transactions as having been - * committed - */ - if (!RelationIsValid(LogRelation)) - return (bool) (status == XID_COMMIT); /* - * before going to the buffer manager, check our single item cache to + * Before going to the commit log manager, check our single item cache to * see if we didn't just check the transaction status a moment ago. */ if (TransactionIdEquals(transactionId, cachedTestXid)) - return (bool) - (status == cachedTestXidStatus); + return (status == cachedTestXidStatus); /* - * compute the item pointer corresponding to the page containing our - * transaction id. We save the item in our cache to speed up things - * if we happen to ask for the same xid's status more than once. + * Also, check to see if the transaction ID is a permanent one. */ - TransComputeBlockNumber(LogRelation, transactionId, &blockNumber); - xidstatus = TransBlockNumberGetXidStatus(LogRelation, - blockNumber, - transactionId, - &fail); - - if (!fail) + if (! TransactionIdIsNormal(transactionId)) { - - /* - * DO NOT cache status for transactions in unknown state !!! - */ - if (xidstatus == XID_COMMIT || xidstatus == XID_ABORT) - { - TransactionIdStore(transactionId, &cachedTestXid); - cachedTestXidStatus = xidstatus; - } - return (bool) (status == xidstatus); + if (TransactionIdEquals(transactionId, BootstrapTransactionId)) + return (status == TRANSACTION_STATUS_COMMITTED); + if (TransactionIdEquals(transactionId, FrozenTransactionId)) + return (status == TRANSACTION_STATUS_COMMITTED); + return (status == TRANSACTION_STATUS_ABORTED); } /* - * here the block didn't contain the information we wanted + * Get the status. */ - elog(ERROR, "TransactionLogTest: failed to get xidstatus"); + xidstatus = TransactionIdGetStatus(transactionId); - /* - * so lint is happy... - */ - return false; + /* + * DO NOT cache status for unfinished transactions! + */ + if (xidstatus != TRANSACTION_STATUS_IN_PROGRESS) + { + TransactionIdStore(transactionId, &cachedTestXid); + cachedTestXidStatus = xidstatus; + } + + return (status == xidstatus); } /* -------------------------------- @@ -165,24 +99,10 @@ static void TransactionLogUpdate(TransactionId transactionId, /* trans id to update */ XidStatus status) /* new trans status */ { - BlockNumber blockNumber; - bool fail = false; /* success/failure */ - /* - * during initialization we don't record any updates. + * update the commit log */ - if (!RelationIsValid(LogRelation)) - return; - - /* - * update the log relation - */ - TransComputeBlockNumber(LogRelation, transactionId, &blockNumber); - TransBlockNumberSetXidStatus(LogRelation, - blockNumber, - transactionId, - status, - &fail); + TransactionIdSetStatus(transactionId, status); /* * update (invalidate) our single item TransactionLogTest cache. @@ -191,85 +111,21 @@ TransactionLogUpdate(TransactionId transactionId, /* trans id to update */ cachedTestXidStatus = status; } -/* ---------------------------------------------------------------- - * transaction recovery code - * ---------------------------------------------------------------- - */ - /* -------------------------------- - * TransRecover - * - * preform transaction recovery checking. - * - * Note: this should only be preformed if no other backends - * are running. This is known by the postmaster and - * conveyed by the postmaster passing a "do recovery checking" - * flag to the backend. - * - * here we get the last recorded transaction from the log, - * get the "last" and "next" transactions from the variable relation - * and then preform some integrity tests: - * - * 1) No transaction may exist higher then the "next" available - * transaction recorded in the variable relation. If this is the - * case then it means either the log or the variable relation - * has become corrupted. - * - * 2) The last committed transaction may not be higher then the - * next available transaction for the same reason. - * - * 3) The last recorded transaction may not be lower then the - * last committed transaction. (the reverse is ok - it means - * that some transactions have aborted since the last commit) - * - * Here is what the proper situation looks like. The line - * represents the data stored in the log. 'c' indicates the - * transaction was recorded as committed, 'a' indicates an - * abortted transaction and '.' represents information not - * recorded. These may correspond to in progress transactions. - * - * c c a c . . a . . . . . . . . . . - * | | - * last next - * - * Since "next" is only incremented by GetNewTransactionId() which - * is called when transactions are started. Hence if there - * are commits or aborts after "next", then it means we committed - * or aborted BEFORE we started the transaction. This is the - * rational behind constraint (1). - * - * Likewise, "last" should never greater then "next" for essentially - * the same reason - it would imply we committed before we started. - * This is the reasoning for (2). - * - * (3) implies we may never have a situation such as: + * AmiTransactionOverride * - * c c a c . . a c . . . . . . . . . - * | | - * last next - * - * where there is a 'c' greater then "last". - * - * Recovery checking is more difficult in the case where - * several backends are executing concurrently because the - * transactions may be executing in the other backends. - * So, we only do recovery stuff when the backend is explicitly - * passed a flag on the command line. + * This function is used to manipulate the bootstrap flag. * -------------------------------- */ -static void -TransRecover(Relation logRelation) +void +AmiTransactionOverride(bool flag) { + AMI_OVERRIDE = flag; } /* ---------------------------------------------------------------- * Interface functions * - * InitializeTransactionLog - * ======== - * this function (called near cinit) initializes - * the transaction log, time and variable relations. - * * TransactionId DidCommit * TransactionId DidAbort * TransactionId IsInProgress @@ -279,104 +135,13 @@ TransRecover(Relation logRelation) * * TransactionId Commit * TransactionId Abort - * TransactionId SetInProgress * ======== * these functions set the transaction status - * of the specified xid. TransactionIdCommit() also - * records the current time in the time relation - * and updates the variable relation counter. + * of the specified xid. * * ---------------------------------------------------------------- */ -/* - * InitializeTransactionLog - * Initializes transaction logging. - */ -void -InitializeTransactionLog(void) -{ - Relation logRelation; - MemoryContext oldContext; - - /* - * don't do anything during bootstrapping - */ - if (AMI_OVERRIDE) - return; - - /* - * disable the transaction system so the access methods don't - * interfere during initialization. - */ - OverrideTransactionSystem(true); - - /* - * make sure allocations occur within the top memory context so that - * our log management structures are protected from garbage collection - * at the end of every transaction. - */ - oldContext = MemoryContextSwitchTo(TopMemoryContext); - - /* - * first open the log and time relations (these are created by amiint - * so they are guaranteed to exist) - */ - logRelation = heap_openr(LogRelationName, NoLock); - - /* - * XXX TransactionLogUpdate requires that LogRelation is valid so we - * temporarily set it so we can initialize things properly. This could - * be done cleaner. - */ - LogRelation = logRelation; - - /* - * if we have a virgin database, we initialize the log relation by - * committing the BootstrapTransactionId and we initialize the - * variable relation by setting the next available transaction id to - * FirstNormalTransactionId. OID initialization happens as a side - * effect of bootstrapping in varsup.c. - */ - SpinAcquire(OidGenLockId); - if (!TransactionIdDidCommit(BootstrapTransactionId)) - { - TransactionLogUpdate(BootstrapTransactionId, XID_COMMIT); - Assert(!IsUnderPostmaster && - TransactionIdEquals(ShmemVariableCache->nextXid, - FirstNormalTransactionId)); - ShmemVariableCache->nextXid = FirstNormalTransactionId; - } - else if (RecoveryCheckingEnabled()) - { - - /* - * if we have a pre-initialized database and if the perform - * recovery checking flag was passed then we do our database - * integrity checking. - */ - TransRecover(logRelation); - } - LogRelation = (Relation) NULL; - SpinRelease(OidGenLockId); - - /* - * now re-enable the transaction system - */ - OverrideTransactionSystem(false); - - /* - * instantiate the global variables - */ - LogRelation = logRelation; - - /* - * restore the memory context to the previous context before we return - * from initialization. - */ - MemoryContextSwitchTo(oldContext); -} - /* -------------------------------- * TransactionId DidCommit * TransactionId DidAbort @@ -397,16 +162,15 @@ TransactionIdDidCommit(TransactionId transactionId) if (AMI_OVERRIDE) return true; - return TransactionLogTest(transactionId, XID_COMMIT); + return TransactionLogTest(transactionId, TRANSACTION_STATUS_COMMITTED); } /* - * TransactionIdDidAborted + * TransactionIdDidAbort * True iff transaction associated with the identifier did abort. * * Note: * Assumes transaction identifier is valid. - * XXX Is this unneeded? */ bool /* true if given transaction aborted */ TransactionIdDidAbort(TransactionId transactionId) @@ -414,7 +178,7 @@ TransactionIdDidAbort(TransactionId transactionId) if (AMI_OVERRIDE) return false; - return TransactionLogTest(transactionId, XID_ABORT); + return TransactionLogTest(transactionId, TRANSACTION_STATUS_ABORTED); } /* @@ -422,22 +186,22 @@ TransactionIdDidAbort(TransactionId transactionId) * PROC structures of all running backend. - vadim 11/26/96 * * Old comments: - * true if given transaction neither committed nor aborted - + * true if given transaction has neither committed nor aborted + */ +#ifdef NOT_USED bool TransactionIdIsInProgress(TransactionId transactionId) { if (AMI_OVERRIDE) return false; - return TransactionLogTest(transactionId, XID_INPROGRESS); + return TransactionLogTest(transactionId, TRANSACTION_STATUS_IN_PROGRESS); } - */ +#endif /* NOT_USED */ /* -------------------------------- * TransactionId Commit * TransactionId Abort - * TransactionId SetInProgress * -------------------------------- */ @@ -454,7 +218,7 @@ TransactionIdCommit(TransactionId transactionId) if (AMI_OVERRIDE) return; - TransactionLogUpdate(transactionId, XID_COMMIT); + TransactionLogUpdate(transactionId, TRANSACTION_STATUS_COMMITTED); } /* @@ -470,5 +234,5 @@ TransactionIdAbort(TransactionId transactionId) if (AMI_OVERRIDE) return; - TransactionLogUpdate(transactionId, XID_ABORT); + TransactionLogUpdate(transactionId, TRANSACTION_STATUS_ABORTED); } |