PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
standby.c File Reference
#include "postgres.h"
#include "access/transam.h"
#include "access/twophase.h"
#include "access/xact.h"
#include "access/xlog.h"
#include "access/xloginsert.h"
#include "miscadmin.h"
#include "pgstat.h"
#include "storage/bufmgr.h"
#include "storage/lmgr.h"
#include "storage/proc.h"
#include "storage/procarray.h"
#include "storage/sinvaladt.h"
#include "storage/standby.h"
#include "utils/ps_status.h"
#include "utils/timeout.h"
#include "utils/timestamp.h"
Include dependency graph for standby.c:

Go to the source code of this file.

Macros

#define STANDBY_INITIAL_WAIT_US   1000
 

Functions

static void ResolveRecoveryConflictWithVirtualXIDs (VirtualTransactionId *waitlist, ProcSignalReason reason)
 
static void SendRecoveryConflictWithBufferPin (ProcSignalReason reason)
 
static XLogRecPtr LogCurrentRunningXacts (RunningTransactions CurrRunningXacts)
 
static void LogAccessExclusiveLocks (int nlocks, xl_standby_lock *locks)
 
void InitRecoveryTransactionEnvironment (void)
 
void ShutdownRecoveryTransactionEnvironment (void)
 
static TimestampTz GetStandbyLimitTime (void)
 
static bool WaitExceedsMaxStandbyDelay (void)
 
void ResolveRecoveryConflictWithSnapshot (TransactionId latestRemovedXid, RelFileNode node)
 
void ResolveRecoveryConflictWithTablespace (Oid tsid)
 
void ResolveRecoveryConflictWithDatabase (Oid dbid)
 
void ResolveRecoveryConflictWithLock (LOCKTAG locktag)
 
void ResolveRecoveryConflictWithBufferPin (void)
 
void CheckRecoveryConflictDeadlock (void)
 
void StandbyDeadLockHandler (void)
 
void StandbyTimeoutHandler (void)
 
void StandbyLockTimeoutHandler (void)
 
void StandbyAcquireAccessExclusiveLock (TransactionId xid, Oid dbOid, Oid relOid)
 
static void StandbyReleaseLocks (TransactionId xid)
 
void StandbyReleaseLockTree (TransactionId xid, int nsubxids, TransactionId *subxids)
 
void StandbyReleaseAllLocks (void)
 
void StandbyReleaseOldLocks (int nxids, TransactionId *xids)
 
void standby_redo (XLogReaderState *record)
 
XLogRecPtr LogStandbySnapshot (void)
 
void LogAccessExclusiveLock (Oid dbOid, Oid relOid)
 
void LogAccessExclusiveLockPrepare (void)
 
void LogStandbyInvalidations (int nmsgs, SharedInvalidationMessage *msgs, bool relcacheInitFileInval)
 

Variables

int vacuum_defer_cleanup_age
 
int max_standby_archive_delay = 30 * 1000
 
int max_standby_streaming_delay = 30 * 1000
 
static ListRecoveryLockList
 
static int standbyWait_us = STANDBY_INITIAL_WAIT_US
 

Macro Definition Documentation

#define STANDBY_INITIAL_WAIT_US   1000

Definition at line 151 of file standby.c.

Referenced by ResolveRecoveryConflictWithVirtualXIDs().

Function Documentation

void CheckRecoveryConflictDeadlock ( void  )

Definition at line 515 of file standby.c.

References Assert, ereport, errcode(), errdetail(), errmsg(), ERROR, HoldingBufferPinThatDelaysRecovery(), and InRecovery.

Referenced by ProcSleep().

516 {
517  Assert(!InRecovery); /* do not call in Startup process */
518 
520  return;
521 
522  /*
523  * Error message should match ProcessInterrupts() but we avoid calling
524  * that because we aren't handling an interrupt at this point. Note that
525  * we only cancel the current transaction here, so if we are in a
526  * subtransaction and the pin is held by a parent, then the Startup
527  * process will continue to wait even though we have avoided deadlock.
528  */
529  ereport(ERROR,
530  (errcode(ERRCODE_T_R_DEADLOCK_DETECTED),
531  errmsg("canceling statement due to conflict with recovery"),
532  errdetail("User transaction caused buffer deadlock with recovery.")));
533 }
bool InRecovery
Definition: xlog.c:192
int errcode(int sqlerrcode)
Definition: elog.c:575
#define ERROR
Definition: elog.h:43
int errdetail(const char *fmt,...)
Definition: elog.c:873
#define ereport(elevel, rest)
Definition: elog.h:122
#define Assert(condition)
Definition: c.h:675
bool HoldingBufferPinThatDelaysRecovery(void)
Definition: bufmgr.c:3692
int errmsg(const char *fmt,...)
Definition: elog.c:797
static TimestampTz GetStandbyLimitTime ( void  )
static

Definition at line 127 of file standby.c.

References GetXLogReceiptTime(), max_standby_archive_delay, max_standby_streaming_delay, and TimestampTzPlusMilliseconds.

Referenced by ResolveRecoveryConflictWithBufferPin(), ResolveRecoveryConflictWithLock(), and WaitExceedsMaxStandbyDelay().

128 {
129  TimestampTz rtime;
130  bool fromStream;
131 
132  /*
133  * The cutoff time is the last WAL data receipt time plus the appropriate
134  * delay variable. Delay of -1 means wait forever.
135  */
136  GetXLogReceiptTime(&rtime, &fromStream);
137  if (fromStream)
138  {
140  return 0; /* wait forever */
142  }
143  else
144  {
146  return 0; /* wait forever */
148  }
149 }
int max_standby_archive_delay
Definition: standby.c:38
int64 TimestampTz
Definition: timestamp.h:39
#define TimestampTzPlusMilliseconds(tz, ms)
Definition: timestamp.h:56
void GetXLogReceiptTime(TimestampTz *rtime, bool *fromStream)
Definition: xlog.c:6107
int max_standby_streaming_delay
Definition: standby.c:39
void InitRecoveryTransactionEnvironment ( void  )

Definition at line 63 of file standby.c.

References VirtualTransactionId::backendId, GetNextLocalTransactionId(), VirtualTransactionId::localTransactionId, MyBackendId, SharedInvalBackendInit(), STANDBY_INITIALIZED, standbyState, and VirtualXactLockTableInsert().

Referenced by StartupXLOG().

64 {
66 
67  /*
68  * Initialize shared invalidation management for Startup process, being
69  * careful to register ourselves as a sendOnly process so we don't need to
70  * read messages, nor will we get signalled when the queue starts filling
71  * up.
72  */
74 
75  /*
76  * Lock a virtual transaction id for Startup process.
77  *
78  * We need to do GetNextLocalTransactionId() because
79  * SharedInvalBackendInit() leaves localTransactionid invalid and the lock
80  * manager doesn't like that at all.
81  *
82  * Note that we don't need to run XactLockTableInsert() because nobody
83  * needs to wait on xids. That sounds a little strange, but table locks
84  * are held by vxids and row level locks are held by xids. All queries
85  * hold AccessShareLocks so never block while we write or lock new rows.
86  */
87  vxid.backendId = MyBackendId;
90 
92 }
BackendId MyBackendId
Definition: globals.c:72
void SharedInvalBackendInit(bool sendOnly)
Definition: sinvaladt.c:258
LocalTransactionId localTransactionId
Definition: lock.h:66
LocalTransactionId GetNextLocalTransactionId(void)
Definition: sinvaladt.c:769
void VirtualXactLockTableInsert(VirtualTransactionId vxid)
Definition: lock.c:4221
BackendId backendId
Definition: lock.h:65
HotStandbyState standbyState
Definition: xlog.c:195
void LogAccessExclusiveLock ( Oid  dbOid,
Oid  relOid 
)

Definition at line 1047 of file standby.c.

References xl_standby_lock::dbOid, GetCurrentTransactionId(), LogAccessExclusiveLocks(), MyXactFlags, xl_standby_lock::relOid, XACT_FLAGS_ACQUIREDACCESSEXCLUSIVELOCK, and xl_standby_lock::xid.

Referenced by LockAcquireExtended().

1048 {
1049  xl_standby_lock xlrec;
1050 
1051  xlrec.xid = GetCurrentTransactionId();
1052 
1053  /*
1054  * Decode the locktag back to the original values, to avoid sending lots
1055  * of empty bytes with every message. See lock.h to check how a locktag
1056  * is defined for LOCKTAG_RELATION
1057  */
1058  xlrec.dbOid = dbOid;
1059  xlrec.relOid = relOid;
1060 
1061  LogAccessExclusiveLocks(1, &xlrec);
1063 }
static void LogAccessExclusiveLocks(int nlocks, xl_standby_lock *locks)
Definition: standby.c:1029
#define XACT_FLAGS_ACQUIREDACCESSEXCLUSIVELOCK
Definition: xact.h:93
TransactionId GetCurrentTransactionId(void)
Definition: xact.c:417
int MyXactFlags
Definition: xact.c:118
TransactionId xid
Definition: lockdefs.h:51
void LogAccessExclusiveLockPrepare ( void  )

Definition at line 1069 of file standby.c.

References GetCurrentTransactionId().

Referenced by LockAcquireExtended().

1070 {
1071  /*
1072  * Ensure that a TransactionId has been assigned to this transaction, for
1073  * two reasons, both related to lock release on the standby. First, we
1074  * must assign an xid so that RecordTransactionCommit() and
1075  * RecordTransactionAbort() do not optimise away the transaction
1076  * completion record which recovery relies upon to release locks. It's a
1077  * hack, but for a corner case not worth adding code for into the main
1078  * commit path. Second, we must assign an xid before the lock is recorded
1079  * in shared memory, otherwise a concurrently executing
1080  * GetRunningTransactionLocks() might see a lock associated with an
1081  * InvalidTransactionId which we later assert cannot happen.
1082  */
1083  (void) GetCurrentTransactionId();
1084 }
TransactionId GetCurrentTransactionId(void)
Definition: xact.c:417
static void LogAccessExclusiveLocks ( int  nlocks,
xl_standby_lock locks 
)
static

Definition at line 1029 of file standby.c.

References xl_standby_locks::nlocks, offsetof, XLOG_MARK_UNIMPORTANT, XLOG_STANDBY_LOCK, XLogBeginInsert(), XLogInsert(), XLogRegisterData(), and XLogSetRecordFlags().

Referenced by LogAccessExclusiveLock(), and LogStandbySnapshot().

1030 {
1031  xl_standby_locks xlrec;
1032 
1033  xlrec.nlocks = nlocks;
1034 
1035  XLogBeginInsert();
1036  XLogRegisterData((char *) &xlrec, offsetof(xl_standby_locks, locks));
1037  XLogRegisterData((char *) locks, nlocks * sizeof(xl_standby_lock));
1039 
1040  (void) XLogInsert(RM_STANDBY_ID, XLOG_STANDBY_LOCK);
1041 }
#define XLOG_STANDBY_LOCK
Definition: standbydefs.h:34
void XLogSetRecordFlags(uint8 flags)
Definition: xloginsert.c:397
void XLogRegisterData(char *data, int len)
Definition: xloginsert.c:323
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:415
#define XLOG_MARK_UNIMPORTANT
Definition: xlog.h:193
void XLogBeginInsert(void)
Definition: xloginsert.c:120
#define offsetof(type, field)
Definition: c.h:555
static XLogRecPtr LogCurrentRunningXacts ( RunningTransactions  CurrRunningXacts)
static

Definition at line 969 of file standby.c.

References DEBUG2, elog, xl_running_xacts::latestCompletedXid, RunningTransactionsData::latestCompletedXid, MinSizeOfXactRunningXacts, xl_running_xacts::nextXid, RunningTransactionsData::nextXid, xl_running_xacts::oldestRunningXid, RunningTransactionsData::oldestRunningXid, xl_running_xacts::subxcnt, RunningTransactionsData::subxcnt, xl_running_xacts::subxid_overflow, RunningTransactionsData::subxid_overflow, trace_recovery(), xl_running_xacts::xcnt, RunningTransactionsData::xcnt, RunningTransactionsData::xids, XLOG_MARK_UNIMPORTANT, XLOG_RUNNING_XACTS, XLogBeginInsert(), XLogInsert(), XLogRegisterData(), XLogSetAsyncXactLSN(), and XLogSetRecordFlags().

Referenced by LogStandbySnapshot().

