On 2012-12-05 16:15:38 -0500, Tom Lane wrote:
> Simon Riggs <si...@2ndquadrant.com> writes:
> > On 5 December 2012 18:48, Tom Lane <t...@sss.pgh.pa.us> wrote:
> >> On further thought, it seems like recovery_pause_at_target is rather
> >> misdesigned anyway, and taking recovery target parameters from
> >> recovery.conf is an obsolete API that was designed in a world before hot
> >> standby.  What I suggest people really want, if they're trying to
> >> interactively determine how far to roll forward, is this:
> >> ...
>
> > Can't remember why we didn't go for the full API last time. I'll have
> > another go, in HEAD.
>
> That's fine, but the immediate question is what are we doing to fix
> the back branches.  I think everyone is clear that we should be testing
> LocalHotStandbyActive rather than precursor conditions to see if a pause
> is allowed, but are we going to do anything more than that?

I'd like to have inclusive/non-inclusive stops some resemblance of
sanity.

Raw patch including your earlier LocalHotStandbyActive one attached.

> The only other thing I really wanted to do is not have the in-loop pause
> occur after we've taken actions that are effectively part of the WAL
> apply step.  I think ideally it should happen just before or after the
> recoveryStopsHere stanza.  Last night I worried about adding an extra
> spinlock acquire to make that work, but today I wonder if we couldn't
> get away with just a naked
>
>       if (xlogctl->recoveryPause)
>               recoveryPausesHere();

> The argument for this is that although we might fetch a slightly stale
> value of the shared variable, it can't be very stale --- certainly no
> older than the spinlock acquisition near the bottom of the previous
> iteration of the loop.  And this is a highly asynchronous feature
> anyhow, so fuzziness of plus or minus one WAL record in when the pause
> gets honored is not going to be detectable.  Hence an extra spinlock
> acquisition is not worth the cost.

Seems safe enough to me.  But I am not sure its necessary, if we move
the recoveryPausesHere() down after replaying the record, fetching
inside the spinlock for recoveryLastRecPtr seems to be natural enough.

Greetings,

Andres Freund
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 187b609..e962f62 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -5923,6 +5923,10 @@ recoveryStopsHere(XLogRecord *record, bool *includeThis)
 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.")));
@@ -6697,19 +6701,18 @@ StartupXLOG(void)
 				 */
 				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;
+
+					/* break out if we have non-inclusive recovery target */
 					if (!recoveryApply)
+					{
+						recoveryPausesHere();
 						break;
+					}
 				}
 
 				/* Setup error traceback support for ereport() */
@@ -6737,19 +6740,14 @@ StartupXLOG(void)
 				/*
 				 * Update shared replayEndRecPtr before replaying this record,
 				 * so that XLogFlush will update minRecoveryPoint correctly.
+				 *
+				 * While we have the lock, also check for a pause request.
 				 */
 				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
 				 */
@@ -6790,10 +6788,19 @@ StartupXLOG(void)
 				 */
 				SpinLockAcquire(&xlogctl->info_lck);
 				xlogctl->recoveryLastRecPtr = EndRecPtr;
+				recoveryPause = xlogctl->recoveryPause;
 				SpinLockRelease(&xlogctl->info_lck);
 
 				LastRec = ReadRecPtr;
 
+
+				if (recoveryPause)
+					recoveryPausesHere();
+
+				/* if we have inclusive recovery target */
+				if (!recoveryStopsHere)
+					break;
+
 				record = ReadRecord(NULL, LOG, false);
 			} while (record != NULL && recoveryContinue);
 
-- 
Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-bugs

Reply via email to