On Wed, Dec 9, 2009 at 6:25 PM, Fujii Masao <masao.fu...@gmail.com> wrote: > 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.
Here's an updated version of my "New XLOG record indicating WAL-skipping" patch. http://archives.postgresql.org/pgsql-hackers/2009-12/msg00788.php This is rebased to CVS HEAD. 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 *************** *** 1976,1981 **** heap_insert(Relation relation, HeapTuple tup, CommandId cid, --- 1976,1988 ---- 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 *************** *** 560,565 **** XLogInsert(RmgrId rmid, uint8 info, XLogRecData *rdata) --- 560,566 ---- 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()) *************** *** 709,717 **** 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(); --- 710,718 ---- * 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(); *************** *** 3593,3600 **** 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) { --- 3594,3601 ---- 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) { *************** *** 3606,3611 **** got_record:; --- 3607,3622 ---- 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, *************** *** 3801,3806 **** got_record:; --- 3812,3830 ---- */ 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:; *************** *** 7204,7209 **** RequestXLogSwitch(void) --- 7228,7263 ---- } /* + * 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 *************** *** 7345,7350 **** xlog_redo(XLogRecPtr lsn, XLogRecord *record) --- 7399,7408 ---- LWLockRelease(ControlFileLock); } } + else if (info == XLOG_UNLOGGED) + { + /* nothing to do here */ + } } void *************** *** 7394,7399 **** xlog_desc(StringInfo buf, uint8 xl_info, char *rec) --- 7452,7461 ---- appendStringInfo(buf, "backup end: %X/%X", startpoint.xlogid, startpoint.xrecoff); } + 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 *************** *** 7050,7055 **** copy_relation_data(SMgrRelation src, SMgrRelation dst, --- 7050,7062 ---- */ 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 *************** *** 260,265 **** extern XLogRecPtr GetRedoRecPtr(void); --- 260,267 ---- 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 *************** *** 63,68 **** typedef struct CheckPoint --- 63,69 ---- #define XLOG_NEXTOID 0x30 #define XLOG_SWITCH 0x40 #define XLOG_BACKUP_END 0x50 + #define XLOG_UNLOGGED 0x60 /* 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