PostgreSQL Source Code  git master
varsup.c File Reference
#include "postgres.h"
#include "access/clog.h"
#include "access/commit_ts.h"
#include "access/subtrans.h"
#include "access/transam.h"
#include "access/xact.h"
#include "access/xlogutils.h"
#include "commands/dbcommands.h"
#include "miscadmin.h"
#include "postmaster/autovacuum.h"
#include "storage/pmsignal.h"
#include "storage/proc.h"
#include "utils/syscache.h"
Include dependency graph for varsup.c:

Go to the source code of this file.

Macros

#define VAR_OID_PREFETCH   8192
 

Functions

FullTransactionId GetNewTransactionId (bool isSubXact)
 
FullTransactionId ReadNextFullTransactionId (void)
 
void AdvanceNextFullTransactionIdPastXid (TransactionId xid)
 
void AdvanceOldestClogXid (TransactionId oldest_datfrozenxid)
 
void SetTransactionIdLimit (TransactionId oldest_datfrozenxid, Oid oldest_datoid)
 
bool ForceTransactionIdLimitUpdate (void)
 
Oid GetNewObjectId (void)
 
static void SetNextObjectId (Oid nextOid)
 
void StopGeneratingPinnedObjectIds (void)
 

Variables

VariableCache ShmemVariableCache = NULL
 

Macro Definition Documentation

◆ VAR_OID_PREFETCH

#define VAR_OID_PREFETCH   8192

Definition at line 31 of file varsup.c.

Function Documentation

◆ AdvanceNextFullTransactionIdPastXid()

void AdvanceNextFullTransactionIdPastXid ( TransactionId  xid)

Definition at line 277 of file varsup.c.

278 {
279  FullTransactionId newNextFullXid;
280  TransactionId next_xid;
281  uint32 epoch;
282 
283  /*
284  * It is safe to read nextXid without a lock, because this is only called
285  * from the startup process or single-process mode, meaning that no other
286  * process can modify it.
287  */
289 
290  /* Fast return if this isn't an xid high enough to move the needle. */
292  if (!TransactionIdFollowsOrEquals(xid, next_xid))
293  return;
294 
295  /*
296  * Compute the FullTransactionId that comes after the given xid. To do
297  * this, we preserve the existing epoch, but detect when we've wrapped
298  * into a new epoch. This is necessary because WAL records and 2PC state
299  * currently contain 32 bit xids. The wrap logic is safe in those cases
300  * because the span of active xids cannot exceed one epoch at any given
301  * point in the WAL stream.
302  */
305  if (unlikely(xid < next_xid))
306  ++epoch;
307  newNextFullXid = FullTransactionIdFromEpochAndXid(epoch, xid);
308 
309  /*
310  * We still need to take a lock to modify the value when there are
311  * concurrent readers.
312  */
313  LWLockAcquire(XidGenLock, LW_EXCLUSIVE);
314  ShmemVariableCache->nextXid = newNextFullXid;
315  LWLockRelease(XidGenLock);
316 }
unsigned int uint32
Definition: c.h:495
#define unlikely(x)
Definition: c.h:300
uint32 TransactionId
Definition: c.h:641
bool IsUnderPostmaster
Definition: globals.c:113
Assert(fmt[strlen(fmt) - 1] !='\n')
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1195
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1808
@ LW_EXCLUSIVE
Definition: lwlock.h:116
#define AmStartupProcess()
Definition: miscadmin.h:452
FullTransactionId nextXid
Definition: transam.h:220
bool TransactionIdFollowsOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:329
#define EpochFromFullTransactionId(x)
Definition: transam.h:47
#define XidFromFullTransactionId(x)
Definition: transam.h:48
static FullTransactionId FullTransactionIdFromEpochAndXid(uint32 epoch, TransactionId xid)
Definition: transam.h:71
#define TransactionIdAdvance(dest)
Definition: transam.h:91
VariableCache ShmemVariableCache
Definition: varsup.c:34
static const unsigned __int64 epoch

References AmStartupProcess, Assert(), epoch, EpochFromFullTransactionId, FullTransactionIdFromEpochAndXid(), IsUnderPostmaster, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), VariableCacheData::nextXid, ShmemVariableCache, TransactionIdAdvance, TransactionIdFollowsOrEquals(), unlikely, and XidFromFullTransactionId.

