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; /* ----------