aboutsummaryrefslogtreecommitdiff
path: root/src/backend/access/transam/xlog.c
diff options
context:
space:
mode:
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>2014-01-08 11:39:55 +0200
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>2014-01-08 14:33:58 +0200
commite56430c620357a3150e84e7fff9cc494031042a5 (patch)
tree1d5e8c416bf0614ced55672590b38ed5aafa94ab /src/backend/access/transam/xlog.c
parent9402169a35e8231a1ee66ade5a6e97ed97494f74 (diff)
downloadpostgresql-e56430c620357a3150e84e7fff9cc494031042a5.tar.gz
postgresql-e56430c620357a3150e84e7fff9cc494031042a5.zip
Fix bug in determining when recovery has reached consistency.
When starting WAL replay from an online checkpoint, the last replayed WAL record variable was initialized using the checkpoint record's location, even though the records between the REDO location and the checkpoint record had not been replayed yet. That was noted as "slightly confusing" but harmless in the comment, but in some cases, it fooled CheckRecoveryConsistency to incorrectly conclude that we had already reached a consistent state immediately at the beginning of WAL replay. That caused the system to accept read-only connections in hot standby mode too early, and also PANICs with message "WAL contains references to invalid pages". Fix by initializing the variables to the REDO location instead. In 9.2 and above, change CheckRecoveryConsistency() to use lastReplayedEndRecPtr variable when checking if backup end location has been reached. It was inconsistently using EndRecPtr for that check, but lastReplayedEndRecPtr when checking min recovery point. It made no difference before this patch, because in all the places where CheckRecoveryConsistency was called the two variables were the same, but it was always an accident waiting to happen, and would have been wrong after this patch anyway. Report and analysis by Tomonari Katsumata, bug #8686. Backpatch to 9.0, where hot standby was introduced.
Diffstat (limited to 'src/backend/access/transam/xlog.c')
-rw-r--r--src/backend/access/transam/xlog.c16
1 files changed, 4 insertions, 12 deletions
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index efaba469cc8..720f18116e9 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -6507,20 +6507,12 @@ StartupXLOG(void)
}
/*
- * Initialize shared replayEndRecPtr, lastReplayedEndRecPtr, and
- * recoveryLastXTime.
- *
- * This is slightly confusing if we're starting from an online
- * checkpoint; we've just read and replayed the checkpoint record, but
- * we're going to start replay from its redo pointer, which precedes
- * the location of the checkpoint record itself. So even though the
- * last record we've replayed is indeed ReadRecPtr, we haven't
- * replayed all the preceding records yet. That's OK for the current
- * use of these variables.
+ * Initialize shared variables for tracking progress of WAL replay,
+ * as if we had just replayed the record before the REDO location.
*/
SpinLockAcquire(&xlogctl->info_lck);
- xlogctl->replayEndRecPtr = ReadRecPtr;
- xlogctl->lastReplayedEndRecPtr = EndRecPtr;
+ xlogctl->replayEndRecPtr = checkPoint.redo;
+ xlogctl->lastReplayedEndRecPtr = checkPoint.redo;
xlogctl->recoveryLastXTime = 0;
xlogctl->recoveryPause = false;
SpinLockRelease(&xlogctl->info_lck);