On Wed, Dec 9, 2009 at 10:51 AM, Fujii Masao <masao.fu...@gmail.com> wrote: > On Wed, Dec 9, 2009 at 10:12 AM, Tom Lane <t...@sss.pgh.pa.us> wrote: >> Fujii Masao <masao.fu...@gmail.com> writes: >>> Thought? Am I missing something? >> >> This seems terribly overdesigned. Just emit a warning when you see >> the "unlogged op" record and have done. > > Sounds quite simple. OK, I'll do so.
Here is the patch: - Write an XLOG UNLOGGED record in WAL if WAL-logging is skipped for only the reason that WAL archiving is not enabled and such record has not been written yet. - Cause archive recovery to end if an XLOG UNLOGGED record is found during it. I add this patch to the CommitFest 2010-01. Regards, -- Fujii Masao NIPPON TELEGRAPH AND TELEPHONE CORPORATION NTT Open Source Software Center
*** a/src/backend/access/heap/heapam.c --- b/src/backend/access/heap/heapam.c *************** *** 1972,1977 **** heap_insert(Relation relation, HeapTuple tup, CommandId cid, --- 1972,1984 ---- PageSetTLI(page, ThisTimeLineID); } + /* + * Write an XLOG UNLOGGED record if WAL-logging is skipped for the reason + * that WAL archiving is not enabled. + */ + if (options & HEAP_INSERT_SKIP_WAL && !relation->rd_istemp) + XLogSkipLogging(); + END_CRIT_SECTION(); UnlockReleaseBuffer(buffer); *** a/src/backend/access/nbtree/nbtsort.c --- b/src/backend/access/nbtree/nbtsort.c *************** *** 215,220 **** _bt_leafbuild(BTSpool *btspool, BTSpool *btspool2) --- 215,227 ---- */ wstate.btws_use_wal = XLogArchivingActive() && !wstate.index->rd_istemp; + /* + * Write an XLOG UNLOGGED record if WAL-logging is skipped for the reason + * that WAL archiving is not enabled. + */ + if (!XLogArchivingActive() && !wstate.index->rd_istemp) + XLogSkipLogging(); + /* reserve the metapage */ wstate.btws_pages_alloced = BTREE_METAPAGE + 1; wstate.btws_pages_written = 0; *** a/src/backend/access/transam/xlog.c --- b/src/backend/access/transam/xlog.c *************** *** 550,555 **** XLogInsert(RmgrId rmid, uint8 info, XLogRecData *rdata) --- 550,556 ---- bool updrqst; bool doPageWrites; bool isLogSwitch = (rmid == RM_XLOG_ID && info == XLOG_SWITCH); + bool isLogUnlogged = (rmid == RM_XLOG_ID && info == XLOG_UNLOGGED); /* cross-check on whether we should be here or not */ if (!XLogInsertAllowed()) *************** *** 699,707 **** begin:; * error checking in ReadRecord. This means that all callers of * XLogInsert must supply at least some not-in-a-buffer data. However, we * make an exception for XLOG SWITCH records because we don't want them to ! * ever cross a segment boundary. */ ! if (len == 0 && !isLogSwitch) elog(PANIC, "invalid xlog record length %u", len); START_CRIT_SECTION(); --- 700,708 ---- * error checking in ReadRecord. This means that all callers of * XLogInsert must supply at least some not-in-a-buffer data. However, we * make an exception for XLOG SWITCH records because we don't want them to ! * ever cross a segment boundary. Also XLOG UNLOGGED records are exception. */ ! if (len == 0 && !isLogSwitch && !isLogUnlogged) elog(PANIC, "invalid xlog record length %u", len); START_CRIT_SECTION(); *************** *** 3551,3558 **** ReadRecord(XLogRecPtr *RecPtr, int emode) got_record:; /* ! * xl_len == 0 is bad data for everything except XLOG SWITCH, where it is ! * required. */ if (record->xl_rmid == RM_XLOG_ID && record->xl_info == XLOG_SWITCH) { --- 3552,3559 ---- got_record:; /* ! * xl_len == 0 is bad data for everything except XLOG SWITCH and XLOG UNLOGGED, ! * where it is required. */ if (record->xl_rmid == RM_XLOG_ID && record->xl_info == XLOG_SWITCH) { *************** *** 3564,3569 **** got_record:; --- 3565,3580 ---- goto next_record_is_invalid; } } + else if (record->xl_rmid == RM_XLOG_ID && record->xl_info == XLOG_UNLOGGED) + { + if (record->xl_len != 0) + { + ereport(emode, + (errmsg("invalid xlog unlogged operation record at %X/%X", + RecPtr->xlogid, RecPtr->xrecoff))); + goto next_record_is_invalid; + } + } else if (record->xl_len == 0) { ereport(emode, *************** *** 3759,3764 **** got_record:; --- 3770,3788 ---- */ readOff = XLogSegSize - XLOG_BLCKSZ; } + + /* + * Special processing if it's an XLOG UNLOGGED record and we are doing + * an archive recovery. + */ + if (record->xl_rmid == RM_XLOG_ID && record->xl_info == XLOG_UNLOGGED && + InArchiveRecovery) + { + ereport(emode, + (errmsg("unlogged operation record is found at %X/%X", + RecPtr->xlogid, RecPtr->xrecoff))); + goto next_record_is_invalid; + } return (XLogRecord *) buffer; next_record_is_invalid:; *************** *** 6998,7003 **** RequestXLogSwitch(void) --- 7022,7057 ---- } /* + * Write an XLOG UNLOGGED record. + */ + void + XLogSkipLogging(void) + { + XLogRecData rdata; + static bool skipped = false; + + /* + * If an XLOG UNLOGGED record has already been written since + * postmaster has started, we need to do nothing here. + * + * We can reduce the number of an XLOG UNLOGGED records written + * by sharing the flag 'skipped' between backends. But this is + * not worthwhile. + */ + if (skipped) + return; + skipped = true; + + /* XLOG UNLOGGED, alone among xlog record types, has no data */ + rdata.buffer = InvalidBuffer; + rdata.data = NULL; + rdata.len = 0; + rdata.next = NULL; + + XLogInsert(RM_XLOG_ID, XLOG_UNLOGGED, &rdata); + } + + /* * XLOG resource manager's routines * * Definitions of info values are in include/catalog/pg_control.h, though *************** *** 7100,7105 **** xlog_redo(XLogRecPtr lsn, XLogRecord *record) --- 7154,7163 ---- { /* nothing to do here */ } + else if (info == XLOG_UNLOGGED) + { + /* nothing to do here */ + } } void *************** *** 7140,7145 **** xlog_desc(StringInfo buf, uint8 xl_info, char *rec) --- 7198,7207 ---- { appendStringInfo(buf, "xlog switch"); } + else if (info == XLOG_UNLOGGED) + { + appendStringInfo(buf, "xlog unlogged"); + } else appendStringInfo(buf, "UNKNOWN"); } *** a/src/backend/commands/cluster.c --- b/src/backend/commands/cluster.c *************** *** 801,806 **** copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex) --- 801,813 ---- */ use_wal = XLogArchivingActive() && !NewHeap->rd_istemp; + /* + * Write an XLOG UNLOGGED record if WAL-logging is skipped for the reason + * that WAL archiving is not enabled. + */ + if (!XLogArchivingActive() && !NewHeap->rd_istemp) + XLogSkipLogging(); + /* use_wal off requires rd_targblock be initially invalid */ Assert(NewHeap->rd_targblock == InvalidBlockNumber); *** a/src/backend/commands/tablecmds.c --- b/src/backend/commands/tablecmds.c *************** *** 7109,7114 **** copy_relation_data(SMgrRelation src, SMgrRelation dst, --- 7109,7121 ---- */ use_wal = XLogArchivingActive() && !istemp; + /* + * Write an XLOG UNLOGGED record if WAL-logging is skipped for the reason + * that WAL archiving is not enabled. + */ + if (!XLogArchivingActive() && !istemp) + XLogSkipLogging(); + nblocks = smgrnblocks(src, forkNum); for (blkno = 0; blkno < nblocks; blkno++) *** a/src/include/access/xlog.h --- b/src/include/access/xlog.h *************** *** 218,223 **** extern XLogRecPtr GetRedoRecPtr(void); --- 218,225 ---- extern XLogRecPtr GetInsertRecPtr(void); extern void GetNextXidAndEpoch(TransactionId *xid, uint32 *epoch); + extern void XLogSkipLogging(void); + extern void StartupProcessMain(void); #endif /* XLOG_H */ *** a/src/include/catalog/pg_control.h --- b/src/include/catalog/pg_control.h *************** *** 48,53 **** typedef struct CheckPoint --- 48,54 ---- #define XLOG_NOOP 0x20 #define XLOG_NEXTOID 0x30 #define XLOG_SWITCH 0x40 + #define XLOG_UNLOGGED 0x50 /* System status indicator */
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers