11
11
* Portions Copyright (c) 1994, Regents of the University of California
12
12
*
13
13
* 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 $
15
15
*
16
16
*-------------------------------------------------------------------------
17
17
*/
@@ -127,6 +127,9 @@ WaitExceedsMaxStandbyDelay(void)
127
127
long delay_secs ;
128
128
int delay_usecs ;
129
129
130
+ if (MaxStandbyDelay == -1 )
131
+ return false;
132
+
130
133
/* Are we past max_standby_delay? */
131
134
TimestampDifference (GetLatestXLogTime (), GetCurrentTimestamp (),
132
135
& delay_secs , & delay_usecs );
@@ -351,15 +354,15 @@ ResolveRecoveryConflictWithLock(Oid dbOid, Oid relOid)
351
354
* they hold one of the buffer pins that is blocking Startup process. If so,
352
355
* backends will take an appropriate error action, ERROR or FATAL.
353
356
*
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
356
359
* 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() .
363
366
*/
364
367
void
365
368
ResolveRecoveryConflictWithBufferPin (void )
@@ -368,11 +371,23 @@ ResolveRecoveryConflictWithBufferPin(void)
368
371
369
372
Assert (InHotStandby );
370
373
371
- /*
372
- * Signal immediately or set alarm for later.
373
- */
374
374
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
+ }
376
391
else
377
392
{
378
393
TimestampTz now ;
@@ -386,13 +401,25 @@ ResolveRecoveryConflictWithBufferPin(void)
386
401
& standby_delay_secs , & standby_delay_usecs );
387
402
388
403
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
+ }
390
410
else
391
411
{
392
412
TimestampTz fin_time ; /* Expected wake-up time by timer */
393
413
long timer_delay_secs ; /* Amount of time we set timer for */
394
414
int timer_delay_usecs = 0 ;
395
415
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
+
396
423
/*
397
424
* How much longer we should wait?
398
425
*/
@@ -435,15 +462,18 @@ ResolveRecoveryConflictWithBufferPin(void)
435
462
}
436
463
437
464
void
438
- SendRecoveryConflictWithBufferPin (void )
465
+ SendRecoveryConflictWithBufferPin (ProcSignalReason reason )
439
466
{
467
+ Assert (reason == PROCSIG_RECOVERY_CONFLICT_BUFFERPIN ||
468
+ reason == PROCSIG_RECOVERY_CONFLICT_STARTUP_DEADLOCK );
469
+
440
470
/*
441
471
* We send signal to all backends to ask them if they are holding
442
472
* the buffer pin which is delaying the Startup process. We must
443
473
* not set the conflict flag yet, since most backends will be innocent.
444
474
* Let the SIGUSR1 handling in each backend decide their own fate.
445
475
*/
446
- CancelDBBackends (InvalidOid , PROCSIG_RECOVERY_CONFLICT_BUFFERPIN , false);
476
+ CancelDBBackends (InvalidOid , reason , false);
447
477
}
448
478
449
479
/*
0 commit comments