diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index dcb2d3303c..11d63bd4e8 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -1543,6 +1543,10 @@ postgres 27093 0.0 0.0 30096 2752 ? Ss 11:34 0:00 postgres: ser
WALWrite>
Waiting for a write to a WAL file.
+
+ RecoveryConflict>
+ Waiting for conflict resolution of query running on standby.
+
diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c
index 3a50488db3..9a7dca8577 100644
--- a/src/backend/postmaster/pgstat.c
+++ b/src/backend/postmaster/pgstat.c
@@ -3443,6 +3443,9 @@ pgstat_get_wait_timeout(WaitEventTimeout w)
case WAIT_EVENT_RECOVERY_APPLY_DELAY:
event_name = "RecoveryApplyDelay";
break;
+ case WAIT_EVENT_RECOVERY_CONFLICT:
+ event_name = "RecoveryConflict";
+ break;
/* no default case, so that compiler will warn */
}
diff --git a/src/backend/storage/ipc/standby.c b/src/backend/storage/ipc/standby.c
index 6259070722..17792e4678 100644
--- a/src/backend/storage/ipc/standby.c
+++ b/src/backend/storage/ipc/standby.c
@@ -148,8 +148,8 @@ GetStandbyLimitTime(void)
}
}
-#define STANDBY_INITIAL_WAIT_US 1000
-static int standbyWait_us = STANDBY_INITIAL_WAIT_US;
+#define STANDBY_INITIAL_WAIT_MS 1
+static int standbyWait_ms = STANDBY_INITIAL_WAIT_MS;
/*
* Standby wait logic for ResolveRecoveryConflictWithVirtualXIDs.
@@ -160,8 +160,7 @@ static bool
WaitExceedsMaxStandbyDelay(void)
{
TimestampTz ltime;
-
- CHECK_FOR_INTERRUPTS();
+ int rc;
/* Are we past the limit time? */
ltime = GetStandbyLimitTime();
@@ -171,15 +170,32 @@ WaitExceedsMaxStandbyDelay(void)
/*
* Sleep a bit (this is essential to avoid busy-waiting).
*/
- pg_usleep(standbyWait_us);
+ rc = WaitLatch(MyLatch,
+ WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
+ standbyWait_ms,
+ WAIT_EVENT_RECOVERY_CONFLICT);
+
+ if (rc & WL_LATCH_SET)
+ ResetLatch(MyLatch);
+
+ /* emergency bailout if postmaster has died */
+ if (rc & WL_POSTMASTER_DEATH)
+ proc_exit(1);
/*
- * Progressively increase the sleep times, but not to more than 1s, since
- * pg_usleep isn't interruptable on some platforms.
+ * Progressively increase the sleep times, but not to more than 1s.
+ * This process is expected to wake up reasonably fast after the
+ * transactions this is waiting for are committed.
*/
- standbyWait_us *= 2;
- if (standbyWait_us > 1000000)
- standbyWait_us = 1000000;
+ if (rc & WL_TIMEOUT)
+ {
+ standbyWait_ms *= 2;
+ if (standbyWait_ms > 1000)
+ standbyWait_ms = 1000;
+ }
+
+ /* An interrupt may have occurred while waiting */
+ CHECK_FOR_INTERRUPTS();
return false;
}
@@ -206,8 +222,8 @@ ResolveRecoveryConflictWithVirtualXIDs(VirtualTransactionId *waitlist,
while (VirtualTransactionIdIsValid(*waitlist))
{
- /* reset standbyWait_us for each xact we wait for */
- standbyWait_us = STANDBY_INITIAL_WAIT_US;
+ /* reset standbyWait_ms for each xact we wait for */
+ standbyWait_ms = STANDBY_INITIAL_WAIT_MS;
/* wait until the virtual xid is gone */
while (!VirtualXactLock(*waitlist, false))
diff --git a/src/include/pgstat.h b/src/include/pgstat.h
index f2daf32e1a..24148c9ac2 100644
--- a/src/include/pgstat.h
+++ b/src/include/pgstat.h
@@ -803,7 +803,8 @@ typedef enum
{
WAIT_EVENT_BASE_BACKUP_THROTTLE = PG_WAIT_TIMEOUT,
WAIT_EVENT_PG_SLEEP,
- WAIT_EVENT_RECOVERY_APPLY_DELAY
+ WAIT_EVENT_RECOVERY_APPLY_DELAY,
+ WAIT_EVENT_RECOVERY_CONFLICT
} WaitEventTimeout;
/* ----------