From: Heikki Linnakangas Date: Wed, 20 Jan 2010 19:43:40 +0000 (+0000) Subject: Write a WAL record whenever we perform an operation without WAL-logging X-Git-Tag: REL9_0_ALPHA4~211 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=09b115f70684ea20dc344faab1a96f2831d3ee75;p=postgresql Write a WAL record whenever we perform an operation without WAL-logging that would've been WAL-logged if archiving was enabled. If we encounter such records in archive recovery anyway, we know that some data is missing from the log. A WARNING is emitted in that case. Original patch by Fujii Masao, with changes by me. --- diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c index 5cd4f005c6..ce661a8d1b 100644 --- a/src/backend/access/heap/heapam.c +++ b/src/backend/access/heap/heapam.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.282 2010/01/14 11:08:00 sriggs Exp $ + * $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.283 2010/01/20 19:43:40 heikki Exp $ * * * INTERFACE ROUTINES @@ -5074,10 +5074,16 @@ heap2_desc(StringInfo buf, uint8 xl_info, char *rec) void heap_sync(Relation rel) { + char reason[NAMEDATALEN + 30]; + /* temp tables never need fsync */ if (rel->rd_istemp) return; + snprintf(reason, sizeof(reason), "heap inserts on \"%s\"", + RelationGetRelationName(rel)); + XLogReportUnloggedStatement(reason); + /* main heap */ FlushRelationBuffers(rel); /* FlushRelationBuffers will have opened rd_smgr */ diff --git a/src/backend/access/nbtree/nbtsort.c b/src/backend/access/nbtree/nbtsort.c index 68747beae5..772215c181 100644 --- a/src/backend/access/nbtree/nbtsort.c +++ b/src/backend/access/nbtree/nbtsort.c @@ -59,7 +59,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtsort.c,v 1.122 2010/01/15 09:19:00 heikki Exp $ + * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtsort.c,v 1.123 2010/01/20 19:43:40 heikki Exp $ * *------------------------------------------------------------------------- */ @@ -215,6 +215,18 @@ _bt_leafbuild(BTSpool *btspool, BTSpool *btspool2) */ wstate.btws_use_wal = XLogIsNeeded() && !wstate.index->rd_istemp; + /* + * Write an XLOG UNLOGGED record if WAL-logging was skipped because + * WAL archiving is not enabled. + */ + if (!wstate.btws_use_wal && !wstate.index->rd_istemp) + { + char reason[NAMEDATALEN + 20]; + snprintf(reason, sizeof(reason), "b-tree build on \"%s\"", + RelationGetRelationName(wstate.index)); + XLogReportUnloggedStatement(reason); + } + /* reserve the metapage */ wstate.btws_pages_alloced = BTREE_METAPAGE + 1; wstate.btws_pages_written = 0; diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index a0dddcad81..a7ff66a6b8 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.358 2010/01/15 09:19:00 heikki Exp $ + * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.359 2010/01/20 19:43:40 heikki Exp $ * *------------------------------------------------------------------------- */ @@ -7561,6 +7561,31 @@ RequestXLogSwitch(void) return RecPtr; } +/* + * Write an XLOG UNLOGGED record, indicating that some operation was + * performed on data that we fsync()'d directly to disk, skipping + * WAL-logging. + * + * Such operations screw up archive recovery, so we complain if we see + * these records during archive recovery. That shouldn't happen in a + * correctly configured server, but you can induce it by temporarily + * disabling archiving and restarting, so it's good to at least get a + * warning of silent data loss in such cases. These records serve no + * other purpose and are simply ignored during crash recovery. + */ +void +XLogReportUnloggedStatement(char *reason) +{ + XLogRecData rdata; + + rdata.buffer = InvalidBuffer; + rdata.data = reason; + rdata.len = strlen(reason) + 1; + rdata.next = NULL; + + XLogInsert(RM_XLOG_ID, XLOG_UNLOGGED, &rdata); +} + /* * XLOG resource manager's routines * @@ -7703,6 +7728,19 @@ xlog_redo(XLogRecPtr lsn, XLogRecord *record) LWLockRelease(ControlFileLock); } } + else if (info == XLOG_UNLOGGED) + { + if (InArchiveRecovery) + { + /* + * Note: We don't print the reason string from the record, + * because that gets added as a line using xlog_desc() + */ + ereport(WARNING, + (errmsg("unlogged operation performed, data may be missing"), + errhint("This can happen if you temporarily disable archive_mode without taking a new base backup."))); + } + } } void @@ -7752,6 +7790,12 @@ xlog_desc(StringInfo buf, uint8 xl_info, char *rec) appendStringInfo(buf, "backup end: %X/%X", startpoint.xlogid, startpoint.xrecoff); } + else if (info == XLOG_UNLOGGED) + { + char *reason = rec; + + appendStringInfo(buf, "unlogged operation: %s", reason); + } else appendStringInfo(buf, "UNKNOWN"); } diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c index 913ba1681c..56d040590b 100644 --- a/src/backend/commands/cluster.c +++ b/src/backend/commands/cluster.c @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/cluster.c,v 1.193 2010/01/15 09:19:01 heikki Exp $ + * $PostgreSQL: pgsql/src/backend/commands/cluster.c,v 1.194 2010/01/20 19:43:40 heikki Exp $ * *------------------------------------------------------------------------- */ @@ -821,6 +821,18 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex, */ use_wal = XLogIsNeeded() && !NewHeap->rd_istemp; + /* + * Write an XLOG UNLOGGED record if WAL-logging was skipped because + * WAL archiving is not enabled. + */ + if (!use_wal && !NewHeap->rd_istemp) + { + char reason[NAMEDATALEN + 20]; + snprintf(reason, sizeof(reason), "CLUSTER on \"%s\"", + RelationGetRelationName(NewHeap)); + XLogReportUnloggedStatement(reason); + } + /* use_wal off requires rd_targblock be initially invalid */ Assert(NewHeap->rd_targblock == InvalidBlockNumber); diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 43d8c0c56b..0c5ccdcb45 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.316 2010/01/17 22:56:21 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.317 2010/01/20 19:43:40 heikki Exp $ * *------------------------------------------------------------------------- */ @@ -7015,6 +7015,19 @@ ATExecSetTableSpace(Oid tableOid, Oid newTableSpace) heap_close(pg_class, RowExclusiveLock); + /* + * Write an XLOG UNLOGGED record if WAL-logging was skipped because + * WAL archiving is not enabled. + */ + if (!XLogIsNeeded() && !rel->rd_istemp) + { + char reason[NAMEDATALEN + 40]; + snprintf(reason, sizeof(reason), "ALTER TABLE SET TABLESPACE on \"%s\"", + RelationGetRelationName(rel)); + + XLogReportUnloggedStatement(reason); + } + relation_close(rel, NoLock); /* Make sure the reltablespace change is visible */ @@ -7043,6 +7056,10 @@ copy_relation_data(SMgrRelation src, SMgrRelation dst, /* * We need to log the copied data in WAL iff WAL archiving/streaming is * enabled AND it's not a temp rel. + * + * Note: If you change the conditions here, update the conditions in + * ATExecSetTableSpace() for when an XLOG UNLOGGED record is written + * to match. */ use_wal = XLogIsNeeded() && !istemp; diff --git a/src/include/access/xlog.h b/src/include/access/xlog.h index d0cb6550b6..ca4d7f289a 100644 --- a/src/include/access/xlog.h +++ b/src/include/access/xlog.h @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/access/xlog.h,v 1.97 2010/01/16 00:04:41 tgl Exp $ + * $PostgreSQL: pgsql/src/include/access/xlog.h,v 1.98 2010/01/20 19:43:40 heikki Exp $ */ #ifndef XLOG_H #define XLOG_H @@ -278,6 +278,7 @@ extern void InitXLOGAccess(void); extern void CreateCheckPoint(int flags); extern bool CreateRestartPoint(int flags); extern void XLogPutNextOid(Oid nextOid); +extern void XLogReportUnloggedStatement(char *reason); extern XLogRecPtr GetRedoRecPtr(void); extern XLogRecPtr GetInsertRecPtr(void); extern XLogRecPtr GetWriteRecPtr(void); diff --git a/src/include/catalog/pg_control.h b/src/include/catalog/pg_control.h index bac3e2a7ee..f064ef4aca 100644 --- a/src/include/catalog/pg_control.h +++ b/src/include/catalog/pg_control.h @@ -8,7 +8,7 @@ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/catalog/pg_control.h,v 1.48 2010/01/04 12:50:50 heikki Exp $ + * $PostgreSQL: pgsql/src/include/catalog/pg_control.h,v 1.49 2010/01/20 19:43:40 heikki Exp $ * *------------------------------------------------------------------------- */ @@ -63,6 +63,7 @@ typedef struct CheckPoint #define XLOG_NEXTOID 0x30 #define XLOG_SWITCH 0x40 #define XLOG_BACKUP_END 0x50 +#define XLOG_UNLOGGED 0x60 /* System status indicator */