Referenced by ApplyWalRecord(), multixact_redo(), ProcArrayApplyRecoveryInfo(), ProcessTwoPhaseBuffer(), RecordKnownAssignedTransactionIds(), xact_redo_abort(), and xact_redo_commit().

◆ AdvanceOldestClogXid()

void AdvanceOldestClogXid ( TransactionId  oldest_datfrozenxid)

Definition at line 328 of file varsup.c.

329 {
330  LWLockAcquire(XactTruncationLock, LW_EXCLUSIVE);
332  oldest_datfrozenxid))
333  {
334  ShmemVariableCache->oldestClogXid = oldest_datfrozenxid;
335  }
336  LWLockRelease(XactTruncationLock);
337 }
TransactionId oldestClogXid
Definition: transam.h:253
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:280

References LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), VariableCacheData::oldestClogXid, ShmemVariableCache, and TransactionIdPrecedes().

Referenced by BootStrapXLOG(), clog_redo(), StartupXLOG(), and TruncateCLOG().

◆ ForceTransactionIdLimitUpdate()

bool ForceTransactionIdLimitUpdate ( void  )

Definition at line 490 of file varsup.c.

491 {
492  TransactionId nextXid;
493  TransactionId xidVacLimit;
494  TransactionId oldestXid;
495  Oid oldestXidDB;
496 
497  /* Locking is probably not really necessary, but let's be careful */
498  LWLockAcquire(XidGenLock, LW_SHARED);
500  xidVacLimit = ShmemVariableCache->xidVacLimit;
501  oldestXid = ShmemVariableCache->oldestXid;
502  oldestXidDB = ShmemVariableCache->oldestXidDB;
503  LWLockRelease(XidGenLock);
504 
505  if (!TransactionIdIsNormal(oldestXid))
506  return true; /* shouldn't happen, but just in case */
507  if (!TransactionIdIsValid(xidVacLimit))
508  return true; /* this shouldn't happen anymore either */
509  if (TransactionIdFollowsOrEquals(nextXid, xidVacLimit))
510  return true; /* past xidVacLimit, don't delay updating */
512  return true; /* could happen, per comments above */
513  return false;
514 }
@ LW_SHARED
Definition: lwlock.h:117
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
unsigned int Oid
Definition: postgres_ext.h:31
TransactionId oldestXid
Definition: transam.h:222
TransactionId xidVacLimit
Definition: transam.h:223
@ DATABASEOID
Definition: syscache.h:55
#define SearchSysCacheExists1(cacheId, key1)
Definition: syscache.h:191
#define TransactionIdIsValid(xid)
Definition: transam.h:41
#define TransactionIdIsNormal(xid)
Definition: transam.h:42

References DATABASEOID, LW_SHARED, LWLockAcquire(), LWLockRelease(), VariableCacheData::nextXid, ObjectIdGetDatum(), VariableCacheData::oldestXid, VariableCacheData::oldestXidDB, SearchSysCacheExists1, ShmemVariableCache, TransactionIdFollowsOrEquals(), TransactionIdIsNormal, TransactionIdIsValid, XidFromFullTransactionId, and VariableCacheData::xidVacLimit.

Referenced by vac_update_datfrozenxid().

◆ GetNewObjectId()

Oid GetNewObjectId ( void  )

Definition at line 528 of file varsup.c.

529 {
530  Oid result;
531 
532  /* safety check, we should never get this far in a HS standby */
533  if (RecoveryInProgress())
534  elog(ERROR, "cannot assign OIDs during recovery");
535 
536  LWLockAcquire(OidGenLock, LW_EXCLUSIVE);
537 
538  /*
539  * Check for wraparound of the OID counter. We *must* not return 0
540  * (InvalidOid), and in normal operation we mustn't return anything below
541  * FirstNormalObjectId since that range is reserved for initdb (see
542  * IsCatalogRelationOid()). Note we are relying on unsigned comparison.
543  *
544  * During initdb, we start the OID generator at FirstGenbkiObjectId, so we
545  * only wrap if before that point when in bootstrap or standalone mode.
546  * The first time through this routine after normal postmaster start, the
547  * counter will be forced up to FirstNormalObjectId. This mechanism
548  * leaves the OIDs between FirstGenbkiObjectId and FirstNormalObjectId
549  * available for automatic assignment during initdb, while ensuring they
550  * will never conflict with user-assigned OIDs.
551  */
553  {
555  {
556  /* wraparound, or first post-initdb assignment, in normal mode */
559  }
560  else
561  {
562  /* we may be bootstrapping, so don't enforce the full range */
564  {
565  /* wraparound in standalone mode (unlikely but possible) */
568  }
569  }
570  }
571 
572  /* If we run out of logged for use oids then we must log more */
573  if (ShmemVariableCache->oidCount == 0)
574  {
577  }
578 
579  result = ShmemVariableCache->nextOid;
580 
583 
584  LWLockRelease(OidGenLock);
585 
586  return result;
587 }
#define ERROR
Definition: elog.h:39
bool IsPostmasterEnvironment
Definition: globals.c:112
uint32 oidCount
Definition: transam.h:215
#define FirstGenbkiObjectId
Definition: transam.h:195
#define FirstNormalObjectId
Definition: transam.h:197
#define VAR_OID_PREFETCH
Definition: varsup.c:31
bool RecoveryInProgress(void)
Definition: xlog.c:5948
void XLogPutNextOid(Oid nextOid)
Definition: xlog.c:7531

References elog(), ERROR, FirstGenbkiObjectId, FirstNormalObjectId, IsPostmasterEnvironment, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), VariableCacheData::nextOid, VariableCacheData::oidCount, RecoveryInProgress(), ShmemVariableCache, VAR_OID_PREFETCH, and XLogPutNextOid().

Referenced by GetNewOidWithIndex(), and GetNewRelFileNumber().

◆ GetNewTransactionId()

FullTransactionId GetNewTransactionId ( bool  isSubXact)

Definition at line 50 of file varsup.c.

51 {
52  FullTransactionId full_xid;
53  TransactionId xid;
54 
55  /*
56  * Workers synchronize transaction state at the beginning of each parallel
57  * operation, so we can't account for new XIDs after that point.
58  */
59  if (IsInParallelMode())
60  elog(ERROR, "cannot assign TransactionIds during a parallel operation");
61 
62  /*
63  * During bootstrap initialization, we return the special bootstrap
64  * transaction id.
65  */
67  {
68  Assert(!isSubXact);
72  }
73 
74  /* safety check, we should never get this far in a HS standby */
75  if (RecoveryInProgress())
76  elog(ERROR, "cannot assign TransactionIds during recovery");
77 
78  LWLockAcquire(XidGenLock, LW_EXCLUSIVE);
79 
80  full_xid = ShmemVariableCache->nextXid;
81  xid = XidFromFullTransactionId(full_xid);
82 
83  /*----------
84  * Check to see if it's safe to assign another XID. This protects against
85  * catastrophic data loss due to XID wraparound. The basic rules are:
86  *
87  * If we're past xidVacLimit, start trying to force autovacuum cycles.
88  * If we're past xidWarnLimit, start issuing warnings.
89  * If we're past xidStopLimit, refuse to execute transactions, unless
90  * we are running in single-user mode (which gives an escape hatch
91  * to the DBA who somehow got past the earlier defenses).
92  *
93  * Note that this coding also appears in GetNewMultiXactId.
94  *----------
95  */
97  {
98  /*
99  * For safety's sake, we release XidGenLock while sending signals,
100  * warnings, etc. This is not so much because we care about
101  * preserving concurrency in this situation, as to avoid any
102  * possibility of deadlock while doing get_database_name(). First,
103  * copy all the shared values we'll need in this path.
104  */
108  Oid oldest_datoid = ShmemVariableCache->oldestXidDB;
109 
110  LWLockRelease(XidGenLock);
111 
112  /*
113  * To avoid swamping the postmaster with signals, we issue the autovac
114  * request only once per 64K transaction starts. This still gives
115  * plenty of chances before we get into real trouble.
116  */
117  if (IsUnderPostmaster && (xid % 65536) == 0)
119 
120  if (IsUnderPostmaster &&
121  TransactionIdFollowsOrEquals(xid, xidStopLimit))
122  {
123  char *oldest_datname = get_database_name(oldest_datoid);
124 
125  /* complain even if that DB has disappeared */
126  if (oldest_datname)
127  ereport(ERROR,
128  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
129  errmsg("database is not accepting commands to avoid wraparound data loss in database \"%s\"",
130  oldest_datname),
131  errhint("Stop the postmaster and vacuum that database in single-user mode.\n"
132  "You might also need to commit or roll back old prepared transactions, or drop stale replication slots.")));
133  else
134  ereport(ERROR,
135  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
136  errmsg("database is not accepting commands to avoid wraparound data loss in database with OID %u",
137  oldest_datoid),
138  errhint("Stop the postmaster and vacuum that database in single-user mode.\n"
139  "You might also need to commit or roll back old prepared transactions, or drop stale replication slots.")));
140  }
141  else if (TransactionIdFollowsOrEquals(xid, xidWarnLimit))
142  {
143  char *oldest_datname = get_database_name(oldest_datoid);
144 
145  /* complain even if that DB has disappeared */
146  if (oldest_datname)
148  (errmsg("database \"%s\" must be vacuumed within %u transactions",
149  oldest_datname,
150  xidWrapLimit - xid),
151  errhint("To avoid a database shutdown, execute a database-wide VACUUM in that database.\n"
152  "You might also need to commit or roll back old prepared transactions, or drop stale replication slots.")));
153  else
155  (errmsg("database with OID %u must be vacuumed within %u transactions",
156  oldest_datoid,
157  xidWrapLimit - xid),
158  errhint("To avoid a database shutdown, execute a database-wide VACUUM in that database.\n"
159  "You might also need to commit or roll back old prepared transactions, or drop stale replication slots.")));
160  }
161 
162  /* Re-acquire lock and start over */
163  LWLockAcquire(XidGenLock, LW_EXCLUSIVE);
164  full_xid = ShmemVariableCache->nextXid;
165  xid = XidFromFullTransactionId(full_xid);
166  }
167 
168  /*
169  * If we are allocating the first XID of a new page of the commit log,
170  * zero out that commit-log page before returning. We must do this while
171  * holding XidGenLock, else another xact could acquire and commit a later
172  * XID before we zero the page. Fortunately, a page of the commit log
173  * holds 32K or more transactions, so we don't have to do this very often.
174  *
175  * Extend pg_subtrans and pg_commit_ts too.
176  */
177  ExtendCLOG(xid);
178  ExtendCommitTs(xid);
179  ExtendSUBTRANS(xid);
180 
181  /*
182  * Now advance the nextXid counter. This must not happen until after we
183  * have successfully completed ExtendCLOG() --- if that routine fails, we
184  * want the next incoming transaction to try it again. We cannot assign
185  * more XIDs until there is CLOG space for them.
186  */
188 
189  /*
190  * We must store the new XID into the shared ProcArray before releasing
191  * XidGenLock. This ensures that every active XID older than
192  * latestCompletedXid is present in the ProcArray, which is essential for
193  * correct OldestXmin tracking; see src/backend/access/transam/README.
194  *
195  * Note that readers of ProcGlobal->xids/PGPROC->xid should be careful to
196  * fetch the value for each proc only once, rather than assume they can
197  * read a value multiple times and get the same answer each time. Note we
198  * are assuming that TransactionId and int fetch/store are atomic.
199  *
200  * The same comments apply to the subxact xid count and overflow fields.
201  *
202  * Use of a write barrier prevents dangerous code rearrangement in this
203  * function; other backends could otherwise e.g. be examining my subxids
204  * info concurrently, and we don't want them to see an invalid
205  * intermediate state, such as an incremented nxids before the array entry
206  * is filled.
207  *
208  * Other processes that read nxids should do so before reading xids
209  * elements with a pg_read_barrier() in between, so that they can be sure
210  * not to read an uninitialized array element; see
211  * src/backend/storage/lmgr/README.barrier.
212  *
213  * If there's no room to fit a subtransaction XID into PGPROC, set the
214  * cache-overflowed flag instead. This forces readers to look in
215  * pg_subtrans to map subtransaction XIDs up to top-level XIDs. There is a
216  * race-condition window, in that the new XID will not appear as running
217  * until its parent link has been placed into pg_subtrans. However, that
218  * will happen before anyone could possibly have a reason to inquire about
219  * the status of the XID, so it seems OK. (Snapshots taken during this
220  * window *will* include the parent XID, so they will deliver the correct
221  * answer later on when someone does have a reason to inquire.)
222  */
223  if (!isSubXact)
224  {
229 
230  /* LWLockRelease acts as barrier */
231  MyProc->xid = xid;
232  ProcGlobal->xids[MyProc->pgxactoff] = xid;
233  }
234  else
235  {
237  int nxids = MyProc->subxidStatus.count;
238 
239  Assert(substat->count == MyProc->subxidStatus.count);
241 
242  if (nxids < PGPROC_MAX_CACHED_SUBXIDS)
243  {
244  MyProc->subxids.xids[nxids] = xid;
246  MyProc->subxidStatus.count = substat->count = nxids + 1;
247  }
248  else
249  MyProc->subxidStatus.overflowed = substat->overflowed = true;
250  }
251 
252  LWLockRelease(XidGenLock);
253 
254  return full_xid;
255 }
#define pg_write_barrier()
Definition: atomics.h:154
void ExtendCLOG(TransactionId newestXact)
Definition: clog.c:839
void ExtendCommitTs(TransactionId newestXact)
Definition: commit_ts.c:796
char * get_database_name(Oid dbid)
Definition: dbcommands.c:3084
int errhint(const char *fmt,...)
Definition: elog.c:1316
int errcode(int sqlerrcode)
Definition: elog.c:858
int errmsg(const char *fmt,...)
Definition: elog.c:1069
#define WARNING
Definition: elog.h:36
#define ereport(elevel,...)
Definition: elog.h:149
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:414
void SendPostmasterSignal(PMSignalReason reason)
Definition: pmsignal.c:181
@ PMSIGNAL_START_AUTOVAC_LAUNCHER
Definition: pmsignal.h:38
#define PGPROC_MAX_CACHED_SUBXIDS
Definition: proc.h:38
PGPROC * MyProc
Definition: proc.c:66
PROC_HDR * ProcGlobal
Definition: proc.c:78
int pgxactoff
Definition: proc.h:188
XidCacheStatus subxidStatus
Definition: proc.h:254
TransactionId xid
Definition: proc.h:173
struct XidCache subxids
Definition: proc.h:256
XidCacheStatus * subxidStates
Definition: proc.h:371
TransactionId * xids
Definition: proc.h:365
TransactionId xidWrapLimit
Definition: transam.h:226
TransactionId xidWarnLimit
Definition: transam.h:224
TransactionId xidStopLimit
Definition: transam.h:225
bool overflowed
Definition: proc.h:45
uint8 count
Definition: proc.h:43
TransactionId xids[PGPROC_MAX_CACHED_SUBXIDS]
Definition: proc.h:50
void ExtendSUBTRANS(TransactionId newestXact)
Definition: subtrans.c:308
#define BootstrapTransactionId
Definition: transam.h:32
static void FullTransactionIdAdvance(FullTransactionId *dest)
Definition: transam.h:128
bool IsInParallelMode(void)
Definition: xact.c:1069

References Assert(), BootstrapTransactionId, XidCacheStatus::count, elog(), ereport, errcode(), errhint(), errmsg(), ERROR, ExtendCLOG(), ExtendCommitTs(), ExtendSUBTRANS(), FullTransactionIdAdvance(), FullTransactionIdFromEpochAndXid(), get_database_name(), IsBootstrapProcessingMode, IsInParallelMode(), IsUnderPostmaster, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MyProc, VariableCacheData::nextXid, VariableCacheData::oldestXidDB, XidCacheStatus::overflowed, pg_write_barrier, PGPROC_MAX_CACHED_SUBXIDS, PGPROC::pgxactoff, PMSIGNAL_START_AUTOVAC_LAUNCHER, ProcGlobal, RecoveryInProgress(), SendPostmasterSignal(), ShmemVariableCache, PGPROC::subxids, PROC_HDR::subxidStates, PGPROC::subxidStatus, TransactionIdFollowsOrEquals(), WARNING, PGPROC::xid, XidFromFullTransactionId, XidCache::xids, PROC_HDR::xids, VariableCacheData::xidStopLimit, VariableCacheData::xidVacLimit, VariableCacheData::xidWarnLimit, and VariableCacheData::xidWrapLimit.

Referenced by AssignTransactionId().

◆ ReadNextFullTransactionId()

