Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit b46bd55

Browse files
committed
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.
1 parent b37e177 commit b46bd55

File tree

2 files changed

+22
-18
lines changed

2 files changed

+22
-18
lines changed

doc/src/sgml/backup.sgml

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- $PostgreSQL: pgsql/doc/src/sgml/backup.sgml,v 2.102 2007/09/26 22:36:30 tgl Exp $ -->
1+
<!-- $PostgreSQL: pgsql/doc/src/sgml/backup.sgml,v 2.103 2007/09/29 01:36:10 tgl Exp $ -->
22

33
<chapter id="backup">
44
<title>Backup and Restore</title>
@@ -1174,11 +1174,9 @@ restore_command = 'copy /mnt/server/archivedir/%f "%p"' # Windows
11741174

11751175
<para>
11761176
To deal with these problems, <productname>PostgreSQL</> has a notion
1177-
of <firstterm>timelines</>. Each time you recover to a point-in-time
1178-
earlier than the end of the WAL sequence, a new timeline is created
1179-
to identify the series of WAL records generated after that recovery.
1180-
(If recovery proceeds all the way to the end of WAL, however, we do not
1181-
start a new timeline: we just extend the existing one.) The timeline
1177+
of <firstterm>timelines</>. Whenever an archive recovery is completed,
1178+
a new timeline is created to identify the series of WAL records
1179+
generated after that recovery. The timeline
11821180
ID number is part of WAL segment file names, and so a new timeline does
11831181
not overwrite the WAL data generated by previous timelines. It is
11841182
in fact possible to archive many different timelines. While that might

src/backend/access/transam/xlog.c

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.282 2007/09/26 22:36:30 tgl Exp $
10+
* $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.283 2007/09/29 01:36:10 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -4518,7 +4518,8 @@ exitArchiveRecovery(TimeLineID endTLI, uint32 endLogId, uint32 endLogSeg)
45184518
*
45194519
* Note that if we are establishing a new timeline, ThisTimeLineID is
45204520
* already set to the new value, and so we will create a new file instead
4521-
* of overwriting any existing file.
4521+
* of overwriting any existing file. (This is, in fact, always the case
4522+
* at present.)
45224523
*/
45234524
snprintf(recoveryPath, MAXPGPATH, XLOGDIR "/RECOVERYXLOG");
45244525
XLogFilePath(xlogpath, ThisTimeLineID, endLogId, endLogSeg);
@@ -4700,7 +4701,7 @@ StartupXLOG(void)
47004701
XLogCtlInsert *Insert;
47014702
CheckPoint checkPoint;
47024703
bool wasShutdown;
4703-
bool needNewTimeLine = false;
4704+
bool reachedStopPoint = false;
47044705
bool haveBackupLabel = false;
47054706
XLogRecPtr RecPtr,
47064707
LastRec,
@@ -5010,7 +5011,7 @@ StartupXLOG(void)
50105011
*/
50115012
if (recoveryStopsHere(record, &recoveryApply))
50125013
{
5013-
needNewTimeLine = true; /* see below */
5014+
reachedStopPoint = true; /* see below */
50145015
recoveryContinue = false;
50155016
if (!recoveryApply)
50165017
break;
@@ -5078,24 +5079,29 @@ StartupXLOG(void)
50785079
*/
50795080
if (XLByteLT(EndOfLog, ControlFile->minRecoveryPoint))
50805081
{
5081-
if (needNewTimeLine) /* stopped because of stop request */
5082+
if (reachedStopPoint) /* stopped because of stop request */
50825083
ereport(FATAL,
50835084
(errmsg("requested recovery stop point is before end time of backup dump")));
5084-
else
5085-
/* ran off end of WAL */
5085+
else /* ran off end of WAL */
50865086
ereport(FATAL,
50875087
(errmsg("WAL ends before end time of backup dump")));
50885088
}
50895089

50905090
/*
50915091
* Consider whether we need to assign a new timeline ID.
50925092
*
5093-
* If we stopped short of the end of WAL during recovery, then we are
5094-
* generating a new timeline and must assign it a unique new ID.
5095-
* Otherwise, we can just extend the timeline we were in when we ran out
5096-
* of WAL.
5093+
* If we are doing an archive recovery, we always assign a new ID. This
5094+
* handles a couple of issues. If we stopped short of the end of WAL
5095+
* during recovery, then we are clearly generating a new timeline and must
5096+
* assign it a unique new ID. Even if we ran to the end, modifying the
5097+
* current last segment is problematic because it may result in trying
5098+
* to overwrite an already-archived copy of that segment, and we encourage
5099+
* DBAs to make their archive_commands reject that. We can dodge the
5100+
* problem by making the new active segment have a new timeline ID.
5101+
*
5102+
* In a normal crash recovery, we can just extend the timeline we were in.
50975103
*/
5098-
if (needNewTimeLine)
5104+
if (InArchiveRecovery)
50995105
{
51005106
ThisTimeLineID = findNewestTimeLine(recoveryTargetTLI) + 1;
51015107
ereport(LOG,

0 commit comments

Comments
 (0)