diff options
Diffstat (limited to 'src/backend/access')
-rw-r--r-- | src/backend/access/heap/heapam.c | 34 | ||||
-rw-r--r-- | src/backend/access/heap/hio.c | 12 | ||||
-rw-r--r-- | src/backend/access/heap/tuptoaster.c | 4 | ||||
-rw-r--r-- | src/backend/access/nbtree/nbtinsert.c | 14 | ||||
-rw-r--r-- | src/backend/access/nbtree/nbtpage.c | 7 | ||||
-rw-r--r-- | src/backend/access/transam/xact.c | 180 | ||||
-rw-r--r-- | src/backend/access/transam/xlog.c | 18 |
7 files changed, 169 insertions, 100 deletions
diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c index 1abb938fdf8..e9f69476283 100644 --- a/src/backend/access/heap/heapam.c +++ b/src/backend/access/heap/heapam.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.143 2002/07/30 16:08:33 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.144 2002/08/06 02:36:33 tgl Exp $ * * * INTERFACE ROUTINES @@ -1155,6 +1155,7 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid) pgstat_count_heap_insert(&relation->pgstat_info); /* XLOG stuff */ + if (!relation->rd_istemp) { xl_heap_insert xlrec; xl_heap_header xlhdr; @@ -1204,6 +1205,12 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid) PageSetLSN(page, recptr); PageSetSUI(page, ThisStartUpID); } + else + { + /* No XLOG record, but still need to flag that XID exists on disk */ + MyXactMadeTempRelUpdate = true; + } + END_CRIT_SECTION(); LockBuffer(buffer, BUFFER_LOCK_UNLOCK); @@ -1323,12 +1330,15 @@ l1: } START_CRIT_SECTION(); + /* store transaction information of xact deleting the tuple */ tp.t_data->t_infomask &= ~(HEAP_XMAX_COMMITTED | HEAP_XMAX_INVALID | HEAP_MARKED_FOR_UPDATE); HeapTupleHeaderSetXmax(tp.t_data, GetCurrentTransactionId()); HeapTupleHeaderSetCmax(tp.t_data, cid); + /* XLOG stuff */ + if (!relation->rd_istemp) { xl_heap_delete xlrec; XLogRecPtr recptr; @@ -1351,12 +1361,17 @@ l1: PageSetLSN(dp, recptr); PageSetSUI(dp, ThisStartUpID); } + else + { + /* No XLOG record, but still need to flag that XID exists on disk */ + MyXactMadeTempRelUpdate = true; + } + END_CRIT_SECTION(); LockBuffer(buffer, BUFFER_LOCK_UNLOCK); #ifdef TUPLE_TOASTER_ACTIVE - /* * If the relation has toastable attributes, we need to delete no * longer needed items there too. We have to do this before @@ -1659,6 +1674,7 @@ l2: oldtup.t_data->t_ctid = newtup->t_self; /* XLOG stuff */ + if (!relation->rd_istemp) { XLogRecPtr recptr = log_heap_update(relation, buffer, oldtup.t_self, newbuf, newtup, false); @@ -1671,6 +1687,11 @@ l2: PageSetLSN(BufferGetPage(buffer), recptr); PageSetSUI(BufferGetPage(buffer), ThisStartUpID); } + else + { + /* No XLOG record, but still need to flag that XID exists on disk */ + MyXactMadeTempRelUpdate = true; + } END_CRIT_SECTION(); @@ -1927,6 +1948,9 @@ log_heap_clean(Relation reln, Buffer buffer, char *unused, int unlen) XLogRecPtr recptr; XLogRecData rdata[3]; + /* Caller should not call me on a temp relation */ + Assert(!reln->rd_istemp); + xlrec.node = reln->rd_node; xlrec.block = BufferGetBlockNumber(buffer); rdata[0].buffer = InvalidBuffer; @@ -1978,6 +2002,9 @@ log_heap_update(Relation reln, Buffer oldbuf, ItemPointerData from, Page page = BufferGetPage(newbuf); uint8 info = (move) ? XLOG_HEAP_MOVE : XLOG_HEAP_UPDATE; + /* Caller should not call me on a temp relation */ + Assert(!reln->rd_istemp); + xlrec.target.node = reln->rd_node; xlrec.target.tid = from; xlrec.newtid = newtup->t_self; @@ -2012,7 +2039,8 @@ log_heap_update(Relation reln, Buffer oldbuf, ItemPointerData from, xid[0] = HeapTupleHeaderGetXmax(newtup->t_data); xid[1] = HeapTupleHeaderGetXmin(newtup->t_data); memcpy((char *) &xlhdr + hsize, - (char *) xid, 2 * sizeof(TransactionId)); + (char *) xid, + 2 * sizeof(TransactionId)); hsize += 2 * sizeof(TransactionId); } rdata[2].buffer = newbuf; diff --git a/src/backend/access/heap/hio.c b/src/backend/access/heap/hio.c index 602ad748d9b..67eb4ad7e24 100644 --- a/src/backend/access/heap/hio.c +++ b/src/backend/access/heap/hio.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Id: hio.c,v 1.45 2002/06/20 20:29:25 momjian Exp $ + * $Id: hio.c,v 1.46 2002/08/06 02:36:33 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -102,6 +102,7 @@ RelationGetBufferForTuple(Relation relation, Size len, Size pageFreeSpace; BlockNumber targetBlock, otherBlock; + bool needLock; len = MAXALIGN(len); /* be conservative */ @@ -231,9 +232,12 @@ RelationGetBufferForTuple(Relation relation, Size len, * * We have to use a lock to ensure no one else is extending the rel at * the same time, else we will both try to initialize the same new - * page. + * page. We can skip locking for new or temp relations, however, + * since no one else could be accessing them. */ - if (!relation->rd_myxactonly) + needLock = !(relation->rd_isnew || relation->rd_istemp); + + if (needLock) LockPage(relation, 0, ExclusiveLock); /* @@ -249,7 +253,7 @@ RelationGetBufferForTuple(Relation relation, Size len, * Release the file-extension lock; it's now OK for someone else to * extend the relation some more. */ - if (!relation->rd_myxactonly) + if (needLock) UnlockPage(relation, 0, ExclusiveLock); /* diff --git a/src/backend/access/heap/tuptoaster.c b/src/backend/access/heap/tuptoaster.c index 2945cf3458c..1c09af2b308 100644 --- a/src/backend/access/heap/tuptoaster.c +++ b/src/backend/access/heap/tuptoaster.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/heap/tuptoaster.c,v 1.33 2002/07/20 05:16:56 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/heap/tuptoaster.c,v 1.34 2002/08/06 02:36:33 tgl Exp $ * * * INTERFACE ROUTINES @@ -915,7 +915,7 @@ toast_save_datum(Relation rel, Datum value) */ idxres = index_insert(toastidx, t_values, t_nulls, &(toasttup->t_self), - toastrel, toastidx->rd_uniqueindex); + toastrel, toastidx->rd_index->indisunique); if (idxres == NULL) elog(ERROR, "Failed to insert index entry for TOAST tuple"); diff --git a/src/backend/access/nbtree/nbtinsert.c b/src/backend/access/nbtree/nbtinsert.c index c0190859b7b..16d63e03c99 100644 --- a/src/backend/access/nbtree/nbtinsert.c +++ b/src/backend/access/nbtree/nbtinsert.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.94 2002/07/02 05:48:44 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.95 2002/08/06 02:36:33 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -623,8 +623,11 @@ _bt_insertuple(Relation rel, Buffer buf, BTPageOpaque pageop = (BTPageOpaque) PageGetSpecialPointer(page); START_CRIT_SECTION(); + _bt_pgaddtup(rel, page, itemsz, btitem, newitemoff, "page"); + /* XLOG stuff */ + if (!rel->rd_istemp) { xl_btree_insert xlrec; uint8 flag = XLOG_BTREE_INSERT; @@ -866,6 +869,9 @@ _bt_split(Relation rel, Buffer buf, OffsetNumber firstright, * NO ELOG(ERROR) till right sibling is updated. */ START_CRIT_SECTION(); + + /* XLOG stuff */ + if (!rel->rd_istemp) { xl_btree_split xlrec; int flag = (newitemonleft) ? @@ -891,7 +897,7 @@ _bt_split(Relation rel, Buffer buf, OffsetNumber firstright, BlockIdSet(&(xlrec.rightblk), ropaque->btpo_next); /* - * Dirrect access to page is not good but faster - we should + * Direct access to page is not good but faster - we should * implement some new func in page API. */ xlrec.leftlen = ((PageHeader) leftpage)->pd_special - @@ -1352,6 +1358,7 @@ _bt_newroot(Relation rel, Buffer lbuf, Buffer rbuf) (metad->btm_level)++; /* XLOG stuff */ + if (!rel->rd_istemp) { xl_btree_newroot xlrec; XLogRecPtr recptr; @@ -1366,7 +1373,7 @@ _bt_newroot(Relation rel, Buffer lbuf, Buffer rbuf) rdata[0].next = &(rdata[1]); /* - * Dirrect access to page is not good but faster - we should + * Direct access to page is not good but faster - we should * implement some new func in page API. */ rdata[1].buffer = InvalidBuffer; @@ -1388,6 +1395,7 @@ _bt_newroot(Relation rel, Buffer lbuf, Buffer rbuf) PageSetLSN(rpage, recptr); PageSetSUI(rpage, ThisStartUpID); } + END_CRIT_SECTION(); /* write and let go of metapage buffer */ diff --git a/src/backend/access/nbtree/nbtpage.c b/src/backend/access/nbtree/nbtpage.c index 386cb6a07a5..110de694066 100644 --- a/src/backend/access/nbtree/nbtpage.c +++ b/src/backend/access/nbtree/nbtpage.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtpage.c,v 1.57 2002/06/20 20:29:25 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtpage.c,v 1.58 2002/08/06 02:36:33 tgl Exp $ * * NOTES * Postgres btree pages look like ordinary relation pages. The opaque @@ -173,6 +173,7 @@ _bt_getroot(Relation rel, int access) rootopaque->btpo_flags |= (BTP_LEAF | BTP_ROOT); /* XLOG stuff */ + if (!rel->rd_istemp) { xl_btree_newroot xlrec; XLogRecPtr recptr; @@ -187,7 +188,8 @@ _bt_getroot(Relation rel, int access) rdata.next = NULL; recptr = XLogInsert(RM_BTREE_ID, - XLOG_BTREE_NEWROOT | XLOG_BTREE_LEAF, &rdata); + XLOG_BTREE_NEWROOT | XLOG_BTREE_LEAF, + &rdata); PageSetLSN(rootpage, recptr); PageSetSUI(rootpage, ThisStartUpID); @@ -457,6 +459,7 @@ _bt_itemdel(Relation rel, Buffer buf, ItemPointer tid) PageIndexTupleDelete(page, offno); /* XLOG stuff */ + if (!rel->rd_istemp) { xl_btree_delete xlrec; XLogRecPtr recptr; 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. |