Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit1a4ab9e

Browse files
committed
If recovery_target_timeline is set to 'latest' and standby mode is enabled,
periodically rescan the archive for new timelines, while waiting for new WALsegments to arrive. This allows you to set up a standby server that followsthe TLI change if another standby server is promoted to master. Before this,you had to restart the standby server to make it notice the new timeline.This patch only scans the archive for TLI changes, it won't follow a TLIchange in streaming replication. That is much needed too, but it would be amuch bigger patch than I dare to sneak in this late in the release cycle.There was discussion on improving the sanity checking of the WAL segments sothat the system would notice more reliably if the new timeline isn't anancestor of the current one, but that is not included in this patch.Reviewed by Fujii Masao.
1 parentbcf85e3 commit1a4ab9e

File tree

3 files changed

+83
-5
lines changed

3 files changed

+83
-5
lines changed

‎doc/src/sgml/high-availability.sgml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -660,7 +660,10 @@ protocol to make nodes agree on a serializable transactional order.
660660
command file <filename>recovery.conf</> in the standby's cluster data
661661
directory, and turn on <varname>standby_mode</>. Set
662662
<varname>restore_command</> to a simple command to copy files from
663-
the WAL archive.
663+
the WAL archive. If you plan to have multiple standby servers for high
664+
availability purposes, set <varname>recovery_target_timeline</> to
665+
<literal>latest</>, to make the standby server follow the timeline change
666+
that occurs at failover to another standby.
664667
</para>
665668

666669
<note>

‎doc/src/sgml/recovery-config.sgml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,9 @@ restore_command = 'copy "C:\\server\\archivedir\\%f" "%p"' # Windows
240240
<para>
241241
Specifies recovering into a particular timeline. The default is
242242
to recover along the same timeline that was current when the
243-
base backup was taken. You only need to set this parameter
243+
base backup was taken. Setting this to <literal>latest</> recovers
244+
to the latest timeline found in the archive, which is useful in
245+
a standby server. Other than that you only need to set this parameter
244246
in complex re-recovery situations, where you need to return to
245247
a state that itself was reached after a point-in-time recovery.
246248
See <xref linkend="backup-timelines"> for discussion.

‎src/backend/access/transam/xlog.c

Lines changed: 76 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,8 @@ static bool recoveryStopAfter;
214214
*
215215
* recoveryTargetTLI: the desired timeline that we want to end in.
216216
*
217+
* recoveryTargetIsLatest: was the requested target timeline 'latest'?
218+
*
217219
* expectedTLIs: an integer list of recoveryTargetTLI and the TLIs of
218220
* its known parents, newest first (so recoveryTargetTLI is always the
219221
* first list member).Only these TLIs are expected to be seen in the WAL
@@ -227,6 +229,7 @@ static bool recoveryStopAfter;
227229
* to decrease.
228230
*/
229231
staticTimeLineIDrecoveryTargetTLI;
232+
staticboolrecoveryTargetIsLatest= false;
230233
staticList*expectedTLIs;
231234
staticTimeLineIDcurFileTLI;
232235

@@ -637,6 +640,7 @@ static bool ValidXLOGHeader(XLogPageHeader hdr, int emode);
637640
staticXLogRecord*ReadCheckpointRecord(XLogRecPtrRecPtr,intwhichChkpt);
638641
staticList*readTimeLineHistory(TimeLineIDtargetTLI);
639642
staticboolexistsTimeLineHistory(TimeLineIDprobeTLI);
643+
staticboolrescanLatestTimeLine(void);
640644
staticTimeLineIDfindNewestTimeLine(TimeLineIDstartTLI);
641645
staticvoidwriteTimeLineHistory(TimeLineIDnewTLI,TimeLineIDparentTLI,
642646
TimeLineIDendTLI,
@@ -4253,6 +4257,62 @@ existsTimeLineHistory(TimeLineID probeTLI)
42534257
}
42544258
}
42554259

