aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/access/heap/rewriteheap.c12
-rw-r--r--src/backend/access/nbtree/nbtsort.c15
-rw-r--r--src/backend/access/transam/xlog.c210
-rw-r--r--src/backend/commands/cluster.c19
-rw-r--r--src/backend/commands/copy.c9
-rw-r--r--src/backend/commands/tablecmds.c27
-rw-r--r--src/backend/executor/execMain.c9
-rw-r--r--src/backend/postmaster/postmaster.c8
-rw-r--r--src/backend/replication/walsender.c20
-rw-r--r--src/backend/storage/ipc/standby.c4
-rw-r--r--src/backend/utils/misc/guc.c14
-rw-r--r--src/backend/utils/misc/postgresql.conf.sample1
-rw-r--r--src/bin/pg_controldata/pg_controldata.c28
-rw-r--r--src/bin/pg_resetxlog/pg_resetxlog.c11
-rw-r--r--src/include/access/xlog.h27
-rw-r--r--src/include/access/xlog_internal.h4
-rw-r--r--src/include/catalog/pg_control.h21
-rw-r--r--src/include/replication/walsender.h3
18 files changed, 261 insertions, 181 deletions
diff --git a/src/backend/access/heap/rewriteheap.c b/src/backend/access/heap/rewriteheap.c
index 5c60c1f130d..e35fbeb9b1a 100644
--- a/src/backend/access/heap/rewriteheap.c
+++ b/src/backend/access/heap/rewriteheap.c
@@ -96,7 +96,7 @@
* Portions Copyright (c) 1994-5, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/heap/rewriteheap.c,v 1.21 2010/02/26 02:00:33 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/access/heap/rewriteheap.c,v 1.22 2010/04/28 16:10:40 heikki Exp $
*
*-------------------------------------------------------------------------
*/
@@ -278,16 +278,6 @@ end_heap_rewrite(RewriteState state)
(char *) state->rs_buffer, true);
}
- /* Write an XLOG UNLOGGED record if WAL-logging was skipped */
- if (!state->rs_use_wal && !state->rs_new_rel->rd_istemp)
- {
- char reason[NAMEDATALEN + 30];
-
- snprintf(reason, sizeof(reason), "heap rewrite on \"%s\"",
- RelationGetRelationName(state->rs_new_rel));
- XLogReportUnloggedStatement(reason);
- }
-
/*
* If the rel isn't temp, must fsync before commit. We use heap_sync to
* ensure that the toast table gets fsync'd too.
diff --git a/src/backend/access/nbtree/nbtsort.c b/src/backend/access/nbtree/nbtsort.c
index 84540b73530..15964e127e5 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.124 2010/02/26 02:00:34 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtsort.c,v 1.125 2010/04/28 16:10:40 heikki Exp $
*
*-------------------------------------------------------------------------
*/
@@ -215,19 +215,6 @@ _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 6812cf5e9a4..2d3dab39fe5 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.404 2010/04/27 09:25:18 heikki Exp $
+ * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.405 2010/04/28 16:10:40 heikki Exp $
*
*-------------------------------------------------------------------------
*/
@@ -76,6 +76,7 @@ int MaxStandbyDelay = 30;
bool fullPageWrites = true;
bool log_checkpoints = false;
int sync_method = DEFAULT_SYNC_METHOD;
+int wal_level = WAL_LEVEL_MINIMAL;
#ifdef WAL_DEBUG
bool XLOG_DEBUG = false;
@@ -97,6 +98,13 @@ bool XLOG_DEBUG = false;
/*
* GUC support
*/
+const struct config_enum_entry wal_level_options[] = {
+ {"minimal", WAL_LEVEL_MINIMAL, false},
+ {"archive", WAL_LEVEL_ARCHIVE, false},
+ {"hot_standby", WAL_LEVEL_HOT_STANDBY, false},
+ {NULL, 0, false}
+};
+
const struct config_enum_entry sync_method_options[] = {
{"fsync", SYNC_METHOD_FSYNC, false},
#ifdef HAVE_FSYNC_WRITETHROUGH
@@ -501,6 +509,18 @@ static bool reachedMinRecoveryPoint = false;
static bool InRedo = false;
/*
+ * Information logged when we detect a change in one of the parameters
+ * important for Hot Standby.
+ */
+typedef struct xl_parameter_change
+{
+ int MaxConnections;
+ int max_prepared_xacts;
+ int max_locks_per_xact;
+ int wal_level;
+} xl_parameter_change;
+
+/*
* Flags set by interrupt handlers for later service in the redo loop.
*/
static volatile sig_atomic_t got_SIGHUP = false;
@@ -522,7 +542,8 @@ static void readRecoveryCommandFile(void);
static void exitArchiveRecovery(TimeLineID endTLI,
uint32 endLogId, uint32 endLogSeg);
static bool recoveryStopsHere(XLogRecord *record, bool *includeThis);
-static void CheckRequiredParameterValues(CheckPoint checkPoint);
+static void CheckRequiredParameterValues(void);
+static void XLogReportParameters(void);
static void LocalSetXLogInsertAllowed(void);
static void CheckPointGuts(XLogRecPtr checkPointRedo, int flags);
@@ -4922,6 +4943,13 @@ BootStrapXLOG(void)
ControlFile->time = checkPoint.time;
ControlFile->checkPoint = checkPoint.redo;
ControlFile->checkPointCopy = checkPoint;
+
+ /* Set important parameter values for use when replaying WAL */
+ ControlFile->MaxConnections = MaxConnections;
+ ControlFile->max_prepared_xacts = max_prepared_xacts;
+ ControlFile->max_locks_per_xact = max_locks_per_xact;
+ ControlFile->wal_level = wal_level;
+
/* some additional ControlFile fields are set in WriteControlFile() */
WriteControlFile();
@@ -5539,17 +5567,18 @@ GetLatestXLogTime(void)
}
/*
- * Note that text field supplied is a parameter name and does not require translation
+ * Note that text field supplied is a parameter name and does not require
+ * translation
*/
-#define RecoveryRequiresIntParameter(param_name, currValue, checkpointValue) \
+#define RecoveryRequiresIntParameter(param_name, currValue, minValue) \
{ \
- if (currValue < checkpointValue) \
+ if (currValue < minValue) \
ereport(ERROR, \
(errmsg("recovery connections cannot continue because " \
"%s = %u is a lower setting than on WAL source server (value was %u)", \
param_name, \
currValue, \
- checkpointValue))); \
+ minValue))); \
}
/*
@@ -5557,21 +5586,37 @@ GetLatestXLogTime(void)
* for various aspects of recovery operation.
*/
static void
-CheckRequiredParameterValues(CheckPoint checkPoint)
+CheckRequiredParameterValues(void)
{
- /* We ignore autovacuum_max_workers when we make this test. */
- RecoveryRequiresIntParameter("max_connections",
- MaxConnections, checkPoint.MaxConnections);
+ /*
+ * For archive recovery, the WAL must be generated with at least
+ * 'archive' wal_level.
+ */
+ if (InArchiveRecovery && ControlFile->wal_level == WAL_LEVEL_MINIMAL)
+ {
+ ereport(WARNING,
+ (errmsg("WAL was generated with wal_level='minimal', data may be missing"),
+ errhint("This happens if you temporarily set wal_level='minimal' without taking a new base backup.")));
+ }
- RecoveryRequiresIntParameter("max_prepared_xacts",
- max_prepared_xacts, checkPoint.max_prepared_xacts);
- RecoveryRequiresIntParameter("max_locks_per_xact",
- max_locks_per_xact, checkPoint.max_locks_per_xact);
+ /*
+ * For Hot Standby, the WAL must be generated with 'hot_standby' mode,
+ * and we must have at least as many backend slots as the primary.
+ */
+ if (InArchiveRecovery && XLogRequestRecoveryConnections)
+ {
+ if (ControlFile->wal_level < WAL_LEVEL_HOT_STANDBY)
+ ereport(ERROR,
+ (errmsg("recovery connections cannot start because wal_level was not set to 'hot_standby' on the WAL source server")));
- if (!checkPoint.XLogStandbyInfoMode)
- ereport(ERROR,
- (errmsg("recovery connections cannot start because the recovery_connections "
- "parameter is disabled on the WAL source server")));
+ /* We ignore autovacuum_max_workers when we make this test. */
+ RecoveryRequiresIntParameter("max_connections",
+ MaxConnections, ControlFile->MaxConnections);
+ RecoveryRequiresIntParameter("max_prepared_xacts",
+ max_prepared_xacts, ControlFile->max_prepared_xacts);
+ RecoveryRequiresIntParameter("max_locks_per_xact",
+ max_locks_per_xact, ControlFile->max_locks_per_xact);
+ }
}
/*
@@ -5904,6 +5949,9 @@ StartupXLOG(void)
BACKUP_LABEL_FILE, BACKUP_LABEL_OLD)));
}
+ /* Check that the GUCs used to generate the WAL allow recovery */
+ CheckRequiredParameterValues();
+
/*
* Initialize recovery connections, if enabled. We won't let backends
* in yet, not until we've reached the min recovery point specified in
@@ -5915,8 +5963,6 @@ StartupXLOG(void)
TransactionId *xids;
int nxids;
- CheckRequiredParameterValues(checkPoint);
-
ereport(DEBUG1,
(errmsg("initializing recovery connections")));
@@ -6401,6 +6447,13 @@ StartupXLOG(void)
}
/*
+ * If any of the critical GUCs have changed, log them before we allow
+ * backends to write WAL.
+ */
+ LocalSetXLogInsertAllowed();
+ XLogReportParameters();
+
+ /*
* All done. Allow backends to write WAL. (Although the bool flag is
* probably atomic in itself, we use the info_lck here to ensure that
* there are no race conditions concerning visibility of other recent
@@ -6998,12 +7051,6 @@ CreateCheckPoint(int flags)
MemSet(&checkPoint, 0, sizeof(checkPoint));
checkPoint.time = (pg_time_t) time(NULL);
- /* Set important parameter values for use when replaying WAL */
- checkPoint.MaxConnections = MaxConnections;
- checkPoint.max_prepared_xacts = max_prepared_xacts;
- checkPoint.max_locks_per_xact = max_locks_per_xact;
- checkPoint.XLogStandbyInfoMode = XLogStandbyInfoActive();
-
/*
* We must hold WALInsertLock while examining insert state to determine
* the checkpoint REDO pointer.
@@ -7647,28 +7694,49 @@ RequestXLogSwitch(void)
}
/*
- * 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.
+ * Check if any of the GUC parameters that are critical for hot standby
+ * have changed, and update the value in pg_control file if necessary.
*/
-void
-XLogReportUnloggedStatement(char *reason)
+static void
+XLogReportParameters(void)
{
- XLogRecData rdata;
+ if (wal_level != ControlFile->wal_level ||
+ MaxConnections != ControlFile->MaxConnections ||
+ max_prepared_xacts != ControlFile->max_prepared_xacts ||
+ max_locks_per_xact != max_locks_per_xact)
+ {
+ /*
+ * The change in number of backend slots doesn't need to be
+ * WAL-logged if archiving is not enabled, as you can't start
+ * archive recovery with wal_level='minimal' anyway. We don't
+ * really care about the values in pg_control either if
+ * wal_level='minimal', but seems better to keep them up-to-date
+ * to avoid confusion.
+ */
+ if (wal_level != ControlFile->wal_level || XLogIsNeeded())
+ {
+ XLogRecData rdata;
+ xl_parameter_change xlrec;
- rdata.buffer = InvalidBuffer;
- rdata.data = reason;
- rdata.len = strlen(reason) + 1;
- rdata.next = NULL;
+ xlrec.MaxConnections = MaxConnections;
+ xlrec.max_prepared_xacts = max_prepared_xacts;
+ xlrec.max_locks_per_xact = max_locks_per_xact;
+ xlrec.wal_level = wal_level;
+
+ rdata.buffer = InvalidBuffer;
+ rdata.data = (char *) &xlrec;
+ rdata.len = sizeof(xlrec);
+ rdata.next = NULL;
+
+ XLogInsert(RM_XLOG_ID, XLOG_PARAMETER_CHANGE, &rdata);
+ }
- XLogInsert(RM_XLOG_ID, XLOG_UNLOGGED, &rdata);
+ ControlFile->MaxConnections = MaxConnections;
+ ControlFile->max_prepared_xacts = max_prepared_xacts;
+ ControlFile->max_locks_per_xact = max_locks_per_xact;
+ ControlFile->wal_level = wal_level;
+ UpdateControlFile();
+ }
}
/*
@@ -7709,10 +7777,6 @@ xlog_redo(XLogRecPtr lsn, XLogRecord *record)
checkPoint.nextMultiOffset);
SetTransactionIdLimit(checkPoint.oldestXid, checkPoint.oldestXidDB);
- /* Check to see if any changes to max_connections give problems */
- if (standbyState != STANDBY_DISABLED)
- CheckRequiredParameterValues(checkPoint);
-
/*
* If we see a shutdown checkpoint while waiting for an
* end-of-backup record, the backup was cancelled and the
@@ -7844,18 +7908,21 @@ xlog_redo(XLogRecPtr lsn, XLogRecord *record)
LWLockRelease(ControlFileLock);
}
}
- else if (info == XLOG_UNLOGGED)
+ else if (info == XLOG_PARAMETER_CHANGE)
{
- 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.")));
- }
+ xl_parameter_change xlrec;
+
+ /* Update our copy of the parameters in pg_control */
+ memcpy(&xlrec, XLogRecGetData(record), sizeof(xl_parameter_change));
+
+ ControlFile->MaxConnections = xlrec.MaxConnections;
+ ControlFile->max_prepared_xacts = xlrec.max_prepared_xacts;
+ ControlFile->max_locks_per_xact = xlrec.max_locks_per_xact;
+ ControlFile->wal_level = xlrec.wal_level;
+ UpdateControlFile();
+
+ /* Check to see if any changes to max_connections give problems */
+ CheckRequiredParameterValues();
}
}
@@ -7906,11 +7973,30 @@ xlog_desc(StringInfo buf, uint8 xl_info, char *rec)
appendStringInfo(buf, "backup end: %X/%X",
startpoint.xlogid, startpoint.xrecoff);
}
- else if (info == XLOG_UNLOGGED)
+ else if (info == XLOG_PARAMETER_CHANGE)
{
- char *reason = rec;
+ xl_parameter_change xlrec;
+ const char *wal_level_str;
+ const struct config_enum_entry *entry;
+
+ memcpy(&xlrec, rec, sizeof(xl_parameter_change));
+
+ /* Find a string representation for wal_level */
+ wal_level_str = "?";
+ for (entry = wal_level_options; entry->name; entry++)
+ {
+ if (entry->val == xlrec.wal_level)
+ {
+ wal_level_str = entry->name;
+ break;
+ }
+ }
- appendStringInfo(buf, "unlogged operation: %s", reason);
+ appendStringInfo(buf, "parameter change: max_connections=%d max_prepared_xacts=%d max_locks_per_xact=%d wal_level=%s",
+ xlrec.MaxConnections,
+ xlrec.max_prepared_xacts,
+ xlrec.max_locks_per_xact,
+ wal_level_str);
}
else
appendStringInfo(buf, "UNKNOWN");
diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c
index 78df9a8da85..7a1b8e885be 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.202 2010/02/26 02:00:37 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/cluster.c,v 1.203 2010/04/28 16:10:41 heikki Exp $
*
*-------------------------------------------------------------------------
*/
@@ -787,23 +787,6 @@ 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 + 32];
-
- if (OldIndex != NULL)
- snprintf(reason, sizeof(reason), "CLUSTER on \"%s\"",
- RelationGetRelationName(NewHeap));
- else
- snprintf(reason, sizeof(reason), "VACUUM FULL on \"%s\"",
- RelationGetRelationName(NewHeap));
- XLogReportUnloggedStatement(reason);
- }
-
/* use_wal off requires smgr_targblock be initially invalid */
Assert(RelationGetTargetBlock(NewHeap) == InvalidBlockNumber);
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 9031cd1fa51..4e95a8315ce 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.326 2010/02/26 02:00:38 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.327 2010/04/28 16:10:41 heikki Exp $
*
*-------------------------------------------------------------------------
*/
@@ -2223,14 +2223,7 @@ CopyFrom(CopyState cstate)
* indexes since those use WAL anyway)
*/
if (hi_options & HEAP_INSERT_SKIP_WAL)
- {
- char reason[NAMEDATALEN + 30];
-
- snprintf(reason, sizeof(reason), "COPY FROM on \"%s\"",
- RelationGetRelationName(cstate->rel));
- XLogReportUnloggedStatement(reason);
heap_sync(cstate->rel);
- }
}
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index dda0b2e847e..18e2f571283 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.329 2010/03/20 00:43:42 rhaas Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.330 2010/04/28 16:10:41 heikki Exp $
*
*-------------------------------------------------------------------------
*/
@@ -3272,14 +3272,7 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap)
/* If we skipped writing WAL, then we need to sync the heap. */
if (hi_options & HEAP_INSERT_SKIP_WAL)
- {
- char reason[NAMEDATALEN + 30];
-
- snprintf(reason, sizeof(reason), "table rewrite on \"%s\"",
- RelationGetRelationName(newrel));
- XLogReportUnloggedStatement(reason);
heap_sync(newrel);
- }
heap_close(newrel, NoLock);
}
@@ -7021,20 +7014,6 @@ 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 */
@@ -7063,10 +7042,6 @@ 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/backend/executor/execMain.c b/src/backend/executor/execMain.c
index 151299555cf..0b6cbcc4af0 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -26,7 +26,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.348 2010/02/26 02:00:41 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.349 2010/04/28 16:10:42 heikki Exp $
*
*-------------------------------------------------------------------------
*/
@@ -2241,14 +2241,7 @@ CloseIntoRel(QueryDesc *queryDesc)
/* If we skipped using WAL, must heap_sync before commit */
if (myState->hi_options & HEAP_INSERT_SKIP_WAL)
- {
- char reason[NAMEDATALEN + 30];
-
- snprintf(reason, sizeof(reason), "SELECT INTO on \"%s\"",
- RelationGetRelationName(myState->rel));
- XLogReportUnloggedStatement(reason);
heap_sync(myState->rel);
- }
/* close rel, but keep lock until commit */
heap_close(myState->rel, NoLock);
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index d77ffd07438..f5396df0668 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -37,7 +37,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.605 2010/04/08 01:39:37 rhaas Exp $
+ * $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.606 2010/04/28 16:10:42 heikki Exp $
*
* NOTES
*
@@ -728,6 +728,12 @@ PostmasterMain(int argc, char *argv[])
write_stderr("%s: superuser_reserved_connections must be less than max_connections\n", progname);
ExitPostmaster(1);
}
+ if (XLogArchiveMode && wal_level == WAL_LEVEL_MINIMAL)
+ ereport(ERROR,
+ (errmsg("WAL archival (archive_mode='on') requires wal_level 'archive' or 'hot_standby'")));
+ if (max_wal_senders > 0 && wal_level == WAL_LEVEL_MINIMAL)
+ ereport(ERROR,
+ (errmsg("WAL streaming (max_wal_senders > 0) requires wal_level 'archive' or 'hot_standby")));
/*
* Other one-time internal sanity checks can go here, if they are fast.
diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c
index 1c1e9f17d2d..6c41844b5f8 100644
--- a/src/backend/replication/walsender.c
+++ b/src/backend/replication/walsender.c
@@ -30,7 +30,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/replication/walsender.c,v 1.17 2010/04/21 00:51:56 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/replication/walsender.c,v 1.18 2010/04/28 16:10:42 heikki Exp $
*
*-------------------------------------------------------------------------
*/
@@ -253,6 +253,24 @@ WalSndHandshake(void)
{
StringInfoData buf;
+ /*
+ * Check that we're logging enough information in the
+ * WAL for log-shipping.
+ *
+ * NOTE: This only checks the current value of
+ * wal_level. Even if the current setting is not
+ * 'minimal', there can be old WAL in the pg_xlog
+ * directory that was created with 'minimal'.
+ * So this is not bulletproof, the purpose is
+ * just to give a user-friendly error message that
+ * hints how to configure the system correctly.
+ */
+ if (wal_level == WAL_LEVEL_MINIMAL)
+ ereport(FATAL,
+ (errcode(ERRCODE_CANNOT_CONNECT_NOW),
+ errmsg("standby connections not allowed because wal_level='minimal'")));
+
+
/* Send a CopyOutResponse message, and start streaming */
pq_beginmessage(&buf, 'H');
pq_sendbyte(&buf, 0);
diff --git a/src/backend/storage/ipc/standby.c b/src/backend/storage/ipc/standby.c
index e8a4fc2e938..30723327cd2 100644
--- a/src/backend/storage/ipc/standby.c
+++ b/src/backend/storage/ipc/standby.c
@@ -11,7 +11,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/storage/ipc/standby.c,v 1.19 2010/04/23 23:21:44 rhaas Exp $
+ * $PostgreSQL: pgsql/src/backend/storage/ipc/standby.c,v 1.20 2010/04/28 16:10:42 heikki Exp $
*
*-------------------------------------------------------------------------
*/
@@ -256,7 +256,7 @@ ResolveRecoveryConflictWithSnapshot(TransactionId latestRemovedXid, RelFileNode
*/
if (!TransactionIdIsValid(latestRemovedXid))
{
- elog(DEBUG1, "Invalid latestremovexXid reported, using latestcompletedxid instead");
+ elog(DEBUG1, "invalid latestremovexXid reported, using latestcompletedxid instead");
LWLockAcquire(ProcArrayLock, LW_SHARED);
latestRemovedXid = ShmemVariableCache->latestCompletedXid;
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index e7266d5fb10..2404da84419 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -10,7 +10,7 @@
* Written by Peter Eisentraut <peter_e@gmx.net>.
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.551 2010/04/22 19:40:03 petere Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.552 2010/04/28 16:10:42 heikki Exp $
*
*--------------------------------------------------------------------
*/
@@ -340,6 +340,7 @@ static const struct config_enum_entry constraint_exclusion_options[] = {
/*
* Options for enum values stored in other modules
*/
+extern const struct config_enum_entry wal_level_options[];
extern const struct config_enum_entry sync_method_options[];
/*
@@ -2785,6 +2786,15 @@ static struct config_enum ConfigureNamesEnum[] =
},
{
+ {"wal_level", PGC_POSTMASTER, WAL_SETTINGS,
+ gettext_noop("Set the level of information written to the WAL."),
+ NULL
+ },
+ &wal_level,
+ WAL_LEVEL_MINIMAL, wal_level_options, NULL
+ },
+
+ {
{"wal_sync_method", PGC_SIGHUP, WAL_SETTINGS,
gettext_noop("Selects the method used for forcing WAL updates to disk."),
NULL
@@ -7862,7 +7872,7 @@ pg_timezone_abbrev_initialize(void)
static const char *
show_archive_command(void)
{
- if (XLogArchiveMode)
+ if (XLogArchivingActive())
return XLogArchiveCommand;
else
return "(disabled)";
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index 92763eb523a..57497115689 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -150,6 +150,7 @@
# - Settings -
+#wal_level = minimal # minimal, archive, or hot_standby
#fsync = on # turns forced synchronization on or off
#synchronous_commit = on # immediate fsync at commit
#wal_sync_method = fsync # the default is the first option
diff --git a/src/bin/pg_controldata/pg_controldata.c b/src/bin/pg_controldata/pg_controldata.c
index 2735a6611e2..839de98842b 100644
--- a/src/bin/pg_controldata/pg_controldata.c
+++ b/src/bin/pg_controldata/pg_controldata.c
@@ -6,15 +6,16 @@
* copyright (c) Oliver Elphick <olly@lfix.co.uk>, 2001;
* licence: BSD
*
- * $PostgreSQL: pgsql/src/bin/pg_controldata/pg_controldata.c,v 1.46 2010/01/04 12:50:49 heikki Exp $
+ * $PostgreSQL: pgsql/src/bin/pg_controldata/pg_controldata.c,v 1.47 2010/04/28 16:10:43 heikki Exp $
*/
-#include "postgres_fe.h"
+#include "postgres.h"
#include <unistd.h>
#include <time.h>
#include <sys/stat.h>
#include <fcntl.h>
+#include "access/xlog.h"
#include "catalog/pg_control.h"
@@ -60,6 +61,21 @@ dbState(DBState state)
return _("unrecognized status code");
}
+static const char *
+wal_level_str(WalLevel wal_level)
+{
+ switch (wal_level)
+ {
+ case WAL_LEVEL_MINIMAL:
+ return "minimal";
+ case WAL_LEVEL_ARCHIVE:
+ return "archive";
+ case WAL_LEVEL_HOT_STANDBY:
+ return "hot_standby";
+ }
+ return _("unrecognized wal_level");
+}
+
int
main(int argc, char *argv[])
@@ -206,6 +222,14 @@ main(int argc, char *argv[])
printf(_("Backup start location: %X/%X\n"),
ControlFile.backupStartPoint.xlogid,
ControlFile.backupStartPoint.xrecoff);
+ printf(_("Last wal_level setting: %s\n"),
+ wal_level_str(ControlFile.wal_level));
+ printf(_("Last max_connections setting: %d\n"),
+ ControlFile.MaxConnections);
+ printf(_("Last max_prepared_xacts setting: %d\n"),
+ ControlFile.max_prepared_xacts);
+ printf(_("Last max_locks_per_xact setting: %d\n"),
+ ControlFile.max_locks_per_xact);
printf(_("Maximum data alignment: %u\n"),
ControlFile.maxAlign);
/* we don't print floatFormat since can't say much useful about it */
diff --git a/src/bin/pg_resetxlog/pg_resetxlog.c b/src/bin/pg_resetxlog/pg_resetxlog.c
index d14df9cec8b..a8a43c44f00 100644
--- a/src/bin/pg_resetxlog/pg_resetxlog.c
+++ b/src/bin/pg_resetxlog/pg_resetxlog.c
@@ -23,7 +23,7 @@
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/bin/pg_resetxlog/pg_resetxlog.c,v 1.78 2010/02/26 02:01:17 momjian Exp $
+ * $PostgreSQL: pgsql/src/bin/pg_resetxlog/pg_resetxlog.c,v 1.79 2010/04/28 16:10:43 heikki Exp $
*
*-------------------------------------------------------------------------
*/
@@ -628,6 +628,15 @@ RewriteControlFile(void)
ControlFile.backupStartPoint.xlogid = 0;
ControlFile.backupStartPoint.xrecoff = 0;
+ /*
+ * Use the defaults for max_* settings. The values don't matter
+ * as long as wal_level='minimal'.
+ */
+ ControlFile.MaxConnections = 100;
+ ControlFile.max_prepared_xacts = 0;
+ ControlFile.max_locks_per_xact = 64;
+ ControlFile.wal_level = WAL_LEVEL_MINIMAL;
+
/* Now we can force the recorded xlog seg size to the right thing. */
ControlFile.xlog_seg_size = XLogSegSize;
diff --git a/src/include/access/xlog.h b/src/include/access/xlog.h
index 4812997659f..6936a2a5791 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.109 2010/04/20 11:15:06 rhaas Exp $
+ * $PostgreSQL: pgsql/src/include/access/xlog.h,v 1.110 2010/04/28 16:10:43 heikki Exp $
*/
#ifndef XLOG_H
#define XLOG_H
@@ -195,24 +195,26 @@ extern int XLogArchiveTimeout;
extern bool log_checkpoints;
extern bool XLogRequestRecoveryConnections;
extern int MaxStandbyDelay;
+/* WAL levels */
+typedef enum WalLevel
+{
+ WAL_LEVEL_MINIMAL = 0,
+ WAL_LEVEL_ARCHIVE,
+ WAL_LEVEL_HOT_STANDBY
+} WalLevel;
+extern int wal_level;
-#define XLogArchivingActive() (XLogArchiveMode)
+#define XLogArchivingActive() (XLogArchiveMode && wal_level >= WAL_LEVEL_ARCHIVE)
#define XLogArchiveCommandSet() (XLogArchiveCommand[0] != '\0')
/*
- * This is in walsender.c, but declared here so that we don't need to include
- * walsender.h in all files that check XLogIsNeeded()
- */
-extern int max_wal_senders;
-
-/*
- * Is WAL-logging necessary? We need to log an XLOG record iff either
- * WAL archiving is enabled or XLOG streaming is allowed.
+ * Is WAL-logging necessary for archival or log-shipping, or can we skip
+ * WAL-logging if we fsync() the data before committing instead?
*/
-#define XLogIsNeeded() (XLogArchivingActive() || (max_wal_senders > 0))
+#define XLogIsNeeded() (wal_level >= WAL_LEVEL_ARCHIVE)
/* Do we need to WAL-log information required only for Hot Standby? */
-#define XLogStandbyInfoActive() (XLogRequestRecoveryConnections && XLogIsNeeded())
+#define XLogStandbyInfoActive() (wal_level >= WAL_LEVEL_HOT_STANDBY)
#ifdef WAL_DEBUG
extern bool XLOG_DEBUG;
@@ -293,7 +295,6 @@ 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/access/xlog_internal.h b/src/include/access/xlog_internal.h
index fa21f0a916a..3f0930f3951 100644
--- a/src/include/access/xlog_internal.h
+++ b/src/include/access/xlog_internal.h
@@ -11,7 +11,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_internal.h,v 1.32 2010/04/12 10:40:43 heikki Exp $
+ * $PostgreSQL: pgsql/src/include/access/xlog_internal.h,v 1.33 2010/04/28 16:10:43 heikki Exp $
*/
#ifndef XLOG_INTERNAL_H
#define XLOG_INTERNAL_H
@@ -71,7 +71,7 @@ typedef struct XLogContRecord
/*
* Each page of XLOG file has a header like this:
*/
-#define XLOG_PAGE_MAGIC 0x9003 /* can be used as WAL version indicator */
+#define XLOG_PAGE_MAGIC 0xD064 /* can be used as WAL version indicator */
typedef struct XLogPageHeaderData
{
diff --git a/src/include/catalog/pg_control.h b/src/include/catalog/pg_control.h
index 7342468d055..8deef6d354d 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.53 2010/04/23 20:21:31 sriggs Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_control.h,v 1.54 2010/04/28 16:10:43 heikki Exp $
*
*-------------------------------------------------------------------------
*/
@@ -21,7 +21,7 @@
/* Version identifier for this pg_control format */
-#define PG_CONTROL_VERSION 901
+#define PG_CONTROL_VERSION 902
/*
* Body of CheckPoint XLOG records. This is declared here because we keep
@@ -41,12 +41,6 @@ typedef struct CheckPoint
Oid oldestXidDB; /* database with minimum datfrozenxid */
pg_time_t time; /* time stamp of checkpoint */
- /* Important parameter settings at time of shutdown checkpoints */
- int MaxConnections;
- int max_prepared_xacts;
- int max_locks_per_xact;
- bool XLogStandbyInfoMode;
-
/*
* Oldest XID still running. This is only needed to initialize hot standby
* mode from an online checkpoint, so we only bother calculating this for
@@ -63,7 +57,7 @@ typedef struct CheckPoint
#define XLOG_NEXTOID 0x30
#define XLOG_SWITCH 0x40
#define XLOG_BACKUP_END 0x50
-#define XLOG_UNLOGGED 0x60
+#define XLOG_PARAMETER_CHANGE 0x60
/* System status indicator */
@@ -142,6 +136,15 @@ typedef struct ControlFileData
XLogRecPtr backupStartPoint;
/*
+ * Parameter settings that determine if the WAL can be used for archival
+ * or hot standby.
+ */
+ int wal_level;
+ int MaxConnections;
+ int max_prepared_xacts;
+ int max_locks_per_xact;
+
+ /*
* This data is used to check for hardware-architecture compatibility of
* the database and the backend executable. We need not check endianness
* explicitly, since the pg_control version will surely look wrong to a
diff --git a/src/include/replication/walsender.h b/src/include/replication/walsender.h
index abb8312ecf7..d43ad912e76 100644
--- a/src/include/replication/walsender.h
+++ b/src/include/replication/walsender.h
@@ -5,7 +5,7 @@
*
* Portions Copyright (c) 2010-2010, PostgreSQL Global Development Group
*
- * $PostgreSQL: pgsql/src/include/replication/walsender.h,v 1.2 2010/02/26 02:01:27 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/replication/walsender.h,v 1.3 2010/04/28 16:10:43 heikki Exp $
*
*-------------------------------------------------------------------------
*/
@@ -39,6 +39,7 @@ extern bool am_walsender;
/* user-settable parameters */
extern int WalSndDelay;
+extern int max_wal_senders;
extern int WalSenderMain(void);
extern void WalSndSignals(void);