970 {
971  xl_running_xacts xlrec;
972  XLogRecPtr recptr;
973 
974  xlrec.xcnt = CurrRunningXacts->xcnt;
975  xlrec.subxcnt = CurrRunningXacts->subxcnt;
976  xlrec.subxid_overflow = CurrRunningXacts->subxid_overflow;
977  xlrec.nextXid = CurrRunningXacts->nextXid;
978  xlrec.oldestRunningXid = CurrRunningXacts->oldestRunningXid;
979  xlrec.latestCompletedXid = CurrRunningXacts->latestCompletedXid;
980 
981  /* Header */
982  XLogBeginInsert();
984  XLogRegisterData((char *) (&xlrec), MinSizeOfXactRunningXacts);
985 
986  /* array of TransactionIds */
987  if (xlrec.xcnt > 0)
988  XLogRegisterData((char *) CurrRunningXacts->xids,
989  (xlrec.xcnt + xlrec.subxcnt) * sizeof(TransactionId));
990 
991  recptr = XLogInsert(RM_STANDBY_ID, XLOG_RUNNING_XACTS);
992 
993  if (CurrRunningXacts->subxid_overflow)
995  "snapshot of %u running transactions overflowed (lsn %X/%X oldest xid %u latest complete %u next xid %u)",
996  CurrRunningXacts->xcnt,
997  (uint32) (recptr >> 32), (uint32) recptr,
998  CurrRunningXacts->oldestRunningXid,
999  CurrRunningXacts->latestCompletedXid,
1000  CurrRunningXacts->nextXid);
1001  else
1003  "snapshot of %u+%u running transaction ids (lsn %X/%X oldest xid %u latest complete %u next xid %u)",
1004  CurrRunningXacts->xcnt, CurrRunningXacts->subxcnt,
1005  (uint32) (recptr >> 32), (uint32) recptr,
1006  CurrRunningXacts->oldestRunningXid,
1007  CurrRunningXacts->latestCompletedXid,
1008  CurrRunningXacts->nextXid);
1009 
1010  /*
1011  * Ensure running_xacts information is synced to disk not too far in the
1012  * future. We don't want to stall anything though (i.e. use XLogFlush()),
1013  * so we let the wal writer do it during normal operation.
1014  * XLogSetAsyncXactLSN() conveniently will mark the LSN as to-be-synced
1015  * and nudge the WALWriter into action if sleeping. Check
1016  * XLogBackgroundFlush() for details why a record might not be flushed
1017  * without it.
1018  */
1019  XLogSetAsyncXactLSN(recptr);
1020 
1021  return recptr;
1022 }
TransactionId oldestRunningXid
Definition: standby.h:76
uint32 TransactionId
Definition: c.h:397
TransactionId * xids
Definition: standby.h:79
int trace_recovery(int trace_level)
Definition: elog.c:3753
TransactionId latestCompletedXid
Definition: standby.h:77
TransactionId latestCompletedXid
Definition: standbydefs.h:54
#define DEBUG2
Definition: elog.h:24
unsigned int uint32
Definition: c.h:268
void XLogSetRecordFlags(uint8 flags)
Definition: xloginsert.c:397
#define MinSizeOfXactRunningXacts
Definition: standby.h:55
void XLogRegisterData(char *data, int len)
Definition: xloginsert.c:323
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:415
void XLogSetAsyncXactLSN(XLogRecPtr asyncXactLSN)
Definition: xlog.c:2604
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define XLOG_MARK_UNIMPORTANT
Definition: xlog.h:193
TransactionId nextXid
Definition: standbydefs.h:52
TransactionId nextXid
Definition: standby.h:75
TransactionId oldestRunningXid
Definition: standbydefs.h:53
#define XLOG_RUNNING_XACTS
Definition: standbydefs.h:35
#define elog
Definition: elog.h:219
void XLogBeginInsert(void)
Definition: xloginsert.c:120
void LogStandbyInvalidations ( int  nmsgs,
SharedInvalidationMessage msgs,
bool  relcacheInitFileInval 
)

Definition at line 1091 of file standby.c.

References xl_invalidations::dbId, MinSizeOfInvalidations, MyDatabaseId, MyDatabaseTableSpace, xl_invalidations::nmsgs, xl_invalidations::relcacheInitFileInval, xl_invalidations::tsId, XLOG_INVALIDATIONS, XLogBeginInsert(), XLogInsert(), and XLogRegisterData().

Referenced by RecordTransactionCommit().

1093 {
1094  xl_invalidations xlrec;
1095 
1096  /* prepare record */
1097  memset(&xlrec, 0, sizeof(xlrec));
1098  xlrec.dbId = MyDatabaseId;
1099  xlrec.tsId = MyDatabaseTableSpace;
1100  xlrec.relcacheInitFileInval = relcacheInitFileInval;
1101  xlrec.nmsgs = nmsgs;
1102 
1103  /* perform insertion */
1104  XLogBeginInsert();
1105  XLogRegisterData((char *) (&xlrec), MinSizeOfInvalidations);
1106  XLogRegisterData((char *) msgs,
1107  nmsgs * sizeof(SharedInvalidationMessage));
1108  XLogInsert(RM_STANDBY_ID, XLOG_INVALIDATIONS);
1109 }
#define XLOG_INVALIDATIONS
Definition: standbydefs.h:36
Oid MyDatabaseTableSpace
Definition: globals.c:78
bool relcacheInitFileInval
Definition: standbydefs.h:67
#define MinSizeOfInvalidations
Definition: standbydefs.h:72
void XLogRegisterData(char *data, int len)
Definition: xloginsert.c:323
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:415
Oid MyDatabaseId
Definition: globals.c:76
void XLogBeginInsert(void)
Definition: xloginsert.c:120
XLogRecPtr LogStandbySnapshot ( void  )

Definition at line 909 of file standby.c.

References Assert, GetRunningTransactionData(), GetRunningTransactionLocks(), LogAccessExclusiveLocks(), LogCurrentRunningXacts(), LWLockRelease(), pfree(), wal_level, WAL_LEVEL_LOGICAL, and XLogStandbyInfoActive.

Referenced by BackgroundWriterMain(), CreateCheckPoint(), and ReplicationSlotReserveWal().

910 {
911  XLogRecPtr recptr;
912  RunningTransactions running;
913  xl_standby_lock *locks;
914  int nlocks;
915 
917 
918  /*
919  * Get details of any AccessExclusiveLocks being held at the moment.
920  */
921  locks = GetRunningTransactionLocks(&nlocks);
922  if (nlocks > 0)
923  LogAccessExclusiveLocks(nlocks, locks);
924  pfree(locks);
925 
926  /*
927  * Log details of all in-progress transactions. This should be the last
928  * record we write, because standby will open up when it sees this.
929  */
930  running = GetRunningTransactionData();
931 
932  /*
933  * GetRunningTransactionData() acquired ProcArrayLock, we must release it.
934  * For Hot Standby this can be done before inserting the WAL record
935  * because ProcArrayApplyRecoveryInfo() rechecks the commit status using
936  * the clog. For logical decoding, though, the lock can't be released
937  * early because the clog might be "in the future" from the POV of the
938  * historic snapshot. This would allow for situations where we're waiting
939  * for the end of a transaction listed in the xl_running_xacts record
940  * which, according to the WAL, has committed before the xl_running_xacts
941  * record. Fortunately this routine isn't executed frequently, and it's
942  * only a shared lock.
943  */
945  LWLockRelease(ProcArrayLock);
946 
947  recptr = LogCurrentRunningXacts(running);
948 
949  /* Release lock if we kept it longer ... */
951  LWLockRelease(ProcArrayLock);
952 
953  /* GetRunningTransactionData() acquired XidGenLock, we must release it */
954  LWLockRelease(XidGenLock);
955 
956  return recptr;
957 }
static void LogAccessExclusiveLocks(int nlocks, xl_standby_lock *locks)
Definition: standby.c:1029
int wal_level
Definition: xlog.c:104
xl_standby_lock * GetRunningTransactionLocks(int *nlocks)
Definition: lock.c:3762
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
void pfree(void *pointer)
Definition: mcxt.c:950
static XLogRecPtr LogCurrentRunningXacts(RunningTransactions CurrRunningXacts)
Definition: standby.c:969
#define XLogStandbyInfoActive()
Definition: xlog.h:159
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:675
RunningTransactions GetRunningTransactionData(void)
Definition: procarray.c:1926
void ResolveRecoveryConflictWithBufferPin ( void  )

Definition at line 434 of file standby.c.

References Assert, DeadlockTimeout, EnableTimeoutParams::delay_ms, disable_all_timeouts(), enable_timeout_after(), enable_timeouts(), EnableTimeoutParams::fin_time, GetCurrentTimestamp(), GetStandbyLimitTime(), EnableTimeoutParams::id, InHotStandby, PG_WAIT_BUFFER_PIN, PROCSIG_RECOVERY_CONFLICT_BUFFERPIN, ProcWaitForSignal(), SendRecoveryConflictWithBufferPin(), STANDBY_DEADLOCK_TIMEOUT, STANDBY_TIMEOUT, TMPARAM_AFTER, TMPARAM_AT, and EnableTimeoutParams::type.

