diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/access/heap/rewriteheap.c | 12 | ||||
-rw-r--r-- | src/backend/access/nbtree/nbtsort.c | 15 | ||||
-rw-r--r-- | src/backend/access/transam/xlog.c | 210 | ||||
-rw-r--r-- | src/backend/commands/cluster.c | 19 | ||||
-rw-r--r-- | src/backend/commands/copy.c | 9 | ||||
-rw-r--r-- | src/backend/commands/tablecmds.c | 27 | ||||
-rw-r--r-- | src/backend/executor/execMain.c | 9 | ||||
-rw-r--r-- | src/backend/postmaster/postmaster.c | 8 | ||||
-rw-r--r-- | src/backend/replication/walsender.c | 20 | ||||
-rw-r--r-- | src/backend/storage/ipc/standby.c | 4 | ||||
-rw-r--r-- | src/backend/utils/misc/guc.c | 14 | ||||
-rw-r--r-- | src/backend/utils/misc/postgresql.conf.sample | 1 | ||||
-rw-r--r-- | src/bin/pg_controldata/pg_controldata.c | 28 | ||||
-rw-r--r-- | src/bin/pg_resetxlog/pg_resetxlog.c | 11 | ||||
-rw-r--r-- | src/include/access/xlog.h | 27 | ||||
-rw-r--r-- | src/include/access/xlog_internal.h | 4 | ||||
-rw-r--r-- | src/include/catalog/pg_control.h | 21 | ||||
-rw-r--r-- | src/include/replication/walsender.h | 3 |
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); |