From: Heikki Linnakangas Date: Tue, 27 Jan 2009 16:40:59 +0000 (+0200) Subject: Revert the recovery.conf file renaming change. Remove the (remains of the) code X-Git-Url: http://git.postgresql.org/gitweb/static/gitweb.js?a=commitdiff_plain;h=ed3b0f06704089423e888e02328ba5ddb8aae158;p=users%2Fsimon%2Fpostgres.git Revert the recovery.conf file renaming change. Remove the (remains of the) code to pass the redo location of the first checkpoint from startup process to bgwriter. Silence LOG warning about bgwriter not being started yet when the startup checkpoint is requested. --- diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 3005e44c53..06ff2a5147 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -4816,13 +4816,18 @@ exitArchiveRecovery(TimeLineID endTLI, uint32 endLogId, uint32 endLogSeg) unlink(recoveryPath); /* ignore any error */ /* - * As of 8.4 we no longer rename the recovery.conf file out of the - * way until after we have performed a full checkpoint. This ensures - * that any crash between now and the end of the checkpoint does not - * attempt to restart from a WAL file that is no longer available to us. - * As soon as we remove recovery.conf we lose our recovery_command and - * cannot reaccess WAL files from the archive. - */ + * Rename the config file out of the way, so that we don't accidentally + * re-enter archive recovery mode in a subsequent crash. We have already + * restored all the WAL segments we need from the archive, and we trust + * that they are not going to go away even if we crash. (XXX: should + * we fsync() them all to ensure that?) + */ + unlink(RECOVERY_COMMAND_DONE); + if (rename(RECOVERY_COMMAND_FILE, RECOVERY_COMMAND_DONE) != 0) + ereport(FATAL, + (errcode_for_file_access(), + errmsg("could not rename file \"%s\" to \"%s\": %m", + RECOVERY_COMMAND_FILE, RECOVERY_COMMAND_DONE))); ereport(LOG, (errmsg("archive recovery complete"))); @@ -5547,39 +5552,21 @@ StartupXLOG(void) } /* - * Prior to 8.4 we wrote a Shutdown Checkpoint at the end of recovery. - * This could add minutes to the startup time, so we want bgwriter - * to perform it. This then frees the Startup process to complete so we can - * allow transactions and WAL inserts. We still write a checkpoint, but - * it will be an online checkpoint. Online checkpoints have a redo - * location that can be prior to the actual checkpoint record. So we want - * to derive that redo location *before* we let anybody else write WAL, - * otherwise we might miss some WAL records if we crash. + * If we had to replay any WAL records, request a checkpoint. This isn't + * strictly necessary: if we crash now, the recovery will simply restart + * from the same point where it started this time around (or from the + * last restartpoint). The control file is left in DB_IN_*_RECOVERY + * state; the first checkpoint will change that to DB_IN_PRODUCTION. */ if (performedRecovery) { -#ifdef DEADCODE - XLogRecPtr redo; - - /* - * We must grab the pointer before anybody writes WAL - */ - redo = GetRedoLocationForCheckpoint(); - - /* - * Tell the bgwriter - */ - SetRedoLocationForArchiveCheckpoint(redo); -#endif /* * Okay, we can come up now. Allow others to write WAL. */ XLogCtl->SharedRecoveryProcessingMode = false; - /* - * Now request checkpoint - */ - RequestCheckpoint(CHECKPOINT_FORCE | CHECKPOINT_IMMEDIATE); + RequestCheckpoint(CHECKPOINT_FORCE | CHECKPOINT_IMMEDIATE | + CHECKPOINT_STARTUP); } else { @@ -5978,7 +5965,6 @@ CreateCheckPoint(int flags) uint32 _logSeg; TransactionId *inCommitXids; int nInCommit; - bool leavingArchiveRecovery = false; /* * Acquire CheckpointLock to ensure only one checkpoint happens at a time. @@ -5997,13 +5983,6 @@ CreateCheckPoint(int flags) MemSet(&CheckpointStats, 0, sizeof(CheckpointStats)); CheckpointStats.ckpt_start_t = GetCurrentTimestamp(); - /* - * Find out if this is the first checkpoint after archive recovery. - */ - LWLockAcquire(ControlFileLock, LW_EXCLUSIVE); - leavingArchiveRecovery = (ControlFile->state == DB_IN_ARCHIVE_RECOVERY); - LWLockRelease(ControlFileLock); - /* * Use a critical section to force system panic if we have trouble. */ @@ -6030,69 +6009,62 @@ CreateCheckPoint(int flags) checkPoint.ThisTimeLineID = ThisTimeLineID; checkPoint.time = (pg_time_t) time(NULL); -#ifdef DEADCODE - if (leavingArchiveRecovery) - checkPoint.redo = GetRedoLocationForArchiveCheckpoint(); - else -#endif - { - /* - * We must hold WALInsertLock while examining insert state to determine - * the checkpoint REDO pointer. - */ - LWLockAcquire(WALInsertLock, LW_EXCLUSIVE); + /* + * We must hold WALInsertLock while examining insert state to determine + * the checkpoint REDO pointer. + */ + LWLockAcquire(WALInsertLock, LW_EXCLUSIVE); - /* - * If this isn't a shutdown or forced checkpoint, and we have not inserted - * any XLOG records since the start of the last checkpoint, skip the - * checkpoint. The idea here is to avoid inserting duplicate checkpoints - * when the system is idle. That wastes log space, and more importantly it - * exposes us to possible loss of both current and previous checkpoint - * records if the machine crashes just as we're writing the update. - * (Perhaps it'd make even more sense to checkpoint only when the previous - * checkpoint record is in a different xlog page?) - * - * We have to make two tests to determine that nothing has happened since - * the start of the last checkpoint: current insertion point must match - * the end of the last checkpoint record, and its redo pointer must point - * to itself. - */ - if ((flags & (CHECKPOINT_IS_SHUTDOWN | CHECKPOINT_FORCE)) == 0) + /* + * If this isn't a shutdown or forced checkpoint, and we have not inserted + * any XLOG records since the start of the last checkpoint, skip the + * checkpoint. The idea here is to avoid inserting duplicate checkpoints + * when the system is idle. That wastes log space, and more importantly it + * exposes us to possible loss of both current and previous checkpoint + * records if the machine crashes just as we're writing the update. + * (Perhaps it'd make even more sense to checkpoint only when the previous + * checkpoint record is in a different xlog page?) + * + * We have to make two tests to determine that nothing has happened since + * the start of the last checkpoint: current insertion point must match + * the end of the last checkpoint record, and its redo pointer must point + * to itself. + */ + if ((flags & (CHECKPOINT_IS_SHUTDOWN | CHECKPOINT_FORCE)) == 0) + { + XLogRecPtr curInsert; + + INSERT_RECPTR(curInsert, Insert, Insert->curridx); + if (curInsert.xlogid == ControlFile->checkPoint.xlogid && + curInsert.xrecoff == ControlFile->checkPoint.xrecoff + + MAXALIGN(SizeOfXLogRecord + sizeof(CheckPoint)) && + ControlFile->checkPoint.xlogid == + ControlFile->checkPointCopy.redo.xlogid && + ControlFile->checkPoint.xrecoff == + ControlFile->checkPointCopy.redo.xrecoff) { - XLogRecPtr curInsert; - - INSERT_RECPTR(curInsert, Insert, Insert->curridx); - if (curInsert.xlogid == ControlFile->checkPoint.xlogid && - curInsert.xrecoff == ControlFile->checkPoint.xrecoff + - MAXALIGN(SizeOfXLogRecord + sizeof(CheckPoint)) && - ControlFile->checkPoint.xlogid == - ControlFile->checkPointCopy.redo.xlogid && - ControlFile->checkPoint.xrecoff == - ControlFile->checkPointCopy.redo.xrecoff) - { - LWLockRelease(WALInsertLock); - LWLockRelease(CheckpointLock); - END_CRIT_SECTION(); - return; - } + LWLockRelease(WALInsertLock); + LWLockRelease(CheckpointLock); + END_CRIT_SECTION(); + return; } + } - /* - * Compute new REDO record ptr = location of next XLOG record. - * - * NB: this is NOT necessarily where the checkpoint record itself will be, - * since other backends may insert more XLOG records while we're off doing - * the buffer flush work. Those XLOG records are logically after the - * checkpoint, even though physically before it. Got that? - */ - checkPoint.redo = GetRedoLocationForCheckpoint(); + /* + * Compute new REDO record ptr = location of next XLOG record. + * + * NB: this is NOT necessarily where the checkpoint record itself will be, + * since other backends may insert more XLOG records while we're off doing + * the buffer flush work. Those XLOG records are logically after the + * checkpoint, even though physically before it. Got that? + */ + checkPoint.redo = GetRedoLocationForCheckpoint(); - /* - * Now we can release WAL insert lock, allowing other xacts to proceed - * while we are flushing disk buffers. - */ - LWLockRelease(WALInsertLock); - } + /* + * Now we can release WAL insert lock, allowing other xacts to proceed + * while we are flushing disk buffers. + */ + LWLockRelease(WALInsertLock); /* * If enabled, log checkpoint start. We postpone this until now so as not @@ -6225,21 +6197,6 @@ CreateCheckPoint(int flags) LWLockRelease(ControlFileLock); - if (leavingArchiveRecovery) - { - /* - * Rename the config file out of the way, so that we don't accidentally - * re-enter archive recovery mode in a subsequent crash. Prior to - * 8.4 this step was performed at end of exitArchiveRecovery(). - */ - unlink(RECOVERY_COMMAND_DONE); - if (rename(RECOVERY_COMMAND_FILE, RECOVERY_COMMAND_DONE) != 0) - ereport(ERROR, - (errcode_for_file_access(), - errmsg("could not rename file \"%s\" to \"%s\": %m", - RECOVERY_COMMAND_FILE, RECOVERY_COMMAND_DONE))); - } - /* Update shared-memory copy of checkpoint XID/epoch */ { /* use volatile pointer to prevent code rearrangement */ diff --git a/src/backend/postmaster/bgwriter.c b/src/backend/postmaster/bgwriter.c index 8923c3a194..a4c12de2b0 100644 --- a/src/backend/postmaster/bgwriter.c +++ b/src/backend/postmaster/bgwriter.c @@ -880,6 +880,7 @@ BgWriterShmemInit(void) * * flags is a bitwise OR of the following: * CHECKPOINT_IS_SHUTDOWN: checkpoint is for database shutdown. + * CHECKPOINT_IS_STARTUP: checkpoint is for database startup. * CHECKPOINT_IMMEDIATE: finish the checkpoint ASAP, * ignoring checkpoint_completion_target parameter. * CHECKPOINT_FORCE: force a checkpoint even if no XLOG activity has occured @@ -946,6 +947,18 @@ RequestCheckpoint(int flags) { if (BgWriterShmem->bgwriter_pid == 0) { + /* + * The only difference between a startup checkpoint and a normal + * online checkpoint is that it's quite normal for the bgwriter + * to not be up yet when the startup checkpoint is requested. + * (it might be, though). That's ok, background writer will + * perform the checkpoint as soon as it starts up. + */ + if (flags & CHECKPOINT_STARTUP) + { + Assert(!(flags & CHECKPOINT_WAIT)); + break; + } if (ntries >= 20) /* max wait 2.0 sec */ { elog((flags & CHECKPOINT_WAIT) ? ERROR : LOG, diff --git a/src/include/access/xlog.h b/src/include/access/xlog.h index 897974efae..6f58b8040f 100644 --- a/src/include/access/xlog.h +++ b/src/include/access/xlog.h @@ -170,11 +170,12 @@ extern bool XLOG_DEBUG; #define CHECKPOINT_IS_SHUTDOWN 0x0001 /* Checkpoint is for shutdown */ #define CHECKPOINT_IMMEDIATE 0x0002 /* Do it without delays */ #define CHECKPOINT_FORCE 0x0004 /* Force even if no activity */ +#define CHECKPOINT_STARTUP 0x0008 /* Startup checkpoint */ /* These are important to RequestCheckpoint */ -#define CHECKPOINT_WAIT 0x0008 /* Wait for completion */ +#define CHECKPOINT_WAIT 0x0010 /* Wait for completion */ /* These indicate the cause of a checkpoint request */ -#define CHECKPOINT_CAUSE_XLOG 0x0010 /* XLOG consumption */ -#define CHECKPOINT_CAUSE_TIME 0x0020 /* Elapsed time */ +#define CHECKPOINT_CAUSE_XLOG 0x0020 /* XLOG consumption */ +#define CHECKPOINT_CAUSE_TIME 0x0040 /* Elapsed time */ /* Checkpoint statistics */ typedef struct CheckpointStatsData diff --git a/src/include/postmaster/bgwriter.h b/src/include/postmaster/bgwriter.h index 00eb7a4fa7..35f24d68c2 100644 --- a/src/include/postmaster/bgwriter.h +++ b/src/include/postmaster/bgwriter.h @@ -27,8 +27,6 @@ extern void BackgroundWriterMain(void); extern void RequestCheckpoint(int flags); extern void RequestRestartPointCompletion(void); -extern XLogRecPtr GetRedoLocationForArchiveCheckpoint(void); -extern void SetRedoLocationForArchiveCheckpoint(XLogRecPtr redo); extern void CheckpointWriteDelay(int flags, double progress);