PostgreSQL Source Code  git master
vacuum.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * vacuum.c
4  * The postgres vacuum cleaner.
5  *
6  * This file now includes only control and dispatch code for VACUUM and
7  * ANALYZE commands. Regular VACUUM is implemented in vacuumlazy.c,
8  * ANALYZE in analyze.c, and VACUUM FULL is a variant of CLUSTER, handled
9  * in cluster.c.
10  *
11  *
12  * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
13  * Portions Copyright (c) 1994, Regents of the University of California
14  *
15  *
16  * IDENTIFICATION
17  * src/backend/commands/vacuum.c
18  *
19  *-------------------------------------------------------------------------
20  */
21 #include "postgres.h"
22 
23 #include <math.h>
24 
25 #include "access/clog.h"
26 #include "access/commit_ts.h"
27 #include "access/genam.h"
28 #include "access/heapam.h"
29 #include "access/htup_details.h"
30 #include "access/multixact.h"
31 #include "access/tableam.h"
32 #include "access/transam.h"
33 #include "access/xact.h"
34 #include "catalog/namespace.h"
35 #include "catalog/pg_database.h"
36 #include "catalog/pg_inherits.h"
37 #include "catalog/pg_namespace.h"
38 #include "commands/cluster.h"
39 #include "commands/defrem.h"
40 #include "commands/vacuum.h"
41 #include "miscadmin.h"
42 #include "nodes/makefuncs.h"
43 #include "pgstat.h"
44 #include "postmaster/autovacuum.h"
46 #include "storage/bufmgr.h"
47 #include "storage/lmgr.h"
48 #include "storage/proc.h"
49 #include "storage/procarray.h"
50 #include "utils/acl.h"
51 #include "utils/fmgroids.h"
52 #include "utils/guc.h"
53 #include "utils/memutils.h"
54 #include "utils/snapmgr.h"
55 #include "utils/syscache.h"
56 
57 
58 /*
59  * GUC parameters
60  */
67 
68 
69 /* A few variables that don't seem worth passing around as parameters */
70 static MemoryContext vac_context = NULL;
72 
73 
74 /*
75  * Variables for cost-based parallel vacuum. See comments atop
76  * compute_parallel_delay to understand how it works.
77  */
81 
82 /* non-export function prototypes */
83 static List *expand_vacuum_rel(VacuumRelation *vrel, int options);
84 static List *get_all_vacuum_rels(int options);
85 static void vac_truncate_clog(TransactionId frozenXID,
86  MultiXactId minMulti,
87  TransactionId lastSaneFrozenXid,
88  MultiXactId lastSaneMinMulti);
89 static bool vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params);
90 static double compute_parallel_delay(void);
92 
93 /*
94  * Primary entry point for manual VACUUM and ANALYZE commands
95  *
96  * This is mainly a preparation wrapper for the real operations that will
97  * happen in vacuum().
98  */
99 void
100 ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
101 {
102  VacuumParams params;
103  bool verbose = false;
104  bool skip_locked = false;
105  bool analyze = false;
106  bool freeze = false;
107  bool full = false;
108  bool disable_page_skipping = false;
109  bool process_toast = true;
110  ListCell *lc;
111 
112  /* index_cleanup and truncate values unspecified for now */
115 
116  /* By default parallel vacuum is enabled */
117  params.nworkers = 0;
118 
119  /* Parse options list */
120  foreach(lc, vacstmt->options)
121  {
122  DefElem *opt = (DefElem *) lfirst(lc);
123 
124  /* Parse common options for VACUUM and ANALYZE */
125  if (strcmp(opt->defname, "verbose") == 0)
126  verbose = defGetBoolean(opt);
127  else if (strcmp(opt->defname, "skip_locked") == 0)
128  skip_locked = defGetBoolean(opt);
129  else if (!vacstmt->is_vacuumcmd)
130  ereport(ERROR,
131  (errcode(ERRCODE_SYNTAX_ERROR),
132  errmsg("unrecognized ANALYZE option \"%s\"", opt->defname),
133  parser_errposition(pstate, opt->location)));
134 
135  /* Parse options available on VACUUM */
136  else if (strcmp(opt->defname, "analyze") == 0)
137  analyze = defGetBoolean(opt);
138  else if (strcmp(opt->defname, "freeze") == 0)
139  freeze = defGetBoolean(opt);
140  else if (strcmp(opt->defname, "full") == 0)
141  full = defGetBoolean(opt);
142  else if (strcmp(opt->defname, "disable_page_skipping") == 0)
143  disable_page_skipping = defGetBoolean(opt);
144  else if (strcmp(opt->defname, "index_cleanup") == 0)
145  {
146  /* Interpret no string as the default, which is 'auto' */
147  if (!opt->arg)
149  else
150  {
151  char *sval = defGetString(opt);
152 
153  /* Try matching on 'auto' string, or fall back on boolean */
154  if (pg_strcasecmp(sval, "auto") == 0)
156  else
158  }
159  }
160  else if (strcmp(opt->defname, "process_toast") == 0)
161  process_toast = defGetBoolean(opt);
162  else if (strcmp(opt->defname, "truncate") == 0)
163  params.truncate = get_vacoptval_from_boolean(opt);
164  else if (strcmp(opt->defname, "parallel") == 0)
165  {
166  if (opt->arg == NULL)
167  {
168  ereport(ERROR,
169  (errcode(ERRCODE_SYNTAX_ERROR),
170  errmsg("parallel option requires a value between 0 and %d",
172  parser_errposition(pstate, opt->location)));
173  }
174  else
175  {
176  int nworkers;
177 
178  nworkers = defGetInt32(opt);
179  if (nworkers < 0 || nworkers > MAX_PARALLEL_WORKER_LIMIT)
180  ereport(ERROR,
181  (errcode(ERRCODE_SYNTAX_ERROR),
182  errmsg("parallel workers for vacuum must be between 0 and %d",
183  MAX_PARALLEL_WORKER_LIMIT),
184  parser_errposition(pstate, opt->location)));
185 
186  /*
187  * Disable parallel vacuum, if user has specified parallel
188  * degree as zero.
189  */
190  if (nworkers == 0)
191  params.nworkers = -1;
192  else
193  params.nworkers = nworkers;
194  }
195  }
196  else
197  ereport(ERROR,
198  (errcode(ERRCODE_SYNTAX_ERROR),
199  errmsg("unrecognized VACUUM option \"%s\"", opt->defname),
200  parser_errposition(pstate, opt->location)));
201  }
202 
203  /* Set vacuum options */
204  params.options =
205  (vacstmt->is_vacuumcmd ? VACOPT_VACUUM : VACOPT_ANALYZE) |
206  (verbose ? VACOPT_VERBOSE : 0) |
207  (skip_locked ? VACOPT_SKIP_LOCKED : 0) |
208  (analyze ? VACOPT_ANALYZE : 0) |
209  (freeze ? VACOPT_FREEZE : 0) |
210  (full ? VACOPT_FULL : 0) |
211  (disable_page_skipping ? VACOPT_DISABLE_PAGE_SKIPPING : 0) |
212  (process_toast ? VACOPT_PROCESS_TOAST : 0);
213 
214  /* sanity checks on options */
215  Assert(params.options & (VACOPT_VACUUM | VACOPT_ANALYZE));
216  Assert((params.options & VACOPT_VACUUM) ||
217  !(params.options & (VACOPT_FULL | VACOPT_FREEZE)));
218 
219  if ((params.options & VACOPT_FULL) && params.nworkers > 0)
220  ereport(ERROR,
221  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
222  errmsg("VACUUM FULL cannot be performed in parallel")));
223 
224  /*
225  * Make sure VACOPT_ANALYZE is specified if any column lists are present.
226  */
227  if (!(params.options & VACOPT_ANALYZE))
228  {
229  ListCell *lc;
230 
231  foreach(lc, vacstmt->rels)
232  {
234 
235  if (vrel->va_cols != NIL)
236  ereport(ERROR,
237  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
238  errmsg("ANALYZE option must be specified when a column list is provided")));
239  }
240  }
241 
242  /*
243  * All freeze ages are zero if the FREEZE option is given; otherwise pass
244  * them as -1 which means to use the default values.
245  */
246  if (params.options & VACOPT_FREEZE)
247  {
248  params.freeze_min_age = 0;
249  params.freeze_table_age = 0;
250  params.multixact_freeze_min_age = 0;
251  params.multixact_freeze_table_age = 0;
252  }
253  else
254  {
255  params.freeze_min_age = -1;
256  params.freeze_table_age = -1;
257  params.multixact_freeze_min_age = -1;
258  params.multixact_freeze_table_age = -1;
259  }
260 
261  /* user-invoked vacuum is never "for wraparound" */
262  params.is_wraparound = false;
263 
264  /* user-invoked vacuum never uses this parameter */
265  params.log_min_duration = -1;
266 
267  /* Now go through the common routine */
268  vacuum(vacstmt->rels, &params, NULL, isTopLevel);
269 }
270 
271 /*
272  * Internal entry point for VACUUM and ANALYZE commands.
273  *
274  * relations, if not NIL, is a list of VacuumRelation to process; otherwise,
275  * we process all relevant tables in the database. For each VacuumRelation,
276  * if a valid OID is supplied, the table with that OID is what to process;
277  * otherwise, the VacuumRelation's RangeVar indicates what to process.
278  *
279  * params contains a set of parameters that can be used to customize the
280  * behavior.
281  *
282  * bstrategy is normally given as NULL, but in autovacuum it can be passed
283  * in to use the same buffer strategy object across multiple vacuum() calls.
284  *
285  * isTopLevel should be passed down from ProcessUtility.
286  *
287  * It is the caller's responsibility that all parameters are allocated in a
288  * memory context that will not disappear at transaction commit.
289  */
290 void
291 vacuum(List *relations, VacuumParams *params,
292  BufferAccessStrategy bstrategy, bool isTopLevel)
293 {
294  static bool in_vacuum = false;
295 
296  const char *stmttype;
297  volatile bool in_outer_xact,
298  use_own_xacts;
299 
300  Assert(params != NULL);
301 
302  stmttype = (params->options & VACOPT_VACUUM) ? "VACUUM" : "ANALYZE";
303 
304  /*
305  * We cannot run VACUUM inside a user transaction block; if we were inside
306  * a transaction, then our commit- and start-transaction-command calls
307  * would not have the intended effect! There are numerous other subtle
308  * dependencies on this, too.
309  *
310  * ANALYZE (without VACUUM) can run either way.
311  */
312  if (params->options & VACOPT_VACUUM)
313  {
314  PreventInTransactionBlock(isTopLevel, stmttype);
315  in_outer_xact = false;
316  }
317  else
318  in_outer_xact = IsInTransactionBlock(isTopLevel);
319 
320  /*
321  * Due to static variables vac_context, anl_context and vac_strategy,
322  * vacuum() is not reentrant. This matters when VACUUM FULL or ANALYZE
323  * calls a hostile index expression that itself calls ANALYZE.
324  */
325  if (in_vacuum)
326  ereport(ERROR,
327  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
328  errmsg("%s cannot be executed from VACUUM or ANALYZE",
329  stmttype)));
330 
331  /*
332  * Sanity check DISABLE_PAGE_SKIPPING option.
333  */
334  if ((params->options & VACOPT_FULL) != 0 &&
335  (params->options & VACOPT_DISABLE_PAGE_SKIPPING) != 0)
336  ereport(ERROR,
337  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
338  errmsg("VACUUM option DISABLE_PAGE_SKIPPING cannot be used with FULL")));
339 
340  /* sanity check for PROCESS_TOAST */
341  if ((params->options & VACOPT_FULL) != 0 &&
342  (params->options & VACOPT_PROCESS_TOAST) == 0)
343  ereport(ERROR,
344  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
345  errmsg("PROCESS_TOAST required with VACUUM FULL")));
346 
347  /*
348  * Send info about dead objects to the statistics collector, unless we are
349  * in autovacuum --- autovacuum.c does this for itself.
350  */
351  if ((params->options & VACOPT_VACUUM) && !IsAutoVacuumWorkerProcess())
353 
354  /*
355  * Create special memory context for cross-transaction storage.
356  *
357  * Since it is a child of PortalContext, it will go away eventually even
358  * if we suffer an error; there's no need for special abort cleanup logic.
359  */
360  vac_context = AllocSetContextCreate(PortalContext,
361  "Vacuum",
363 
364  /*
365  * If caller didn't give us a buffer strategy object, make one in the
366  * cross-transaction memory context.
367  */
368  if (bstrategy == NULL)
369  {
370  MemoryContext old_context = MemoryContextSwitchTo(vac_context);
371 
372  bstrategy = GetAccessStrategy(BAS_VACUUM);
373  MemoryContextSwitchTo(old_context);
374  }
375  vac_strategy = bstrategy;
376 
377  /*
378  * Build list of relation(s) to process, putting any new data in
379  * vac_context for safekeeping.
380  */
381  if (relations != NIL)
382  {
383  List *newrels = NIL;
384  ListCell *lc;
385 
386  foreach(lc, relations)
387  {
389  List *sublist;
390  MemoryContext old_context;
391 
392  sublist = expand_vacuum_rel(vrel, params->options);
393  old_context = MemoryContextSwitchTo(vac_context);
394  newrels = list_concat(newrels, sublist);
395  MemoryContextSwitchTo(old_context);
396  }
397  relations = newrels;
398  }
399  else
400  relations = get_all_vacuum_rels(params->options);
401 
402  /*
403  * Decide whether we need to start/commit our own transactions.
404  *
405  * For VACUUM (with or without ANALYZE): always do so, so that we can
406  * release locks as soon as possible. (We could possibly use the outer
407  * transaction for a one-table VACUUM, but handling TOAST tables would be
408  * problematic.)
409  *
410  * For ANALYZE (no VACUUM): if inside a transaction block, we cannot
411  * start/commit our own transactions. Also, there's no need to do so if
412  * only processing one relation. For multiple relations when not within a
413  * transaction block, and also in an autovacuum worker, use own
414  * transactions so we can release locks sooner.
415  */
416  if (params->options & VACOPT_VACUUM)
417  use_own_xacts = true;
418  else
419  {
420  Assert(params->options & VACOPT_ANALYZE);
422  use_own_xacts = true;
423  else if (in_outer_xact)
424  use_own_xacts = false;
425  else if (list_length(relations) > 1)
426  use_own_xacts = true;
427  else
428  use_own_xacts = false;
429  }
430 
431  /*
432  * vacuum_rel expects to be entered with no transaction active; it will
433  * start and commit its own transaction. But we are called by an SQL
434  * command, and so we are executing inside a transaction already. We
435  * commit the transaction started in PostgresMain() here, and start
436  * another one before exiting to match the commit waiting for us back in
437  * PostgresMain().
438  */
439  if (use_own_xacts)
440  {
441  Assert(!in_outer_xact);
442 
443  /* ActiveSnapshot is not set by autovacuum */
444  if (ActiveSnapshotSet())
446 
447  /* matches the StartTransaction in PostgresMain() */
449  }
450 
451  /* Turn vacuum cost accounting on or off, and set/clear in_vacuum */
452  PG_TRY();
453  {
454  ListCell *cur;
455 
456  in_vacuum = true;
458  VacuumCostBalance = 0;
459  VacuumPageHit = 0;
460  VacuumPageMiss = 0;
461  VacuumPageDirty = 0;
463  VacuumSharedCostBalance = NULL;
464  VacuumActiveNWorkers = NULL;
465 
466  /*
467  * Loop to process each selected relation.
468  */
469  foreach(cur, relations)
470  {
472 
473  if (params->options & VACOPT_VACUUM)
474  {
475  if (!vacuum_rel(vrel->oid, vrel->relation, params))
476  continue;
477  }
478 
479  if (params->options & VACOPT_ANALYZE)
480  {
481  /*
482  * If using separate xacts, start one for analyze. Otherwise,
483  * we can use the outer transaction.
484  */
485  if (use_own_xacts)
486  {
488  /* functions in indexes may want a snapshot set */
490  }
491 
492  analyze_rel(vrel->oid, vrel->relation, params,
493  vrel->va_cols, in_outer_xact, vac_strategy);
494 
495  if (use_own_xacts)
496  {
499  }
500  else
501  {
502  /*
503  * If we're not using separate xacts, better separate the
504  * ANALYZE actions with CCIs. This avoids trouble if user
505  * says "ANALYZE t, t".
506  */
508  }
509  }
510  }
511  }
512  PG_FINALLY();
513  {
514  in_vacuum = false;
515  VacuumCostActive = false;
516  }
517  PG_END_TRY();
518 
519  /*
520  * Finish up processing.
521  */
522  if (use_own_xacts)
523  {
524  /* here, we are not in a transaction */
525 
526  /*
527  * This matches the CommitTransaction waiting for us in
528  * PostgresMain().
529  */
531  }
532 
533  if ((params->options & VACOPT_VACUUM) && !IsAutoVacuumWorkerProcess())
534  {
535  /*
536  * Update pg_database.datfrozenxid, and truncate pg_xact if possible.
537  * (autovacuum.c does this for itself.)
538  */
540  }
541 
542  /*
543  * Clean up working storage --- note we must do this after
544  * StartTransactionCommand, else we might be trying to delete the active
545  * context!
546  */
547  MemoryContextDelete(vac_context);
548  vac_context = NULL;
549 }
550 
551 /*
552  * Check if a given relation can be safely vacuumed or analyzed. If the
553  * user is not the relation owner, issue a WARNING log message and return
554  * false to let the caller decide what to do with this relation. This
555  * routine is used to decide if a relation can be processed for VACUUM or
556  * ANALYZE.
557  */
558 bool
560 {
561  char *relname;
562 
563  Assert((options & (VACOPT_VACUUM | VACOPT_ANALYZE)) != 0);
564 
565  /*
566  * Check permissions.
567  *
568  * We allow the user to vacuum or analyze a table if he is superuser, the
569  * table owner, or the database owner (but in the latter case, only if
570  * it's not a shared relation). pg_class_ownercheck includes the
571  * superuser case.
572  *
573  * Note we choose to treat permissions failure as a WARNING and keep
574  * trying to vacuum or analyze the rest of the DB --- is this appropriate?
575  */
576  if (pg_class_ownercheck(relid, GetUserId()) ||
577  (pg_database_ownercheck(MyDatabaseId, GetUserId()) && !reltuple->relisshared))
578  return true;
579 
580  relname = NameStr(reltuple->relname);
581 
582  if ((options & VACOPT_VACUUM) != 0)
583  {
584  if (reltuple->relisshared)
586  (errmsg("skipping \"%s\" --- only superuser can vacuum it",
587  relname)));
588  else if (reltuple->relnamespace == PG_CATALOG_NAMESPACE)
590  (errmsg("skipping \"%s\" --- only superuser or database owner can vacuum it",
591  relname)));
592  else
594  (errmsg("skipping \"%s\" --- only table or database owner can vacuum it",
595  relname)));
596 
597  /*
598  * For VACUUM ANALYZE, both logs could show up, but just generate
599  * information for VACUUM as that would be the first one to be
600  * processed.
601  */
602  return false;
603  }
604 
605  if ((options & VACOPT_ANALYZE) != 0)
606  {
607  if (reltuple->relisshared)
609  (errmsg("skipping \"%s\" --- only superuser can analyze it",
610  relname)));
611  else if (reltuple->relnamespace == PG_CATALOG_NAMESPACE)
613  (errmsg("skipping \"%s\" --- only superuser or database owner can analyze it",
614  relname)));
615  else
617  (errmsg("skipping \"%s\" --- only table or database owner can analyze it",
618  relname)));
619  }
620 
621  return false;
622 }
623 
624 
625 /*
626  * vacuum_open_relation
627  *
628  * This routine is used for attempting to open and lock a relation which
629  * is going to be vacuumed or analyzed. If the relation cannot be opened
630  * or locked, a log is emitted if possible.
631  */
632 Relation
634  bool verbose, LOCKMODE lmode)
635 {
636  Relation rel;
637  bool rel_lock = true;
638  int elevel;
639 
640  Assert((options & (VACOPT_VACUUM | VACOPT_ANALYZE)) != 0);
641 
642  /*
643  * Open the relation and get the appropriate lock on it.
644  *
645  * There's a race condition here: the relation may have gone away since
646  * the last time we saw it. If so, we don't need to vacuum or analyze it.
647  *
648  * If we've been asked not to wait for the relation lock, acquire it first
649  * in non-blocking mode, before calling try_relation_open().
650  */
651  if (!(options & VACOPT_SKIP_LOCKED))
652  rel = try_relation_open(relid, lmode);
653  else if (ConditionalLockRelationOid(relid, lmode))
654  rel = try_relation_open(relid, NoLock);
655  else
656  {
657  rel = NULL;
658  rel_lock = false;
659  }
660 
661  /* if relation is opened, leave */
662  if (rel)
663  return rel;
664 
665  /*
666  * Relation could not be opened, hence generate if possible a log
667  * informing on the situation.
668  *
669  * If the RangeVar is not defined, we do not have enough information to
670  * provide a meaningful log statement. Chances are that the caller has
671  * intentionally not provided this information so that this logging is
672  * skipped, anyway.
673  */
674  if (relation == NULL)
675  return NULL;
676 
677  /*
678  * Determine the log level.
679  *
680  * For manual VACUUM or ANALYZE, we emit a WARNING to match the log
681  * statements in the permission checks; otherwise, only log if the caller
682  * so requested.
683  */
685  elevel = WARNING;
686  else if (verbose)
687  elevel = LOG;
688  else
689  return NULL;
690 
691  if ((options & VACOPT_VACUUM) != 0)
692  {
693  if (!rel_lock)
694  ereport(elevel,
695  (errcode(ERRCODE_LOCK_NOT_AVAILABLE),
696  errmsg("skipping vacuum of \"%s\" --- lock not available",
697  relation->relname)));
698  else
699  ereport(elevel,
701  errmsg("skipping vacuum of \"%s\" --- relation no longer exists",
702  relation->relname)));
703 
704  /*
705  * For VACUUM ANALYZE, both logs could show up, but just generate
706  * information for VACUUM as that would be the first one to be
707  * processed.
708  */
709  return NULL;
710  }
711 
712  if ((options & VACOPT_ANALYZE) != 0)
713  {
714  if (!rel_lock)
715  ereport(elevel,
716  (errcode(ERRCODE_LOCK_NOT_AVAILABLE),
717  errmsg("skipping analyze of \"%s\" --- lock not available",
718  relation->relname)));
719  else
720  ereport(elevel,
722  errmsg("skipping analyze of \"%s\" --- relation no longer exists",
723  relation->relname)));
724  }
725 
726  return NULL;
727 }
728 
729 
730 /*
731  * Given a VacuumRelation, fill in the table OID if it wasn't specified,
732  * and optionally add VacuumRelations for partitions of the table.
733  *
734  * If a VacuumRelation does not have an OID supplied and is a partitioned
735  * table, an extra entry will be added to the output for each partition.
736  * Presently, only autovacuum supplies OIDs when calling vacuum(), and
737  * it does not want us to expand partitioned tables.
738  *
739  * We take care not to modify the input data structure, but instead build
740  * new VacuumRelation(s) to return. (But note that they will reference
741  * unmodified parts of the input, eg column lists.) New data structures
742  * are made in vac_context.
743  */
744 static List *
746 {
747  List *vacrels = NIL;
748  MemoryContext oldcontext;
749 
750  /* If caller supplied OID, there's nothing we need do here. */
751  if (OidIsValid(vrel->oid))
752  {
753  oldcontext = MemoryContextSwitchTo(vac_context);
754  vacrels = lappend(vacrels, vrel);
755  MemoryContextSwitchTo(oldcontext);
756  }
757  else
758  {
759  /* Process a specific relation, and possibly partitions thereof */
760  Oid relid;
761  HeapTuple tuple;
762  Form_pg_class classForm;
763  bool include_parts;
764  int rvr_opts;
765 
766  /*
767  * Since autovacuum workers supply OIDs when calling vacuum(), no
768  * autovacuum worker should reach this code.
769  */
771 
772  /*
773  * We transiently take AccessShareLock to protect the syscache lookup
774  * below, as well as find_all_inheritors's expectation that the caller
775  * holds some lock on the starting relation.
776  */
777  rvr_opts = (options & VACOPT_SKIP_LOCKED) ? RVR_SKIP_LOCKED : 0;
778  relid = RangeVarGetRelidExtended(vrel->relation,
780  rvr_opts,
781  NULL, NULL);
782 
783  /*
784  * If the lock is unavailable, emit the same log statement that
785  * vacuum_rel() and analyze_rel() would.
786  */
787  if (!OidIsValid(relid))
788  {
789  if (options & VACOPT_VACUUM)
791  (errcode(ERRCODE_LOCK_NOT_AVAILABLE),
792  errmsg("skipping vacuum of \"%s\" --- lock not available",
793  vrel->relation->relname)));
794  else
796  (errcode(ERRCODE_LOCK_NOT_AVAILABLE),
797  errmsg("skipping analyze of \"%s\" --- lock not available",
798  vrel->relation->relname)));
799  return vacrels;
800  }
801 
802  /*
803  * To check whether the relation is a partitioned table and its
804  * ownership, fetch its syscache entry.
805  */
806  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
807  if (!HeapTupleIsValid(tuple))
808  elog(ERROR, "cache lookup failed for relation %u", relid);
809  classForm = (Form_pg_class) GETSTRUCT(tuple);
810 
811  /*
812  * Make a returnable VacuumRelation for this rel if user is a proper
813  * owner.
814  */
815  if (vacuum_is_relation_owner(relid, classForm, options))
816  {
817  oldcontext = MemoryContextSwitchTo(vac_context);
818  vacrels = lappend(vacrels, makeVacuumRelation(vrel->relation,
819  relid,
820  vrel->va_cols));
821  MemoryContextSwitchTo(oldcontext);
822  }
823 
824 
825  include_parts = (classForm->relkind == RELKIND_PARTITIONED_TABLE);
826  ReleaseSysCache(tuple);
827 
828  /*
829  * If it is, make relation list entries for its partitions. Note that
830  * the list returned by find_all_inheritors() includes the passed-in
831  * OID, so we have to skip that. There's no point in taking locks on
832  * the individual partitions yet, and doing so would just add
833  * unnecessary deadlock risk. For this last reason we do not check
834  * yet the ownership of the partitions, which get added to the list to
835  * process. Ownership will be checked later on anyway.
836  */
837  if (include_parts)
838  {
839  List *part_oids = find_all_inheritors(relid, NoLock, NULL);
840  ListCell *part_lc;
841 
842  foreach(part_lc, part_oids)
843  {
844  Oid part_oid = lfirst_oid(part_lc);
845 
846  if (part_oid == relid)
847  continue; /* ignore original table */
848 
849  /*
850  * We omit a RangeVar since it wouldn't be appropriate to
851  * complain about failure to open one of these relations
852  * later.
853  */
854  oldcontext = MemoryContextSwitchTo(vac_context);
855  vacrels = lappend(vacrels, makeVacuumRelation(NULL,
856  part_oid,
857  vrel->va_cols));
858  MemoryContextSwitchTo(oldcontext);
859  }
860  }
861 
862  /*
863  * Release lock again. This means that by the time we actually try to
864  * process the table, it might be gone or renamed. In the former case
865  * we'll silently ignore it; in the latter case we'll process it
866  * anyway, but we must beware that the RangeVar doesn't necessarily
867  * identify it anymore. This isn't ideal, perhaps, but there's little
868  * practical alternative, since we're typically going to commit this
869  * transaction and begin a new one between now and then. Moreover,
870  * holding locks on multiple relations would create significant risk
871  * of deadlock.
872  */
874  }
875 
876  return vacrels;
877 }
878 
879 /*
880  * Construct a list of VacuumRelations for all vacuumable rels in
881  * the current database. The list is built in vac_context.
882  */
883 static List *
885 {
886  List *vacrels = NIL;
887  Relation pgclass;
888  TableScanDesc scan;
889  HeapTuple tuple;
890 
891  pgclass = table_open(RelationRelationId, AccessShareLock);
892 
893  scan = table_beginscan_catalog(pgclass, 0, NULL);
894 
895  while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
896  {
897  Form_pg_class classForm = (Form_pg_class) GETSTRUCT(tuple);
898  MemoryContext oldcontext;
899  Oid relid = classForm->oid;
900 
901  /* check permissions of relation */
902  if (!vacuum_is_relation_owner(relid, classForm, options))
903  continue;
904 
905  /*
906  * We include partitioned tables here; depending on which operation is
907  * to be performed, caller will decide whether to process or ignore
908  * them.
909  */
910  if (classForm->relkind != RELKIND_RELATION &&
911  classForm->relkind != RELKIND_MATVIEW &&
912  classForm->relkind != RELKIND_PARTITIONED_TABLE)
913  continue;
914 
915  /*
916  * Build VacuumRelation(s) specifying the table OIDs to be processed.
917  * We omit a RangeVar since it wouldn't be appropriate to complain
918  * about failure to open one of these relations later.
919  */
920  oldcontext = MemoryContextSwitchTo(vac_context);
921  vacrels = lappend(vacrels, makeVacuumRelation(NULL,
922  relid,
923  NIL));
924  MemoryContextSwitchTo(oldcontext);
925  }
926 
927  table_endscan(scan);
928  table_close(pgclass, AccessShareLock);
929 
930  return vacrels;
931 }
932 
933 /*
934  * vacuum_set_xid_limits() -- compute oldestXmin and freeze cutoff points
935  *
936  * Input parameters are the target relation, applicable freeze age settings.
937  *
938  * The output parameters are:
939  * - oldestXmin is the cutoff value used to distinguish whether tuples are
940  * DEAD or RECENTLY_DEAD (see HeapTupleSatisfiesVacuum).
941  * - freezeLimit is the Xid below which all Xids are replaced by
942  * FrozenTransactionId during vacuum.
943  * - xidFullScanLimit (computed from freeze_table_age parameter)
944  * represents a minimum Xid value; a table whose relfrozenxid is older than
945  * this will have a full-table vacuum applied to it, to freeze tuples across
946  * the whole table. Vacuuming a table younger than this value can use a
947  * partial scan.
948  * - multiXactCutoff is the value below which all MultiXactIds are removed from
949  * Xmax.
950  * - mxactFullScanLimit is a value against which a table's relminmxid value is
951  * compared to produce a full-table vacuum, as with xidFullScanLimit.
952  *
953  * xidFullScanLimit and mxactFullScanLimit can be passed as NULL if caller is
954  * not interested.
955  */
956 void
958  int freeze_min_age,
959  int freeze_table_age,
960  int multixact_freeze_min_age,
961  int multixact_freeze_table_age,
962  TransactionId *oldestXmin,
963  TransactionId *freezeLimit,
964  TransactionId *xidFullScanLimit,
965  MultiXactId *multiXactCutoff,
966  MultiXactId *mxactFullScanLimit)
967 {
968  int freezemin;
969  int mxid_freezemin;
970  int effective_multixact_freeze_max_age;
971  TransactionId limit;
972  TransactionId safeLimit;
973  MultiXactId oldestMxact;
974  MultiXactId mxactLimit;
975  MultiXactId safeMxactLimit;
976 
977  /*
978  * We can always ignore processes running lazy vacuum. This is because we
979  * use these values only for deciding which tuples we must keep in the
980  * tables. Since lazy vacuum doesn't write its XID anywhere (usually no
981  * XID assigned), it's safe to ignore it. In theory it could be
982  * problematic to ignore lazy vacuums in a full vacuum, but keep in mind
983  * that only one vacuum process can be working on a particular table at
984  * any time, and that each vacuum is always an independent transaction.
985  */
986  *oldestXmin = GetOldestNonRemovableTransactionId(rel);
987 
989  {
990  TransactionId limit_xmin;
991  TimestampTz limit_ts;
992 
993  if (TransactionIdLimitedForOldSnapshots(*oldestXmin, rel,
994  &limit_xmin, &limit_ts))
995  {
996  /*
997  * TODO: We should only set the threshold if we are pruning on the
998  * basis of the increased limits. Not as crucial here as it is
999  * for opportunistic pruning (which often happens at a much higher
1000  * frequency), but would still be a significant improvement.
1001  */
1002  SetOldSnapshotThresholdTimestamp(limit_ts, limit_xmin);
1003  *oldestXmin = limit_xmin;
1004  }
1005  }
1006 
1007  Assert(TransactionIdIsNormal(*oldestXmin));
1008 
1009  /*
1010  * Determine the minimum freeze age to use: as specified by the caller, or
1011  * vacuum_freeze_min_age, but in any case not more than half
1012  * autovacuum_freeze_max_age, so that autovacuums to prevent XID
1013  * wraparound won't occur too frequently.
1014  */
1015  freezemin = freeze_min_age;
1016  if (freezemin < 0)
1017  freezemin = vacuum_freeze_min_age;
1018  freezemin = Min(freezemin, autovacuum_freeze_max_age / 2);
1019  Assert(freezemin >= 0);
1020 
1021  /*
1022  * Compute the cutoff XID, being careful not to generate a "permanent" XID
1023  */
1024  limit = *oldestXmin - freezemin;
1025  if (!TransactionIdIsNormal(limit))
1026  limit = FirstNormalTransactionId;
1027 
1028  /*
1029  * If oldestXmin is very far back (in practice, more than
1030  * autovacuum_freeze_max_age / 2 XIDs old), complain and force a minimum
1031  * freeze age of zero.
1032  */
1034  if (!TransactionIdIsNormal(safeLimit))
1035  safeLimit = FirstNormalTransactionId;
1036 
1037  if (TransactionIdPrecedes(limit, safeLimit))
1038  {
1039  ereport(WARNING,
1040  (errmsg("oldest xmin is far in the past"),
1041  errhint("Close open transactions soon to avoid wraparound problems.\n"
1042  "You might also need to commit or roll back old prepared transactions, or drop stale replication slots.")));
1043  limit = *oldestXmin;
1044  }
1045 
1046  *freezeLimit = limit;
1047 
1048  /*
1049  * Compute the multixact age for which freezing is urgent. This is
1050  * normally autovacuum_multixact_freeze_max_age, but may be less if we are
1051  * short of multixact member space.
1052  */
1053  effective_multixact_freeze_max_age = MultiXactMemberFreezeThreshold();
1054 
1055  /*
1056  * Determine the minimum multixact freeze age to use: as specified by
1057  * caller, or vacuum_multixact_freeze_min_age, but in any case not more
1058  * than half effective_multixact_freeze_max_age, so that autovacuums to
1059  * prevent MultiXact wraparound won't occur too frequently.
1060  */
1061  mxid_freezemin = multixact_freeze_min_age;
1062  if (mxid_freezemin < 0)
1063  mxid_freezemin = vacuum_multixact_freeze_min_age;
1064  mxid_freezemin = Min(mxid_freezemin,
1065  effective_multixact_freeze_max_age / 2);
1066  Assert(mxid_freezemin >= 0);
1067 
1068  /* compute the cutoff multi, being careful to generate a valid value */
1069  oldestMxact = GetOldestMultiXactId();
1070  mxactLimit = oldestMxact - mxid_freezemin;
1071  if (mxactLimit < FirstMultiXactId)
1072  mxactLimit = FirstMultiXactId;
1073 
1074  safeMxactLimit =
1075  ReadNextMultiXactId() - effective_multixact_freeze_max_age;
1076  if (safeMxactLimit < FirstMultiXactId)
1077  safeMxactLimit = FirstMultiXactId;
1078 
1079  if (MultiXactIdPrecedes(mxactLimit, safeMxactLimit))
1080  {
1081  ereport(WARNING,
1082  (errmsg("oldest multixact is far in the past"),
1083  errhint("Close open transactions with multixacts soon to avoid wraparound problems.")));
1084  /* Use the safe limit, unless an older mxact is still running */
1085  if (MultiXactIdPrecedes(oldestMxact, safeMxactLimit))
1086  mxactLimit = oldestMxact;
1087  else
1088  mxactLimit = safeMxactLimit;
1089  }
1090 
1091  *multiXactCutoff = mxactLimit;
1092 
1093  if (xidFullScanLimit != NULL)
1094  {
1095  int freezetable;
1096 
1097  Assert(mxactFullScanLimit != NULL);
1098 
1099  /*
1100  * Determine the table freeze age to use: as specified by the caller,
1101  * or vacuum_freeze_table_age, but in any case not more than
1102  * autovacuum_freeze_max_age * 0.95, so that if you have e.g nightly
1103  * VACUUM schedule, the nightly VACUUM gets a chance to freeze tuples
1104  * before anti-wraparound autovacuum is launched.
1105  */
1106  freezetable = freeze_table_age;
1107  if (freezetable < 0)
1108  freezetable = vacuum_freeze_table_age;
1109  freezetable = Min(freezetable, autovacuum_freeze_max_age * 0.95);
1110  Assert(freezetable >= 0);
1111 
1112  /*
1113  * Compute XID limit causing a full-table vacuum, being careful not to
1114  * generate a "permanent" XID.
1115  */
1116  limit = ReadNextTransactionId() - freezetable;
1117  if (!TransactionIdIsNormal(limit))
1118  limit = FirstNormalTransactionId;
1119 
1120  *xidFullScanLimit = limit;
1121 
1122  /*
1123  * Similar to the above, determine the table freeze age to use for
1124  * multixacts: as specified by the caller, or
1125  * vacuum_multixact_freeze_table_age, but in any case not more than
1126  * autovacuum_multixact_freeze_table_age * 0.95, so that if you have
1127  * e.g. nightly VACUUM schedule, the nightly VACUUM gets a chance to
1128  * freeze multixacts before anti-wraparound autovacuum is launched.
1129  */
1130  freezetable = multixact_freeze_table_age;
1131  if (freezetable < 0)
1132  freezetable = vacuum_multixact_freeze_table_age;
1133  freezetable = Min(freezetable,
1134  effective_multixact_freeze_max_age * 0.95);
1135  Assert(freezetable >= 0);
1136 
1137  /*
1138  * Compute MultiXact limit causing a full-table vacuum, being careful
1139  * to generate a valid MultiXact value.
1140  */
1141  mxactLimit = ReadNextMultiXactId() - freezetable;
1142  if (mxactLimit < FirstMultiXactId)
1143  mxactLimit = FirstMultiXactId;
1144 
1145  *mxactFullScanLimit = mxactLimit;
1146  }
1147  else
1148  {
1149  Assert(mxactFullScanLimit == NULL);
1150  }
1151 }
1152 
1153 /*
1154  * vacuum_xid_failsafe_check() -- Used by VACUUM's wraparound failsafe
1155  * mechanism to determine if its table's relfrozenxid and relminmxid are now
1156  * dangerously far in the past.
1157  *
1158  * Input parameters are the target relation's relfrozenxid and relminmxid.
1159  *
1160  * When we return true, VACUUM caller triggers the failsafe.
1161  */
1162 bool
1164 {
1165  TransactionId xid_skip_limit;
1166  MultiXactId multi_skip_limit;
1167  int skip_index_vacuum;
1168 
1169  Assert(TransactionIdIsNormal(relfrozenxid));
1170  Assert(MultiXactIdIsValid(relminmxid));
1171 
1172  /*
1173  * Determine the index skipping age to use. In any case no less than
1174  * autovacuum_freeze_max_age * 1.05.
1175  */
1176  skip_index_vacuum = Max(vacuum_failsafe_age, autovacuum_freeze_max_age * 1.05);
1177 
1178  xid_skip_limit = ReadNextTransactionId() - skip_index_vacuum;
1179  if (!TransactionIdIsNormal(xid_skip_limit))
1180  xid_skip_limit = FirstNormalTransactionId;
1181 
1182  if (TransactionIdPrecedes(relfrozenxid, xid_skip_limit))
1183  {
1184  /* The table's relfrozenxid is too old */
1185  return true;
1186  }
1187 
1188  /*
1189  * Similar to above, determine the index skipping age to use for
1190  * multixact. In any case no less than autovacuum_multixact_freeze_max_age *
1191  * 1.05.
1192  */
1193  skip_index_vacuum = Max(vacuum_multixact_failsafe_age,
1195 
1196  multi_skip_limit = ReadNextMultiXactId() - skip_index_vacuum;
1197  if (multi_skip_limit < FirstMultiXactId)
1198  multi_skip_limit = FirstMultiXactId;
1199 
1200  if (MultiXactIdPrecedes(relminmxid, multi_skip_limit))
1201  {
1202  /* The table's relminmxid is too old */
1203  return true;
1204  }
1205 
1206  return false;
1207 }
1208 
1209 /*
1210  * vac_estimate_reltuples() -- estimate the new value for pg_class.reltuples
1211  *
1212  * If we scanned the whole relation then we should just use the count of
1213  * live tuples seen; but if we did not, we should not blindly extrapolate
1214  * from that number, since VACUUM may have scanned a quite nonrandom
1215  * subset of the table. When we have only partial information, we take
1216  * the old value of pg_class.reltuples/pg_class.relpages as a measurement
1217  * of the tuple density in the unscanned pages.
1218  *
1219  * Note: scanned_tuples should count only *live* tuples, since
1220  * pg_class.reltuples is defined that way.
1221  */
1222 double
1224  BlockNumber total_pages,
1225  BlockNumber scanned_pages,
1226  double scanned_tuples)
1227 {
1228  BlockNumber old_rel_pages = relation->rd_rel->relpages;
1229  double old_rel_tuples = relation->rd_rel->reltuples;
1230  double old_density;
1231  double unscanned_pages;
1232  double total_tuples;
1233 
1234  /* If we did scan the whole table, just use the count as-is */
1235  if (scanned_pages >= total_pages)
1236  return scanned_tuples;
1237 
1238  /*
1239  * If scanned_pages is zero but total_pages isn't, keep the existing value
1240  * of reltuples. (Note: we might be returning -1 in this case.)
1241  */
1242  if (scanned_pages == 0)
1243  return old_rel_tuples;
1244 
1245  /*
1246  * If old density is unknown, we can't do much except scale up
1247  * scanned_tuples to match total_pages.
1248  */
1249  if (old_rel_tuples < 0 || old_rel_pages == 0)
1250  return floor((scanned_tuples / scanned_pages) * total_pages + 0.5);
1251 
1252  /*
1253  * Okay, we've covered the corner cases. The normal calculation is to
1254  * convert the old measurement to a density (tuples per page), then
1255  * estimate the number of tuples in the unscanned pages using that figure,
1256  * and finally add on the number of tuples in the scanned pages.
1257  */
1258  old_density = old_rel_tuples / old_rel_pages;
1259  unscanned_pages = (double) total_pages - (double) scanned_pages;
1260  total_tuples = old_density * unscanned_pages + scanned_tuples;
1261  return floor(total_tuples + 0.5);
1262 }
1263 
1264 
1265 /*
1266  * vac_update_relstats() -- update statistics for one relation
1267  *
1268  * Update the whole-relation statistics that are kept in its pg_class
1269  * row. There are additional stats that will be updated if we are
1270  * doing ANALYZE, but we always update these stats. This routine works
1271  * for both index and heap relation entries in pg_class.
1272  *
1273  * We violate transaction semantics here by overwriting the rel's
1274  * existing pg_class tuple with the new values. This is reasonably
1275  * safe as long as we're sure that the new values are correct whether or
1276  * not this transaction commits. The reason for doing this is that if
1277  * we updated these tuples in the usual way, vacuuming pg_class itself
1278  * wouldn't work very well --- by the time we got done with a vacuum
1279  * cycle, most of the tuples in pg_class would've been obsoleted. Of
1280  * course, this only works for fixed-size not-null columns, but these are.
1281  *
1282  * Another reason for doing it this way is that when we are in a lazy
1283  * VACUUM and have PROC_IN_VACUUM set, we mustn't do any regular updates.
1284  * Somebody vacuuming pg_class might think they could delete a tuple
1285  * marked with xmin = our xid.
1286  *
1287  * In addition to fundamentally nontransactional statistics such as
1288  * relpages and relallvisible, we try to maintain certain lazily-updated
1289  * DDL flags such as relhasindex, by clearing them if no longer correct.
1290  * It's safe to do this in VACUUM, which can't run in parallel with
1291  * CREATE INDEX/RULE/TRIGGER and can't be part of a transaction block.
1292  * However, it's *not* safe to do it in an ANALYZE that's within an
1293  * outer transaction, because for example the current transaction might
1294  * have dropped the last index; then we'd think relhasindex should be
1295  * cleared, but if the transaction later rolls back this would be wrong.
1296  * So we refrain from updating the DDL flags if we're inside an outer
1297  * transaction. This is OK since postponing the flag maintenance is
1298  * always allowable.
1299  *
1300  * Note: num_tuples should count only *live* tuples, since
1301  * pg_class.reltuples is defined that way.
1302  *
1303  * This routine is shared by VACUUM and ANALYZE.
1304  */
1305 void
1307  BlockNumber num_pages, double num_tuples,
1308  BlockNumber num_all_visible_pages,
1309  bool hasindex, TransactionId frozenxid,
1310  MultiXactId minmulti,
1311  bool in_outer_xact)
1312 {
1313  Oid relid = RelationGetRelid(relation);
1314  Relation rd;
1315  HeapTuple ctup;
1316  Form_pg_class pgcform;
1317  bool dirty;
1318 
1319  rd = table_open(RelationRelationId, RowExclusiveLock);
1320 
1321  /* Fetch a copy of the tuple to scribble on */
1323  if (!HeapTupleIsValid(ctup))
1324  elog(ERROR, "pg_class entry for relid %u vanished during vacuuming",
1325  relid);
1326  pgcform = (Form_pg_class) GETSTRUCT(ctup);
1327 
1328  /* Apply statistical updates, if any, to copied tuple */
1329 
1330  dirty = false;
1331  if (pgcform->relpages != (int32) num_pages)
1332  {
1333  pgcform->relpages = (int32) num_pages;
1334  dirty = true;
1335  }
1336  if (pgcform->reltuples != (float4) num_tuples)
1337  {
1338  pgcform->reltuples = (float4) num_tuples;
1339  dirty = true;
1340  }
1341  if (pgcform->relallvisible != (int32) num_all_visible_pages)
1342  {
1343  pgcform->relallvisible = (int32) num_all_visible_pages;
1344  dirty = true;
1345  }
1346 
1347  /* Apply DDL updates, but not inside an outer transaction (see above) */
1348 
1349  if (!in_outer_xact)
1350  {
1351  /*
1352  * If we didn't find any indexes, reset relhasindex.
1353  */
1354  if (pgcform->relhasindex && !hasindex)
1355  {
1356  pgcform->relhasindex = false;
1357  dirty = true;
1358  }
1359 
1360  /* We also clear relhasrules and relhastriggers if needed */
1361  if (pgcform->relhasrules && relation->rd_rules == NULL)
1362  {
1363  pgcform->relhasrules = false;
1364  dirty = true;
1365  }
1366  if (pgcform->relhastriggers && relation->trigdesc == NULL)
1367  {
1368  pgcform->relhastriggers = false;
1369  dirty = true;
1370  }
1371  }
1372 
1373  /*
1374  * Update relfrozenxid, unless caller passed InvalidTransactionId
1375  * indicating it has no new data.
1376  *
1377  * Ordinarily, we don't let relfrozenxid go backwards: if things are
1378  * working correctly, the only way the new frozenxid could be older would
1379  * be if a previous VACUUM was done with a tighter freeze_min_age, in
1380  * which case we don't want to forget the work it already did. However,
1381  * if the stored relfrozenxid is "in the future", then it must be corrupt
1382  * and it seems best to overwrite it with the cutoff we used this time.
1383  * This should match vac_update_datfrozenxid() concerning what we consider
1384  * to be "in the future".
1385  */
1386  if (TransactionIdIsNormal(frozenxid) &&
1387  pgcform->relfrozenxid != frozenxid &&
1388  (TransactionIdPrecedes(pgcform->relfrozenxid, frozenxid) ||
1390  pgcform->relfrozenxid)))
1391  {
1392  pgcform->relfrozenxid = frozenxid;
1393  dirty = true;
1394  }
1395 
1396  /* Similarly for relminmxid */
1397  if (MultiXactIdIsValid(minmulti) &&
1398  pgcform->relminmxid != minmulti &&
1399  (MultiXactIdPrecedes(pgcform->relminmxid, minmulti) ||
1400  MultiXactIdPrecedes(ReadNextMultiXactId(), pgcform->relminmxid)))
1401  {
1402  pgcform->relminmxid = minmulti;
1403  dirty = true;
1404  }
1405 
1406  /* If anything changed, write out the tuple. */
1407  if (dirty)
1408  heap_inplace_update(rd, ctup);
1409 
1411 }
1412 
1413 
1414 /*
1415  * vac_update_datfrozenxid() -- update pg_database.datfrozenxid for our DB
1416  *
1417  * Update pg_database's datfrozenxid entry for our database to be the
1418  * minimum of the pg_class.relfrozenxid values.
1419  *
1420  * Similarly, update our datminmxid to be the minimum of the
1421  * pg_class.relminmxid values.
1422  *
1423  * If we are able to advance either pg_database value, also try to
1424  * truncate pg_xact and pg_multixact.
1425  *
1426  * We violate transaction semantics here by overwriting the database's
1427  * existing pg_database tuple with the new values. This is reasonably
1428  * safe since the new values are correct whether or not this transaction
1429  * commits. As with vac_update_relstats, this avoids leaving dead tuples
1430  * behind after a VACUUM.
1431  */
1432 void
1434 {
1435  HeapTuple tuple;
1436  Form_pg_database dbform;
1437  Relation relation;
1438  SysScanDesc scan;
1439  HeapTuple classTup;
1440  TransactionId newFrozenXid;
1441  MultiXactId newMinMulti;
1442  TransactionId lastSaneFrozenXid;
1443  MultiXactId lastSaneMinMulti;
1444  bool bogus = false;
1445  bool dirty = false;
1446  ScanKeyData key[1];
1447 
1448  /*
1449  * Restrict this task to one backend per database. This avoids race
1450  * conditions that would move datfrozenxid or datminmxid backward. It
1451  * avoids calling vac_truncate_clog() with a datfrozenxid preceding a
1452  * datfrozenxid passed to an earlier vac_truncate_clog() call.
1453  */
1455 
1456  /*
1457  * Initialize the "min" calculation with
1458  * GetOldestNonRemovableTransactionId(), which is a reasonable
1459  * approximation to the minimum relfrozenxid for not-yet-committed
1460  * pg_class entries for new tables; see AddNewRelationTuple(). So we
1461  * cannot produce a wrong minimum by starting with this.
1462  */
1463  newFrozenXid = GetOldestNonRemovableTransactionId(NULL);
1464 
1465  /*
1466  * Similarly, initialize the MultiXact "min" with the value that would be
1467  * used on pg_class for new tables. See AddNewRelationTuple().
1468  */
1469  newMinMulti = GetOldestMultiXactId();
1470 
1471  /*
1472  * Identify the latest relfrozenxid and relminmxid values that we could
1473  * validly see during the scan. These are conservative values, but it's
1474  * not really worth trying to be more exact.
1475  */
1476  lastSaneFrozenXid = ReadNextTransactionId();
1477  lastSaneMinMulti = ReadNextMultiXactId();
1478 
1479  /*
1480  * We must seqscan pg_class to find the minimum Xid, because there is no
1481  * index that can help us here.
1482  */
1483  relation = table_open(RelationRelationId, AccessShareLock);
1484 
1485  scan = systable_beginscan(relation, InvalidOid, false,
1486  NULL, 0, NULL);
1487 
1488  while ((classTup = systable_getnext(scan)) != NULL)
1489  {
1490  Form_pg_class classForm = (Form_pg_class) GETSTRUCT(classTup);
1491 
1492  /*
1493  * Only consider relations able to hold unfrozen XIDs (anything else
1494  * should have InvalidTransactionId in relfrozenxid anyway).
1495  */
1496  if (classForm->relkind != RELKIND_RELATION &&
1497  classForm->relkind != RELKIND_MATVIEW &&
1498  classForm->relkind != RELKIND_TOASTVALUE)
1499  {
1500  Assert(!TransactionIdIsValid(classForm->relfrozenxid));
1501  Assert(!MultiXactIdIsValid(classForm->relminmxid));
1502  continue;
1503  }
1504 
1505  /*
1506  * Some table AMs might not need per-relation xid / multixid horizons.
1507  * It therefore seems reasonable to allow relfrozenxid and relminmxid
1508  * to not be set (i.e. set to their respective Invalid*Id)
1509  * independently. Thus validate and compute horizon for each only if
1510  * set.
1511  *
1512  * If things are working properly, no relation should have a
1513  * relfrozenxid or relminmxid that is "in the future". However, such
1514  * cases have been known to arise due to bugs in pg_upgrade. If we
1515  * see any entries that are "in the future", chicken out and don't do
1516  * anything. This ensures we won't truncate clog & multixact SLRUs
1517  * before those relations have been scanned and cleaned up.
1518  */
1519 
1520  if (TransactionIdIsValid(classForm->relfrozenxid))
1521  {
1522  Assert(TransactionIdIsNormal(classForm->relfrozenxid));
1523 
1524  /* check for values in the future */
1525  if (TransactionIdPrecedes(lastSaneFrozenXid, classForm->relfrozenxid))
1526  {
1527  bogus = true;
1528  break;
1529  }
1530 
1531  /* determine new horizon */
1532  if (TransactionIdPrecedes(classForm->relfrozenxid, newFrozenXid))
1533  newFrozenXid = classForm->relfrozenxid;
1534  }
1535 
1536  if (MultiXactIdIsValid(classForm->relminmxid))
1537  {
1538  /* check for values in the future */
1539  if (MultiXactIdPrecedes(lastSaneMinMulti, classForm->relminmxid))
1540  {
1541  bogus = true;
1542  break;
1543  }
1544 
1545  /* determine new horizon */
1546  if (MultiXactIdPrecedes(classForm->relminmxid, newMinMulti))
1547  newMinMulti = classForm->relminmxid;
1548  }
1549  }
1550 
1551  /* we're done with pg_class */
1552  systable_endscan(scan);
1553  table_close(relation, AccessShareLock);
1554 
1555  /* chicken out if bogus data found */
1556  if (bogus)
1557  return;
1558 
1559  Assert(TransactionIdIsNormal(newFrozenXid));
1560  Assert(MultiXactIdIsValid(newMinMulti));
1561 
1562  /* Now fetch the pg_database tuple we need to update. */
1563  relation = table_open(DatabaseRelationId, RowExclusiveLock);
1564 
1565  /*
1566  * Get the pg_database tuple to scribble on. Note that this does not
1567  * directly rely on the syscache to avoid issues with flattened toast
1568  * values for the in-place update.
1569  */
1570  ScanKeyInit(&key[0],
1571  Anum_pg_database_oid,
1572  BTEqualStrategyNumber, F_OIDEQ,
1574 
1575  scan = systable_beginscan(relation, DatabaseOidIndexId, true,
1576  NULL, 1, key);
1577  tuple = systable_getnext(scan);
1578  tuple = heap_copytuple(tuple);
1579  systable_endscan(scan);
1580 
1581  if (!HeapTupleIsValid(tuple))
1582  elog(ERROR, "could not find tuple for database %u", MyDatabaseId);
1583 
1584  dbform = (Form_pg_database) GETSTRUCT(tuple);
1585 
1586  /*
1587  * As in vac_update_relstats(), we ordinarily don't want to let
1588  * datfrozenxid go backward; but if it's "in the future" then it must be
1589  * corrupt and it seems best to overwrite it.
1590  */
1591  if (dbform->datfrozenxid != newFrozenXid &&
1592  (TransactionIdPrecedes(dbform->datfrozenxid, newFrozenXid) ||
1593  TransactionIdPrecedes(lastSaneFrozenXid, dbform->datfrozenxid)))
1594  {
1595  dbform->datfrozenxid = newFrozenXid;
1596  dirty = true;
1597  }
1598  else
1599  newFrozenXid = dbform->datfrozenxid;
1600 
1601  /* Ditto for datminmxid */
1602  if (dbform->datminmxid != newMinMulti &&
1603  (MultiXactIdPrecedes(dbform->datminmxid, newMinMulti) ||
1604  MultiXactIdPrecedes(lastSaneMinMulti, dbform->datminmxid)))
1605  {
1606  dbform->datminmxid = newMinMulti;
1607  dirty = true;
1608  }
1609  else
1610  newMinMulti = dbform->datminmxid;
1611 
1612  if (dirty)
1613  heap_inplace_update(relation, tuple);
1614 
1615  heap_freetuple(tuple);
1616  table_close(relation, RowExclusiveLock);
1617 
1618  /*
1619  * If we were able to advance datfrozenxid or datminmxid, see if we can
1620  * truncate pg_xact and/or pg_multixact. Also do it if the shared
1621  * XID-wrap-limit info is stale, since this action will update that too.
1622  */
1623  if (dirty || ForceTransactionIdLimitUpdate())
1624  vac_truncate_clog(newFrozenXid, newMinMulti,
1625  lastSaneFrozenXid, lastSaneMinMulti);
1626 }
1627 
1628 
1629 /*
1630  * vac_truncate_clog() -- attempt to truncate the commit log
1631  *
1632  * Scan pg_database to determine the system-wide oldest datfrozenxid,
1633  * and use it to truncate the transaction commit log (pg_xact).
1634  * Also update the XID wrap limit info maintained by varsup.c.
1635  * Likewise for datminmxid.
1636  *
1637  * The passed frozenXID and minMulti are the updated values for my own
1638  * pg_database entry. They're used to initialize the "min" calculations.
1639  * The caller also passes the "last sane" XID and MXID, since it has
1640  * those at hand already.
1641  *
1642  * This routine is only invoked when we've managed to change our
1643  * DB's datfrozenxid/datminmxid values, or we found that the shared
1644  * XID-wrap-limit info is stale.
1645  */
1646 static void
1648  MultiXactId minMulti,
1649  TransactionId lastSaneFrozenXid,
1650  MultiXactId lastSaneMinMulti)
1651 {
1653  Relation relation;
1654  TableScanDesc scan;
1655  HeapTuple tuple;
1656  Oid oldestxid_datoid;
1657  Oid minmulti_datoid;
1658  bool bogus = false;
1659  bool frozenAlreadyWrapped = false;
1660 
1661  /* Restrict task to one backend per cluster; see SimpleLruTruncate(). */
1662  LWLockAcquire(WrapLimitsVacuumLock, LW_EXCLUSIVE);
1663 
1664  /* init oldest datoids to sync with my frozenXID/minMulti values */
1665  oldestxid_datoid = MyDatabaseId;
1666  minmulti_datoid = MyDatabaseId;
1667 
1668  /*
1669  * Scan pg_database to compute the minimum datfrozenxid/datminmxid
1670  *
1671  * Since vac_update_datfrozenxid updates datfrozenxid/datminmxid in-place,
1672  * the values could change while we look at them. Fetch each one just
1673  * once to ensure sane behavior of the comparison logic. (Here, as in
1674  * many other places, we assume that fetching or updating an XID in shared
1675  * storage is atomic.)
1676  *
1677  * Note: we need not worry about a race condition with new entries being
1678  * inserted by CREATE DATABASE. Any such entry will have a copy of some
1679  * existing DB's datfrozenxid, and that source DB cannot be ours because
1680  * of the interlock against copying a DB containing an active backend.
1681  * Hence the new entry will not reduce the minimum. Also, if two VACUUMs
1682  * concurrently modify the datfrozenxid's of different databases, the
1683  * worst possible outcome is that pg_xact is not truncated as aggressively
1684  * as it could be.
1685  */
1686  relation = table_open(DatabaseRelationId, AccessShareLock);
1687 
1688  scan = table_beginscan_catalog(relation, 0, NULL);
1689 
1690  while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
1691  {
1692  volatile FormData_pg_database *dbform = (Form_pg_database) GETSTRUCT(tuple);
1693  TransactionId datfrozenxid = dbform->datfrozenxid;
1694  TransactionId datminmxid = dbform->datminmxid;
1695 
1696  Assert(TransactionIdIsNormal(datfrozenxid));
1697  Assert(MultiXactIdIsValid(datminmxid));
1698 
1699  /*
1700  * If things are working properly, no database should have a
1701  * datfrozenxid or datminmxid that is "in the future". However, such
1702  * cases have been known to arise due to bugs in pg_upgrade. If we
1703  * see any entries that are "in the future", chicken out and don't do
1704  * anything. This ensures we won't truncate clog before those
1705  * databases have been scanned and cleaned up. (We will issue the
1706  * "already wrapped" warning if appropriate, though.)
1707  */
1708  if (TransactionIdPrecedes(lastSaneFrozenXid, datfrozenxid) ||
1709  MultiXactIdPrecedes(lastSaneMinMulti, datminmxid))
1710  bogus = true;
1711 
1712  if (TransactionIdPrecedes(nextXID, datfrozenxid))
1713  frozenAlreadyWrapped = true;
1714  else if (TransactionIdPrecedes(datfrozenxid, frozenXID))
1715  {
1716  frozenXID = datfrozenxid;
1717  oldestxid_datoid = dbform->oid;
1718  }
1719 
1720  if (MultiXactIdPrecedes(datminmxid, minMulti))
1721  {
1722  minMulti = datminmxid;
1723  minmulti_datoid = dbform->oid;
1724  }
1725  }
1726 
1727  table_endscan(scan);
1728 
1729  table_close(relation, AccessShareLock);
1730 
1731  /*
1732  * Do not truncate CLOG if we seem to have suffered wraparound already;
1733  * the computed minimum XID might be bogus. This case should now be
1734  * impossible due to the defenses in GetNewTransactionId, but we keep the
1735  * test anyway.
1736  */
1737  if (frozenAlreadyWrapped)
1738  {
1739  ereport(WARNING,
1740  (errmsg("some databases have not been vacuumed in over 2 billion transactions"),
1741  errdetail("You might have already suffered transaction-wraparound data loss.")));
1742  return;
1743  }
1744 
1745  /* chicken out if data is bogus in any other way */
1746  if (bogus)
1747  return;
1748 
1749  /*
1750  * Advance the oldest value for commit timestamps before truncating, so
1751  * that if a user requests a timestamp for a transaction we're truncating
1752  * away right after this point, they get NULL instead of an ugly "file not
1753  * found" error from slru.c. This doesn't matter for xact/multixact
1754  * because they are not subject to arbitrary lookups from users.
1755  */
1756  AdvanceOldestCommitTsXid(frozenXID);
1757 
1758  /*
1759  * Truncate CLOG, multixact and CommitTs to the oldest computed value.
1760  */
1761  TruncateCLOG(frozenXID, oldestxid_datoid);
1762  TruncateCommitTs(frozenXID);
1763  TruncateMultiXact(minMulti, minmulti_datoid);
1764 
1765  /*
1766  * Update the wrap limit for GetNewTransactionId and creation of new
1767  * MultiXactIds. Note: these functions will also signal the postmaster
1768  * for an(other) autovac cycle if needed. XXX should we avoid possibly
1769  * signaling twice?
1770  */
1771  SetTransactionIdLimit(frozenXID, oldestxid_datoid);
1772  SetMultiXactIdLimit(minMulti, minmulti_datoid, false);
1773 
1774  LWLockRelease(WrapLimitsVacuumLock);
1775 }
1776 
1777 
1778 /*
1779  * vacuum_rel() -- vacuum one heap relation
1780  *
1781  * relid identifies the relation to vacuum. If relation is supplied,
1782  * use the name therein for reporting any failure to open/lock the rel;
1783  * do not use it once we've successfully opened the rel, since it might
1784  * be stale.
1785  *
1786  * Returns true if it's okay to proceed with a requested ANALYZE
1787  * operation on this table.
1788  *
1789  * Doing one heap at a time incurs extra overhead, since we need to
1790  * check that the heap exists again just before we vacuum it. The
1791  * reason that we do this is so that vacuuming can be spread across
1792  * many small transactions. Otherwise, two-phase locking would require
1793  * us to lock the entire database during one pass of the vacuum cleaner.
1794  *
1795  * At entry and exit, we are not inside a transaction.
1796  */
1797 static bool
1798 vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params)
1799 {
1800  LOCKMODE lmode;
1801  Relation rel;
1802  LockRelId lockrelid;
1803  Oid toast_relid;
1804  Oid save_userid;
1805  int save_sec_context;
1806  int save_nestlevel;
1807 
1808  Assert(params != NULL);
1809 
1810  /* Begin a transaction for vacuuming this relation */
1812 
1813  if (!(params->options & VACOPT_FULL))
1814  {
1815  /*
1816  * In lazy vacuum, we can set the PROC_IN_VACUUM flag, which lets
1817  * other concurrent VACUUMs know that they can ignore this one while
1818  * determining their OldestXmin. (The reason we don't set it during a
1819  * full VACUUM is exactly that we may have to run user-defined
1820  * functions for functional indexes, and we want to make sure that if
1821  * they use the snapshot set above, any tuples it requires can't get
1822  * removed from other tables. An index function that depends on the
1823  * contents of other tables is arguably broken, but we won't break it
1824  * here by violating transaction semantics.)
1825  *
1826  * We also set the VACUUM_FOR_WRAPAROUND flag, which is passed down by
1827  * autovacuum; it's used to avoid canceling a vacuum that was invoked
1828  * in an emergency.
1829  *
1830  * Note: these flags remain set until CommitTransaction or
1831  * AbortTransaction. We don't want to clear them until we reset
1832  * MyProc->xid/xmin, otherwise GetOldestNonRemovableTransactionId()
1833  * might appear to go backwards, which is probably Not Good. (We also
1834  * set PROC_IN_VACUUM *before* taking our own snapshot, so that our
1835  * xmin doesn't become visible ahead of setting the flag.)
1836  */
1837  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
1839  if (params->is_wraparound)
1842  LWLockRelease(ProcArrayLock);
1843  }
1844 
1845  /*
1846  * Need to acquire a snapshot to prevent pg_subtrans from being truncated,
1847  * cutoff xids in local memory wrapping around, and to have updated xmin
1848  * horizons.
1849  */
1851 
1852  /*
1853  * Check for user-requested abort. Note we want this to be inside a
1854  * transaction, so xact.c doesn't issue useless WARNING.
1855  */
1857 
1858  /*
1859  * Determine the type of lock we want --- hard exclusive lock for a FULL
1860  * vacuum, but just ShareUpdateExclusiveLock for concurrent vacuum. Either
1861  * way, we can be sure that no other backend is vacuuming the same table.
1862  */
1863  lmode = (params->options & VACOPT_FULL) ?
1865 
1866  /* open the relation and get the appropriate lock on it */
1867  rel = vacuum_open_relation(relid, relation, params->options,
1868  params->log_min_duration >= 0, lmode);
1869 
1870  /* leave if relation could not be opened or locked */
1871  if (!rel)
1872  {
1875  return false;
1876  }
1877 
1878  /*
1879  * Check if relation needs to be skipped based on ownership. This check
1880  * happens also when building the relation list to vacuum for a manual
1881  * operation, and needs to be done additionally here as VACUUM could
1882  * happen across multiple transactions where relation ownership could have
1883  * changed in-between. Make sure to only generate logs for VACUUM in this
1884  * case.
1885  */
1887  rel->rd_rel,
1888  params->options & VACOPT_VACUUM))
1889  {
1890  relation_close(rel, lmode);
1893  return false;
1894  }
1895 
1896  /*
1897  * Check that it's of a vacuumable relkind.
1898  */
1899  if (rel->rd_rel->relkind != RELKIND_RELATION &&
1900  rel->rd_rel->relkind != RELKIND_MATVIEW &&
1901  rel->rd_rel->relkind != RELKIND_TOASTVALUE &&
1902  rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
1903  {
1904  ereport(WARNING,
1905  (errmsg("skipping \"%s\" --- cannot vacuum non-tables or special system tables",
1906  RelationGetRelationName(rel))));
1907  relation_close(rel, lmode);
1910  return false;
1911  }
1912 
1913  /*
1914  * Silently ignore tables that are temp tables of other backends ---
1915  * trying to vacuum these will lead to great unhappiness, since their
1916  * contents are probably not up-to-date on disk. (We don't throw a
1917  * warning here; it would just lead to chatter during a database-wide
1918  * VACUUM.)
1919  */
1920  if (RELATION_IS_OTHER_TEMP(rel))
1921  {
1922  relation_close(rel, lmode);
1925  return false;
1926  }
1927 
1928  /*
1929  * Silently ignore partitioned tables as there is no work to be done. The
1930  * useful work is on their child partitions, which have been queued up for
1931  * us separately.
1932  */
1933  if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
1934  {
1935  relation_close(rel, lmode);
1938  /* It's OK to proceed with ANALYZE on this table */
1939  return true;
1940  }
1941 
1942  /*
1943  * Get a session-level lock too. This will protect our access to the
1944  * relation across multiple transactions, so that we can vacuum the
1945  * relation's TOAST table (if any) secure in the knowledge that no one is
1946  * deleting the parent relation.
1947  *
1948  * NOTE: this cannot block, even if someone else is waiting for access,
1949  * because the lock manager knows that both lock requests are from the
1950  * same process.
1951  */
1952  lockrelid = rel->rd_lockInfo.lockRelId;
1953  LockRelationIdForSession(&lockrelid, lmode);
1954 
1955  /*
1956  * Set index_cleanup option based on index_cleanup reloption if it wasn't
1957  * specified in VACUUM command, or when running in an autovacuum worker
1958  */
1959  if (params->index_cleanup == VACOPTVALUE_UNSPECIFIED)
1960  {
1961  StdRdOptIndexCleanup vacuum_index_cleanup;
1962 
1963  if (rel->rd_options == NULL)
1964  vacuum_index_cleanup = STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO;
1965  else
1966  vacuum_index_cleanup =
1967  ((StdRdOptions *) rel->rd_options)->vacuum_index_cleanup;
1968 
1969  if (vacuum_index_cleanup == STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO)
1970  params->index_cleanup = VACOPTVALUE_AUTO;
1971  else if (vacuum_index_cleanup == STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON)
1973  else
1974  {
1975  Assert(vacuum_index_cleanup ==
1978  }
1979  }
1980 
1981  /*
1982  * Set truncate option based on truncate reloption if it wasn't specified
1983  * in VACUUM command, or when running in an autovacuum worker
1984  */
1985  if (params->truncate == VACOPTVALUE_UNSPECIFIED)
1986  {
1987  if (rel->rd_options == NULL ||
1988  ((StdRdOptions *) rel->rd_options)->vacuum_truncate)
1989  params->truncate = VACOPTVALUE_ENABLED;
1990  else
1991  params->truncate = VACOPTVALUE_DISABLED;
1992  }
1993 
1994  /*
1995  * Remember the relation's TOAST relation for later, if the caller asked
1996  * us to process it. In VACUUM FULL, though, the toast table is
1997  * automatically rebuilt by cluster_rel so we shouldn't recurse to it.
1998  */
1999  if ((params->options & VACOPT_PROCESS_TOAST) != 0 &&
2000  (params->options & VACOPT_FULL) == 0)
2001  toast_relid = rel->rd_rel->reltoastrelid;
2002  else
2003  toast_relid = InvalidOid;
2004 
2005  /*
2006  * Switch to the table owner's userid, so that any index functions are run
2007  * as that user. Also lock down security-restricted operations and
2008  * arrange to make GUC variable changes local to this command. (This is
2009  * unnecessary, but harmless, for lazy VACUUM.)
2010  */
2011  GetUserIdAndSecContext(&save_userid, &save_sec_context);
2012  SetUserIdAndSecContext(rel->rd_rel->relowner,
2013  save_sec_context | SECURITY_RESTRICTED_OPERATION);
2014  save_nestlevel = NewGUCNestLevel();
2015 
2016  /*
2017  * Do the actual work --- either FULL or "lazy" vacuum
2018  */
2019  if (params->options & VACOPT_FULL)
2020  {
2021  ClusterParams cluster_params = {0};
2022 
2023  /* close relation before vacuuming, but hold lock until commit */
2024  relation_close(rel, NoLock);
2025  rel = NULL;
2026 
2027  if ((params->options & VACOPT_VERBOSE) != 0)
2028  cluster_params.options |= CLUOPT_VERBOSE;
2029 
2030  /* VACUUM FULL is now a variant of CLUSTER; see cluster.c */
2031  cluster_rel(relid, InvalidOid, &cluster_params);
2032  }
2033  else
2034  table_relation_vacuum(rel, params, vac_strategy);
2035 
2036  /* Roll back any GUC changes executed by index functions */
2037  AtEOXact_GUC(false, save_nestlevel);
2038 
2039  /* Restore userid and security context */
2040  SetUserIdAndSecContext(save_userid, save_sec_context);
2041 
2042  /* all done with this class, but hold lock until commit */
2043  if (rel)
2044  relation_close(rel, NoLock);
2045 
2046  /*
2047  * Complete the transaction and free all temporary memory used.
2048  */
2051 
2052  /*
2053  * If the relation has a secondary toast rel, vacuum that too while we
2054  * still hold the session lock on the main table. Note however that
2055  * "analyze" will not get done on the toast table. This is good, because
2056  * the toaster always uses hardcoded index access and statistics are
2057  * totally unimportant for toast relations.
2058  */
2059  if (toast_relid != InvalidOid)
2060  vacuum_rel(toast_relid, NULL, params);
2061 
2062  /*
2063  * Now release the session-level lock on the main table.
2064  */
2065  UnlockRelationIdForSession(&lockrelid, lmode);
2066 
2067  /* Report that we really did it. */
2068  return true;
2069 }
2070 
2071 
2072 /*
2073  * Open all the vacuumable indexes of the given relation, obtaining the
2074  * specified kind of lock on each. Return an array of Relation pointers for
2075  * the indexes into *Irel, and the number of indexes into *nindexes.
2076  *
2077  * We consider an index vacuumable if it is marked insertable (indisready).
2078  * If it isn't, probably a CREATE INDEX CONCURRENTLY command failed early in
2079  * execution, and what we have is too corrupt to be processable. We will
2080  * vacuum even if the index isn't indisvalid; this is important because in a
2081  * unique index, uniqueness checks will be performed anyway and had better not
2082  * hit dangling index pointers.
2083  */
2084 void
2086  int *nindexes, Relation **Irel)
2087 {
2088  List *indexoidlist;
2089  ListCell *indexoidscan;
2090  int i;
2091 
2092  Assert(lockmode != NoLock);
2093 
2094  indexoidlist = RelationGetIndexList(relation);
2095 
2096  /* allocate enough memory for all indexes */
2097  i = list_length(indexoidlist);
2098 
2099  if (i > 0)
2100  *Irel = (Relation *) palloc(i * sizeof(Relation));
2101  else
2102  *Irel = NULL;
2103 
2104  /* collect just the ready indexes */
2105  i = 0;
2106  foreach(indexoidscan, indexoidlist)
2107  {
2108  Oid indexoid = lfirst_oid(indexoidscan);
2109  Relation indrel;
2110 
2111  indrel = index_open(indexoid, lockmode);
2112  if (indrel->rd_index->indisready)
2113  (*Irel)[i++] = indrel;
2114  else
2115  index_close(indrel, lockmode);
2116  }
2117 
2118  *nindexes = i;
2119 
2120  list_free(indexoidlist);
2121 }
2122 
2123 /*
2124  * Release the resources acquired by vac_open_indexes. Optionally release
2125  * the locks (say NoLock to keep 'em).
2126  */
2127 void
2128 vac_close_indexes(int nindexes, Relation *Irel, LOCKMODE lockmode)
2129 {
2130  if (Irel == NULL)
2131  return;
2132 
2133  while (nindexes--)
2134  {
2135  Relation ind = Irel[nindexes];
2136 
2137  index_close(ind, lockmode);
2138  }
2139  pfree(Irel);
2140 }
2141 
2142 /*
2143  * vacuum_delay_point --- check for interrupts and cost-based delay.
2144  *
2145  * This should be called in each major loop of VACUUM processing,
2146  * typically once per page processed.
2147  */
2148 void
2150 {
2151  double msec = 0;
2152 
2153  /* Always check for interrupts */
2155 
2157  return;
2158 
2159  /*
2160  * For parallel vacuum, the delay is computed based on the shared cost
2161  * balance. See compute_parallel_delay.
2162  */
2163  if (VacuumSharedCostBalance != NULL)
2164  msec = compute_parallel_delay();
2165  else if (VacuumCostBalance >= VacuumCostLimit)
2167 
2168  /* Nap if appropriate */
2169  if (msec > 0)
2170  {
2171  if (msec > VacuumCostDelay * 4)
2172  msec = VacuumCostDelay * 4;
2173 
2174  (void) WaitLatch(MyLatch,
2176  msec,
2179 
2180  VacuumCostBalance = 0;
2181 
2182  /* update balance values for workers */
2184 
2185  /* Might have gotten an interrupt while sleeping */
2187  }
2188 }
2189 
2190 /*
2191  * Computes the vacuum delay for parallel workers.
2192  *
2193  * The basic idea of a cost-based delay for parallel vacuum is to allow each
2194  * worker to sleep in proportion to the share of work it's done. We achieve this
2195  * by allowing all parallel vacuum workers including the leader process to
2196  * have a shared view of cost related parameters (mainly VacuumCostBalance).
2197  * We allow each worker to update it as and when it has incurred any cost and
2198  * then based on that decide whether it needs to sleep. We compute the time
2199  * to sleep for a worker based on the cost it has incurred
2200  * (VacuumCostBalanceLocal) and then reduce the VacuumSharedCostBalance by
2201  * that amount. This avoids putting to sleep those workers which have done less
2202  * I/O than other workers and therefore ensure that workers
2203  * which are doing more I/O got throttled more.
2204  *
2205  * We allow a worker to sleep only if it has performed I/O above a certain
2206  * threshold, which is calculated based on the number of active workers
2207  * (VacuumActiveNWorkers), and the overall cost balance is more than
2208  * VacuumCostLimit set by the system. Testing reveals that we achieve
2209  * the required throttling if we force a worker that has done more than 50%
2210  * of its share of work to sleep.
2211  */
2212 static double
2214 {
2215  double msec = 0;
2216  uint32 shared_balance;
2217  int nworkers;
2218 
2219  /* Parallel vacuum must be active */
2220  Assert(VacuumSharedCostBalance);
2221 
2222  nworkers = pg_atomic_read_u32(VacuumActiveNWorkers);
2223 
2224  /* At least count itself */
2225  Assert(nworkers >= 1);
2226 
2227  /* Update the shared cost balance value atomically */
2228  shared_balance = pg_atomic_add_fetch_u32(VacuumSharedCostBalance, VacuumCostBalance);
2229 
2230  /* Compute the total local balance for the current worker */
2232 
2233  if ((shared_balance >= VacuumCostLimit) &&
2234  (VacuumCostBalanceLocal > 0.5 * ((double) VacuumCostLimit / nworkers)))
2235  {
2236  /* Compute sleep time based on the local cost balance */
2238  pg_atomic_sub_fetch_u32(VacuumSharedCostBalance, VacuumCostBalanceLocal);
2240  }
2241 
2242  /*
2243  * Reset the local balance as we accumulated it into the shared value.
2244  */
2245  VacuumCostBalance = 0;
2246 
2247  return msec;
2248 }
2249 
2250 /*
2251  * A wrapper function of defGetBoolean().
2252  *
2253  * This function returns VACOPTVALUE_ENABLED and VACOPTVALUE_DISABLED instead
2254  * of true and false.
2255  */
2256 static VacOptValue
2258 {
2260 }
BufferAccessStrategy GetAccessStrategy(BufferAccessStrategyType btype)
Definition: freelist.c:542
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:680
#define NIL
Definition: pg_list.h:65
bool ConditionalLockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:152
void analyze_rel(Oid relid, RangeVar *relation, VacuumParams *params, List *va_cols, bool in_outer_xact, BufferAccessStrategy bstrategy)
Definition: analyze.c:120
static double compute_parallel_delay(void)
Definition: vacuum.c:2213
int multixact_freeze_table_age
Definition: vacuum.h:216
void vac_close_indexes(int nindexes, Relation *Irel, LOCKMODE lockmode)
Definition: vacuum.c:2128
LockRelId lockRelId
Definition: rel.h:45
void vacuum(List *relations, VacuumParams *params, BufferAccessStrategy bstrategy, bool isTopLevel)
Definition: vacuum.c:291
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:218
#define AllocSetContextCreate
Definition: memutils.h:173
int64 VacuumPageMiss
Definition: globals.c:148
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
int errhint(const char *fmt,...)
Definition: elog.c:1156
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:595
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
#define ERRCODE_UNDEFINED_TABLE
Definition: pgbench.c:78
pg_atomic_uint32 * VacuumActiveNWorkers
Definition: vacuum.c:79
double vac_estimate_reltuples(Relation relation, BlockNumber total_pages, BlockNumber scanned_pages, double scanned_tuples)
Definition: vacuum.c:1223
int VacuumCostBalance
Definition: globals.c:151
int vacuum_multixact_freeze_table_age
Definition: vacuum.c:64
void TruncateCLOG(TransactionId oldestXact, Oid oldestxid_datoid)
Definition: clog.c:879
#define WL_TIMEOUT
Definition: latch.h:128
#define VACOPT_DISABLE_PAGE_SKIPPING
Definition: vacuum.h:185
static bool vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params)
Definition: vacuum.c:1798
RangeVar * relation
Definition: parsenodes.h:3360
uint32 TransactionId
Definition: c.h:587
#define SECURITY_RESTRICTED_OPERATION
Definition: miscadmin.h:312
TableScanDesc table_beginscan_catalog(Relation relation, int nkeys, struct ScanKeyData *key)
Definition: tableam.c:112
void vac_update_datfrozenxid(void)
Definition: vacuum.c:1433
void SetUserIdAndSecContext(Oid userid, int sec_context)
Definition: miscinit.c:590
int LOCKMODE
Definition: lockdefs.h:26
Oid GetUserId(void)
Definition: miscinit.c:478
void UnlockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:200
FormData_pg_database * Form_pg_database
Definition: pg_database.h:81
PGPROC * MyProc
Definition: proc.c:68
#define ExclusiveLock
Definition: lockdefs.h:44
int64 TimestampTz
Definition: timestamp.h:39
VacuumRelation * makeVacuumRelation(RangeVar *relation, Oid oid, List *va_cols)
Definition: makefuncs.c:809
#define VACOPT_ANALYZE
Definition: vacuum.h:179
static bool OldSnapshotThresholdActive(void)
Definition: snapmgr.h:101
static uint32 pg_atomic_sub_fetch_u32(volatile pg_atomic_uint32 *ptr, int32 sub_)
Definition: atomics.h:401
void LockDatabaseFrozenIds(LOCKMODE lockmode)
Definition: lmgr.c:470
void CommitTransactionCommand(void)
Definition: xact.c:2939
int64 VacuumPageHit
Definition: globals.c:147
#define Min(x, y)
Definition: c.h:986
bool is_vacuumcmd
Definition: parsenodes.h:3347
#define PROC_VACUUM_FOR_WRAPAROUND
Definition: proc.h:60
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
static void table_relation_vacuum(Relation rel, struct VacuumParams *params, BufferAccessStrategy bstrategy)
Definition: tableam.h:1675
#define AccessShareLock
Definition: lockdefs.h:36
static BufferAccessStrategy vac_strategy
Definition: vacuum.c:71
int32 defGetInt32(DefElem *def)
Definition: define.c:166
struct cursor * cur
Definition: ecpg.c:28
int autovacuum_multixact_freeze_max_age
Definition: autovacuum.c:126
List * list_concat(List *list1, const List *list2)
Definition: list.c:530
int errcode(int sqlerrcode)
Definition: elog.c:698
PROC_HDR * ProcGlobal
Definition: proc.c:80
static uint32 pg_atomic_add_fetch_u32(volatile pg_atomic_uint32 *ptr, int32 add_)
Definition: atomics.h:386
StdRdOptIndexCleanup
Definition: rel.h:311
void vacuum_set_xid_limits(Relation rel, int freeze_min_age, int freeze_table_age, int multixact_freeze_min_age, int multixact_freeze_table_age, TransactionId *oldestXmin, TransactionId *freezeLimit, TransactionId *xidFullScanLimit, MultiXactId *multiXactCutoff, MultiXactId *mxactFullScanLimit)
Definition: vacuum.c:957
int64 VacuumPageDirty
Definition: globals.c:149
#define CLUOPT_VERBOSE
Definition: cluster.h:24
uint8 statusFlags
Definition: proc.h:189
uint32 BlockNumber
Definition: block.h:31
void PopActiveSnapshot(void)
Definition: snapmgr.c:759
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
VacOptValue truncate
Definition: vacuum.h:223
static TransactionId ReadNextTransactionId(void)
Definition: transam.h:316
#define LOG
Definition: elog.h:26
Form_pg_class rd_rel
Definition: rel.h:109
bool TransactionIdLimitedForOldSnapshots(TransactionId recentXmin, Relation relation, TransactionId *limit_xid, TimestampTz *limit_ts)
Definition: snapmgr.c:1751
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
NameData relname
Definition: pg_class.h:38
unsigned int Oid
Definition: postgres_ext.h:31
Snapshot GetTransactionSnapshot(void)
Definition: snapmgr.c:250
#define OidIsValid(objectId)
Definition: c.h:710
void AdvanceOldestCommitTsXid(TransactionId oldestXact)
Definition: commit_ts.c:904
int freeze_table_age
Definition: vacuum.h:213
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:383
Relation try_relation_open(Oid relationId, LOCKMODE lockmode)
Definition: relation.c:89
void ResetLatch(Latch *latch)
Definition: latch.c:660
void SetOldSnapshotThresholdTimestamp(TimestampTz ts, TransactionId xlimit)
Definition: snapmgr.c:1672
signed int int32
Definition: c.h:429
static List * expand_vacuum_rel(VacuumRelation *vrel, int options)
Definition: vacuum.c:745
int WaitLatch(Latch *latch, int wakeEvents, long timeout, uint32 wait_event_info)
Definition: latch.c:452
#define VACOPT_PROCESS_TOAST
Definition: vacuum.h:184
MemoryContext PortalContext
Definition: mcxt.c:57
VacOptValue
Definition: vacuum.h:195
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1803
bool ForceTransactionIdLimitUpdate(void)
Definition: varsup.c:490
char * relname
Definition: primnodes.h:68
bool defGetBoolean(DefElem *def)
Definition: define.c:111
Form_pg_index rd_index
Definition: rel.h:187
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:502
bits32 options
Definition: vacuum.h:211
void pfree(void *pointer)
Definition: mcxt.c:1169
#define PROC_IN_VACUUM
Definition: proc.h:55
TransactionId GetOldestNonRemovableTransactionId(Relation rel)
Definition: procarray.c:2005
#define FirstNormalTransactionId
Definition: transam.h:34
void UnlockRelationIdForSession(LockRelId *relid, LOCKMODE lockmode)
Definition: lmgr.c:383
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
Definition: rel.h:37
int VacuumCostLimit
Definition: globals.c:144
void LockRelationIdForSession(LockRelId *relid, LOCKMODE lockmode)
Definition: lmgr.c:370
int autovacuum_freeze_max_age
Definition: autovacuum.c:125
int freeze_min_age
Definition: vacuum.h:212
char * defGetString(DefElem *def)
Definition: define.c:49
int vacuum_multixact_freeze_min_age
Definition: vacuum.c:63
TriggerDesc * trigdesc
Definition: rel.h:115
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:195
bool is_wraparound
Definition: vacuum.h:218
#define lfirst_node(type, lc)
Definition: pg_list.h:172
#define NoLock
Definition: lockdefs.h:34
LockInfoData rd_lockInfo
Definition: rel.h:112
HeapTuple heap_getnext(TableScanDesc sscan, ScanDirection direction)
Definition: heapam.c:1340
void PushActiveSnapshot(Snapshot snap)
Definition: snapmgr.c:680
void GetUserIdAndSecContext(Oid *userid, int *sec_context)
Definition: miscinit.c:583
int location
Definition: parsenodes.h:749
#define RowExclusiveLock
Definition: lockdefs.h:38
void AtEOXact_GUC(bool isCommit, int nestLevel)
Definition: guc.c:6218
int errdetail(const char *fmt,...)
Definition: elog.c:1042
static MemoryContext vac_context
Definition: vacuum.c:70
void PreventInTransactionBlock(bool isTopLevel, const char *stmtType)
Definition: xact.c:3379
#define RelationGetRelationName(relation)
Definition: rel.h:511
int vacuum_failsafe_age
Definition: vacuum.c:65
void cluster_rel(Oid tableOid, Oid indexOid, ClusterParams *params)
Definition: cluster.c:277
Oid RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode, uint32 flags, RangeVarGetRelidCallback callback, void *callback_arg)
Definition: namespace.c:237
unsigned int uint32
Definition: c.h:441
#define MultiXactIdIsValid(multi)
Definition: multixact.h:28
bool ActiveSnapshotSet(void)
Definition: snapmgr.c:798
bool vacuum_xid_failsafe_check(TransactionId relfrozenxid, MultiXactId relminmxid)
Definition: vacuum.c:1163
#define FirstMultiXactId
Definition: multixact.h:25
#define VACOPT_FREEZE
Definition: vacuum.h:181
static VacOptValue get_vacoptval_from_boolean(DefElem *def)
Definition: vacuum.c:2257
bool IsAutoVacuumWorkerProcess(void)
Definition: autovacuum.c:3454
void pgstat_vacuum_stat(void)
Definition: pgstat.c:1076
int MultiXactMemberFreezeThreshold(void)
Definition: multixact.c:2828
bool pg_database_ownercheck(Oid db_oid, Oid roleid)
Definition: aclchk.c:5236
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
void TruncateCommitTs(TransactionId oldestXact)
Definition: commit_ts.c:851
int vacuum_multixact_failsafe_age
Definition: vacuum.c:66
Node * arg
Definition: parsenodes.h:747
List * lappend(List *list, void *datum)
Definition: list.c:336
bool IsInTransactionBlock(bool isTopLevel)
Definition: xact.c:3492
static int verbose
#define WARNING
Definition: elog.h:40
void vac_open_indexes(Relation relation, LOCKMODE lockmode, int *nindexes, Relation **Irel)
Definition: vacuum.c:2085
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
float float4
Definition: c.h:564
int VacuumCostBalanceLocal
Definition: vacuum.c:80
VacOptValue index_cleanup
Definition: vacuum.h:222
pg_atomic_uint32 * VacuumSharedCostBalance
Definition: vacuum.c:78
static int elevel
Definition: vacuumlazy.c:403
#define PG_FINALLY()
Definition: elog.h:330
MultiXactId GetOldestMultiXactId(void)
Definition: multixact.c:2506
void CommandCounterIncrement(void)
Definition: xact.c:1021
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
Oid MyDatabaseId
Definition: globals.c:88
bits32 options
Definition: cluster.h:29
void SetMultiXactIdLimit(MultiXactId oldest_datminmxid, Oid oldest_datoid, bool is_startup)
Definition: multixact.c:2213
#define InvalidOid
Definition: postgres_ext.h:36
TransactionId datfrozenxid
Definition: pg_database.h:62
#define ereport(elevel,...)
Definition: elog.h:157
TransactionId MultiXactId
Definition: c.h:597
#define Max(x, y)
Definition: c.h:980
#define ShareUpdateExclusiveLock
Definition: lockdefs.h:39
uint32 bits32
Definition: c.h:450
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
Definition: vacuum.c:100
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: relation.c:206
#define Assert(condition)
Definition: c.h:804
#define VACOPT_VACUUM
Definition: vacuum.h:178
#define lfirst(lc)
Definition: pg_list.h:169
#define RELATION_IS_OTHER_TEMP(relation)
Definition: rel.h:631
#define VACOPT_FULL
Definition: vacuum.h:182
bool pg_class_ownercheck(Oid class_oid, Oid roleid)
Definition: aclchk.c:4818
void StartTransactionCommand(void)
Definition: xact.c:2838
RuleLock * rd_rules
Definition: rel.h:113
void SetTransactionIdLimit(TransactionId oldest_datfrozenxid, Oid oldest_datoid)
Definition: varsup.c:345
int nworkers
Definition: vacuum.h:230
static int list_length(const List *l)
Definition: pg_list.h:149
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:111
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1199
int vacuum_freeze_min_age
Definition: vacuum.c:61
TransactionId datminmxid
Definition: pg_database.h:65
int log_min_duration
Definition: vacuum.h:219
volatile sig_atomic_t InterruptPending
Definition: globals.c:30
bool MultiXactIdPrecedes(MultiXactId multi1, MultiXactId multi2)
Definition: multixact.c:3159
#define VACOPT_VERBOSE
Definition: vacuum.h:180
static void vac_truncate_clog(TransactionId frozenXID, MultiXactId minMulti, TransactionId lastSaneFrozenXid, MultiXactId lastSaneMinMulti)
Definition: vacuum.c:1647
List * RelationGetIndexList(Relation relation)
Definition: relcache.c:4573
int vacuum_freeze_table_age
Definition: vacuum.c:62
void index_close(Relation relation, LOCKMODE lockmode)
Definition: indexam.c:158
static void table_endscan(TableScanDesc scan)
Definition: tableam.h:991
FormData_pg_class * Form_pg_class
Definition: pg_class.h:153
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:175
#define AccessExclusiveLock
Definition: lockdefs.h:45
List * find_all_inheritors(Oid parentrelId, LOCKMODE lockmode, List **numparents)
Definition: pg_inherits.c:256
int NewGUCNestLevel(void)
Definition: guc.c:6204
void * palloc(Size size)
Definition: mcxt.c:1062
int errmsg(const char *fmt,...)
Definition: elog.c:909
void heap_inplace_update(Relation relation, HeapTuple tuple)
Definition: heapam.c:5991
double VacuumCostDelay
Definition: globals.c:145
#define VACOPT_SKIP_LOCKED
Definition: vacuum.h:183
List * options
Definition: parsenodes.h:3345
void list_free(List *list)
Definition: list.c:1391
#define elog(elevel,...)
Definition: elog.h:232
int i
int pgxactoff
Definition: proc.h:148
#define NameStr(name)
Definition: c.h:681
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
void AutoVacuumUpdateDelay(void)
Definition: autovacuum.c:1780
FormData_pg_database
Definition: pg_database.h:74
struct Latch * MyLatch
Definition: globals.c:57
char * defname
Definition: parsenodes.h:746
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:120
Relation vacuum_open_relation(Oid relid, RangeVar *relation, bits32 options, bool verbose, LOCKMODE lmode)
Definition: vacuum.c:633
bool vacuum_is_relation_owner(Oid relid, Form_pg_class reltuple, bits32 options)
Definition: vacuum.c:559
uint8 * statusFlags
Definition: proc.h:333
#define TransactionIdIsValid(xid)
Definition: transam.h:41
#define MAX_PARALLEL_WORKER_LIMIT
void vacuum_delay_point(void)
Definition: vacuum.c:2149
#define TransactionIdIsNormal(xid)
Definition: transam.h:42
#define PG_TRY()
Definition: elog.h:313
void TruncateMultiXact(MultiXactId newOldestMulti, Oid newOldestMultiDB)
Definition: multixact.c:2944
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
void vac_update_relstats(Relation relation, BlockNumber num_pages, double num_tuples, BlockNumber num_all_visible_pages, bool hasindex, TransactionId frozenxid, MultiXactId minmulti, bool in_outer_xact)
Definition: vacuum.c:1306
Definition: pg_list.h:50
#define WL_LATCH_SET
Definition: latch.h:125
#define RelationGetRelid(relation)
Definition: rel.h:477
int multixact_freeze_min_age
Definition: vacuum.h:214
static long analyze(struct nfa *nfa)
Definition: regc_nfa.c:2987
Relation index_open(Oid relationId, LOCKMODE lockmode)
Definition: indexam.c:132
#define PG_END_TRY()
Definition: elog.h:338
bytea * rd_options
Definition: rel.h:170
#define BTEqualStrategyNumber
Definition: stratnum.h:31
#define lfirst_oid(lc)
Definition: pg_list.h:171
#define WL_EXIT_ON_PM_DEATH
Definition: latch.h:130
bool VacuumCostActive
Definition: globals.c:152
static List * get_all_vacuum_rels(int options)
Definition: vacuum.c:884
static uint32 pg_atomic_read_u32(volatile pg_atomic_uint32 *ptr)
Definition: atomics.h:241
MultiXactId ReadNextMultiXactId(void)
Definition: multixact.c:723
List * rels
Definition: parsenodes.h:3346