diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2002-08-06 02:36:35 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2002-08-06 02:36:35 +0000 |
commit | 5df307c7782518c4a3c19ffd05c7cb591b97e23c (patch) | |
tree | 0ff988dc5b7b115e9f6bbf29852dd4bad7fcaeea /src/backend/access/transam | |
parent | 35cd432b185938c33967c9fa48223ce33e1c66bd (diff) | |
download | postgresql-5df307c7782518c4a3c19ffd05c7cb591b97e23c.tar.gz postgresql-5df307c7782518c4a3c19ffd05c7cb591b97e23c.zip |
Restructure local-buffer handling per recent pghackers discussion.
The local buffer manager is no longer used for newly-created relations
(unless they are TEMP); a new non-TEMP relation goes through the shared
bufmgr and thus will participate normally in checkpoints. But TEMP relations
use the local buffer manager throughout their lifespan. Also, operations
in TEMP relations are not logged in WAL, thus improving performance.
Since it's no longer necessary to fsync relations as they move out of the
local buffers into shared buffers, quite a lot of smgr.c/md.c/fd.c code
is no longer needed and has been removed: there's no concept of a dirty
relation anymore in md.c/fd.c, and we never fsync anything but WAL.
Still TODO: improve local buffer management algorithms so that it would
be reasonable to increase NLocBuffer.
Diffstat (limited to 'src/backend/access/transam')
-rw-r--r-- | src/backend/access/transam/xact.c | 180 | ||||
-rw-r--r-- | src/backend/access/transam/xlog.c | 18 |
2 files changed, 112 insertions, 86 deletions
diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c index 3a992f6ccfe..c9b60daef56 100644 --- a/src/backend/access/transam/xact.c +++ b/src/backend/access/transam/xact.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.129 2002/08/02 22:36:05 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.130 2002/08/06 02:36:33 tgl Exp $ * * NOTES * Transaction aborts can now occur two ways: @@ -505,44 +505,32 @@ AtStart_Memory(void) * ---------------------------------------------------------------- */ -/* -------------------------------- +/* * RecordTransactionCommit - * - * Note: the two calls to BufferManagerFlush() exist to ensure - * that data pages are written before log pages. These - * explicit calls should be replaced by a more efficient - * ordered page write scheme in the buffer manager - * -cim 3/18/90 - * -------------------------------- */ void RecordTransactionCommit(void) { - TransactionId xid; - bool leak; - - leak = BufferPoolCheckLeak(); - - xid = GetCurrentTransactionId(); - /* - * We only need to log the commit in xlog and clog if the transaction made - * any transaction-controlled XLOG entries. (Otherwise, its XID appears - * nowhere in permanent storage, so no one will ever care if it - * committed.) However, we must flush XLOG to disk if we made any XLOG - * entries, whether in or out of transaction control. For example, if we - * reported a nextval() result to the client, this ensures that any XLOG - * record generated by nextval will hit the disk before we report the - * transaction committed. + * If we made neither any XLOG entries nor any temp-rel updates, + * we can omit recording the transaction commit at all. */ - if (MyXactMadeXLogEntry) + if (MyXactMadeXLogEntry || MyXactMadeTempRelUpdate) { + TransactionId xid = GetCurrentTransactionId(); XLogRecPtr recptr; + /* Tell bufmgr and smgr to prepare for commit */ BufmgrCommit(); START_CRIT_SECTION(); + /* + * We only need to log the commit in xlog if the transaction made any + * transaction-controlled XLOG entries. (Otherwise, its XID appears + * nowhere in permanent storage, so no one else will ever care if it + * committed.) + */ if (MyLastRecPtr.xrecoff != 0) { /* Need to emit a commit record */ @@ -567,30 +555,48 @@ RecordTransactionCommit(void) } /* - * Sleep before flush! So we can flush more than one commit - * records per single fsync. (The idea is some other backend may - * do the XLogFlush while we're sleeping. This needs work still, - * because on most Unixen, the minimum select() delay is 10msec or - * more, which is way too long.) - * - * We do not sleep if enableFsync is not turned on, nor if there are - * fewer than CommitSiblings other backends with active - * transactions. + * We must flush our XLOG entries to disk if we made any XLOG entries, + * whether in or out of transaction control. For example, if we + * reported a nextval() result to the client, this ensures that any + * XLOG record generated by nextval will hit the disk before we report + * the transaction committed. */ - if (CommitDelay > 0 && enableFsync && - CountActiveBackends() >= CommitSiblings) + if (MyXactMadeXLogEntry) { - struct timeval delay; + /* + * Sleep before flush! So we can flush more than one commit + * records per single fsync. (The idea is some other backend may + * do the XLogFlush while we're sleeping. This needs work still, + * because on most Unixen, the minimum select() delay is 10msec or + * more, which is way too long.) + * + * We do not sleep if enableFsync is not turned on, nor if there + * are fewer than CommitSiblings other backends with active + * transactions. + */ + if (CommitDelay > 0 && enableFsync && + CountActiveBackends() >= CommitSiblings) + { + struct timeval delay; - delay.tv_sec = 0; - delay.tv_usec = CommitDelay; - (void) select(0, NULL, NULL, NULL, &delay); - } + delay.tv_sec = 0; + delay.tv_usec = CommitDelay; + (void) select(0, NULL, NULL, NULL, &delay); + } - XLogFlush(recptr); + XLogFlush(recptr); + } - /* Mark the transaction committed in clog, if needed */ - if (MyLastRecPtr.xrecoff != 0) + /* + * We must mark the transaction committed in clog if its XID appears + * either in permanent rels or in local temporary rels. We test + * this by seeing if we made transaction-controlled entries *OR* + * local-rel tuple updates. Note that if we made only the latter, + * we have not emitted an XLOG record for our commit, and so in the + * event of a crash the clog update might be lost. This is okay + * because no one else will ever care whether we committed. + */ + if (MyLastRecPtr.xrecoff != 0 || MyXactMadeTempRelUpdate) TransactionIdCommit(xid); END_CRIT_SECTION(); @@ -599,12 +605,10 @@ RecordTransactionCommit(void) /* Break the chain of back-links in the XLOG records I output */ MyLastRecPtr.xrecoff = 0; MyXactMadeXLogEntry = false; + MyXactMadeTempRelUpdate = false; /* Show myself as out of the transaction in PGPROC array */ MyProc->logRec.xrecoff = 0; - - if (leak) - ResetBufferPool(true); } @@ -615,8 +619,10 @@ RecordTransactionCommit(void) static void AtCommit_Cache(void) { - /* Check for relcache reference-count leaks */ - AtEOXactRelationCache(true); + /* + * Clean up the relation cache. + */ + AtEOXact_RelationCache(true); /* * Make catalog changes visible to all backends. */ @@ -679,45 +685,60 @@ AtCommit_Memory(void) * ---------------------------------------------------------------- */ -/* -------------------------------- +/* * RecordTransactionAbort - * -------------------------------- */ static void RecordTransactionAbort(void) { - TransactionId xid = GetCurrentTransactionId(); - /* - * We only need to log the abort in xlog and clog if the transaction made - * any transaction-controlled XLOG entries. (Otherwise, its XID appears - * nowhere in permanent storage, so no one will ever care if it - * committed.) We do not flush XLOG to disk in any case, since the - * default assumption after a crash would be that we aborted, anyway. - * - * Extra check here is to catch case that we aborted partway through - * RecordTransactionCommit ... + * If we made neither any transaction-controlled XLOG entries nor any + * temp-rel updates, we can omit recording the transaction abort at all. + * No one will ever care that it aborted. */ - if (MyLastRecPtr.xrecoff != 0 && !TransactionIdDidCommit(xid)) + if (MyLastRecPtr.xrecoff != 0 || MyXactMadeTempRelUpdate) { - XLogRecData rdata; - xl_xact_abort xlrec; - XLogRecPtr recptr; + TransactionId xid = GetCurrentTransactionId(); - xlrec.xtime = time(NULL); - rdata.buffer = InvalidBuffer; - rdata.data = (char *) (&xlrec); - rdata.len = SizeOfXactAbort; - rdata.next = NULL; + /* + * Catch the scenario where we aborted partway through + * RecordTransactionCommit ... + */ + if (TransactionIdDidCommit(xid)) + elog(PANIC, "RecordTransactionAbort: xact %u already committed", + xid); START_CRIT_SECTION(); /* - * SHOULD SAVE ARRAY OF RELFILENODE-s TO DROP + * We only need to log the abort in XLOG if the transaction made any + * transaction-controlled XLOG entries. (Otherwise, its XID appears + * nowhere in permanent storage, so no one else will ever care if it + * committed.) We do not flush XLOG to disk in any case, since the + * default assumption after a crash would be that we aborted, anyway. */ - recptr = XLogInsert(RM_XACT_ID, XLOG_XACT_ABORT, &rdata); + if (MyLastRecPtr.xrecoff != 0) + { + XLogRecData rdata; + xl_xact_abort xlrec; + XLogRecPtr recptr; + + xlrec.xtime = time(NULL); + rdata.buffer = InvalidBuffer; + rdata.data = (char *) (&xlrec); + rdata.len = SizeOfXactAbort; + rdata.next = NULL; + + /* + * SHOULD SAVE ARRAY OF RELFILENODE-s TO DROP + */ + recptr = XLogInsert(RM_XACT_ID, XLOG_XACT_ABORT, &rdata); + } - /* Mark the transaction aborted in clog */ + /* + * Mark the transaction aborted in clog. This is not absolutely + * necessary but we may as well do it while we are here. + */ TransactionIdAbort(xid); END_CRIT_SECTION(); @@ -726,14 +747,10 @@ RecordTransactionAbort(void) /* Break the chain of back-links in the XLOG records I output */ MyLastRecPtr.xrecoff = 0; MyXactMadeXLogEntry = false; + MyXactMadeTempRelUpdate = false; /* Show myself as out of the transaction in PGPROC array */ MyProc->logRec.xrecoff = 0; - - /* - * Tell bufmgr and smgr to release resources. - */ - ResetBufferPool(false); /* false -> is abort */ } /* -------------------------------- @@ -743,7 +760,7 @@ RecordTransactionAbort(void) static void AtAbort_Cache(void) { - AtEOXactRelationCache(false); + AtEOXact_RelationCache(false); AtEOXactInvalidationMessages(false); } @@ -975,7 +992,6 @@ CommitTransaction(void) * noncritical resource releasing. */ - RelationPurgeLocalRelation(true); smgrDoPendingDeletes(true); AtEOXact_GUC(true); @@ -989,6 +1005,8 @@ CommitTransaction(void) AtCommit_Locks(); AtEOXact_CatCache(true); AtCommit_Memory(); + AtEOXact_Buffers(true); + smgrabort(); AtEOXact_Files(); /* Count transaction commit in statistics collector */ @@ -1076,7 +1094,6 @@ AbortTransaction(void) LWLockRelease(SInvalLock); } - RelationPurgeLocalRelation(false); smgrDoPendingDeletes(false); AtEOXact_GUC(false); @@ -1089,6 +1106,7 @@ AbortTransaction(void) AtAbort_Cache(); AtEOXact_CatCache(false); AtAbort_Memory(); + AtEOXact_Buffers(false); AtEOXact_Files(); AtAbort_Locks(); diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 872722b856c..fbe61e5691c 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Header: /cvsroot/pgsql/src/backend/access/transam/xlog.c,v 1.100 2002/08/05 01:24:13 thomas Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/transam/xlog.c,v 1.101 2002/08/06 02:36:33 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -136,11 +136,20 @@ bool InRecovery = false; * to be set true. The latter can be used to test whether the current xact * made any loggable changes (including out-of-xact changes, such as * sequence updates). + * + * When we insert/update/delete a tuple in a temporary relation, we do not + * make any XLOG record, since we don't care about recovering the state of + * the temp rel after a crash. However, we will still need to remember + * whether our transaction committed or aborted in that case. So, we must + * set MyXactMadeTempRelUpdate true to indicate that the XID will be of + * interest later. */ XLogRecPtr MyLastRecPtr = {0, 0}; bool MyXactMadeXLogEntry = false; +bool MyXactMadeTempRelUpdate = false; + /* * ProcLastRecPtr points to the start of the last XLOG record inserted by the * current backend. It is updated for all inserts, transaction-controlled @@ -2923,6 +2932,7 @@ ShutdownXLOG(void) /* suppress in-transaction check in CreateCheckPoint */ MyLastRecPtr.xrecoff = 0; MyXactMadeXLogEntry = false; + MyXactMadeTempRelUpdate = false; CritSectionCount++; CreateDummyCaches(); @@ -3084,12 +3094,10 @@ CreateCheckPoint(bool shutdown) /* * Having constructed the checkpoint record, ensure all shmem disk - * buffers are flushed to disk. + * buffers and commit-log buffers are flushed to disk. */ - FlushBufferPool(); - - /* And commit-log buffers, too */ CheckPointCLOG(); + FlushBufferPool(); /* * Now insert the checkpoint record into XLOG. |