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:190
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:671
bool HoldingBufferPinThatDelaysRecovery(void)
Definition: bufmgr.c:3675
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
double TimestampTz
Definition: timestamp.h:51
#define TimestampTzPlusMilliseconds(tz, ms)
Definition: timestamp.h:80
void GetXLogReceiptTime(TimestampTz *rtime, bool *fromStream)
Definition: xlog.c:6049
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:193
void LogAccessExclusiveLock ( Oid  dbOid,
Oid  relOid 
)

Definition at line 1051 of file standby.c.

References xl_standby_lock::dbOid, GetTopTransactionId(), LogAccessExclusiveLocks(), xl_standby_lock::relOid, and xl_standby_lock::xid.

Referenced by LockAcquireExtended().

1052 {
1053  xl_standby_lock xlrec;
1054 
1055  xlrec.xid = GetTopTransactionId();
1056 
1057  /*
1058  * Decode the locktag back to the original values, to avoid sending lots
1059  * of empty bytes with every message. See lock.h to check how a locktag
1060  * is defined for LOCKTAG_RELATION
1061  */
1062  xlrec.dbOid = dbOid;
1063  xlrec.relOid = relOid;
1064 
1065  LogAccessExclusiveLocks(1, &xlrec);
1066 }
static void LogAccessExclusiveLocks(int nlocks, xl_standby_lock *locks)
Definition: standby.c:1033
TransactionId GetTopTransactionId(void)
Definition: xact.c:388
TransactionId xid
Definition: lockdefs.h:51
void LogAccessExclusiveLockPrepare ( void  )

Definition at line 1072 of file standby.c.

References GetTopTransactionId().

Referenced by LockAcquireExtended().

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

Definition at line 1033 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().

1034 {
1035  xl_standby_locks xlrec;
1036 
1037  xlrec.nlocks = nlocks;
1038 
1039  XLogBeginInsert();
1040  XLogRegisterData((char *) &xlrec, offsetof(xl_standby_locks, locks));
1041  XLogRegisterData((char *) locks, nlocks * sizeof(xl_standby_lock));
1043 
1044  (void) XLogInsert(RM_STANDBY_ID, XLOG_STANDBY_LOCK);
1045 }
#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:551
static XLogRecPtr LogCurrentRunningXacts ( RunningTransactions  CurrRunningXacts)
static

Definition at line 973 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().

974 {
975  xl_running_xacts xlrec;
976  XLogRecPtr recptr;
977 
978  xlrec.xcnt = CurrRunningXacts->xcnt;
979  xlrec.subxcnt = CurrRunningXacts->subxcnt;
980  xlrec.subxid_overflow = CurrRunningXacts->subxid_overflow;
981  xlrec.nextXid = CurrRunningXacts->nextXid;
982  xlrec.oldestRunningXid = CurrRunningXacts->oldestRunningXid;
983  xlrec.latestCompletedXid = CurrRunningXacts->latestCompletedXid;
984 
985  /* Header */
986  XLogBeginInsert();
988  XLogRegisterData((char *) (&xlrec), MinSizeOfXactRunningXacts);
989 
990  /* array of TransactionIds */
991  if (xlrec.xcnt > 0)
992  XLogRegisterData((char *) CurrRunningXacts->xids,
993  (xlrec.xcnt + xlrec.subxcnt) * sizeof(TransactionId));
994 
995  recptr = XLogInsert(RM_STANDBY_ID, XLOG_RUNNING_XACTS);
996 
997  if (CurrRunningXacts->subxid_overflow)
999  "snapshot of %u running transactions overflowed (lsn %X/%X oldest xid %u latest complete %u next xid %u)",
1000  CurrRunningXacts->xcnt,
1001  (uint32) (recptr >> 32), (uint32) recptr,
1002  CurrRunningXacts->oldestRunningXid,
1003  CurrRunningXacts->latestCompletedXid,
1004  CurrRunningXacts->nextXid);
1005  else
1007  "snapshot of %u+%u running transaction ids (lsn %X/%X oldest xid %u latest complete %u next xid %u)",
1008  CurrRunningXacts->xcnt, CurrRunningXacts->subxcnt,
1009  (uint32) (recptr >> 32), (uint32) recptr,
1010  CurrRunningXacts->oldestRunningXid,
1011  CurrRunningXacts->latestCompletedXid,
1012  CurrRunningXacts->nextXid);
1013 
1014  /*
1015  * Ensure running_xacts information is synced to disk not too far in the
1016  * future. We don't want to stall anything though (i.e. use XLogFlush()),
1017  * so we let the wal writer do it during normal operation.
1018  * XLogSetAsyncXactLSN() conveniently will mark the LSN as to-be-synced
1019  * and nudge the WALWriter into action if sleeping. Check
1020  * XLogBackgroundFlush() for details why a record might not be flushed
1021  * without it.
1022  */
1023  XLogSetAsyncXactLSN(recptr);
1024 
1025  return recptr;
1026 }
TransactionId oldestRunningXid
Definition: standby.h:76
uint32 TransactionId
Definition: c.h:394
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:265
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:2594
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 1094 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().