FullTransactionId ReadNextFullTransactionId ( void  )

◆ SetNextObjectId()

static void SetNextObjectId ( Oid  nextOid)
static

Definition at line 596 of file varsup.c.

597 {
598  /* Safety check, this is only allowable during initdb */
600  elog(ERROR, "cannot advance OID counter anymore");
601 
602  /* Taking the lock is, therefore, just pro forma; but do it anyway */
603  LWLockAcquire(OidGenLock, LW_EXCLUSIVE);
604 
605  if (ShmemVariableCache->nextOid > nextOid)
606  elog(ERROR, "too late to advance OID counter to %u, it is now %u",
607  nextOid, ShmemVariableCache->nextOid);
608 
609  ShmemVariableCache->nextOid = nextOid;
611 
612  LWLockRelease(OidGenLock);
613 }

References elog(), ERROR, IsPostmasterEnvironment, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), VariableCacheData::nextOid, VariableCacheData::oidCount, and ShmemVariableCache.

Referenced by StopGeneratingPinnedObjectIds().

◆ SetTransactionIdLimit()

void SetTransactionIdLimit ( TransactionId  oldest_datfrozenxid,
Oid  oldest_datoid 
)

Definition at line 345 of file varsup.c.

346 {
347  TransactionId xidVacLimit;
348  TransactionId xidWarnLimit;
349  TransactionId xidStopLimit;
350  TransactionId xidWrapLimit;
351  TransactionId curXid;
352 
353  Assert(TransactionIdIsNormal(oldest_datfrozenxid));
354 
355  /*
356  * The place where we actually get into deep trouble is halfway around
357  * from the oldest potentially-existing XID. (This calculation is
358  * probably off by one or two counts, because the special XIDs reduce the
359  * size of the loop a little bit. But we throw in plenty of slop below,
360  * so it doesn't matter.)
361  */
362  xidWrapLimit = oldest_datfrozenxid + (MaxTransactionId >> 1);
363  if (xidWrapLimit < FirstNormalTransactionId)
364  xidWrapLimit += FirstNormalTransactionId;
365 
366  /*
367  * We'll refuse to continue assigning XIDs in interactive mode once we get
368  * within 3M transactions of data loss. This leaves lots of room for the
369  * DBA to fool around fixing things in a standalone backend, while not
370  * being significant compared to total XID space. (VACUUM requires an XID
371  * if it truncates at wal_level!=minimal. "VACUUM (ANALYZE)", which a DBA
372  * might do by reflex, assigns an XID. Hence, we had better be sure
373  * there's lots of XIDs left...) Also, at default BLCKSZ, this leaves two
374  * completely-idle segments. In the event of edge-case bugs involving
375  * page or segment arithmetic, idle segments render the bugs unreachable
376  * outside of single-user mode.
377  */
378  xidStopLimit = xidWrapLimit - 3000000;
379  if (xidStopLimit < FirstNormalTransactionId)
380  xidStopLimit -= FirstNormalTransactionId;
381 
382  /*
383  * We'll start complaining loudly when we get within 40M transactions of
384  * data loss. This is kind of arbitrary, but if you let your gas gauge
385  * get down to 2% of full, would you be looking for the next gas station?
386  * We need to be fairly liberal about this number because there are lots
387  * of scenarios where most transactions are done by automatic clients that
388  * won't pay attention to warnings. (No, we're not gonna make this
389  * configurable. If you know enough to configure it, you know enough to
390  * not get in this kind of trouble in the first place.)
391  */
392  xidWarnLimit = xidWrapLimit - 40000000;
393  if (xidWarnLimit < FirstNormalTransactionId)
394  xidWarnLimit -= FirstNormalTransactionId;
395 
396  /*
397  * We'll start trying to force autovacuums when oldest_datfrozenxid gets
398  * to be more than autovacuum_freeze_max_age transactions old.
399  *
400  * Note: guc.c ensures that autovacuum_freeze_max_age is in a sane range,
401  * so that xidVacLimit will be well before xidWarnLimit.
402  *
403  * Note: autovacuum_freeze_max_age is a PGC_POSTMASTER parameter so that
404  * we don't have to worry about dealing with on-the-fly changes in its
405  * value. It doesn't look practical to update shared state from a GUC
406  * assign hook (too many processes would try to execute the hook,
407  * resulting in race conditions as well as crashes of those not connected
408  * to shared memory). Perhaps this can be improved someday. See also
409  * SetMultiXactIdLimit.
410  */
411  xidVacLimit = oldest_datfrozenxid + autovacuum_freeze_max_age;
412  if (xidVacLimit < FirstNormalTransactionId)
413  xidVacLimit += FirstNormalTransactionId;
414 
415  /* Grab lock for just long enough to set the new limit values */
416  LWLockAcquire(XidGenLock, LW_EXCLUSIVE);
417  ShmemVariableCache->oldestXid = oldest_datfrozenxid;
418  ShmemVariableCache->xidVacLimit = xidVacLimit;
419  ShmemVariableCache->xidWarnLimit = xidWarnLimit;
420  ShmemVariableCache->xidStopLimit = xidStopLimit;
421  ShmemVariableCache->xidWrapLimit = xidWrapLimit;
422  ShmemVariableCache->oldestXidDB = oldest_datoid;
424  LWLockRelease(XidGenLock);
425 
426  /* Log the info */
427  ereport(DEBUG1,
428  (errmsg_internal("transaction ID wrap limit is %u, limited by database with OID %u",
429  xidWrapLimit, oldest_datoid)));
430 
431  /*
432  * If past the autovacuum force point, immediately signal an autovac
433  * request. The reason for this is that autovac only processes one
434  * database per invocation. Once it's finished cleaning up the oldest
435  * database, it'll call here, and we'll signal the postmaster to start
436  * another iteration immediately if there are still any old databases.
437  */
438  if (TransactionIdFollowsOrEquals(curXid, xidVacLimit) &&
441 
442  /* Give an immediate warning if past the wrap warn point */
443  if (TransactionIdFollowsOrEquals(curXid, xidWarnLimit) && !InRecovery)
444  {
445  char *oldest_datname;
446 
447  /*
448  * We can be called when not inside a transaction, for example during
449  * StartupXLOG(). In such a case we cannot do database access, so we
450  * must just report the oldest DB's OID.
451  *
452  * Note: it's also possible that get_database_name fails and returns
453  * NULL, for example because the database just got dropped. We'll
454  * still warn, even though the warning might now be unnecessary.
455  */
456  if (IsTransactionState())
457  oldest_datname = get_database_name(oldest_datoid);
458  else
459  oldest_datname = NULL;
460 
461  if (oldest_datname)
463  (errmsg("database \"%s\" must be vacuumed within %u transactions",
464  oldest_datname,
465  xidWrapLimit - curXid),
466  errhint("To avoid a database shutdown, execute a database-wide VACUUM in that database.\n"
467  "You might also need to commit or roll back old prepared transactions, or drop stale replication slots.")));
468  else
470  (errmsg("database with OID %u must be vacuumed within %u transactions",
471  oldest_datoid,
472  xidWrapLimit - curXid),
473  errhint("To avoid a database shutdown, execute a database-wide VACUUM in that database.\n"
474  "You might also need to commit or roll back old prepared transactions, or drop stale replication slots.")));
475  }
476 }
int autovacuum_freeze_max_age
Definition: autovacuum.c:126
int errmsg_internal(const char *fmt,...)
Definition: elog.c:1156
#define DEBUG1
Definition: elog.h:30
#define FirstNormalTransactionId
Definition: transam.h:34
#define MaxTransactionId
Definition: transam.h:35
bool IsTransactionState(void)
Definition: xact.c:378
bool InRecovery
Definition: xlogutils.c:53

