aboutsummaryrefslogtreecommitdiff
path: root/src/backend/access/transam/xlog.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2007-09-29 01:36:19 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2007-09-29 01:36:19 +0000
commit4ef631fe2c1185c85fabdaa495e0562bd0d41741 (patch)
tree7ad88ed89e58ee84678e7bd128ee2bf3e9d49e1f /src/backend/access/transam/xlog.c
parent3f850ee9aae6fb09b92fa58235378a7d6bb83c69 (diff)
downloadpostgresql-4ef631fe2c1185c85fabdaa495e0562bd0d41741.tar.gz
postgresql-4ef631fe2c1185c85fabdaa495e0562bd0d41741.zip
Make archive recovery always start a new timeline, rather than only when a
recovery stop time was used. This avoids a corner-case risk of trying to overwrite an existing archived copy of the last WAL segment, and seems simpler and cleaner all around than the original definition. Per example from Jon Colverson and subsequent analysis by Simon.
Diffstat (limited to 'src/backend/access/transam/xlog.c')
-rw-r--r--src/backend/access/transam/xlog.c30
1 files changed, 18 insertions, 12 deletions
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 4ab57244b0b..63500b304a8 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.258.2.1 2007/08/04 01:42:24 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.258.2.2 2007/09/29 01:36:19 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -4468,7 +4468,8 @@ exitArchiveRecovery(TimeLineID endTLI, uint32 endLogId, uint32 endLogSeg)
*
* Note that if we are establishing a new timeline, ThisTimeLineID is
* already set to the new value, and so we will create a new file instead
- * of overwriting any existing file.
+ * of overwriting any existing file. (This is, in fact, always the case
+ * at present.)
*/
snprintf(recoveryPath, MAXPGPATH, XLOGDIR "/RECOVERYXLOG");
XLogFilePath(xlogpath, ThisTimeLineID, endLogId, endLogSeg);
@@ -4643,7 +4644,7 @@ StartupXLOG(void)
XLogCtlInsert *Insert;
CheckPoint checkPoint;
bool wasShutdown;
- bool needNewTimeLine = false;
+ bool reachedStopPoint = false;
bool haveBackupLabel = false;
XLogRecPtr RecPtr,
LastRec,
@@ -4958,7 +4959,7 @@ StartupXLOG(void)
*/
if (recoveryStopsHere(record, &recoveryApply))
{
- needNewTimeLine = true; /* see below */
+ reachedStopPoint = true; /* see below */
recoveryContinue = false;
if (!recoveryApply)
break;
@@ -5022,11 +5023,10 @@ StartupXLOG(void)
*/
if (XLByteLT(EndOfLog, ControlFile->minRecoveryPoint))
{
- if (needNewTimeLine) /* stopped because of stop request */
+ if (reachedStopPoint) /* stopped because of stop request */
ereport(FATAL,
(errmsg("requested recovery stop point is before end time of backup dump")));
- else
- /* ran off end of WAL */
+ else /* ran off end of WAL */
ereport(FATAL,
(errmsg("WAL ends before end time of backup dump")));
}
@@ -5034,12 +5034,18 @@ StartupXLOG(void)
/*
* Consider whether we need to assign a new timeline ID.
*
- * If we stopped short of the end of WAL during recovery, then we are
- * generating a new timeline and must assign it a unique new ID.
- * Otherwise, we can just extend the timeline we were in when we ran out
- * of WAL.
+ * If we are doing an archive recovery, we always assign a new ID. This
+ * handles a couple of issues. If we stopped short of the end of WAL
+ * during recovery, then we are clearly generating a new timeline and must
+ * assign it a unique new ID. Even if we ran to the end, modifying the
+ * current last segment is problematic because it may result in trying
+ * to overwrite an already-archived copy of that segment, and we encourage
+ * DBAs to make their archive_commands reject that. We can dodge the
+ * problem by making the new active segment have a new timeline ID.
+ *
+ * In a normal crash recovery, we can just extend the timeline we were in.
*/
- if (needNewTimeLine)
+ if (InArchiveRecovery)
{
ThisTimeLineID = findNewestTimeLine(recoveryTargetTLI) + 1;
ereport(LOG,