diff options
author | Heikki Linnakangas <heikki.linnakangas@iki.fi> | 2013-01-17 20:23:00 +0200 |
---|---|---|
committer | Heikki Linnakangas <heikki.linnakangas@iki.fi> | 2013-01-17 20:23:00 +0200 |
commit | 0b6329130e8e4576e97ff763f0e773347e1a88af (patch) | |
tree | 7902ba1fa99ac8124232122ce16231cff0b0e21e /src/backend/access/transam/xlog.c | |
parent | 8ae35e91807508872cabd3b0e8db35fc78e194ac (diff) | |
download | postgresql-0b6329130e8e4576e97ff763f0e773347e1a88af.tar.gz postgresql-0b6329130e8e4576e97ff763f0e773347e1a88af.zip |
Make pg_receivexlog and pg_basebackup -X stream work across timeline switches.
This mirrors the changes done earlier to the server in standby mode. When
receivelog reaches the end of a timeline, as reported by the server, it
fetches the timeline history file of the next timeline, and restarts
streaming from the new timeline by issuing a new START_STREAMING command.
When pg_receivexlog crosses a timeline, it leaves the .partial suffix on the
last segment on the old timeline. This helps you to tell apart a partial
segment left in the directory because of a timeline switch, and a completed
segment. If you just follow a single server, it won't make a difference, but
it can be significant in more complicated scenarios where new WAL is still
generated on the old timeline.
This includes two small changes to the streaming replication protocol:
First, when you reach the end of timeline while streaming, the server now
sends the TLI of the next timeline in the server's history to the client.
pg_receivexlog uses that as the next timeline, so that it doesn't need to
parse the timeline history file like a standby server does. Second, when
BASE_BACKUP command sends the begin and end WAL positions, it now also sends
the timeline IDs corresponding the positions.
Diffstat (limited to 'src/backend/access/transam/xlog.c')
-rw-r--r-- | src/backend/access/transam/xlog.c | 24 |
1 files changed, 21 insertions, 3 deletions
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index ac2b26b4982..90ba32ef0f5 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -4930,7 +4930,7 @@ StartupXLOG(void) * tliSwitchPoint will throw an error if the checkpoint's timeline * is not in expectedTLEs at all. */ - switchpoint = tliSwitchPoint(ControlFile->checkPointCopy.ThisTimeLineID, expectedTLEs); + switchpoint = tliSwitchPoint(ControlFile->checkPointCopy.ThisTimeLineID, expectedTLEs, NULL); ereport(FATAL, (errmsg("requested timeline %u is not a child of this server's history", recoveryTargetTLI), @@ -7870,16 +7870,21 @@ XLogFileNameP(TimeLineID tli, XLogSegNo segno) * non-exclusive backups active at the same time, and they don't conflict * with an exclusive backup either. * + * Returns the minimum WAL position that must be present to restore from this + * backup, and the corresponding timeline ID in *starttli_p. + * * Every successfully started non-exclusive backup must be stopped by calling * do_pg_stop_backup() or do_pg_abort_backup(). */ XLogRecPtr -do_pg_start_backup(const char *backupidstr, bool fast, char **labelfile) +do_pg_start_backup(const char *backupidstr, bool fast, TimeLineID *starttli_p, + char **labelfile) { bool exclusive = (labelfile == NULL); bool backup_started_in_recovery = false; XLogRecPtr checkpointloc; XLogRecPtr startpoint; + TimeLineID starttli; pg_time_t stamp_time; char strfbuf[128]; char xlogfilename[MAXFNAMELEN]; @@ -8021,6 +8026,7 @@ do_pg_start_backup(const char *backupidstr, bool fast, char **labelfile) LWLockAcquire(ControlFileLock, LW_SHARED); checkpointloc = ControlFile->checkPoint; startpoint = ControlFile->checkPointCopy.redo; + starttli = ControlFile->checkPointCopy.ThisTimeLineID; checkpointfpw = ControlFile->checkPointCopy.fullPageWrites; LWLockRelease(ControlFileLock); @@ -8154,6 +8160,8 @@ do_pg_start_backup(const char *backupidstr, bool fast, char **labelfile) /* * We're done. As a convenience, return the starting WAL location. */ + if (starttli_p) + *starttli_p = starttli; return startpoint; } @@ -8190,14 +8198,18 @@ pg_start_backup_callback(int code, Datum arg) * If labelfile is NULL, this stops an exclusive backup. Otherwise this stops * the non-exclusive backup specified by 'labelfile'. + * + * Returns the last WAL position that must be present to restore from this + * backup, and the corresponding timeline ID in *stoptli_p. */ XLogRecPtr -do_pg_stop_backup(char *labelfile, bool waitforarchive) +do_pg_stop_backup(char *labelfile, bool waitforarchive, TimeLineID *stoptli_p) { bool exclusive = (labelfile == NULL); bool backup_started_in_recovery = false; XLogRecPtr startpoint; XLogRecPtr stoppoint; + TimeLineID stoptli; XLogRecData rdata; pg_time_t stamp_time; char strfbuf[128]; @@ -8401,8 +8413,11 @@ do_pg_stop_backup(char *labelfile, bool waitforarchive) LWLockAcquire(ControlFileLock, LW_SHARED); stoppoint = ControlFile->minRecoveryPoint; + stoptli = ControlFile->minRecoveryPointTLI; LWLockRelease(ControlFileLock); + if (stoptli_p) + *stoptli_p = stoptli; return stoppoint; } @@ -8414,6 +8429,7 @@ do_pg_stop_backup(char *labelfile, bool waitforarchive) rdata.buffer = InvalidBuffer; rdata.next = NULL; stoppoint = XLogInsert(RM_XLOG_ID, XLOG_BACKUP_END, &rdata); + stoptli = ThisTimeLineID; /* * Force a switch to a new xlog segment file, so that the backup is valid @@ -8529,6 +8545,8 @@ do_pg_stop_backup(char *labelfile, bool waitforarchive) /* * We're done. As a convenience, return the ending WAL location. */ + if (stoptli_p) + *stoptli_p = stoptli; return stoppoint; } |