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