On Wed, Dec 9, 2009 at 10:51 AM, Fujii Masao <[email protected]> wrote:
> On Wed, Dec 9, 2009 at 10:12 AM, Tom Lane <[email protected]> wrote:
>> Fujii Masao <[email protected]> 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 ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers