aboutsummaryrefslogtreecommitdiff
path: root/src/backend/access/transam/xlog.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/access/transam/xlog.c')
-rw-r--r--src/backend/access/transam/xlog.c50
1 files changed, 34 insertions, 16 deletions
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index b69b082a226..2618c8d3d38 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -5039,13 +5039,19 @@ recoveryStopsHere(XLogRecord *record, bool *includeThis)
}
/*
- * Recheck shared recoveryPause by polling.
+ * Wait until shared recoveryPause flag is cleared.
*
- * XXX Can also be done with shared latch.
+ * XXX Could also be done with shared latch, avoiding the pg_usleep loop.
+ * Probably not worth the trouble though. This state shouldn't be one that
+ * anyone cares about server power consumption in.
*/
static void
recoveryPausesHere(void)
{
+ /* Don't pause unless users can connect! */
+ if (!LocalHotStandbyActive)
+ return;
+
ereport(LOG,
(errmsg("recovery has paused"),
errhint("Execute pg_xlog_replay_resume() to continue.")));
@@ -5806,7 +5812,6 @@ StartupXLOG(void)
{
bool recoveryContinue = true;
bool recoveryApply = true;
- bool recoveryPause = false;
ErrorContextCallback errcallback;
TimestampTz xtime;
@@ -5849,21 +5854,35 @@ StartupXLOG(void)
CheckRecoveryConsistency();
/*
+ * Pause WAL replay, if requested by a hot-standby session via
+ * SetRecoveryPause().
+ *
+ * Note that we intentionally don't take the info_lck spinlock
+ * here. We might therefore read a slightly stale value of
+ * the recoveryPause flag, but it can't be very stale (no
+ * worse than the last spinlock we did acquire). Since a
+ * pause request is a pretty asynchronous thing anyway,
+ * possibly responding to it one WAL record later than we
+ * otherwise would is a minor issue, so it doesn't seem worth
+ * adding another spinlock cycle to prevent that.
+ */
+ if (xlogctl->recoveryPause)
+ recoveryPausesHere();
+
+ /*
* Have we reached our recovery target?
*/
if (recoveryStopsHere(record, &recoveryApply))
{
- /*
- * Pause only if users can connect to send a resume
- * message
- */
- if (recoveryPauseAtTarget && standbyState == STANDBY_SNAPSHOT_READY)
+ if (recoveryPauseAtTarget)
{
SetRecoveryPause(true);
recoveryPausesHere();
}
reachedStopPoint = true; /* see below */
recoveryContinue = false;
+
+ /* Exit loop if we reached non-inclusive recovery target */
if (!recoveryApply)
break;
}
@@ -5896,16 +5915,9 @@ StartupXLOG(void)
*/
SpinLockAcquire(&xlogctl->info_lck);
xlogctl->replayEndRecPtr = EndRecPtr;
- recoveryPause = xlogctl->recoveryPause;
SpinLockRelease(&xlogctl->info_lck);
/*
- * Pause only if users can connect to send a resume message
- */
- if (recoveryPause && standbyState == STANDBY_SNAPSHOT_READY)
- recoveryPausesHere();
-
- /*
* If we are attempting to enter Hot Standby mode, process
* XIDs we see
*/
@@ -5948,10 +5960,16 @@ StartupXLOG(void)
xlogctl->recoveryLastRecPtr = EndRecPtr;
SpinLockRelease(&xlogctl->info_lck);
+ /* Remember this record as the last-applied one */
LastRec = ReadRecPtr;
+ /* Exit loop if we reached inclusive recovery target */
+ if (!recoveryContinue)
+ break;
+
+ /* Else, try to fetch the next WAL record */
record = ReadRecord(NULL, LOG, false);
- } while (record != NULL && recoveryContinue);
+ } while (record != NULL);
/*
* end of main redo apply loop