Referenced by LockBufferForCleanup().

435 {
436  TimestampTz ltime;
437 
439 
440  ltime = GetStandbyLimitTime();
441 
442  if (ltime == 0)
443  {
444  /*
445  * We're willing to wait forever for conflicts, so set timeout for
446  * deadlock check only
447  */
449  }
450  else if (GetCurrentTimestamp() >= ltime)
451  {
452  /*
453  * We're already behind, so clear a path as quickly as possible.
454  */
456  }
457  else
458  {
459  /*
460  * Wake up at ltime, and check for deadlocks as well if we will be
461  * waiting longer than deadlock_timeout
462  */
463  EnableTimeoutParams timeouts[2];
464 
465  timeouts[0].id = STANDBY_TIMEOUT;
466  timeouts[0].type = TMPARAM_AT;
467  timeouts[0].fin_time = ltime;
468  timeouts[1].id = STANDBY_DEADLOCK_TIMEOUT;
469  timeouts[1].type = TMPARAM_AFTER;
470  timeouts[1].delay_ms = DeadlockTimeout;
471  enable_timeouts(timeouts, 2);
472  }
473 
474  /* Wait to be signaled by UnpinBuffer() */
476 
477  /*
478  * Clear any timeout requests established above. We assume here that the
479  * Startup process doesn't have any other timeouts than what this function
480  * uses. If that stops being true, we could cancel the timeouts
481  * individually, but that'd be slower.
482  */
483  disable_all_timeouts(false);
484 }
static TimestampTz GetStandbyLimitTime(void)
Definition: standby.c:127
TimeoutId id
Definition: timeout.h:54
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1569
int64 TimestampTz
Definition: timestamp.h:39
TimeoutType type
Definition: timeout.h:55
#define InHotStandby
Definition: xlog.h:74
void enable_timeouts(const EnableTimeoutParams *timeouts, int count)
Definition: timeout.c:476
void disable_all_timeouts(bool keep_indicators)
Definition: timeout.c:596
static void SendRecoveryConflictWithBufferPin(ProcSignalReason reason)
Definition: standby.c:487
void ProcWaitForSignal(uint32 wait_event_info)
Definition: proc.c:1739
#define PG_WAIT_BUFFER_PIN
Definition: pgstat.h:720
void enable_timeout_after(TimeoutId id, int delay_ms)
Definition: timeout.c:428
#define Assert(condition)
Definition: c.h:675
TimestampTz fin_time
Definition: timeout.h:57
int DeadlockTimeout
Definition: proc.c:60
void ResolveRecoveryConflictWithDatabase ( Oid  dbid)

Definition at line 319 of file standby.c.

References CancelDBBackends(), CountDBBackends(), pg_usleep(), and PROCSIG_RECOVERY_CONFLICT_DATABASE.

Referenced by dbase_redo().

320 {
321  /*
322  * We don't do ResolveRecoveryConflictWithVirtualXIDs() here since that
323  * only waits for transactions and completely idle sessions would block
324  * us. This is rare enough that we do this as simply as possible: no wait,
325  * just force them off immediately.
326  *
327  * No locking is required here because we already acquired
328  * AccessExclusiveLock. Anybody trying to connect while we do this will
329  * block during InitPostgres() and then disconnect when they see the
330  * database has been removed.
331  */
332  while (CountDBBackends(dbid) > 0)
333  {
335 
336  /*
337  * Wait awhile for them to die so that we avoid flooding an
338  * unresponsive backend when system is heavily loaded.
339  */
340  pg_usleep(10000);
341  }
342 }
int CountDBBackends(Oid databaseid)
Definition: procarray.c:2723
void pg_usleep(long microsec)
Definition: signal.c:53
void CancelDBBackends(Oid databaseid, ProcSignalReason sigmode, bool conflictPending)
Definition: procarray.c:2784
void ResolveRecoveryConflictWithLock ( LOCKTAG  locktag)

Definition at line 362 of file standby.c.

References AccessExclusiveLock, Assert, disable_all_timeouts(), enable_timeouts(), EnableTimeoutParams::fin_time, GetCurrentTimestamp(), GetLockConflicts(), GetStandbyLimitTime(), EnableTimeoutParams::id, InHotStandby, LOCKTAG::locktag_type, PG_WAIT_LOCK, PROCSIG_RECOVERY_CONFLICT_LOCK, ProcWaitForSignal(), ResolveRecoveryConflictWithVirtualXIDs(), STANDBY_LOCK_TIMEOUT, TMPARAM_AT, and EnableTimeoutParams::type.

Referenced by ProcSleep().

363 {
364  TimestampTz ltime;
365 
367 
368  ltime = GetStandbyLimitTime();
369 
370  if (GetCurrentTimestamp() >= ltime)
371  {
372  /*
373  * We're already behind, so clear a path as quickly as possible.
374  */
375  VirtualTransactionId *backends;
376 
377  backends = GetLockConflicts(&locktag, AccessExclusiveLock);
380  }
381  else
382  {
383  /*
384  * Wait (or wait again) until ltime
385  */
386  EnableTimeoutParams timeouts[1];
387 
388  timeouts[0].id = STANDBY_LOCK_TIMEOUT;
389  timeouts[0].type = TMPARAM_AT;
390  timeouts[0].fin_time = ltime;
391  enable_timeouts(timeouts, 1);
392  }
393 
394  /* Wait to be signaled by the release of the Relation Lock */
396 
397  /*
398  * Clear any timeout requests established above. We assume here that the
399  * Startup process doesn't have any other outstanding timeouts than those
400  * used by this function. If that stops being true, we could cancel the
401  * timeouts individually, but that'd be slower.
402  */
403  disable_all_timeouts(false);
404 }
#define PG_WAIT_LOCK
Definition: pgstat.h:719
static TimestampTz GetStandbyLimitTime(void)
Definition: standby.c:127
TimeoutId id
Definition: timeout.h:54
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1569
int64 TimestampTz
Definition: timestamp.h:39
TimeoutType type
Definition: timeout.h:55
#define InHotStandby
Definition: xlog.h:74
void enable_timeouts(const EnableTimeoutParams *timeouts, int count)
Definition: timeout.c:476
void disable_all_timeouts(bool keep_indicators)
Definition: timeout.c:596
static void ResolveRecoveryConflictWithVirtualXIDs(VirtualTransactionId *waitlist, ProcSignalReason reason)
Definition: standby.c:194
void ProcWaitForSignal(uint32 wait_event_info)
Definition: proc.c:1739
uint8 locktag_type
Definition: lock.h:185
#define Assert(condition)
Definition: c.h:675
TimestampTz fin_time
Definition: timeout.h:57
#define AccessExclusiveLock
Definition: lockdefs.h:46
VirtualTransactionId * GetLockConflicts(const LOCKTAG *locktag, LOCKMODE lockmode)
Definition: lock.c:2745
void ResolveRecoveryConflictWithSnapshot ( TransactionId  latestRemovedXid,
RelFileNode  node 
)

