diff options
Diffstat (limited to 'src/backend/storage/ipc/standby.c')
-rw-r--r-- | src/backend/storage/ipc/standby.c | 62 |
1 files changed, 46 insertions, 16 deletions
diff --git a/src/backend/storage/ipc/standby.c b/src/backend/storage/ipc/standby.c index 3b3534886c9..fc4295465a1 100644 --- a/src/backend/storage/ipc/standby.c +++ b/src/backend/storage/ipc/standby.c @@ -11,7 +11,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/storage/ipc/standby.c,v 1.11 2010/02/11 19:35:22 sriggs Exp $ + * $PostgreSQL: pgsql/src/backend/storage/ipc/standby.c,v 1.12 2010/02/13 01:32:19 sriggs Exp $ * *------------------------------------------------------------------------- */ @@ -127,6 +127,9 @@ WaitExceedsMaxStandbyDelay(void) long delay_secs; int delay_usecs; + if (MaxStandbyDelay == -1) + return false; + /* Are we past max_standby_delay? */ TimestampDifference(GetLatestXLogTime(), GetCurrentTimestamp(), &delay_secs, &delay_usecs); @@ -351,15 +354,15 @@ ResolveRecoveryConflictWithLock(Oid dbOid, Oid relOid) * they hold one of the buffer pins that is blocking Startup process. If so, * backends will take an appropriate error action, ERROR or FATAL. * - * A secondary purpose of this is to avoid deadlocks that might occur between - * the Startup process and lock waiters. Deadlocks occur because if queries + * We also check for deadlocks before we wait, though applications that cause + * these will be extremely rare. Deadlocks occur because if queries * wait on a lock, that must be behind an AccessExclusiveLock, which can only - * be clared if the Startup process replays a transaction completion record. - * If Startup process is waiting then that is a deadlock. If we allowed a - * setting of max_standby_delay that meant "wait forever" we would then need - * special code to protect against deadlock. Such deadlocks are rare, so the - * code would be almost certainly buggy, so we avoid both long waits and - * deadlocks using the same mechanism. + * be cleared if the Startup process replays a transaction completion record. + * If Startup process is also waiting then that is a deadlock. The deadlock + * can occur if the query is waiting and then the Startup sleeps, or if + * Startup is sleeping and the the query waits on a lock. We protect against + * only the former sequence here, the latter sequence is checked prior to + * the query sleeping, in CheckRecoveryConflictDeadlock(). */ void ResolveRecoveryConflictWithBufferPin(void) @@ -368,11 +371,23 @@ ResolveRecoveryConflictWithBufferPin(void) Assert(InHotStandby); - /* - * Signal immediately or set alarm for later. - */ if (MaxStandbyDelay == 0) - SendRecoveryConflictWithBufferPin(); + { + /* + * We don't want to wait, so just tell everybody holding the pin to + * get out of town. + */ + SendRecoveryConflictWithBufferPin(PROCSIG_RECOVERY_CONFLICT_BUFFERPIN); + } + else if (MaxStandbyDelay == -1) + { + /* + * Send out a request to check for buffer pin deadlocks before we wait. + * This is fairly cheap, so no need to wait for deadlock timeout before + * trying to send it out. + */ + SendRecoveryConflictWithBufferPin(PROCSIG_RECOVERY_CONFLICT_STARTUP_DEADLOCK); + } else { TimestampTz now; @@ -386,7 +401,12 @@ ResolveRecoveryConflictWithBufferPin(void) &standby_delay_secs, &standby_delay_usecs); if (standby_delay_secs >= MaxStandbyDelay) - SendRecoveryConflictWithBufferPin(); + { + /* + * We're already behind, so clear a path as quickly as possible. + */ + SendRecoveryConflictWithBufferPin(PROCSIG_RECOVERY_CONFLICT_BUFFERPIN); + } else { TimestampTz fin_time; /* Expected wake-up time by timer */ @@ -394,6 +414,13 @@ ResolveRecoveryConflictWithBufferPin(void) int timer_delay_usecs = 0; /* + * Send out a request to check for buffer pin deadlocks before we wait. + * This is fairly cheap, so no need to wait for deadlock timeout before + * trying to send it out. + */ + SendRecoveryConflictWithBufferPin(PROCSIG_RECOVERY_CONFLICT_STARTUP_DEADLOCK); + + /* * How much longer we should wait? */ timer_delay_secs = MaxStandbyDelay - standby_delay_secs; @@ -435,15 +462,18 @@ ResolveRecoveryConflictWithBufferPin(void) } void -SendRecoveryConflictWithBufferPin(void) +SendRecoveryConflictWithBufferPin(ProcSignalReason reason) { + Assert(reason == PROCSIG_RECOVERY_CONFLICT_BUFFERPIN || + reason == PROCSIG_RECOVERY_CONFLICT_STARTUP_DEADLOCK); + /* * We send signal to all backends to ask them if they are holding * the buffer pin which is delaying the Startup process. We must * not set the conflict flag yet, since most backends will be innocent. * Let the SIGUSR1 handling in each backend decide their own fate. */ - CancelDBBackends(InvalidOid, PROCSIG_RECOVERY_CONFLICT_BUFFERPIN, false); + CancelDBBackends(InvalidOid, reason, false); } /* |