References Assert(), autovacuum_freeze_max_age, DEBUG1, ereport, errhint(), errmsg(), errmsg_internal(), FirstNormalTransactionId, get_database_name(), InRecovery, IsTransactionState(), IsUnderPostmaster, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MaxTransactionId, VariableCacheData::nextXid, VariableCacheData::oldestXid, VariableCacheData::oldestXidDB, PMSIGNAL_START_AUTOVAC_LAUNCHER, SendPostmasterSignal(), ShmemVariableCache, TransactionIdFollowsOrEquals(), TransactionIdIsNormal, WARNING, XidFromFullTransactionId, VariableCacheData::xidStopLimit, VariableCacheData::xidVacLimit, VariableCacheData::xidWarnLimit, and VariableCacheData::xidWrapLimit.

Referenced by BootStrapXLOG(), StartupXLOG(), vac_truncate_clog(), and xlog_redo().

◆ StopGeneratingPinnedObjectIds()

void StopGeneratingPinnedObjectIds ( void  )

Definition at line 625 of file varsup.c.

626 {
628 }
#define FirstUnpinnedObjectId
Definition: transam.h:196
static void SetNextObjectId(Oid nextOid)
Definition: varsup.c:596

References FirstUnpinnedObjectId, and SetNextObjectId().

Referenced by pg_stop_making_pinned_objects().

Variable Documentation

◆ ShmemVariableCache