1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2025-03-29 21:47:21 +02:00

Move standby timeline check after checkpoint.

The standby timeline check was being performed using pg_control data loaded before the backup started. If the backup was started immediately after a promotion the standby might not have executed a checkpoint and written the new timeline to pg_control.

Instead perform the timeline check after the checkpoint is executed. This should ensure that the new timeline is in pg_control.
This commit is contained in:
David Steele 2022-07-22 16:24:55 -04:00 committed by GitHub
parent cbbe93f592
commit c267ba51b1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 34 additions and 5 deletions

View File

@ -17,6 +17,19 @@
<release date="XXXX-XX-XX" version="2.41dev" title="UNDER DEVELOPMENT">
<release-core-list>
<release-improvement-list>
<release-item>
<github-issue id="1816"/>
<github-pull-request id="1819"/>
<release-item-contributor-list>
<release-item-ideator id="keith.fiske"/>
<release-item-contributor id="david.steele"/>
<release-item-reviewer id="stefan.fercot"/>
</release-item-contributor-list>
<p>Move standby timeline check after checkpoint.</p>
</release-item>
<release-item>
<release-item-contributor-list>
<release-item-ideator id="cynthia.shang"/>

View File

@ -610,9 +610,6 @@ dbReplayWait(Db *const this, const String *const targetLsn, const uint32_t targe
MEM_CONTEXT_TEMP_BEGIN()
{
// Check that the timeline matches the primary
if (dbPgControl(this).timeline != targetTimeline)
THROW_FMT(DbMismatchError, "standby is on timeline %u but expected %u", dbPgControl(this).timeline, targetTimeline);
// Standby checkpoint before the backup started must be <= the target LSN. If not, it indicates that the standby was ahead
// of the primary and cannot be following it.
@ -727,6 +724,13 @@ dbReplayWait(Db *const this, const String *const targetLsn, const uint32_t targe
strZ(checkpointLsn));
}
}
// Reload pg_control in case timeline was updated by the checkpoint
this->pub.pgControl = pgControlFromFile(this->storage);
// Check that the timeline matches the primary
if (dbPgControl(this).timeline != targetTimeline)
THROW_FMT(DbMismatchError, "standby is on timeline %u but expected %u", dbPgControl(this).timeline, targetTimeline);
}
MEM_CONTEXT_TEMP_END();

View File

@ -588,6 +588,14 @@ testRun(void)
HRNPQ_MACRO_CHECKPOINT(2),
HRNPQ_MACRO_CHECKPOINT_TARGET_REACHED_GE_10(2, "5/5", true, "X/X", 0),
// Fail on timeline mismatch
HRNPQ_MACRO_REPLAY_TARGET_REACHED_GE_10(2, "5/5", false, "5/3"),
HRNPQ_MACRO_REPLAY_TARGET_REACHED_PROGRESS_GE_10(2, "5/5", false, "5/3", "5/3", false, 0),
HRNPQ_MACRO_REPLAY_TARGET_REACHED_PROGRESS_GE_10(2, "5/5", false, "5/4", "5/3", true, 0),
HRNPQ_MACRO_REPLAY_TARGET_REACHED_PROGRESS_GE_10(2, "5/5", true, "5/5", "5/4", true, 0),
HRNPQ_MACRO_CHECKPOINT(2),
HRNPQ_MACRO_CHECKPOINT_TARGET_REACHED_GE_10(2, "5/5", true, "X/X", 0),
// Close standby
HRNPQ_MACRO_CLOSE(2),
@ -610,8 +618,6 @@ testRun(void)
TEST_RESULT_STR_Z(backupStartResult.walSegmentName, "000000050000000500000005", "check wal segment name");
TEST_RESULT_STR_Z(backupStartResult.walSegmentCheck, "000000050000000500000005", "check wal segment check");
TEST_ERROR(
dbReplayWait(db.standby, STRDEF("5/5"), 77, 1000), DbMismatchError, "standby is on timeline 5 but expected 77");
TEST_ERROR(
dbReplayWait(db.standby, STRDEF("4/4"), 5, 1000), DbMismatchError, "standby checkpoint '5/5' is ahead of target '4/4'");
@ -632,6 +638,12 @@ testRun(void)
TEST_RESULT_VOID(dbReplayWait(db.standby, STRDEF("5/5"), dbPgControl(db.primary).timeline, 1000), "sync standby");
// Update timeline to demonstrate that it is reloaded in dbReplayWait()
HRN_PG_CONTROL_PUT(storagePgIdxWrite(1), PG_VERSION_93, .timeline = 6, .checkpoint = pgLsnFromStr(STRDEF("5/5")));
TEST_ERROR(
dbReplayWait(db.standby, STRDEF("5/5"), 77, 1000), DbMismatchError, "standby is on timeline 6 but expected 77");
TEST_RESULT_VOID(dbFree(db.standby), "free standby");
TEST_RESULT_STR_Z(dbBackupStop(db.primary).tablespaceMap, "TABLESPACE_MAP_DATA", "stop backup");