1096 {
1097  xl_invalidations xlrec;
1098 
1099  /* prepare record */
1100  memset(&xlrec, 0, sizeof(xlrec));
1101  xlrec.dbId = MyDatabaseId;
1102  xlrec.tsId = MyDatabaseTableSpace;
1103  xlrec.relcacheInitFileInval = relcacheInitFileInval;
1104  xlrec.nmsgs = nmsgs;
1105 
1106  /* perform insertion */
1107  XLogBeginInsert();
1108  XLogRegisterData((char *) (&xlrec), MinSizeOfInvalidations);
1109  XLogRegisterData((char *) msgs,
1110  nmsgs * sizeof(SharedInvalidationMessage));
1111  XLogInsert(RM_STANDBY_ID, XLOG_INVALIDATIONS);
1112 }
#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 913 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().

914 {
915  XLogRecPtr recptr;
916  RunningTransactions running;
917  xl_standby_lock *locks;
918  int nlocks;
919 
921 
922  /*
923  * Get details of any AccessExclusiveLocks being held at the moment.
924  */
925  locks = GetRunningTransactionLocks(&nlocks);
926  if (nlocks > 0)
927  LogAccessExclusiveLocks(nlocks, locks);
928  pfree(locks);
929 
930  /*
931  * Log details of all in-progress transactions. This should be the last
932  * record we write, because standby will open up when it sees this.
933  */
934  running = GetRunningTransactionData();
935 
936  /*
937  * GetRunningTransactionData() acquired ProcArrayLock, we must release it.
938  * For Hot Standby this can be done before inserting the WAL record
939  * because ProcArrayApplyRecoveryInfo() rechecks the commit status using
940  * the clog. For logical decoding, though, the lock can't be released
941  * early because the clog might be "in the future" from the POV of the
942  * historic snapshot. This would allow for situations where we're waiting
943  * for the end of a transaction listed in the xl_running_xacts record
944  * which, according to the WAL, has committed before the xl_running_xacts
945  * record. Fortunately this routine isn't executed frequently, and it's
946  * only a shared lock.
947  */
949  LWLockRelease(ProcArrayLock);
950 
951  recptr = LogCurrentRunningXacts(running);
952 
953  /* Release lock if we kept it longer ... */
955  LWLockRelease(ProcArrayLock);
956 
957  /* GetRunningTransactionData() acquired XidGenLock, we must release it */
958  LWLockRelease(XidGenLock);
959 
960  return recptr;
961 }
static void LogAccessExclusiveLocks(int nlocks, xl_standby_lock *locks)
Definition: standby.c:1033
int wal_level
Definition: xlog.c:102
xl_standby_lock * GetRunningTransactionLocks(int *nlocks)
Definition: lock.c:3762
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1714
void pfree(void *pointer)
Definition: mcxt.c:992
static XLogRecPtr LogCurrentRunningXacts(RunningTransactions CurrRunningXacts)
Definition: standby.c:973
#define XLogStandbyInfoActive()
Definition: xlog.h:159
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:671
RunningTransactions GetRunningTransactionData(void)
Definition: procarray.c:1925
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:1687
TimeoutType type
Definition: timeout.h:55
#define InHotStandby
Definition: xlog.h:74
double TimestampTz
Definition: timestamp.h:51
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:671
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:2722
void pg_usleep(long microsec)
Definition: signal.c:53
void CancelDBBackends(Oid databaseid, ProcSignalReason sigmode, bool conflictPending)
Definition: procarray.c:2783
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:1687
TimeoutType type
Definition: timeout.h:55
#define InHotStandby
Definition: xlog.h:74
double TimestampTz
Definition: timestamp.h:51
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:671
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(), 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:2545
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:2545
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:2620
bool update_process_title
Definition: ps_status.c:35
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1687
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:1820
bool VirtualXactLock(VirtualTransactionId vxid, bool wait)
Definition: lock.c:4291
void pg_usleep(long microsec)
Definition: signal.c:53
double TimestampTz
Definition: timestamp.h:51
void pfree(void *pointer)
Definition: mcxt.c:992
#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:226
#define Assert(condition)
Definition: c.h:671
void * palloc(Size size)
Definition: mcxt.c:891
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:2783
#define InvalidOid
Definition: postgres_ext.h:36
#define Assert(condition)
Definition: c.h:671
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:3254
void StandbyReleaseAllLocks(void)
Definition: standby.c:694
void standby_redo ( XLogReaderState record)

Definition at line 796 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.

797 {
798  uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
799 
800  /* Backup blocks are not used in standby records */
801  Assert(!XLogRecHasAnyBlockRefs(record));
802 
803  /* Do nothing if we're not in hot standby mode */
805  return;
806 
807  if (info == XLOG_STANDBY_LOCK)
808  {
809  xl_standby_locks *xlrec = (xl_standby_locks *) XLogRecGetData(record);
810  int i;
811 
812  for (i = 0; i < xlrec->nlocks; i++)
814  xlrec->locks[i].dbOid,
815  xlrec->locks[i].relOid);
816  }
817  else if (info == XLOG_RUNNING_XACTS)
818  {
819  xl_running_xacts *xlrec = (xl_running_xacts *) XLogRecGetData(record);
820  RunningTransactionsData running;
821 
822  running.xcnt = xlrec->xcnt;
823  running.subxcnt = xlrec->subxcnt;
824  running.subxid_overflow = xlrec->subxid_overflow;
825  running.nextXid = xlrec->nextXid;
826  running.latestCompletedXid = xlrec->latestCompletedXid;
827  running.oldestRunningXid = xlrec->oldestRunningXid;
828  running.xids = xlrec->xids;
829 
830  ProcArrayApplyRecoveryInfo(&running);
831  }
832  else if (info == XLOG_INVALIDATIONS)
833  {
834  xl_invalidations *xlrec = (xl_invalidations *) XLogRecGetData(record);
835 
837  xlrec->nmsgs,
838  xlrec->relcacheInitFileInval,
839  xlrec->dbId,
840  xlrec->tsId);
841  }
842  else
843  elog(PANIC, "standby_redo: unknown op code %u", info);
844 }
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:263
#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:202
TransactionId latestCompletedXid
Definition: standbydefs.h:54
bool relcacheInitFileInval
Definition: standbydefs.h:67
#define XLogRecGetInfo(decoder)
Definition: xlogreader.h:198
TransactionId xid
Definition: lockdefs.h:51
void ProcessCommittedInvalidationMessages(SharedInvalidationMessage *msgs, int nmsgs, bool RelcacheInitFileInval, Oid dbid, Oid tsid)
Definition: inval.c:863
#define Assert(condition)
Definition: c.h:671
#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:606
int i
TransactionId oldestRunningXid
Definition: standbydefs.h:53
#define XLOG_RUNNING_XACTS
Definition: standbydefs.h:35
#define XLogRecHasAnyBlockRefs(decoder)
Definition: xlogreader.h:204
#define elog
Definition: elog.h:219
HotStandbyState standbyState
Definition: xlog.c:193
void StandbyAcquireAccessExclusiveLock ( TransactionId  xid,
Oid  dbOid,
Oid  relOid 
)

Definition at line 606 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().

607 {
608  xl_standby_lock *newlock;
609  LOCKTAG locktag;
610 
611  /* Already processed? */
612  if (!TransactionIdIsValid(xid) ||
613  TransactionIdDidCommit(xid) ||
615  return;
616 
618  "adding recovery lock: db %u rel %u", dbOid, relOid);
619 
620  /* dbOid is InvalidOid when we are locking a shared relation. */
621  Assert(OidIsValid(relOid));
622 
623  newlock = palloc(sizeof(xl_standby_lock));
624  newlock->xid = xid;
625  newlock->dbOid = dbOid;
626  newlock->relOid = relOid;
628 
629  SET_LOCKTAG_RELATION(locktag, newlock->dbOid, newlock->relOid);
630 
631  LockAcquireExtended(&locktag, AccessExclusiveLock, true, false, false);
632 }
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:534
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:671
#define AccessExclusiveLock
Definition: lockdefs.h:46
void * palloc(Size size)
Definition: mcxt.c:891
#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 694 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().

695 {
696  ListCell *cell,
697  *prev,
698  *next;
699  LOCKTAG locktag;
700 
701  elog(trace_recovery(DEBUG2), "release all standby locks");
702 
703  prev = NULL;
704  for (cell = list_head(RecoveryLockList); cell; cell = next)
705  {
706  xl_standby_lock *lock = (xl_standby_lock *) lfirst(cell);
707 
708  next = lnext(cell);
709 
711  "releasing recovery lock: xid %u db %u rel %u",
712  lock->xid, lock->dbOid, lock->relOid);
713  SET_LOCKTAG_RELATION(locktag, lock->dbOid, lock->relOid);
714  if (!LockRelease(&locktag, AccessExclusiveLock, true))
715  elog(LOG,
716  "RecoveryLockList contains entry for lock no longer recorded by lock manager: xid %u database %u relation %u",
717  lock->xid, lock->dbOid, lock->relOid);
719  pfree(lock);
720  }
721 }
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:992
#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:226
#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 635 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().

636 {
637  ListCell *cell,
638  *prev,
639  *next;
640 
641  /*
642  * Release all matching locks and remove them from list
643  */
644  prev = NULL;
645  for (cell = list_head(RecoveryLockList); cell; cell = next)
646  {
647  xl_standby_lock *lock = (xl_standby_lock *) lfirst(cell);
648 
649  next = lnext(cell);
650 
651  if (!TransactionIdIsValid(xid) || lock->xid == xid)
652  {
653  LOCKTAG locktag;
654 
656  "releasing recovery lock: xid %u db %u rel %u",
657  lock->xid, lock->dbOid, lock->relOid);
658  SET_LOCKTAG_RELATION(locktag, lock->dbOid, lock->relOid);
659  if (!LockRelease(&locktag, AccessExclusiveLock, true))
660  elog(LOG,
661  "RecoveryLockList contains entry for lock no longer recorded by lock manager: xid %u database %u relation %u",
662  lock->xid, lock->dbOid, lock->relOid);
663 
665  pfree(lock);
666  }
667  else
668  prev = cell;
669  }
670 }
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:992
#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:226
#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 680 of file standby.c.

References i, and StandbyReleaseLocks().

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

681 {
682  int i;
683 
684  StandbyReleaseLocks(xid);
685 
686  for (i = 0; i < nsubxids; i++)
687  StandbyReleaseLocks(subxids[i]);
688 }
static void StandbyReleaseLocks(TransactionId xid)
Definition: standby.c:635
int i
void StandbyReleaseOldLocks ( int  nxids,
TransactionId xids 
)

Definition at line 729 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().

730 {
731  ListCell *cell,
732  *prev,
733  *next;
734  LOCKTAG locktag;
735 
736  prev = NULL;
737  for (cell = list_head(RecoveryLockList); cell; cell = next)
738  {
739  xl_standby_lock *lock = (xl_standby_lock *) lfirst(cell);
740  bool remove = false;
741 
742  next = lnext(cell);
743 
745 
747  remove = false;
748  else
749  {
750  int i;
751  bool found = false;
752 
753  for (i = 0; i < nxids; i++)
754  {
755  if (lock->xid == xids[i])
756  {
757  found = true;
758  break;
759  }
760  }
761 
762  /*
763  * If its not a running transaction, remove it.
764  */
765  if (!found)
766  remove = true;
767  }
768 
769  if (remove)
770  {
772  "releasing recovery lock: xid %u db %u rel %u",
773  lock->xid, lock->dbOid, lock->relOid);
774  SET_LOCKTAG_RELATION(locktag, lock->dbOid, lock->relOid);
775  if (!LockRelease(&locktag, AccessExclusiveLock, true))
776  elog(LOG,
777  "RecoveryLockList contains entry for lock no longer recorded by lock manager: xid %u database %u relation %u",
778  lock->xid, lock->dbOid, lock->relOid);
780  pfree(lock);
781  }
782  else
783  prev = cell;
784  }
785 }
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:992
#define SET_LOCKTAG_RELATION(locktag, dboid, reloid)
Definition: lock.h:194
bool StandbyTransactionIdIsPrepared(TransactionId xid)
Definition: twophase.c:1295
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:226
#define Assert(condition)
Definition: c.h:671
#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:1687
static int standbyWait_us
Definition: standby.c:152
void pg_usleep(long microsec)
Definition: signal.c:53
double TimestampTz
Definition: timestamp.h:51
#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().