Definition at line 267 of file standby.c.

References RelFileNode::dbNode, GetConflictingVirtualXIDs(), PROCSIG_RECOVERY_CONFLICT_SNAPSHOT, ResolveRecoveryConflictWithVirtualXIDs(), and TransactionIdIsValid.

Referenced by btree_xlog_delete(), btree_xlog_reuse_page(), hash_xlog_vacuum_one_page(), heap_xlog_clean(), heap_xlog_cleanup_info(), heap_xlog_freeze_page(), heap_xlog_visible(), and spgRedoVacuumRedirect().

268 {
269  VirtualTransactionId *backends;
270 
271  /*
272  * If we get passed InvalidTransactionId then we are a little surprised,
273  * but it is theoretically possible in normal running. It also happens
274  * when replaying already applied WAL records after a standby crash or
275  * restart, or when replaying an XLOG_HEAP2_VISIBLE record that marks as
276  * frozen a page which was already all-visible. If latestRemovedXid is
277  * invalid then there is no conflict. That rule applies across all record
278  * types that suffer from this conflict.
279  */
280  if (!TransactionIdIsValid(latestRemovedXid))
281  return;
282 
283  backends = GetConflictingVirtualXIDs(latestRemovedXid,
284  node.dbNode);
285 
288 }
VirtualTransactionId * GetConflictingVirtualXIDs(TransactionId limitXmin, Oid dbOid)
Definition: procarray.c:2546
static void ResolveRecoveryConflictWithVirtualXIDs(VirtualTransactionId *waitlist, ProcSignalReason reason)
Definition: standby.c:194
#define TransactionIdIsValid(xid)
Definition: transam.h:41
void ResolveRecoveryConflictWithTablespace ( Oid  tsid)

Definition at line 291 of file standby.c.

References GetConflictingVirtualXIDs(), InvalidOid, InvalidTransactionId, PROCSIG_RECOVERY_CONFLICT_TABLESPACE, and ResolveRecoveryConflictWithVirtualXIDs().

Referenced by tblspc_redo().

292 {
293  VirtualTransactionId *temp_file_users;
294 
295  /*
296  * Standby users may be currently using this tablespace for their
297  * temporary files. We only care about current users because
298  * temp_tablespace parameter will just ignore tablespaces that no longer
299  * exist.
300  *
301  * Ask everybody to cancel their queries immediately so we can ensure no
302  * temp files remain and we can remove the tablespace. Nuke the entire
303  * site from orbit, it's the only way to be sure.
304  *
305  * XXX: We could work out the pids of active backends using this
306  * tablespace by examining the temp filenames in the directory. We would
307  * then convert the pids into VirtualXIDs before attempting to cancel
308  * them.
309  *
310  * We don't wait for commit because drop tablespace is non-transactional.
311  */
313  InvalidOid);
316 }
VirtualTransactionId * GetConflictingVirtualXIDs(TransactionId limitXmin, Oid dbOid)
Definition: procarray.c:2546
static void ResolveRecoveryConflictWithVirtualXIDs(VirtualTransactionId *waitlist, ProcSignalReason reason)
Definition: standby.c:194
#define InvalidTransactionId
Definition: transam.h:31
#define InvalidOid
Definition: postgres_ext.h:36
static void ResolveRecoveryConflictWithVirtualXIDs ( VirtualTransactionId waitlist,
ProcSignalReason  reason 
)
static

Definition at line 194 of file standby.c.

References Assert, CancelVirtualTransaction(), get_ps_display(), GetCurrentTimestamp(), NULL, palloc(), pfree(), pg_usleep(), set_ps_display(), STANDBY_INITIAL_WAIT_US, standbyWait_us, TimestampDifferenceExceeds(), update_process_title, VirtualTransactionIdIsValid, VirtualXactLock(), and WaitExceedsMaxStandbyDelay().

Referenced by ResolveRecoveryConflictWithLock(), ResolveRecoveryConflictWithSnapshot(), and ResolveRecoveryConflictWithTablespace().

196 {
197  TimestampTz waitStart;
198  char *new_status;
199 
200  /* Fast exit, to avoid a kernel call if there's no work to be done. */
201  if (!VirtualTransactionIdIsValid(*waitlist))
202  return;
203 
204  waitStart = GetCurrentTimestamp();
205  new_status = NULL; /* we haven't changed the ps display */
206 
207  while (VirtualTransactionIdIsValid(*waitlist))
208  {
209  /* reset standbyWait_us for each xact we wait for */
211 
212  /* wait until the virtual xid is gone */
213  while (!VirtualXactLock(*waitlist, false))
214  {
215  /*
216  * Report via ps if we have been waiting for more than 500 msec
217  * (should that be configurable?)
218  */
219  if (update_process_title && new_status == NULL &&
221  500))
222  {
223  const char *old_status;
224  int len;
225 
226  old_status = get_ps_display(&len);
227  new_status = (char *) palloc(len + 8 + 1);
228  memcpy(new_status, old_status, len);
229  strcpy(new_status + len, " waiting");
230  set_ps_display(new_status, false);
231  new_status[len] = '\0'; /* truncate off " waiting" */
232  }
233 
234  /* Is it time to kill it? */
236  {
237  pid_t pid;
238 
239  /*
240  * Now find out who to throw out of the balloon.
241  */
243  pid = CancelVirtualTransaction(*waitlist, reason);
244 
245  /*
246  * Wait a little bit for it to die so that we avoid flooding
247  * an unresponsive backend when system is heavily loaded.
248  */
249  if (pid != 0)
250  pg_usleep(5000L);
251  }
252  }
253 
254  /* The virtual transaction is gone now, wait for the next one */
255  waitlist++;
256  }
257 
258  /* Reset ps display if we changed it */
259  if (new_status)
260  {
261  set_ps_display(new_status, false);
262  pfree(new_status);
263  }
264 }
pid_t CancelVirtualTransaction(VirtualTransactionId vxid, ProcSignalReason sigmode)
Definition: procarray.c:2621
bool update_process_title
Definition: ps_status.c:35
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1569
int64 TimestampTz
Definition: timestamp.h:39
static int standbyWait_us
Definition: standby.c:152
void set_ps_display(const char *activity, bool force)
Definition: ps_status.c:326
bool TimestampDifferenceExceeds(TimestampTz start_time, TimestampTz stop_time, int msec)
Definition: timestamp.c:1648
bool VirtualXactLock(VirtualTransactionId vxid, bool wait)
Definition: lock.c:4291
void pg_usleep(long microsec)
Definition: signal.c:53
void pfree(void *pointer)
Definition: mcxt.c:950
#define STANDBY_INITIAL_WAIT_US
Definition: standby.c:151
const char * get_ps_display(int *displen)
Definition: ps_status.c:405
#define VirtualTransactionIdIsValid(vxid)
Definition: lock.h:72
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
void * palloc(Size size)
Definition: mcxt.c:849
static bool WaitExceedsMaxStandbyDelay(void)
Definition: standby.c:160
static void SendRecoveryConflictWithBufferPin ( ProcSignalReason  reason)
static

Definition at line 487 of file standby.c.

References Assert, CancelDBBackends(), InvalidOid, PROCSIG_RECOVERY_CONFLICT_BUFFERPIN, and PROCSIG_RECOVERY_CONFLICT_STARTUP_DEADLOCK.

Referenced by ResolveRecoveryConflictWithBufferPin(), StandbyDeadLockHandler(), and StandbyTimeoutHandler().

488 {
491 
492  /*
493  * We send signal to all backends to ask them if they are holding the
494  * buffer pin which is delaying the Startup process. We must not set the
495  * conflict flag yet, since most backends will be innocent. Let the
496  * SIGUSR1 handling in each backend decide their own fate.
497  */
498  CancelDBBackends(InvalidOid, reason, false);
499 }
void CancelDBBackends(Oid databaseid, ProcSignalReason sigmode, bool conflictPending)
Definition: procarray.c:2784
#define InvalidOid
Definition: postgres_ext.h:36
#define Assert(condition)
Definition: c.h:675
void ShutdownRecoveryTransactionEnvironment ( void  )

Definition at line 102 of file standby.c.

References ExpireAllKnownAssignedTransactionIds(), StandbyReleaseAllLocks(), and VirtualXactLockTableCleanup().

Referenced by StartupXLOG().

103 {
104  /* Mark all tracked in-progress transactions as finished. */
106 
107  /* Release all locks the tracked transactions were holding */
109 
110  /* Cleanup our VirtualTransaction */
112 }
void VirtualXactLockTableCleanup(void)
Definition: lock.c:4244
void ExpireAllKnownAssignedTransactionIds(void)
Definition: procarray.c:3255
void StandbyReleaseAllLocks(void)
Definition: standby.c:690
void standby_redo ( XLogReaderState record)

Definition at line 792 of file standby.c.

References Assert, xl_invalidations::dbId, xl_standby_lock::dbOid, elog, i, xl_running_xacts::latestCompletedXid, RunningTransactionsData::latestCompletedXid, xl_standby_locks::locks, xl_invalidations::msgs, xl_running_xacts::nextXid, RunningTransactionsData::nextXid, xl_standby_locks::nlocks, xl_invalidations::nmsgs, xl_running_xacts::oldestRunningXid, RunningTransactionsData::oldestRunningXid, PANIC, ProcArrayApplyRecoveryInfo(), ProcessCommittedInvalidationMessages(), xl_invalidations::relcacheInitFileInval, xl_standby_lock::relOid, STANDBY_DISABLED, StandbyAcquireAccessExclusiveLock(), standbyState, xl_running_xacts::subxcnt, RunningTransactionsData::subxcnt, xl_running_xacts::subxid_overflow, RunningTransactionsData::subxid_overflow, xl_invalidations::tsId, xl_running_xacts::xcnt, RunningTransactionsData::xcnt, xl_standby_lock::xid, xl_running_xacts::xids, RunningTransactionsData::xids, XLOG_INVALIDATIONS, XLOG_RUNNING_XACTS, XLOG_STANDBY_LOCK, XLogRecGetData, XLogRecGetInfo, XLogRecHasAnyBlockRefs, and XLR_INFO_MASK.

793 {
794  uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
795 
796  /* Backup blocks are not used in standby records */
797  Assert(!XLogRecHasAnyBlockRefs(record));
798 
799  /* Do nothing if we're not in hot standby mode */
801  return;
802 
803  if (info == XLOG_STANDBY_LOCK)
804  {
805  xl_standby_locks *xlrec = (xl_standby_locks *) XLogRecGetData(record);
806  int i;
807 
808  for (i = 0; i < xlrec->nlocks; i++)
810  xlrec->locks[i].dbOid,
811  xlrec->locks[i].relOid);
812  }
813  else if (info == XLOG_RUNNING_XACTS)
814  {
815  xl_running_xacts *xlrec = (xl_running_xacts *) XLogRecGetData(record);
816  RunningTransactionsData running;
817 
818  running.xcnt = xlrec->xcnt;
819  running.subxcnt = xlrec->subxcnt;
820  running.subxid_overflow = xlrec->subxid_overflow;
821  running.nextXid = xlrec->nextXid;
822  running.latestCompletedXid = xlrec->latestCompletedXid;
823  running.oldestRunningXid = xlrec->oldestRunningXid;
824  running.xids = xlrec->xids;
825 
826  ProcArrayApplyRecoveryInfo(&running);
827  }
828  else if (info == XLOG_INVALIDATIONS)
829  {
830  xl_invalidations *xlrec = (xl_invalidations *) XLogRecGetData(record);
831 
833  xlrec->nmsgs,
834  xlrec->relcacheInitFileInval,
835  xlrec->dbId,
836  xlrec->tsId);
837  }
838  else
839  elog(PANIC, "standby_redo: unknown op code %u", info);
840 }
void ProcArrayApplyRecoveryInfo(RunningTransactions running)
Definition: procarray.c:664
TransactionId oldestRunningXid
Definition: standby.h:76
#define XLOG_INVALIDATIONS
Definition: standbydefs.h:36
unsigned char uint8
Definition: c.h:266
#define XLOG_STANDBY_LOCK
Definition: standbydefs.h:34
TransactionId * xids
Definition: standby.h:79
#define PANIC
Definition: elog.h:53
TransactionId latestCompletedXid
Definition: standby.h:77
TransactionId xids[FLEXIBLE_ARRAY_MEMBER]
Definition: standbydefs.h:56
#define XLogRecGetData(decoder)
Definition: xlogreader.h:218
TransactionId latestCompletedXid
Definition: standbydefs.h:54
bool relcacheInitFileInval
Definition: standbydefs.h:67
#define XLogRecGetInfo(decoder)
Definition: xlogreader.h:214
TransactionId xid
Definition: lockdefs.h:51
void ProcessCommittedInvalidationMessages(SharedInvalidationMessage *msgs, int nmsgs, bool RelcacheInitFileInval, Oid dbid, Oid tsid)
Definition: inval.c:865
#define Assert(condition)
Definition: c.h:675
#define XLR_INFO_MASK
Definition: xlogrecord.h:62
SharedInvalidationMessage msgs[FLEXIBLE_ARRAY_MEMBER]
Definition: standbydefs.h:69
TransactionId nextXid
Definition: standbydefs.h:52
xl_standby_lock locks[FLEXIBLE_ARRAY_MEMBER]
Definition: standbydefs.h:41
TransactionId nextXid
Definition: standby.h:75
void StandbyAcquireAccessExclusiveLock(TransactionId xid, Oid dbOid, Oid relOid)
Definition: standby.c:602
int i
TransactionId oldestRunningXid
Definition: standbydefs.h:53
#define XLOG_RUNNING_XACTS
Definition: standbydefs.h:35
#define XLogRecHasAnyBlockRefs(decoder)
Definition: xlogreader.h:220
#define elog
Definition: elog.h:219
HotStandbyState standbyState
Definition: xlog.c:195
void StandbyAcquireAccessExclusiveLock ( TransactionId  xid,
Oid  dbOid,
Oid  relOid 
)

Definition at line 602 of file standby.c.

References AccessExclusiveLock, Assert, xl_standby_lock::dbOid, DEBUG4, elog, lappend(), LockAcquireExtended(), OidIsValid, palloc(), xl_standby_lock::relOid, SET_LOCKTAG_RELATION, trace_recovery(), TransactionIdDidAbort(), TransactionIdDidCommit(), TransactionIdIsValid, and xl_standby_lock::xid.

Referenced by lock_twophase_standby_recover(), and standby_redo().

603 {
604  xl_standby_lock *newlock;
605  LOCKTAG locktag;
606 
607  /* Already processed? */
608  if (!TransactionIdIsValid(xid) ||
609  TransactionIdDidCommit(xid) ||
611  return;
612 
614  "adding recovery lock: db %u rel %u", dbOid, relOid);
615 
616  /* dbOid is InvalidOid when we are locking a shared relation. */
617  Assert(OidIsValid(relOid));
618 
619  newlock = palloc(sizeof(xl_standby_lock));
620  newlock->xid = xid;
621  newlock->dbOid = dbOid;
622  newlock->relOid = relOid;
624 
625  SET_LOCKTAG_RELATION(locktag, newlock->dbOid, newlock->relOid);
626 
627  LockAcquireExtended(&locktag, AccessExclusiveLock, true, false, false);
628 }
static List * RecoveryLockList
Definition: standby.c:41
Definition: lock.h:179
bool TransactionIdDidCommit(TransactionId transactionId)
Definition: transam.c:125
#define DEBUG4
Definition: elog.h:22
#define OidIsValid(objectId)
Definition: c.h:538
int trace_recovery(int trace_level)
Definition: elog.c:3753
#define SET_LOCKTAG_RELATION(locktag, dboid, reloid)
Definition: lock.h:194
bool TransactionIdDidAbort(TransactionId transactionId)
Definition: transam.c:181
List * lappend(List *list, void *datum)
Definition: list.c:128
TransactionId xid
Definition: lockdefs.h:51
#define Assert(condition)
Definition: c.h:675
#define AccessExclusiveLock
Definition: lockdefs.h:46
void * palloc(Size size)
Definition: mcxt.c:849
#define elog
Definition: elog.h:219
#define TransactionIdIsValid(xid)
Definition: transam.h:41
LockAcquireResult LockAcquireExtended(const LOCKTAG *locktag, LOCKMODE lockmode, bool sessionLock, bool dontWait, bool reportMemoryError)
Definition: lock.c:701
void StandbyDeadLockHandler ( void  )
void StandbyLockTimeoutHandler ( void  )

Definition at line 571 of file standby.c.

Referenced by StartupProcessMain().

572 {
573 }
void StandbyReleaseAllLocks ( void  )

Definition at line 690 of file standby.c.

References AccessExclusiveLock, xl_standby_lock::dbOid, DEBUG2, DEBUG4, elog, lfirst, list_delete_cell(), list_head(), lnext, LockRelease(), LOG, next, NULL, pfree(), xl_standby_lock::relOid, SET_LOCKTAG_RELATION, trace_recovery(), and xl_standby_lock::xid.

Referenced by ShutdownRecoveryTransactionEnvironment().

691 {
692  ListCell *cell,
693  *prev,
694  *next;
695  LOCKTAG locktag;
696 
697  elog(trace_recovery(DEBUG2), "release all standby locks");
698 
699  prev = NULL;
700  for (cell = list_head(RecoveryLockList); cell; cell = next)
701  {
702  xl_standby_lock *lock = (xl_standby_lock *) lfirst(cell);
703 
704  next = lnext(cell);
705 
707  "releasing recovery lock: xid %u db %u rel %u",
708  lock->xid, lock->dbOid, lock->relOid);
709  SET_LOCKTAG_RELATION(locktag, lock->dbOid, lock->relOid);
710  if (!LockRelease(&locktag, AccessExclusiveLock, true))
711  elog(LOG,
712  "RecoveryLockList contains entry for lock no longer recorded by lock manager: xid %u database %u relation %u",
713  lock->xid, lock->dbOid, lock->relOid);
715  pfree(lock);
716  }
717 }
static List * RecoveryLockList
Definition: standby.c:41
static int32 next
Definition: blutils.c:210
Definition: lock.h:179
#define LOG
Definition: elog.h:26
#define DEBUG4
Definition: elog.h:22
int trace_recovery(int trace_level)
Definition: elog.c:3753
void pfree(void *pointer)
Definition: mcxt.c:950
#define DEBUG2
Definition: elog.h:24
#define SET_LOCKTAG_RELATION(locktag, dboid, reloid)
Definition: lock.h:194
static ListCell * list_head(const List *l)
Definition: pg_list.h:77
#define lnext(lc)
Definition: pg_list.h:105
TransactionId xid
Definition: lockdefs.h:51
List * list_delete_cell(List *list, ListCell *cell, ListCell *prev)
Definition: list.c:528
#define NULL
Definition: c.h:229
#define lfirst(lc)
Definition: pg_list.h:106
#define AccessExclusiveLock
Definition: lockdefs.h:46
bool LockRelease(const LOCKTAG *locktag, LOCKMODE lockmode, bool sessionLock)
Definition: lock.c:1818
#define elog
Definition: elog.h:219
static void StandbyReleaseLocks ( TransactionId  xid)
static

Definition at line 631 of file standby.c.

References AccessExclusiveLock, xl_standby_lock::dbOid, DEBUG4, elog, lfirst, list_delete_cell(), list_head(), lnext, LockRelease(), LOG, next, NULL, pfree(), xl_standby_lock::relOid, SET_LOCKTAG_RELATION, trace_recovery(), TransactionIdIsValid, and xl_standby_lock::xid.

Referenced by StandbyReleaseLockTree().

632 {
633  ListCell *cell,
634  *prev,
635  *next;
636 
637  /*
638  * Release all matching locks and remove them from list
639  */
640  prev = NULL;
641  for (cell = list_head(RecoveryLockList); cell; cell = next)
642  {
643  xl_standby_lock *lock = (xl_standby_lock *) lfirst(cell);
644 
645  next = lnext(cell);
646 
647  if (!TransactionIdIsValid(xid) || lock->xid == xid)
648  {
649  LOCKTAG locktag;
650 
652  "releasing recovery lock: xid %u db %u rel %u",
653  lock->xid, lock->dbOid, lock->relOid);
654  SET_LOCKTAG_RELATION(locktag, lock->dbOid, lock->relOid);
655  if (!LockRelease(&locktag, AccessExclusiveLock, true))
656  elog(LOG,
657  "RecoveryLockList contains entry for lock no longer recorded by lock manager: xid %u database %u relation %u",
658  lock->xid, lock->dbOid, lock->relOid);
659 
661  pfree(lock);
662  }
663  else
664  prev = cell;
665  }
666 }
static List * RecoveryLockList
Definition: standby.c:41
static int32 next
Definition: blutils.c:210
Definition: lock.h:179
#define LOG
Definition: elog.h:26
#define DEBUG4
Definition: elog.h:22
int trace_recovery(int trace_level)
Definition: elog.c:3753
void pfree(void *pointer)
Definition: mcxt.c:950
#define SET_LOCKTAG_RELATION(locktag, dboid, reloid)
Definition: lock.h:194
static ListCell * list_head(const List *l)
Definition: pg_list.h:77
#define lnext(lc)
Definition: pg_list.h:105
TransactionId xid
Definition: lockdefs.h:51
List * list_delete_cell(List *list, ListCell *cell, ListCell *prev)
Definition: list.c:528
#define NULL
Definition: c.h:229
#define lfirst(lc)
Definition: pg_list.h:106
#define AccessExclusiveLock
Definition: lockdefs.h:46
bool LockRelease(const LOCKTAG *locktag, LOCKMODE lockmode, bool sessionLock)
Definition: lock.c:1818
#define elog
Definition: elog.h:219
#define TransactionIdIsValid(xid)
Definition: transam.h:41
void StandbyReleaseLockTree ( TransactionId  xid,
int  nsubxids,
TransactionId subxids 
)

Definition at line 676 of file standby.c.

References i, and StandbyReleaseLocks().

Referenced by RecoverPreparedTransactions(), xact_redo_abort(), and xact_redo_commit().

677 {
678  int i;
679 
680  StandbyReleaseLocks(xid);
681 
682  for (i = 0; i < nsubxids; i++)
683  StandbyReleaseLocks(subxids[i]);
684 }
static void StandbyReleaseLocks(TransactionId xid)
Definition: standby.c:631
int i
void StandbyReleaseOldLocks ( int  nxids,
TransactionId xids 
)

Definition at line 725 of file standby.c.

References AccessExclusiveLock, Assert, xl_standby_lock::dbOid, DEBUG4, elog, i, lfirst, list_delete_cell(), list_head(), lnext, LockRelease(), LOG, next, NULL, pfree(), xl_standby_lock::relOid, SET_LOCKTAG_RELATION, StandbyTransactionIdIsPrepared(), trace_recovery(), TransactionIdIsValid, and xl_standby_lock::xid.

Referenced by ProcArrayApplyRecoveryInfo().

726 {
727  ListCell *cell,
728  *prev,
729  *next;
730  LOCKTAG locktag;
731 
732  prev = NULL;
733  for (cell = list_head(RecoveryLockList); cell; cell = next)
734  {
735  xl_standby_lock *lock = (xl_standby_lock *) lfirst(cell);
736  bool remove = false;
737 
738  next = lnext(cell);
739 
741 
743  remove = false;
744  else
745  {
746  int i;
747  bool found = false;
748 
749  for (i = 0; i < nxids; i++)
750  {
751  if (lock->xid == xids[i])
752  {
753  found = true;
754  break;
755  }
756  }
757 
758  /*
759  * If its not a running transaction, remove it.
760  */
761  if (!found)
762  remove = true;
763  }
764 
765  if (remove)
766  {
768  "releasing recovery lock: xid %u db %u rel %u",
769  lock->xid, lock->dbOid, lock->relOid);
770  SET_LOCKTAG_RELATION(locktag, lock->dbOid, lock->relOid);
771  if (!LockRelease(&locktag, AccessExclusiveLock, true))
772  elog(LOG,
773  "RecoveryLockList contains entry for lock no longer recorded by lock manager: xid %u database %u relation %u",
774  lock->xid, lock->dbOid, lock->relOid);
776  pfree(lock);
777  }
778  else
779  prev = cell;
780  }
781 }
static List * RecoveryLockList
Definition: standby.c:41
static int32 next
Definition: blutils.c:210
Definition: lock.h:179
#define LOG
Definition: elog.h:26
#define DEBUG4
Definition: elog.h:22
int trace_recovery(int trace_level)
Definition: elog.c:3753
void pfree(void *pointer)
Definition: mcxt.c:950
#define SET_LOCKTAG_RELATION(locktag, dboid, reloid)
Definition: lock.h:194
bool StandbyTransactionIdIsPrepared(TransactionId xid)
Definition: twophase.c:1297
static ListCell * list_head(const List *l)
Definition: pg_list.h:77
#define lnext(lc)
Definition: pg_list.h:105
TransactionId xid
Definition: lockdefs.h:51
List * list_delete_cell(List *list, ListCell *cell, ListCell *prev)
Definition: list.c:528
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
#define lfirst(lc)
Definition: pg_list.h:106
#define AccessExclusiveLock
Definition: lockdefs.h:46
int i
bool LockRelease(const LOCKTAG *locktag, LOCKMODE lockmode, bool sessionLock)
Definition: lock.c:1818
#define elog
Definition: elog.h:219
#define TransactionIdIsValid(xid)
Definition: transam.h:41
void StandbyTimeoutHandler ( void  )

Definition at line 558 of file standby.c.

References disable_timeout(), PROCSIG_RECOVERY_CONFLICT_BUFFERPIN, SendRecoveryConflictWithBufferPin(), and STANDBY_DEADLOCK_TIMEOUT.

Referenced by StartupProcessMain().

559 {
560  /* forget any pending STANDBY_DEADLOCK_TIMEOUT request */
562 
564 }
static void SendRecoveryConflictWithBufferPin(ProcSignalReason reason)
Definition: standby.c:487
void disable_timeout(TimeoutId id, bool keep_indicator)
Definition: timeout.c:525
static bool WaitExceedsMaxStandbyDelay ( void  )
static

Definition at line 160 of file standby.c.

References CHECK_FOR_INTERRUPTS, GetCurrentTimestamp(), GetStandbyLimitTime(), pg_usleep(), and standbyWait_us.

Referenced by ResolveRecoveryConflictWithVirtualXIDs().

161 {
162  TimestampTz ltime;
163 
165 
166  /* Are we past the limit time? */
167  ltime = GetStandbyLimitTime();
168  if (ltime && GetCurrentTimestamp() >= ltime)
169  return true;
170 
171  /*
172  * Sleep a bit (this is essential to avoid busy-waiting).
173  */
175 
176  /*
177  * Progressively increase the sleep times, but not to more than 1s, since
178  * pg_usleep isn't interruptable on some platforms.
179  */
180  standbyWait_us *= 2;
181  if (standbyWait_us > 1000000)
182  standbyWait_us = 1000000;
183 
184  return false;
185 }
static TimestampTz GetStandbyLimitTime(void)
Definition: standby.c:127
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1569
int64 TimestampTz
Definition: timestamp.h:39
static int standbyWait_us
Definition: standby.c:152
void pg_usleep(long microsec)
Definition: signal.c:53
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:97

Variable Documentation

int max_standby_archive_delay = 30 * 1000

Definition at line 38 of file standby.c.

Referenced by GetStandbyLimitTime().

int max_standby_streaming_delay = 30 * 1000

Definition at line 39 of file standby.c.

Referenced by GetStandbyLimitTime().

List* RecoveryLockList
static

Definition at line 41 of file standby.c.

int standbyWait_us = STANDBY_INITIAL_WAIT_US
static
int vacuum_defer_cleanup_age

Definition at line 37 of file standby.c.

Referenced by GetOldestXmin(), and GetSnapshotData().