On Wed, Dec 9, 2009 at 6:25 PM, Fujii Masao <[email protected]> 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 ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers