1111 * Portions Copyright (c) 1994, Regents of the University of California
1212 *
1313 * IDENTIFICATION
14- * $PostgreSQL: pgsql/src/backend/storage/ipc/standby.c,v 1.11 2010/02/11 19:35:22 sriggs Exp $
14+ * $PostgreSQL: pgsql/src/backend/storage/ipc/standby.c,v 1.12 2010/02/13 01:32:19 sriggs Exp $
1515 *
1616 *-------------------------------------------------------------------------
1717 */
@@ -127,6 +127,9 @@ WaitExceedsMaxStandbyDelay(void)
127127 long delay_secs ;
128128 int delay_usecs ;
129129
130+ if (MaxStandbyDelay == -1 )
131+ return false;
132+
130133 /* Are we past max_standby_delay? */
131134 TimestampDifference (GetLatestXLogTime (), GetCurrentTimestamp (),
132135 & delay_secs , & delay_usecs );
@@ -351,15 +354,15 @@ ResolveRecoveryConflictWithLock(Oid dbOid, Oid relOid)
351354 * they hold one of the buffer pins that is blocking Startup process. If so,
352355 * backends will take an appropriate error action, ERROR or FATAL.
353356 *
354- * A secondary purpose of this is to avoid deadlocks that might occur between
355- * the Startup process and lock waiters. Deadlocks occur because if queries
357+ * We also check for deadlocks before we wait, though applications that cause
358+ * these will be extremely rare. Deadlocks occur because if queries
356359 * wait on a lock, that must be behind an AccessExclusiveLock, which can only
357- * be clared if the Startup process replays a transaction completion record.
358- * If Startup process is waiting then that is a deadlock. If we allowed a
359- * setting of max_standby_delay that meant "wait forever" we would then need
360- * special code to protect against deadlock. Such deadlocks are rare, so the
361- * code would be almost certainly buggy, so we avoid both long waits and
362- * deadlocks using the same mechanism .
360+ * be cleared if the Startup process replays a transaction completion record.
361+ * If Startup process is also waiting then that is a deadlock. The deadlock
362+ * can occur if the query is waiting and then the Startup sleeps, or if
363+ * Startup is sleeping and the the query waits on a lock. We protect against
364+ * only the former sequence here, the latter sequence is checked prior to
365+ * the query sleeping, in CheckRecoveryConflictDeadlock() .
363366 */
364367void
365368ResolveRecoveryConflictWithBufferPin (void )
@@ -368,11 +371,23 @@ ResolveRecoveryConflictWithBufferPin(void)
368371
369372 Assert (InHotStandby );
370373
371- /*
372- * Signal immediately or set alarm for later.
373- */
374374 if (MaxStandbyDelay == 0 )
375- SendRecoveryConflictWithBufferPin ();
375+ {
376+ /*
377+ * We don't want to wait, so just tell everybody holding the pin to
378+ * get out of town.
379+ */
380+ SendRecoveryConflictWithBufferPin (PROCSIG_RECOVERY_CONFLICT_BUFFERPIN );
381+ }
382+ else if (MaxStandbyDelay == -1 )
383+ {
384+ /*
385+ * Send out a request to check for buffer pin deadlocks before we wait.
386+ * This is fairly cheap, so no need to wait for deadlock timeout before
387+ * trying to send it out.
388+ */
389+ SendRecoveryConflictWithBufferPin (PROCSIG_RECOVERY_CONFLICT_STARTUP_DEADLOCK );
390+ }
376391 else
377392 {
378393 TimestampTz now ;
@@ -386,13 +401,25 @@ ResolveRecoveryConflictWithBufferPin(void)
386401 & standby_delay_secs , & standby_delay_usecs );
387402
388403 if (standby_delay_secs >= MaxStandbyDelay )
389- SendRecoveryConflictWithBufferPin ();
404+ {
405+ /*
406+ * We're already behind, so clear a path as quickly as possible.
407+ */
408+ SendRecoveryConflictWithBufferPin (PROCSIG_RECOVERY_CONFLICT_BUFFERPIN );
409+ }
390410 else
391411 {
392412 TimestampTz fin_time ; /* Expected wake-up time by timer */
393413 long timer_delay_secs ; /* Amount of time we set timer for */
394414 int timer_delay_usecs = 0 ;
395415
416+ /*
417+ * Send out a request to check for buffer pin deadlocks before we wait.
418+ * This is fairly cheap, so no need to wait for deadlock timeout before
419+ * trying to send it out.
420+ */
421+ SendRecoveryConflictWithBufferPin (PROCSIG_RECOVERY_CONFLICT_STARTUP_DEADLOCK );
422+
396423 /*
397424 * How much longer we should wait?
398425 */
@@ -435,15 +462,18 @@ ResolveRecoveryConflictWithBufferPin(void)
435462}
436463
437464void
438- SendRecoveryConflictWithBufferPin (void )
465+ SendRecoveryConflictWithBufferPin (ProcSignalReason reason )
439466{
467+ Assert (reason == PROCSIG_RECOVERY_CONFLICT_BUFFERPIN ||
468+ reason == PROCSIG_RECOVERY_CONFLICT_STARTUP_DEADLOCK );
469+
440470 /*
441471 * We send signal to all backends to ask them if they are holding
442472 * the buffer pin which is delaying the Startup process. We must
443473 * not set the conflict flag yet, since most backends will be innocent.
444474 * Let the SIGUSR1 handling in each backend decide their own fate.
445475 */
446- CancelDBBackends (InvalidOid , PROCSIG_RECOVERY_CONFLICT_BUFFERPIN , false);
476+ CancelDBBackends (InvalidOid , reason , false);
447477}
448478
449479/*
0 commit comments