4260+
/*
4261+
* Scan for new timelines that might have appeared in the archive since we
4262+
* started recovery.
4263+
*
4264+
* If there are any, the function changes recovery target TLI to the latest
4265+
* one and returns 'true'.
4266+
*/
4267+
staticbool
4268+
rescanLatestTimeLine(void)
4269+
{
4270+
TimeLineIDnewtarget;
4271+
newtarget=findNewestTimeLine(recoveryTargetTLI);
4272+
if (newtarget!=recoveryTargetTLI)
4273+
{
4274+
/*
4275+
* Determine the list of expected TLIs for the new TLI
4276+
*/
4277+
List*newExpectedTLIs;
4278+
newExpectedTLIs=readTimeLineHistory(newtarget);
4279+
4280+
/*
4281+
* If the current timeline is not part of the history of the
4282+
* new timeline, we cannot proceed to it.
4283+
*
4284+
* XXX This isn't foolproof: The new timeline might have forked from
4285+
* the current one, but before the current recovery location. In that
4286+
* case we will still switch to the new timeline and proceed replaying
4287+
* from it even though the history doesn't match what we already
4288+
* replayed. That's not good. We will likely notice at the next online
4289+
* checkpoint, as the TLI won't match what we expected, but it's
4290+
* not guaranteed. The admin needs to make sure that doesn't happen.
4291+
*/
4292+
if (!list_member_int(newExpectedTLIs,
4293+
(int)recoveryTargetTLI))
4294+
ereport(LOG,
4295+
(errmsg("new timeline %u is not a child of database system timeline %u",
4296+
newtarget,
4297+
ThisTimeLineID)));
4298+
else
4299+
{
4300+
/* Switch target */
4301+
recoveryTargetTLI=newtarget;
4302+
list_free(expectedTLIs);
4303+
expectedTLIs=newExpectedTLIs;
4304+
4305+
XLogCtl->RecoveryTargetTLI=recoveryTargetTLI;
4306+
4307+
ereport(LOG,
4308+
(errmsg("new target timeline is %u",
4309+
recoveryTargetTLI)));
4310+
return true;
4311+
}
4312+
}
4313+
return false;
4314+
}
4315+
42564316
/*
42574317
* Find the newest existing timeline, assuming that startTLI exists.
42584318
*
@@ -5327,11 +5387,13 @@ readRecoveryCommandFile(void)
53275387
(errmsg("recovery target timeline %u does not exist",
53285388
rtli)));
53295389
recoveryTargetTLI=rtli;
5390+
recoveryTargetIsLatest= false;
53305391
}
53315392
else
53325393
{
53335394
/* We start the "latest" search from pg_control's timeline */
53345395
recoveryTargetTLI=findNewestTimeLine(recoveryTargetTLI);
5396+
recoveryTargetIsLatest= true;
53355397
}
53365398
}
53375399

@@ -10032,13 +10094,24 @@ XLogPageRead(XLogRecPtr *RecPtr, int emode, bool fetching_ckpt,
1003210094
{
1003310095
/*
1003410096
* We've exhausted all options for retrieving the
10035-
* file. Retry ...
10097+
* file. Retry.
1003610098
*/
1003710099
failedSources=0;
1003810100

1003910101
/*
10040-
* ... but sleep first if it hasn't been long since
10041-
* last attempt.
10102+
* Before we sleep, re-scan for possible new timelines
10103+
* if we were requested to recover to the latest
10104+
* timeline.
10105+
*/
10106+
if (recoveryTargetIsLatest)
10107+
{
10108+
if (rescanLatestTimeLine())
10109+
continue;
10110+
}
10111+
10112+
/*
10113+
* If it hasn't been long since last attempt, sleep
10114+
* to avoid busy-waiting.
1004210115
*/
1004310116
now= (pg_time_t)time(NULL);
1004410117
if ((now-last_fail_time)<5)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp