make_wal_replay_pause_synchronous.patch
text/x-patch
Filename: make_wal_replay_pause_synchronous.patch
Type: text/x-patch
Part: 0
Message:
Re: Is Recovery actually paused?
Patch
Format: unified
| File | + | − |
|---|---|---|
| src/backend/access/transam/xlog.c | 25 | 5 |
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 8e3b5df7dc..26aadb4178 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -6076,6 +6076,20 @@ void
SetRecoveryPause(bool recoveryPause)
{
SpinLockAcquire(&XLogCtl->info_lck);
+
+ /*
+ * Wait for the application of the record being applied to finish, so that
+ * no records will be applied after this function returns. We don't need to
+ * wait when ending a pause. Anyway we are requesting a recovery pause, we
+ * don't mind a possible slow down of recovery by the info_lck here.
+ */
+ while(recoveryPause && !XLogCtl->recoveryPause &&
+ XLogCtl->replayEndRecPtr != XLogCtl->lastReplayedEndRecPtr)
+ {
+ SpinLockRelease(&XLogCtl->info_lck);
+ pg_usleep(10000L); /* 10 ms */
+ SpinLockAcquire(&XLogCtl->info_lck);
+ }
XLogCtl->recoveryPause = recoveryPause;
SpinLockRelease(&XLogCtl->info_lck);
}
@@ -7262,6 +7276,7 @@ StartupXLOG(void)
do
{
bool switchedTLI = false;
+ bool pause_requested = false;
#ifdef WAL_DEBUG
if (XLOG_DEBUG ||
@@ -7292,11 +7307,9 @@ StartupXLOG(void)
* 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.
+ * worse than the last spinlock we did acquire). We eventually
+ * make sure catching the pause request if any just before
+ * applying this record.
*/
if (((volatile XLogCtlData *) XLogCtl)->recoveryPause)
recoveryPausesHere(false);
@@ -7385,12 +7398,19 @@ StartupXLOG(void)
/*
* Update shared replayEndRecPtr before replaying this record,
* so that XLogFlush will update minRecoveryPoint correctly.
+ * Also we check for the correct value of the recoveryPause
+ * flag here not to have redo overrun during a pause. See
+ * SetRecoveryPuase() for details.
*/
SpinLockAcquire(&XLogCtl->info_lck);
XLogCtl->replayEndRecPtr = EndRecPtr;
XLogCtl->replayEndTLI = ThisTimeLineID;
+ pause_requested = XLogCtl->recoveryPause;
SpinLockRelease(&XLogCtl->info_lck);
+ if (pause_requested)
+ recoveryPausesHere(false);
+
/*
* If we are attempting to enter Hot Standby mode, process
* XIDs we see