Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * varsup.c
4 : * postgres OID & XID variables support routines
5 : *
6 : * Copyright (c) 2000-2017, PostgreSQL Global Development Group
7 : *
8 : * IDENTIFICATION
9 : * src/backend/access/transam/varsup.c
10 : *
11 : *-------------------------------------------------------------------------
12 : */
13 :
14 : #include "postgres.h"
15 :
16 : #include "access/clog.h"
17 : #include "access/commit_ts.h"
18 : #include "access/subtrans.h"
19 : #include "access/transam.h"
20 : #include "access/xact.h"
21 : #include "access/xlog.h"
22 : #include "commands/dbcommands.h"
23 : #include "miscadmin.h"
24 : #include "postmaster/autovacuum.h"
25 : #include "storage/pmsignal.h"
26 : #include "storage/proc.h"
27 : #include "utils/syscache.h"
28 :
29 :
30 : /* Number of OIDs to prefetch (preallocate) per XLOG write */
31 : #define VAR_OID_PREFETCH 8192
32 :
33 : /* pointer to "variable cache" in shared memory (set up by shmem.c) */
34 : VariableCache ShmemVariableCache = NULL;
35 :
36 :
37 : /*
38 : * Allocate the next XID for a new transaction or subtransaction.
39 : *
40 : * The new XID is also stored into MyPgXact before returning.
41 : *
42 : * Note: when this is called, we are actually already inside a valid
43 : * transaction, since XIDs are now not allocated until the transaction
44 : * does something. So it is safe to do a database lookup if we want to
45 : * issue a warning about XID wrap.
46 : */
47 : TransactionId
48 10626 : GetNewTransactionId(bool isSubXact)
49 : {
50 : TransactionId xid;
51 :
52 : /*
53 : * Workers synchronize transaction state at the beginning of each parallel
54 : * operation, so we can't account for new XIDs after that point.
55 : */
56 10626 : if (IsInParallelMode())
57 0 : elog(ERROR, "cannot assign TransactionIds during a parallel operation");
58 :
59 : /*
60 : * During bootstrap initialization, we return the special bootstrap
61 : * transaction id.
62 : */
63 10626 : if (IsBootstrapProcessingMode())
64 : {
65 1 : Assert(!isSubXact);
66 1 : MyPgXact->xid = BootstrapTransactionId;
67 1 : return BootstrapTransactionId;
68 : }
69 :
70 : /* safety check, we should never get this far in a HS standby */
71 10625 : if (RecoveryInProgress())
72 0 : elog(ERROR, "cannot assign TransactionIds during recovery");
73 :
74 10625 : LWLockAcquire(XidGenLock, LW_EXCLUSIVE);
75 :
76 10625 : xid = ShmemVariableCache->nextXid;
77 :
78 : /*----------
79 : * Check to see if it's safe to assign another XID. This protects against
80 : * catastrophic data loss due to XID wraparound. The basic rules are:
81 : *
82 : * If we're past xidVacLimit, start trying to force autovacuum cycles.
83 : * If we're past xidWarnLimit, start issuing warnings.
84 : * If we're past xidStopLimit, refuse to execute transactions, unless
85 : * we are running in single-user mode (which gives an escape hatch
86 : * to the DBA who somehow got past the earlier defenses).
87 : *
88 : * Note that this coding also appears in GetNewMultiXactId.
89 : *----------
90 : */
91 10625 : if (TransactionIdFollowsOrEquals(xid, ShmemVariableCache->xidVacLimit))
92 : {
93 : /*
94 : * For safety's sake, we release XidGenLock while sending signals,
95 : * warnings, etc. This is not so much because we care about
96 : * preserving concurrency in this situation, as to avoid any
97 : * possibility of deadlock while doing get_database_name(). First,
98 : * copy all the shared values we'll need in this path.
99 : */
100 0 : TransactionId xidWarnLimit = ShmemVariableCache->xidWarnLimit;
101 0 : TransactionId xidStopLimit = ShmemVariableCache->xidStopLimit;
102 0 : TransactionId xidWrapLimit = ShmemVariableCache->xidWrapLimit;
103 0 : Oid oldest_datoid = ShmemVariableCache->oldestXidDB;
104 :
105 0 : LWLockRelease(XidGenLock);
106 :
107 : /*
108 : * To avoid swamping the postmaster with signals, we issue the autovac
109 : * request only once per 64K transaction starts. This still gives
110 : * plenty of chances before we get into real trouble.
111 : */
112 0 : if (IsUnderPostmaster && (xid % 65536) == 0)
113 0 : SendPostmasterSignal(PMSIGNAL_START_AUTOVAC_LAUNCHER);
114 :
115 0 : if (IsUnderPostmaster &&
116 0 : TransactionIdFollowsOrEquals(xid, xidStopLimit))
117 : {
118 0 : char *oldest_datname = get_database_name(oldest_datoid);
119 :
120 : /* complain even if that DB has disappeared */
121 0 : if (oldest_datname)
122 0 : ereport(ERROR,
123 : (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
124 : errmsg("database is not accepting commands to avoid wraparound data loss in database \"%s\"",
125 : oldest_datname),
126 : errhint("Stop the postmaster and vacuum that database in single-user mode.\n"
127 : "You might also need to commit or roll back old prepared transactions.")));
128 : else
129 0 : ereport(ERROR,
130 : (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
131 : errmsg("database is not accepting commands to avoid wraparound data loss in database with OID %u",
132 : oldest_datoid),
133 : errhint("Stop the postmaster and vacuum that database in single-user mode.\n"
134 : "You might also need to commit or roll back old prepared transactions.")));
135 : }
136 0 : else if (TransactionIdFollowsOrEquals(xid, xidWarnLimit))
137 : {
138 0 : char *oldest_datname = get_database_name(oldest_datoid);
139 :
140 : /* complain even if that DB has disappeared */
141 0 : if (oldest_datname)
142 0 : ereport(WARNING,
143 : (errmsg("database \"%s\" must be vacuumed within %u transactions",
144 : oldest_datname,
145 : xidWrapLimit - xid),
146 : errhint("To avoid a database shutdown, execute a database-wide VACUUM in that database.\n"
147 : "You might also need to commit or roll back old prepared transactions.")));
148 : else
149 0 : ereport(WARNING,
150 : (errmsg("database with OID %u must be vacuumed within %u transactions",
151 : oldest_datoid,
152 : xidWrapLimit - xid),
153 : errhint("To avoid a database shutdown, execute a database-wide VACUUM in that database.\n"
154 : "You might also need to commit or roll back old prepared transactions.")));
155 : }
156 :
157 : /* Re-acquire lock and start over */
158 0 : LWLockAcquire(XidGenLock, LW_EXCLUSIVE);
159 0 : xid = ShmemVariableCache->nextXid;
160 : }
161 :
162 : /*
163 : * If we are allocating the first XID of a new page of the commit log,
164 : * zero out that commit-log page before returning. We must do this while
165 : * holding XidGenLock, else another xact could acquire and commit a later
166 : * XID before we zero the page. Fortunately, a page of the commit log
167 : * holds 32K or more transactions, so we don't have to do this very often.
168 : *
169 : * Extend pg_subtrans and pg_commit_ts too.
170 : */
171 10625 : ExtendCLOG(xid);
172 10625 : ExtendCommitTs(xid);
173 10625 : ExtendSUBTRANS(xid);
174 :
175 : /*
176 : * Now advance the nextXid counter. This must not happen until after we
177 : * have successfully completed ExtendCLOG() --- if that routine fails, we
178 : * want the next incoming transaction to try it again. We cannot assign
179 : * more XIDs until there is CLOG space for them.
180 : */
181 10625 : TransactionIdAdvance(ShmemVariableCache->nextXid);
182 :
183 : /*
184 : * We must store the new XID into the shared ProcArray before releasing
185 : * XidGenLock. This ensures that every active XID older than
186 : * latestCompletedXid is present in the ProcArray, which is essential for
187 : * correct OldestXmin tracking; see src/backend/access/transam/README.
188 : *
189 : * XXX by storing xid into MyPgXact without acquiring ProcArrayLock, we
190 : * are relying on fetch/store of an xid to be atomic, else other backends
191 : * might see a partially-set xid here. But holding both locks at once
192 : * would be a nasty concurrency hit. So for now, assume atomicity.
193 : *
194 : * Note that readers of PGXACT xid fields should be careful to fetch the
195 : * value only once, rather than assume they can read a value multiple
196 : * times and get the same answer each time.
197 : *
198 : * The same comments apply to the subxact xid count and overflow fields.
199 : *
200 : * A solution to the atomic-store problem would be to give each PGXACT its
201 : * own spinlock used only for fetching/storing that PGXACT's xid and
202 : * related fields.
203 : *
204 : * If there's no room to fit a subtransaction XID into PGPROC, set the
205 : * cache-overflowed flag instead. This forces readers to look in
206 : * pg_subtrans to map subtransaction XIDs up to top-level XIDs. There is a
207 : * race-condition window, in that the new XID will not appear as running
208 : * until its parent link has been placed into pg_subtrans. However, that
209 : * will happen before anyone could possibly have a reason to inquire about
210 : * the status of the XID, so it seems OK. (Snapshots taken during this
211 : * window *will* include the parent XID, so they will deliver the correct
212 : * answer later on when someone does have a reason to inquire.)
213 : */
214 : {
215 : /*
216 : * Use volatile pointer to prevent code rearrangement; other backends
217 : * could be examining my subxids info concurrently, and we don't want
218 : * them to see an invalid intermediate state, such as incrementing
219 : * nxids before filling the array entry. Note we are assuming that
220 : * TransactionId and int fetch/store are atomic.
221 : */
222 10625 : volatile PGPROC *myproc = MyProc;
223 10625 : volatile PGXACT *mypgxact = MyPgXact;
224 :
225 10625 : if (!isSubXact)
226 10561 : mypgxact->xid = xid;
227 : else
228 : {
229 64 : int nxids = mypgxact->nxids;
230 :
231 64 : if (nxids < PGPROC_MAX_CACHED_SUBXIDS)
232 : {
233 64 : myproc->subxids.xids[nxids] = xid;
234 64 : mypgxact->nxids = nxids + 1;
235 : }
236 : else
237 0 : mypgxact->overflowed = true;
238 : }
239 : }
240 :
241 10625 : LWLockRelease(XidGenLock);
242 :
243 10625 : return xid;
244 : }
245 :
246 : /*
247 : * Read nextXid but don't allocate it.
248 : */
249 : TransactionId
250 1480 : ReadNewTransactionId(void)
251 : {
252 : TransactionId xid;
253 :
254 1480 : LWLockAcquire(XidGenLock, LW_SHARED);
255 1480 : xid = ShmemVariableCache->nextXid;
256 1480 : LWLockRelease(XidGenLock);
257 :
258 1480 : return xid;
259 : }
260 :
261 : /*
262 : * Advance the cluster-wide value for the oldest valid clog entry.
263 : *
264 : * We must acquire CLogTruncationLock to advance the oldestClogXid. It's not
265 : * necessary to hold the lock during the actual clog truncation, only when we
266 : * advance the limit, as code looking up arbitrary xids is required to hold
267 : * CLogTruncationLock from when it tests oldestClogXid through to when it
268 : * completes the clog lookup.
269 : */
270 : void
271 4 : AdvanceOldestClogXid(TransactionId oldest_datfrozenxid)
272 : {
273 4 : LWLockAcquire(CLogTruncationLock, LW_EXCLUSIVE);
274 4 : if (TransactionIdPrecedes(ShmemVariableCache->oldestClogXid,
275 : oldest_datfrozenxid))
276 : {
277 3 : ShmemVariableCache->oldestClogXid = oldest_datfrozenxid;
278 : }
279 4 : LWLockRelease(CLogTruncationLock);
280 4 : }
281 :
282 : /*
283 : * Determine the last safe XID to allocate using the currently oldest
284 : * datfrozenxid (ie, the oldest XID that might exist in any database
285 : * of our cluster), and the OID of the (or a) database with that value.
286 : */
287 : void
288 6 : SetTransactionIdLimit(TransactionId oldest_datfrozenxid, Oid oldest_datoid)
289 : {
290 : TransactionId xidVacLimit;
291 : TransactionId xidWarnLimit;
292 : TransactionId xidStopLimit;
293 : TransactionId xidWrapLimit;
294 : TransactionId curXid;
295 :
296 6 : Assert(TransactionIdIsNormal(oldest_datfrozenxid));
297 :
298 : /*
299 : * The place where we actually get into deep trouble is halfway around
300 : * from the oldest potentially-existing XID. (This calculation is
301 : * probably off by one or two counts, because the special XIDs reduce the
302 : * size of the loop a little bit. But we throw in plenty of slop below,
303 : * so it doesn't matter.)
304 : */
305 6 : xidWrapLimit = oldest_datfrozenxid + (MaxTransactionId >> 1);
306 6 : if (xidWrapLimit < FirstNormalTransactionId)
307 0 : xidWrapLimit += FirstNormalTransactionId;
308 :
309 : /*
310 : * We'll refuse to continue assigning XIDs in interactive mode once we get
311 : * within 1M transactions of data loss. This leaves lots of room for the
312 : * DBA to fool around fixing things in a standalone backend, while not
313 : * being significant compared to total XID space. (Note that since
314 : * vacuuming requires one transaction per table cleaned, we had better be
315 : * sure there's lots of XIDs left...)
316 : */
317 6 : xidStopLimit = xidWrapLimit - 1000000;
318 6 : if (xidStopLimit < FirstNormalTransactionId)
319 0 : xidStopLimit -= FirstNormalTransactionId;
320 :
321 : /*
322 : * We'll start complaining loudly when we get within 10M transactions of
323 : * the stop point. This is kind of arbitrary, but if you let your gas
324 : * gauge get down to 1% of full, would you be looking for the next gas
325 : * station? We need to be fairly liberal about this number because there
326 : * are lots of scenarios where most transactions are done by automatic
327 : * clients that won't pay attention to warnings. (No, we're not gonna make
328 : * this configurable. If you know enough to configure it, you know enough
329 : * to not get in this kind of trouble in the first place.)
330 : */
331 6 : xidWarnLimit = xidStopLimit - 10000000;
332 6 : if (xidWarnLimit < FirstNormalTransactionId)
333 0 : xidWarnLimit -= FirstNormalTransactionId;
334 :
335 : /*
336 : * We'll start trying to force autovacuums when oldest_datfrozenxid gets
337 : * to be more than autovacuum_freeze_max_age transactions old.
338 : *
339 : * Note: guc.c ensures that autovacuum_freeze_max_age is in a sane range,
340 : * so that xidVacLimit will be well before xidWarnLimit.
341 : *
342 : * Note: autovacuum_freeze_max_age is a PGC_POSTMASTER parameter so that
343 : * we don't have to worry about dealing with on-the-fly changes in its
344 : * value. It doesn't look practical to update shared state from a GUC
345 : * assign hook (too many processes would try to execute the hook,
346 : * resulting in race conditions as well as crashes of those not connected
347 : * to shared memory). Perhaps this can be improved someday. See also
348 : * SetMultiXactIdLimit.
349 : */
350 6 : xidVacLimit = oldest_datfrozenxid + autovacuum_freeze_max_age;
351 6 : if (xidVacLimit < FirstNormalTransactionId)
352 0 : xidVacLimit += FirstNormalTransactionId;
353 :
354 : /* Grab lock for just long enough to set the new limit values */
355 6 : LWLockAcquire(XidGenLock, LW_EXCLUSIVE);
356 6 : ShmemVariableCache->oldestXid = oldest_datfrozenxid;
357 6 : ShmemVariableCache->xidVacLimit = xidVacLimit;
358 6 : ShmemVariableCache->xidWarnLimit = xidWarnLimit;
359 6 : ShmemVariableCache->xidStopLimit = xidStopLimit;
360 6 : ShmemVariableCache->xidWrapLimit = xidWrapLimit;
361 6 : ShmemVariableCache->oldestXidDB = oldest_datoid;
362 6 : curXid = ShmemVariableCache->nextXid;
363 6 : LWLockRelease(XidGenLock);
364 :
365 : /* Log the info */
366 6 : ereport(DEBUG1,
367 : (errmsg("transaction ID wrap limit is %u, limited by database with OID %u",
368 : xidWrapLimit, oldest_datoid)));
369 :
370 : /*
371 : * If past the autovacuum force point, immediately signal an autovac
372 : * request. The reason for this is that autovac only processes one
373 : * database per invocation. Once it's finished cleaning up the oldest
374 : * database, it'll call here, and we'll signal the postmaster to start
375 : * another iteration immediately if there are still any old databases.
376 : */
377 6 : if (TransactionIdFollowsOrEquals(curXid, xidVacLimit) &&
378 0 : IsUnderPostmaster && !InRecovery)
379 0 : SendPostmasterSignal(PMSIGNAL_START_AUTOVAC_LAUNCHER);
380 :
381 : /* Give an immediate warning if past the wrap warn point */
382 6 : if (TransactionIdFollowsOrEquals(curXid, xidWarnLimit) && !InRecovery)
383 : {
384 : char *oldest_datname;
385 :
386 : /*
387 : * We can be called when not inside a transaction, for example during
388 : * StartupXLOG(). In such a case we cannot do database access, so we
389 : * must just report the oldest DB's OID.
390 : *
391 : * Note: it's also possible that get_database_name fails and returns
392 : * NULL, for example because the database just got dropped. We'll
393 : * still warn, even though the warning might now be unnecessary.
394 : */
395 0 : if (IsTransactionState())
396 0 : oldest_datname = get_database_name(oldest_datoid);
397 : else
398 0 : oldest_datname = NULL;
399 :
400 0 : if (oldest_datname)
401 0 : ereport(WARNING,
402 : (errmsg("database \"%s\" must be vacuumed within %u transactions",
403 : oldest_datname,
404 : xidWrapLimit - curXid),
405 : errhint("To avoid a database shutdown, execute a database-wide VACUUM in that database.\n"
406 : "You might also need to commit or roll back old prepared transactions.")));
407 : else
408 0 : ereport(WARNING,
409 : (errmsg("database with OID %u must be vacuumed within %u transactions",
410 : oldest_datoid,
411 : xidWrapLimit - curXid),
412 : errhint("To avoid a database shutdown, execute a database-wide VACUUM in that database.\n"
413 : "You might also need to commit or roll back old prepared transactions.")));
414 : }
415 6 : }
416 :
417 :
418 : /*
419 : * ForceTransactionIdLimitUpdate -- does the XID wrap-limit data need updating?
420 : *
421 : * We primarily check whether oldestXidDB is valid. The cases we have in
422 : * mind are that that database was dropped, or the field was reset to zero
423 : * by pg_resetwal. In either case we should force recalculation of the
424 : * wrap limit. Also do it if oldestXid is old enough to be forcing
425 : * autovacuums or other actions; this ensures we update our state as soon
426 : * as possible once extra overhead is being incurred.
427 : */
428 : bool
429 46 : ForceTransactionIdLimitUpdate(void)
430 : {
431 : TransactionId nextXid;
432 : TransactionId xidVacLimit;
433 : TransactionId oldestXid;
434 : Oid oldestXidDB;
435 :
436 : /* Locking is probably not really necessary, but let's be careful */
437 46 : LWLockAcquire(XidGenLock, LW_SHARED);
438 46 : nextXid = ShmemVariableCache->nextXid;
439 46 : xidVacLimit = ShmemVariableCache->xidVacLimit;
440 46 : oldestXid = ShmemVariableCache->oldestXid;
441 46 : oldestXidDB = ShmemVariableCache->oldestXidDB;
442 46 : LWLockRelease(XidGenLock);
443 :
444 46 : if (!TransactionIdIsNormal(oldestXid))
445 0 : return true; /* shouldn't happen, but just in case */
446 46 : if (!TransactionIdIsValid(xidVacLimit))
447 0 : return true; /* this shouldn't happen anymore either */
448 46 : if (TransactionIdFollowsOrEquals(nextXid, xidVacLimit))
449 0 : return true; /* past VacLimit, don't delay updating */
450 46 : if (!SearchSysCacheExists1(DATABASEOID, ObjectIdGetDatum(oldestXidDB)))
451 0 : return true; /* could happen, per comments above */
452 46 : return false;
453 : }
454 :
455 :
456 : /*
457 : * GetNewObjectId -- allocate a new OID
458 : *
459 : * OIDs are generated by a cluster-wide counter. Since they are only 32 bits
460 : * wide, counter wraparound will occur eventually, and therefore it is unwise
461 : * to assume they are unique unless precautions are taken to make them so.
462 : * Hence, this routine should generally not be used directly. The only
463 : * direct callers should be GetNewOid() and GetNewRelFileNode() in
464 : * catalog/catalog.c.
465 : */
466 : Oid
467 33858 : GetNewObjectId(void)
468 : {
469 : Oid result;
470 :
471 : /* safety check, we should never get this far in a HS standby */
472 33858 : if (RecoveryInProgress())
473 0 : elog(ERROR, "cannot assign OIDs during recovery");
474 :
475 33858 : LWLockAcquire(OidGenLock, LW_EXCLUSIVE);
476 :
477 : /*
478 : * Check for wraparound of the OID counter. We *must* not return 0
479 : * (InvalidOid); and as long as we have to check that, it seems a good
480 : * idea to skip over everything below FirstNormalObjectId too. (This
481 : * basically just avoids lots of collisions with bootstrap-assigned OIDs
482 : * right after a wrap occurs, so as to avoid a possibly large number of
483 : * iterations in GetNewOid.) Note we are relying on unsigned comparison.
484 : *
485 : * During initdb, we start the OID generator at FirstBootstrapObjectId, so
486 : * we only wrap if before that point when in bootstrap or standalone mode.
487 : * The first time through this routine after normal postmaster start, the
488 : * counter will be forced up to FirstNormalObjectId. This mechanism
489 : * leaves the OIDs between FirstBootstrapObjectId and FirstNormalObjectId
490 : * available for automatic assignment during initdb, while ensuring they
491 : * will never conflict with user-assigned OIDs.
492 : */
493 33858 : if (ShmemVariableCache->nextOid < ((Oid) FirstNormalObjectId))
494 : {
495 2332 : if (IsPostmasterEnvironment)
496 : {
497 : /* wraparound, or first post-initdb assignment, in normal mode */
498 1 : ShmemVariableCache->nextOid = FirstNormalObjectId;
499 1 : ShmemVariableCache->oidCount = 0;
500 : }
501 : else
502 : {
503 : /* we may be bootstrapping, so don't enforce the full range */
504 2331 : if (ShmemVariableCache->nextOid < ((Oid) FirstBootstrapObjectId))
505 : {
506 : /* wraparound in standalone mode (unlikely but possible) */
507 0 : ShmemVariableCache->nextOid = FirstNormalObjectId;
508 0 : ShmemVariableCache->oidCount = 0;
509 : }
510 : }
511 : }
512 :
513 : /* If we run out of logged for use oids then we must log more */
514 33858 : if (ShmemVariableCache->oidCount == 0)
515 : {
516 6 : XLogPutNextOid(ShmemVariableCache->nextOid + VAR_OID_PREFETCH);
517 6 : ShmemVariableCache->oidCount = VAR_OID_PREFETCH;
518 : }
519 :
520 33858 : result = ShmemVariableCache->nextOid;
521 :
522 33858 : (ShmemVariableCache->nextOid)++;
523 33858 : (ShmemVariableCache->oidCount)--;
524 :
525 33858 : LWLockRelease(OidGenLock);
526 :
527 33858 : return result;
528 : }
|