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 includes (a) control and dispatch code for VACUUM and ANALYZE
7  * commands, (b) code to compute various vacuum thresholds, and (c) index
8  * vacuum code.
9  *
10  * VACUUM for heap AM is implemented in vacuumlazy.c, parallel vacuum in
11  * vacuumparallel.c, ANALYZE in analyze.c, and VACUUM FULL is a variant of
12  * CLUSTER, handled in cluster.c.
13  *
14  *
15  * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
16  * Portions Copyright (c) 1994, Regents of the University of California
17  *
18  *
19  * IDENTIFICATION
20  * src/backend/commands/vacuum.c
21  *
22  *-------------------------------------------------------------------------
23  */
24 #include "postgres.h"
25 
26 #include <math.h>
27 
28 #include "access/clog.h"
29 #include "access/commit_ts.h"
30 #include "access/genam.h"
31 #include "access/heapam.h"
32 #include "access/htup_details.h"
33 #include "access/multixact.h"
34 #include "access/tableam.h"
35 #include "access/transam.h"
36 #include "access/xact.h"
37 #include "catalog/namespace.h"
38 #include "catalog/index.h"
39 #include "catalog/pg_database.h"
40 #include "catalog/pg_inherits.h"
41 #include "catalog/pg_namespace.h"
42 #include "commands/cluster.h"
43 #include "commands/defrem.h"
44 #include "commands/vacuum.h"
45 #include "miscadmin.h"
46 #include "nodes/makefuncs.h"
47 #include "pgstat.h"
48 #include "postmaster/autovacuum.h"
50 #include "storage/bufmgr.h"
51 #include "storage/lmgr.h"
52 #include "storage/proc.h"
53 #include "storage/procarray.h"
54 #include "utils/acl.h"
55 #include "utils/fmgroids.h"
56 #include "utils/guc.h"
57 #include "utils/memutils.h"
58 #include "utils/pg_rusage.h"
59 #include "utils/snapmgr.h"
60 #include "utils/syscache.h"
61 
62 
63 /*
64  * GUC parameters
65  */
72 
73 
74 /* A few variables that don't seem worth passing around as parameters */
75 static MemoryContext vac_context = NULL;
77 
78 
79 /*
80  * Variables for cost-based parallel vacuum. See comments atop
81  * compute_parallel_delay to understand how it works.
82  */
86 
87 /* non-export function prototypes */
88 static List *expand_vacuum_rel(VacuumRelation *vrel, int options);
89 static List *get_all_vacuum_rels(int options);
90 static void vac_truncate_clog(TransactionId frozenXID,
91  MultiXactId minMulti,
92  TransactionId lastSaneFrozenXid,
93  MultiXactId lastSaneMinMulti);
94 static bool vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params);
95 static double compute_parallel_delay(void);
97 static bool vac_tid_reaped(ItemPointer itemptr, void *state);
98 static int vac_cmp_itemptr(const void *left, const void *right);
99 
100 /*
101  * Primary entry point for manual VACUUM and ANALYZE commands
102  *
103  * This is mainly a preparation wrapper for the real operations that will
104  * happen in vacuum().
105  */
106 void
107 ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
108 {
109  VacuumParams params;
110  bool verbose = false;
111  bool skip_locked = false;
112  bool analyze = false;
113  bool freeze = false;
114  bool full = false;
115  bool disable_page_skipping = false;
116  bool process_toast = true;
117  ListCell *lc;
118 
119  /* index_cleanup and truncate values unspecified for now */
122 
123  /* By default parallel vacuum is enabled */
124  params.nworkers = 0;
125 
126  /* Parse options list */
127  foreach(lc, vacstmt->options)
128  {
129  DefElem *opt = (DefElem *) lfirst(lc);
130 
131  /* Parse common options for VACUUM and ANALYZE */
132  if (strcmp(opt->defname, "verbose") == 0)
133  verbose = defGetBoolean(opt);
134  else if (strcmp(opt->defname, "skip_locked") == 0)
135  skip_locked = defGetBoolean(opt);
136  else if (!vacstmt->is_vacuumcmd)
137  ereport(ERROR,
138  (errcode(ERRCODE_SYNTAX_ERROR),
139  errmsg("unrecognized ANALYZE option \"%s\"", opt->defname),
140  parser_errposition(pstate, opt->location)));
141 
142  /* Parse options available on VACUUM */
143  else if (strcmp(opt->defname, "analyze") == 0)
144  analyze = defGetBoolean(opt);
145  else if (strcmp(opt->defname, "freeze") == 0)
146  freeze = defGetBoolean(opt);
147  else if (strcmp(opt->defname, "full") == 0)
148  full = defGetBoolean(opt);
149  else if (strcmp(opt->defname, "disable_page_skipping") == 0)
150  disable_page_skipping = defGetBoolean(opt);
151  else if (strcmp(opt->defname, "index_cleanup") == 0)
152  {
153  /* Interpret no string as the default, which is 'auto' */
154  if (!opt->arg)
156  else
157  {
158  char *sval = defGetString(opt);
159 
160  /* Try matching on 'auto' string, or fall back on boolean */
161  if (pg_strcasecmp(sval, "auto") == 0)
163  else
165  }
166  }
167  else if (strcmp(opt->defname, "process_toast") == 0)
168  process_toast = defGetBoolean(opt);
169  else if (strcmp(opt->defname, "truncate") == 0)
170  params.truncate = get_vacoptval_from_boolean(opt);
171  else if (strcmp(opt->defname, "parallel") == 0)
172  {
173  if (opt->arg == NULL)
174  {
175  ereport(ERROR,
176  (errcode(ERRCODE_SYNTAX_ERROR),
177  errmsg("parallel option requires a value between 0 and %d",
179  parser_errposition(pstate, opt->location)));
180  }
181  else
182  {
183  int nworkers;
184 
185  nworkers = defGetInt32(opt);
186  if (nworkers < 0 || nworkers > MAX_PARALLEL_WORKER_LIMIT)
187  ereport(ERROR,
188  (errcode(ERRCODE_SYNTAX_ERROR),
189  errmsg("parallel workers for vacuum must be between 0 and %d",
191  parser_errposition(pstate, opt->location)));
192 
193  /*
194  * Disable parallel vacuum, if user has specified parallel
195  * degree as zero.
196  */
197  if (nworkers == 0)
198  params.nworkers = -1;
199  else
200  params.nworkers = nworkers;
201  }
202  }
203  else
204  ereport(ERROR,
205  (errcode(ERRCODE_SYNTAX_ERROR),
206  errmsg("unrecognized VACUUM option \"%s\"", opt->defname),
207  parser_errposition(pstate, opt->location)));
208  }
209 
210  /* Set vacuum options */
211  params.options =
212  (vacstmt->is_vacuumcmd ? VACOPT_VACUUM : VACOPT_ANALYZE) |
213  (verbose ? VACOPT_VERBOSE : 0) |
214  (skip_locked ? VACOPT_SKIP_LOCKED : 0) |
215  (analyze ? VACOPT_ANALYZE : 0) |
216  (freeze ? VACOPT_FREEZE : 0) |
217  (full ? VACOPT_FULL : 0) |
218  (disable_page_skipping ? VACOPT_DISABLE_PAGE_SKIPPING : 0) |
219  (process_toast ? VACOPT_PROCESS_TOAST : 0);
220 
221  /* sanity checks on options */
223  Assert((params.options & VACOPT_VACUUM) ||
224  !(params.options & (VACOPT_FULL | VACOPT_FREEZE)));
225 
226  if ((params.options & VACOPT_FULL) && params.nworkers > 0)
227  ereport(ERROR,
228  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
229  errmsg("VACUUM FULL cannot be performed in parallel")));
230 
231  /*
232  * Make sure VACOPT_ANALYZE is specified if any column lists are present.
233  */
234  if (!(params.options & VACOPT_ANALYZE))
235  {
236  ListCell *lc;
237 
238  foreach(lc, vacstmt->rels)
239  {
241 
242  if (vrel->va_cols != NIL)
243  ereport(ERROR,
244  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
245  errmsg("ANALYZE option must be specified when a column list is provided")));
246  }
247  }
248 
249  /*
250  * All freeze ages are zero if the FREEZE option is given; otherwise pass
251  * them as -1 which means to use the default values.
252  */
253  if (params.options & VACOPT_FREEZE)
254  {
255  params.freeze_min_age = 0;
256  params.freeze_table_age = 0;
257  params.multixact_freeze_min_age = 0;
258  params.multixact_freeze_table_age = 0;
259  }
260  else
261  {
262  params.freeze_min_age = -1;
263  params.freeze_table_age = -1;
264  params.multixact_freeze_min_age = -1;
265  params.multixact_freeze_table_age = -1;
266  }
267 
268  /* user-invoked vacuum is never "for wraparound" */
269  params.is_wraparound = false;
270 
271  /* user-invoked vacuum uses VACOPT_VERBOSE instead of log_min_duration */
272  params.log_min_duration = -1;
273 
274  /* Now go through the common routine */
275  vacuum(vacstmt->rels, &params, NULL, isTopLevel);
276 }
277 
278 /*
279  * Internal entry point for VACUUM and ANALYZE commands.
280  *
281  * relations, if not NIL, is a list of VacuumRelation to process; otherwise,
282  * we process all relevant tables in the database. For each VacuumRelation,
283  * if a valid OID is supplied, the table with that OID is what to process;
284  * otherwise, the VacuumRelation's RangeVar indicates what to process.
285  *
286  * params contains a set of parameters that can be used to customize the
287  * behavior.
288  *
289  * bstrategy is normally given as NULL, but in autovacuum it can be passed
290  * in to use the same buffer strategy object across multiple vacuum() calls.
291  *
292  * isTopLevel should be passed down from ProcessUtility.
293  *
294  * It is the caller's responsibility that all parameters are allocated in a
295  * memory context that will not disappear at transaction commit.
296  */
297 void
298 vacuum(List *relations, VacuumParams *params,
299  BufferAccessStrategy bstrategy, bool isTopLevel)
300 {
301  static bool in_vacuum = false;
302 
303  const char *stmttype;
304  volatile bool in_outer_xact,
305  use_own_xacts;
306 
307  Assert(params != NULL);
308 
309  stmttype = (params->options & VACOPT_VACUUM) ? "VACUUM" : "ANALYZE";
310 
311  /*
312  * We cannot run VACUUM inside a user transaction block; if we were inside
313  * a transaction, then our commit- and start-transaction-command calls
314  * would not have the intended effect! There are numerous other subtle
315  * dependencies on this, too.
316  *
317  * ANALYZE (without VACUUM) can run either way.
318  */
319  if (params->options & VACOPT_VACUUM)
320  {
321  PreventInTransactionBlock(isTopLevel, stmttype);
322  in_outer_xact = false;
323  }
324  else
325  in_outer_xact = IsInTransactionBlock(isTopLevel);
326 
327  /*
328  * Due to static variables vac_context, anl_context and vac_strategy,
329  * vacuum() is not reentrant. This matters when VACUUM FULL or ANALYZE
330  * calls a hostile index expression that itself calls ANALYZE.
331  */
332  if (in_vacuum)
333  ereport(ERROR,
334  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
335  errmsg("%s cannot be executed from VACUUM or ANALYZE",
336  stmttype)));
337 
338  /*
339  * Sanity check DISABLE_PAGE_SKIPPING option.
340  */
341  if ((params->options & VACOPT_FULL) != 0 &&
342  (params->options & VACOPT_DISABLE_PAGE_SKIPPING) != 0)
343  ereport(ERROR,
344  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
345  errmsg("VACUUM option DISABLE_PAGE_SKIPPING cannot be used with FULL")));
346 
347  /* sanity check for PROCESS_TOAST */
348  if ((params->options & VACOPT_FULL) != 0 &&
349  (params->options & VACOPT_PROCESS_TOAST) == 0)
350  ereport(ERROR,
351  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
352  errmsg("PROCESS_TOAST required with VACUUM FULL")));
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  */
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  {
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;
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  */
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 
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 
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 Xid below which tuples deleted by any xact (that
940  * committed) should be considered DEAD, not just RECENTLY_DEAD.
941  * - oldestMxact is the Mxid below which MultiXacts are definitely not
942  * seen as visible by any running transaction.
943  * - freezeLimit is the Xid below which all Xids are definitely replaced by
944  * FrozenTransactionId during aggressive vacuums.
945  * - multiXactCutoff is the value below which all MultiXactIds are definitely
946  * removed from Xmax during aggressive vacuums.
947  *
948  * Return value indicates if vacuumlazy.c caller should make its VACUUM
949  * operation aggressive. An aggressive VACUUM must advance relfrozenxid up to
950  * FreezeLimit (at a minimum), and relminmxid up to multiXactCutoff (at a
951  * minimum).
952  *
953  * oldestXmin and oldestMxact are the most recent values that can ever be
954  * passed to vac_update_relstats() as frozenxid and minmulti arguments by our
955  * vacuumlazy.c caller later on. These values should be passed when it turns
956  * out that VACUUM will leave no unfrozen XIDs/XMIDs behind in the table.
957  */
958 bool
960  int freeze_min_age,
961  int freeze_table_age,
962  int multixact_freeze_min_age,
963  int multixact_freeze_table_age,
964  TransactionId *oldestXmin,
965  MultiXactId *oldestMxact,
966  TransactionId *freezeLimit,
967  MultiXactId *multiXactCutoff)
968 {
969  int freezemin;
970  int mxid_freezemin;
971  int effective_multixact_freeze_max_age;
972  TransactionId limit;
973  TransactionId safeLimit;
974  MultiXactId mxactLimit;
975  MultiXactId safeMxactLimit;
976  int freezetable;
977 
978  /*
979  * We can always ignore processes running lazy vacuum. This is because we
980  * use these values only for deciding which tuples we must keep in the
981  * tables. Since lazy vacuum doesn't write its XID anywhere (usually no
982  * XID assigned), it's safe to ignore it. In theory it could be
983  * problematic to ignore lazy vacuums in a full vacuum, but keep in mind
984  * that only one vacuum process can be working on a particular table at
985  * any time, and that each vacuum is always an independent transaction.
986  */
987  *oldestXmin = GetOldestNonRemovableTransactionId(rel);
988 
990  {
991  TransactionId limit_xmin;
992  TimestampTz limit_ts;
993 
994  if (TransactionIdLimitedForOldSnapshots(*oldestXmin, rel,
995  &limit_xmin, &limit_ts))
996  {
997  /*
998  * TODO: We should only set the threshold if we are pruning on the
999  * basis of the increased limits. Not as crucial here as it is
1000  * for opportunistic pruning (which often happens at a much higher
1001  * frequency), but would still be a significant improvement.
1002  */
1003  SetOldSnapshotThresholdTimestamp(limit_ts, limit_xmin);
1004  *oldestXmin = limit_xmin;
1005  }
1006  }
1007 
1008  Assert(TransactionIdIsNormal(*oldestXmin));
1009 
1010  /*
1011  * Determine the minimum freeze age to use: as specified by the caller, or
1012  * vacuum_freeze_min_age, but in any case not more than half
1013  * autovacuum_freeze_max_age, so that autovacuums to prevent XID
1014  * wraparound won't occur too frequently.
1015  */
1016  freezemin = freeze_min_age;
1017  if (freezemin < 0)
1018  freezemin = vacuum_freeze_min_age;
1019  freezemin = Min(freezemin, autovacuum_freeze_max_age / 2);
1020  Assert(freezemin >= 0);
1021 
1022  /*
1023  * Compute the cutoff XID, being careful not to generate a "permanent" XID
1024  */
1025  limit = *oldestXmin - freezemin;
1026  if (!TransactionIdIsNormal(limit))
1027  limit = FirstNormalTransactionId;
1028 
1029  /*
1030  * If oldestXmin is very far back (in practice, more than
1031  * autovacuum_freeze_max_age / 2 XIDs old), complain and force a minimum
1032  * freeze age of zero.
1033  */
1035  if (!TransactionIdIsNormal(safeLimit))
1036  safeLimit = FirstNormalTransactionId;
1037 
1038  if (TransactionIdPrecedes(limit, safeLimit))
1039  {
1040  ereport(WARNING,
1041  (errmsg("oldest xmin is far in the past"),
1042  errhint("Close open transactions soon to avoid wraparound problems.\n"
1043  "You might also need to commit or roll back old prepared transactions, or drop stale replication slots.")));
1044  limit = *oldestXmin;
1045  }
1046 
1047  *freezeLimit = limit;
1048 
1049  /*
1050  * Compute the multixact age for which freezing is urgent. This is
1051  * normally autovacuum_multixact_freeze_max_age, but may be less if we are
1052  * short of multixact member space.
1053  */
1054  effective_multixact_freeze_max_age = MultiXactMemberFreezeThreshold();
1055 
1056  /*
1057  * Determine the minimum multixact freeze age to use: as specified by
1058  * caller, or vacuum_multixact_freeze_min_age, but in any case not more
1059  * than half effective_multixact_freeze_max_age, so that autovacuums to
1060  * prevent MultiXact wraparound won't occur too frequently.
1061  */
1062  mxid_freezemin = multixact_freeze_min_age;
1063  if (mxid_freezemin < 0)
1064  mxid_freezemin = vacuum_multixact_freeze_min_age;
1065  mxid_freezemin = Min(mxid_freezemin,
1066  effective_multixact_freeze_max_age / 2);
1067  Assert(mxid_freezemin >= 0);
1068 
1069  /* Remember for caller */
1070  *oldestMxact = GetOldestMultiXactId();
1071 
1072  /* compute the cutoff multi, being careful to generate a valid value */
1073  mxactLimit = *oldestMxact - mxid_freezemin;
1074  if (mxactLimit < FirstMultiXactId)
1075  mxactLimit = FirstMultiXactId;
1076 
1077  safeMxactLimit =
1078  ReadNextMultiXactId() - effective_multixact_freeze_max_age;
1079  if (safeMxactLimit < FirstMultiXactId)
1080  safeMxactLimit = FirstMultiXactId;
1081 
1082  if (MultiXactIdPrecedes(mxactLimit, safeMxactLimit))
1083  {
1084  ereport(WARNING,
1085  (errmsg("oldest multixact is far in the past"),
1086  errhint("Close open transactions with multixacts soon to avoid wraparound problems.")));
1087  /* Use the safe limit, unless an older mxact is still running */
1088  if (MultiXactIdPrecedes(*oldestMxact, safeMxactLimit))
1089  mxactLimit = *oldestMxact;
1090  else
1091  mxactLimit = safeMxactLimit;
1092  }
1093 
1094  *multiXactCutoff = mxactLimit;
1095 
1096  /*
1097  * Done setting output parameters; just need to figure out if caller needs
1098  * to do an aggressive VACUUM or not.
1099  *
1100  * Determine the table freeze age to use: as specified by the caller, or
1101  * 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 an aggressive vacuum, being careful not to
1114  * generate a "permanent" XID
1115  */
1116  limit = ReadNextTransactionId() - freezetable;
1117  if (!TransactionIdIsNormal(limit))
1118  limit = FirstNormalTransactionId;
1119  if (TransactionIdPrecedesOrEquals(rel->rd_rel->relfrozenxid,
1120  limit))
1121  return true;
1122 
1123  /*
1124  * Similar to the above, determine the table freeze age to use for
1125  * multixacts: as specified by the caller, or
1126  * vacuum_multixact_freeze_table_age, but in any case not more than
1127  * autovacuum_multixact_freeze_table_age * 0.95, so that if you have e.g.
1128  * nightly VACUUM schedule, the nightly VACUUM gets a chance to freeze
1129  * multixacts before anti-wraparound autovacuum is launched.
1130  */
1131  freezetable = multixact_freeze_table_age;
1132  if (freezetable < 0)
1133  freezetable = vacuum_multixact_freeze_table_age;
1134  freezetable = Min(freezetable,
1135  effective_multixact_freeze_max_age * 0.95);
1136  Assert(freezetable >= 0);
1137 
1138  /*
1139  * Compute MultiXact limit causing an aggressive vacuum, being careful to
1140  * generate a valid MultiXact value
1141  */
1142  mxactLimit = ReadNextMultiXactId() - freezetable;
1143  if (mxactLimit < FirstMultiXactId)
1144  mxactLimit = FirstMultiXactId;
1145  if (MultiXactIdPrecedesOrEquals(rel->rd_rel->relminmxid,
1146  mxactLimit))
1147  return true;
1148 
1149  return false;
1150 }
1151 
1152 /*
1153  * vacuum_xid_failsafe_check() -- Used by VACUUM's wraparound failsafe
1154  * mechanism to determine if its table's relfrozenxid and relminmxid are now
1155  * dangerously far in the past.
1156  *
1157  * Input parameters are the target relation's relfrozenxid and relminmxid.
1158  *
1159  * When we return true, VACUUM caller triggers the failsafe.
1160  */
1161 bool
1163 {
1164  TransactionId xid_skip_limit;
1165  MultiXactId multi_skip_limit;
1166  int skip_index_vacuum;
1167 
1168  Assert(TransactionIdIsNormal(relfrozenxid));
1169  Assert(MultiXactIdIsValid(relminmxid));
1170 
1171  /*
1172  * Determine the index skipping age to use. In any case no less than
1173  * autovacuum_freeze_max_age * 1.05.
1174  */
1175  skip_index_vacuum = Max(vacuum_failsafe_age, autovacuum_freeze_max_age * 1.05);
1176 
1177  xid_skip_limit = ReadNextTransactionId() - skip_index_vacuum;
1178  if (!TransactionIdIsNormal(xid_skip_limit))
1179  xid_skip_limit = FirstNormalTransactionId;
1180 
1181  if (TransactionIdPrecedes(relfrozenxid, xid_skip_limit))
1182  {
1183  /* The table's relfrozenxid is too old */
1184  return true;
1185  }
1186 
1187  /*
1188  * Similar to above, determine the index skipping age to use for
1189  * multixact. In any case no less than autovacuum_multixact_freeze_max_age *
1190  * 1.05.
1191  */
1192  skip_index_vacuum = Max(vacuum_multixact_failsafe_age,
1194 
1195  multi_skip_limit = ReadNextMultiXactId() - skip_index_vacuum;
1196  if (multi_skip_limit < FirstMultiXactId)
1197  multi_skip_limit = FirstMultiXactId;
1198 
1199  if (MultiXactIdPrecedes(relminmxid, multi_skip_limit))
1200  {
1201  /* The table's relminmxid is too old */
1202  return true;
1203  }
1204 
1205  return false;
1206 }
1207 
1208 /*
1209  * vac_estimate_reltuples() -- estimate the new value for pg_class.reltuples
1210  *
1211  * If we scanned the whole relation then we should just use the count of
1212  * live tuples seen; but if we did not, we should not blindly extrapolate
1213  * from that number, since VACUUM may have scanned a quite nonrandom
1214  * subset of the table. When we have only partial information, we take
1215  * the old value of pg_class.reltuples/pg_class.relpages as a measurement
1216  * of the tuple density in the unscanned pages.
1217  *
1218  * Note: scanned_tuples should count only *live* tuples, since
1219  * pg_class.reltuples is defined that way.
1220  */
1221 double
1223  BlockNumber total_pages,
1224  BlockNumber scanned_pages,
1225  double scanned_tuples)
1226 {
1227  BlockNumber old_rel_pages = relation->rd_rel->relpages;
1228  double old_rel_tuples = relation->rd_rel->reltuples;
1229  double old_density;
1230  double unscanned_pages;
1231  double total_tuples;
1232 
1233  /* If we did scan the whole table, just use the count as-is */
1234  if (scanned_pages >= total_pages)
1235  return scanned_tuples;
1236 
1237  /*
1238  * If scanned_pages is zero but total_pages isn't, keep the existing value
1239  * of reltuples. (Note: we might be returning -1 in this case.)
1240  */
1241  if (scanned_pages == 0)
1242  return old_rel_tuples;
1243 
1244  /*
1245  * When successive VACUUM commands scan the same few pages again and
1246  * again, without anything from the table really changing, there is a risk
1247  * that our beliefs about tuple density will gradually become distorted.
1248  * It's particularly important to avoid becoming confused in this way due
1249  * to vacuumlazy.c implementation details. For example, the tendency for
1250  * our caller to always scan the last heap page should not ever cause us
1251  * to believe that every page in the table must be just like the last
1252  * page.
1253  *
1254  * We apply a heuristic to avoid these problems: if the relation is
1255  * exactly the same size as it was at the end of the last VACUUM, and only
1256  * a few of its pages (less than a quasi-arbitrary threshold of 2%) were
1257  * scanned by this VACUUM, assume that reltuples has not changed at all.
1258  */
1259  if (old_rel_pages == total_pages &&
1260  scanned_pages < (double) total_pages * 0.02)
1261  return old_rel_tuples;
1262 
1263  /*
1264  * If old density is unknown, we can't do much except scale up
1265  * scanned_tuples to match total_pages.
1266  */
1267  if (old_rel_tuples < 0 || old_rel_pages == 0)
1268  return floor((scanned_tuples / scanned_pages) * total_pages + 0.5);
1269 
1270  /*
1271  * Okay, we've covered the corner cases. The normal calculation is to
1272  * convert the old measurement to a density (tuples per page), then
1273  * estimate the number of tuples in the unscanned pages using that figure,
1274  * and finally add on the number of tuples in the scanned pages.
1275  */
1276  old_density = old_rel_tuples / old_rel_pages;
1277  unscanned_pages = (double) total_pages - (double) scanned_pages;
1278  total_tuples = old_density * unscanned_pages + scanned_tuples;
1279  return floor(total_tuples + 0.5);
1280 }
1281 
1282 
1283 /*
1284  * vac_update_relstats() -- update statistics for one relation
1285  *
1286  * Update the whole-relation statistics that are kept in its pg_class
1287  * row. There are additional stats that will be updated if we are
1288  * doing ANALYZE, but we always update these stats. This routine works
1289  * for both index and heap relation entries in pg_class.
1290  *
1291  * We violate transaction semantics here by overwriting the rel's
1292  * existing pg_class tuple with the new values. This is reasonably
1293  * safe as long as we're sure that the new values are correct whether or
1294  * not this transaction commits. The reason for doing this is that if
1295  * we updated these tuples in the usual way, vacuuming pg_class itself
1296  * wouldn't work very well --- by the time we got done with a vacuum
1297  * cycle, most of the tuples in pg_class would've been obsoleted. Of
1298  * course, this only works for fixed-size not-null columns, but these are.
1299  *
1300  * Another reason for doing it this way is that when we are in a lazy
1301  * VACUUM and have PROC_IN_VACUUM set, we mustn't do any regular updates.
1302  * Somebody vacuuming pg_class might think they could delete a tuple
1303  * marked with xmin = our xid.
1304  *
1305  * In addition to fundamentally nontransactional statistics such as
1306  * relpages and relallvisible, we try to maintain certain lazily-updated
1307  * DDL flags such as relhasindex, by clearing them if no longer correct.
1308  * It's safe to do this in VACUUM, which can't run in parallel with
1309  * CREATE INDEX/RULE/TRIGGER and can't be part of a transaction block.
1310  * However, it's *not* safe to do it in an ANALYZE that's within an
1311  * outer transaction, because for example the current transaction might
1312  * have dropped the last index; then we'd think relhasindex should be
1313  * cleared, but if the transaction later rolls back this would be wrong.
1314  * So we refrain from updating the DDL flags if we're inside an outer
1315  * transaction. This is OK since postponing the flag maintenance is
1316  * always allowable.
1317  *
1318  * Note: num_tuples should count only *live* tuples, since
1319  * pg_class.reltuples is defined that way.
1320  *
1321  * This routine is shared by VACUUM and ANALYZE.
1322  */
1323 void
1325  BlockNumber num_pages, double num_tuples,
1326  BlockNumber num_all_visible_pages,
1327  bool hasindex, TransactionId frozenxid,
1328  MultiXactId minmulti,
1329  bool *frozenxid_updated, bool *minmulti_updated,
1330  bool in_outer_xact)
1331 {
1332  Oid relid = RelationGetRelid(relation);
1333  Relation rd;
1334  HeapTuple ctup;
1335  Form_pg_class pgcform;
1336  bool dirty,
1337  futurexid,
1338  futuremxid;
1339  TransactionId oldfrozenxid;
1340  MultiXactId oldminmulti;
1341 
1342  rd = table_open(RelationRelationId, RowExclusiveLock);
1343 
1344  /* Fetch a copy of the tuple to scribble on */
1346  if (!HeapTupleIsValid(ctup))
1347  elog(ERROR, "pg_class entry for relid %u vanished during vacuuming",
1348  relid);
1349  pgcform = (Form_pg_class) GETSTRUCT(ctup);
1350 
1351  /* Apply statistical updates, if any, to copied tuple */
1352 
1353  dirty = false;
1354  if (pgcform->relpages != (int32) num_pages)
1355  {
1356  pgcform->relpages = (int32) num_pages;
1357  dirty = true;
1358  }
1359  if (pgcform->reltuples != (float4) num_tuples)
1360  {
1361  pgcform->reltuples = (float4) num_tuples;
1362  dirty = true;
1363  }
1364  if (pgcform->relallvisible != (int32) num_all_visible_pages)
1365  {
1366  pgcform->relallvisible = (int32) num_all_visible_pages;
1367  dirty = true;
1368  }
1369 
1370  /* Apply DDL updates, but not inside an outer transaction (see above) */
1371 
1372  if (!in_outer_xact)
1373  {
1374  /*
1375  * If we didn't find any indexes, reset relhasindex.
1376  */
1377  if (pgcform->relhasindex && !hasindex)
1378  {
1379  pgcform->relhasindex = false;
1380  dirty = true;
1381  }
1382 
1383  /* We also clear relhasrules and relhastriggers if needed */
1384  if (pgcform->relhasrules && relation->rd_rules == NULL)
1385  {
1386  pgcform->relhasrules = false;
1387  dirty = true;
1388  }
1389  if (pgcform->relhastriggers && relation->trigdesc == NULL)
1390  {
1391  pgcform->relhastriggers = false;
1392  dirty = true;
1393  }
1394  }
1395 
1396  /*
1397  * Update relfrozenxid, unless caller passed InvalidTransactionId
1398  * indicating it has no new data.
1399  *
1400  * Ordinarily, we don't let relfrozenxid go backwards. However, if the
1401  * stored relfrozenxid is "in the future" then it seems best to assume
1402  * it's corrupt, and overwrite with the oldest remaining XID in the table.
1403  * This should match vac_update_datfrozenxid() concerning what we consider
1404  * to be "in the future".
1405  */
1406  oldfrozenxid = pgcform->relfrozenxid;
1407  futurexid = false;
1408  if (frozenxid_updated)
1409  *frozenxid_updated = false;
1410  if (TransactionIdIsNormal(frozenxid) && oldfrozenxid != frozenxid)
1411  {
1412  bool update = false;
1413 
1414  if (TransactionIdPrecedes(oldfrozenxid, frozenxid))
1415  update = true;
1416  else if (TransactionIdPrecedes(ReadNextTransactionId(), oldfrozenxid))
1417  futurexid = update = true;
1418 
1419  if (update)
1420  {
1421  pgcform->relfrozenxid = frozenxid;
1422  dirty = true;
1423  if (frozenxid_updated)
1424  *frozenxid_updated = true;
1425  }
1426  }
1427 
1428  /* Similarly for relminmxid */
1429  oldminmulti = pgcform->relminmxid;
1430  futuremxid = false;
1431  if (minmulti_updated)
1432  *minmulti_updated = false;
1433  if (MultiXactIdIsValid(minmulti) && oldminmulti != minmulti)
1434  {
1435  bool update = false;
1436 
1437  if (MultiXactIdPrecedes(oldminmulti, minmulti))
1438  update = true;
1439  else if (MultiXactIdPrecedes(ReadNextMultiXactId(), oldminmulti))
1440  futuremxid = update = true;
1441 
1442  if (update)
1443  {
1444  pgcform->relminmxid = minmulti;
1445  dirty = true;
1446  if (minmulti_updated)
1447  *minmulti_updated = true;
1448  }
1449  }
1450 
1451  /* If anything changed, write out the tuple. */
1452  if (dirty)
1453  heap_inplace_update(rd, ctup);
1454 
1456 
1457  if (futurexid)
1458  ereport(WARNING,
1460  errmsg_internal("overwrote invalid relfrozenxid value %u with new value %u for table \"%s\"",
1461  oldfrozenxid, frozenxid,
1462  RelationGetRelationName(relation))));
1463  if (futuremxid)
1464  ereport(WARNING,
1466  errmsg_internal("overwrote invalid relminmxid value %u with new value %u for table \"%s\"",
1467  oldminmulti, minmulti,
1468  RelationGetRelationName(relation))));
1469 }
1470 
1471 
1472 /*
1473  * vac_update_datfrozenxid() -- update pg_database.datfrozenxid for our DB
1474  *
1475  * Update pg_database's datfrozenxid entry for our database to be the
1476  * minimum of the pg_class.relfrozenxid values.
1477  *
1478  * Similarly, update our datminmxid to be the minimum of the
1479  * pg_class.relminmxid values.
1480  *
1481  * If we are able to advance either pg_database value, also try to
1482  * truncate pg_xact and pg_multixact.
1483  *
1484  * We violate transaction semantics here by overwriting the database's
1485  * existing pg_database tuple with the new values. This is reasonably
1486  * safe since the new values are correct whether or not this transaction
1487  * commits. As with vac_update_relstats, this avoids leaving dead tuples
1488  * behind after a VACUUM.
1489  */
1490 void
1492 {
1493  HeapTuple tuple;
1494  Form_pg_database dbform;
1495  Relation relation;
1496  SysScanDesc scan;
1497  HeapTuple classTup;
1498  TransactionId newFrozenXid;
1499  MultiXactId newMinMulti;
1500  TransactionId lastSaneFrozenXid;
1501  MultiXactId lastSaneMinMulti;
1502  bool bogus = false;
1503  bool dirty = false;
1504  ScanKeyData key[1];
1505 
1506  /*
1507  * Restrict this task to one backend per database. This avoids race
1508  * conditions that would move datfrozenxid or datminmxid backward. It
1509  * avoids calling vac_truncate_clog() with a datfrozenxid preceding a
1510  * datfrozenxid passed to an earlier vac_truncate_clog() call.
1511  */
1513 
1514  /*
1515  * Initialize the "min" calculation with
1516  * GetOldestNonRemovableTransactionId(), which is a reasonable
1517  * approximation to the minimum relfrozenxid for not-yet-committed
1518  * pg_class entries for new tables; see AddNewRelationTuple(). So we
1519  * cannot produce a wrong minimum by starting with this.
1520  */
1521  newFrozenXid = GetOldestNonRemovableTransactionId(NULL);
1522 
1523  /*
1524  * Similarly, initialize the MultiXact "min" with the value that would be
1525  * used on pg_class for new tables. See AddNewRelationTuple().
1526  */
1527  newMinMulti = GetOldestMultiXactId();
1528 
1529  /*
1530  * Identify the latest relfrozenxid and relminmxid values that we could
1531  * validly see during the scan. These are conservative values, but it's
1532  * not really worth trying to be more exact.
1533  */
1534  lastSaneFrozenXid = ReadNextTransactionId();
1535  lastSaneMinMulti = ReadNextMultiXactId();
1536 
1537  /*
1538  * We must seqscan pg_class to find the minimum Xid, because there is no
1539  * index that can help us here.
1540  */
1541  relation = table_open(RelationRelationId, AccessShareLock);
1542 
1543  scan = systable_beginscan(relation, InvalidOid, false,
1544  NULL, 0, NULL);
1545 
1546  while ((classTup = systable_getnext(scan)) != NULL)
1547  {
1548  Form_pg_class classForm = (Form_pg_class) GETSTRUCT(classTup);
1549 
1550  /*
1551  * Only consider relations able to hold unfrozen XIDs (anything else
1552  * should have InvalidTransactionId in relfrozenxid anyway).
1553  */
1554  if (classForm->relkind != RELKIND_RELATION &&
1555  classForm->relkind != RELKIND_MATVIEW &&
1556  classForm->relkind != RELKIND_TOASTVALUE)
1557  {
1558  Assert(!TransactionIdIsValid(classForm->relfrozenxid));
1559  Assert(!MultiXactIdIsValid(classForm->relminmxid));
1560  continue;
1561  }
1562 
1563  /*
1564  * Some table AMs might not need per-relation xid / multixid horizons.
1565  * It therefore seems reasonable to allow relfrozenxid and relminmxid
1566  * to not be set (i.e. set to their respective Invalid*Id)
1567  * independently. Thus validate and compute horizon for each only if
1568  * set.
1569  *
1570  * If things are working properly, no relation should have a
1571  * relfrozenxid or relminmxid that is "in the future". However, such
1572  * cases have been known to arise due to bugs in pg_upgrade. If we
1573  * see any entries that are "in the future", chicken out and don't do
1574  * anything. This ensures we won't truncate clog & multixact SLRUs
1575  * before those relations have been scanned and cleaned up.
1576  */
1577 
1578  if (TransactionIdIsValid(classForm->relfrozenxid))
1579  {
1580  Assert(TransactionIdIsNormal(classForm->relfrozenxid));
1581 
1582  /* check for values in the future */
1583  if (TransactionIdPrecedes(lastSaneFrozenXid, classForm->relfrozenxid))
1584  {
1585  bogus = true;
1586  break;
1587  }
1588 
1589  /* determine new horizon */
1590  if (TransactionIdPrecedes(classForm->relfrozenxid, newFrozenXid))
1591  newFrozenXid = classForm->relfrozenxid;
1592  }
1593 
1594  if (MultiXactIdIsValid(classForm->relminmxid))
1595  {
1596  /* check for values in the future */
1597  if (MultiXactIdPrecedes(lastSaneMinMulti, classForm->relminmxid))
1598  {
1599  bogus = true;
1600  break;
1601  }
1602 
1603  /* determine new horizon */
1604  if (MultiXactIdPrecedes(classForm->relminmxid, newMinMulti))
1605  newMinMulti = classForm->relminmxid;
1606  }
1607  }
1608 
1609  /* we're done with pg_class */
1610  systable_endscan(scan);
1611  table_close(relation, AccessShareLock);
1612 
1613  /* chicken out if bogus data found */
1614  if (bogus)
1615  return;
1616 
1617  Assert(TransactionIdIsNormal(newFrozenXid));
1618  Assert(MultiXactIdIsValid(newMinMulti));
1619 
1620  /* Now fetch the pg_database tuple we need to update. */
1621  relation = table_open(DatabaseRelationId, RowExclusiveLock);
1622 
1623  /*
1624  * Get the pg_database tuple to scribble on. Note that this does not
1625  * directly rely on the syscache to avoid issues with flattened toast
1626  * values for the in-place update.
1627  */
1628  ScanKeyInit(&key[0],
1629  Anum_pg_database_oid,
1630  BTEqualStrategyNumber, F_OIDEQ,
1632 
1633  scan = systable_beginscan(relation, DatabaseOidIndexId, true,
1634  NULL, 1, key);
1635  tuple = systable_getnext(scan);
1636  tuple = heap_copytuple(tuple);
1637  systable_endscan(scan);
1638 
1639  if (!HeapTupleIsValid(tuple))
1640  elog(ERROR, "could not find tuple for database %u", MyDatabaseId);
1641 
1642  dbform = (Form_pg_database) GETSTRUCT(tuple);
1643 
1644  /*
1645  * As in vac_update_relstats(), we ordinarily don't want to let
1646  * datfrozenxid go backward; but if it's "in the future" then it must be
1647  * corrupt and it seems best to overwrite it.
1648  */
1649  if (dbform->datfrozenxid != newFrozenXid &&
1650  (TransactionIdPrecedes(dbform->datfrozenxid, newFrozenXid) ||
1651  TransactionIdPrecedes(lastSaneFrozenXid, dbform->datfrozenxid)))
1652  {
1653  dbform->datfrozenxid = newFrozenXid;
1654  dirty = true;
1655  }
1656  else
1657  newFrozenXid = dbform->datfrozenxid;
1658 
1659  /* Ditto for datminmxid */
1660  if (dbform->datminmxid != newMinMulti &&
1661  (MultiXactIdPrecedes(dbform->datminmxid, newMinMulti) ||
1662  MultiXactIdPrecedes(lastSaneMinMulti, dbform->datminmxid)))
1663  {
1664  dbform->datminmxid = newMinMulti;
1665  dirty = true;
1666  }
1667  else
1668  newMinMulti = dbform->datminmxid;
1669 
1670  if (dirty)
1671  heap_inplace_update(relation, tuple);
1672 
1673  heap_freetuple(tuple);
1674  table_close(relation, RowExclusiveLock);
1675 
1676  /*
1677  * If we were able to advance datfrozenxid or datminmxid, see if we can
1678  * truncate pg_xact and/or pg_multixact. Also do it if the shared
1679  * XID-wrap-limit info is stale, since this action will update that too.
1680  */
1681  if (dirty || ForceTransactionIdLimitUpdate())
1682  vac_truncate_clog(newFrozenXid, newMinMulti,
1683  lastSaneFrozenXid, lastSaneMinMulti);
1684 }
1685 
1686 
1687 /*
1688  * vac_truncate_clog() -- attempt to truncate the commit log
1689  *
1690  * Scan pg_database to determine the system-wide oldest datfrozenxid,
1691  * and use it to truncate the transaction commit log (pg_xact).
1692  * Also update the XID wrap limit info maintained by varsup.c.
1693  * Likewise for datminmxid.
1694  *
1695  * The passed frozenXID and minMulti are the updated values for my own
1696  * pg_database entry. They're used to initialize the "min" calculations.
1697  * The caller also passes the "last sane" XID and MXID, since it has
1698  * those at hand already.
1699  *
1700  * This routine is only invoked when we've managed to change our
1701  * DB's datfrozenxid/datminmxid values, or we found that the shared
1702  * XID-wrap-limit info is stale.
1703  */
1704 static void
1706  MultiXactId minMulti,
1707  TransactionId lastSaneFrozenXid,
1708  MultiXactId lastSaneMinMulti)
1709 {
1711  Relation relation;
1712  TableScanDesc scan;
1713  HeapTuple tuple;
1714  Oid oldestxid_datoid;
1715  Oid minmulti_datoid;
1716  bool bogus = false;
1717  bool frozenAlreadyWrapped = false;
1718 
1719  /* Restrict task to one backend per cluster; see SimpleLruTruncate(). */
1720  LWLockAcquire(WrapLimitsVacuumLock, LW_EXCLUSIVE);
1721 
1722  /* init oldest datoids to sync with my frozenXID/minMulti values */
1723  oldestxid_datoid = MyDatabaseId;
1724  minmulti_datoid = MyDatabaseId;
1725 
1726  /*
1727  * Scan pg_database to compute the minimum datfrozenxid/datminmxid
1728  *
1729  * Since vac_update_datfrozenxid updates datfrozenxid/datminmxid in-place,
1730  * the values could change while we look at them. Fetch each one just
1731  * once to ensure sane behavior of the comparison logic. (Here, as in
1732  * many other places, we assume that fetching or updating an XID in shared
1733  * storage is atomic.)
1734  *
1735  * Note: we need not worry about a race condition with new entries being
1736  * inserted by CREATE DATABASE. Any such entry will have a copy of some
1737  * existing DB's datfrozenxid, and that source DB cannot be ours because
1738  * of the interlock against copying a DB containing an active backend.
1739  * Hence the new entry will not reduce the minimum. Also, if two VACUUMs
1740  * concurrently modify the datfrozenxid's of different databases, the
1741  * worst possible outcome is that pg_xact is not truncated as aggressively
1742  * as it could be.
1743  */
1744  relation = table_open(DatabaseRelationId, AccessShareLock);
1745 
1746  scan = table_beginscan_catalog(relation, 0, NULL);
1747 
1748  while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
1749  {
1750  volatile FormData_pg_database *dbform = (Form_pg_database) GETSTRUCT(tuple);
1751  TransactionId datfrozenxid = dbform->datfrozenxid;
1752  TransactionId datminmxid = dbform->datminmxid;
1753 
1756 
1757  /*
1758  * If things are working properly, no database should have a
1759  * datfrozenxid or datminmxid that is "in the future". However, such
1760  * cases have been known to arise due to bugs in pg_upgrade. If we
1761  * see any entries that are "in the future", chicken out and don't do
1762  * anything. This ensures we won't truncate clog before those
1763  * databases have been scanned and cleaned up. (We will issue the
1764  * "already wrapped" warning if appropriate, though.)
1765  */
1766  if (TransactionIdPrecedes(lastSaneFrozenXid, datfrozenxid) ||
1767  MultiXactIdPrecedes(lastSaneMinMulti, datminmxid))
1768  bogus = true;
1769 
1770  if (TransactionIdPrecedes(nextXID, datfrozenxid))
1771  frozenAlreadyWrapped = true;
1772  else if (TransactionIdPrecedes(datfrozenxid, frozenXID))
1773  {
1774  frozenXID = datfrozenxid;
1775  oldestxid_datoid = dbform->oid;
1776  }
1777 
1778  if (MultiXactIdPrecedes(datminmxid, minMulti))
1779  {
1780  minMulti = datminmxid;
1781  minmulti_datoid = dbform->oid;
1782  }
1783  }
1784 
1785  table_endscan(scan);
1786 
1787  table_close(relation, AccessShareLock);
1788 
1789  /*
1790  * Do not truncate CLOG if we seem to have suffered wraparound already;
1791  * the computed minimum XID might be bogus. This case should now be
1792  * impossible due to the defenses in GetNewTransactionId, but we keep the
1793  * test anyway.
1794  */
1795  if (frozenAlreadyWrapped)
1796  {
1797  ereport(WARNING,
1798  (errmsg("some databases have not been vacuumed in over 2 billion transactions"),
1799  errdetail("You might have already suffered transaction-wraparound data loss.")));
1800  return;
1801  }
1802 
1803  /* chicken out if data is bogus in any other way */
1804  if (bogus)
1805  return;
1806 
1807  /*
1808  * Advance the oldest value for commit timestamps before truncating, so
1809  * that if a user requests a timestamp for a transaction we're truncating
1810  * away right after this point, they get NULL instead of an ugly "file not
1811  * found" error from slru.c. This doesn't matter for xact/multixact
1812  * because they are not subject to arbitrary lookups from users.
1813  */
1814  AdvanceOldestCommitTsXid(frozenXID);
1815 
1816  /*
1817  * Truncate CLOG, multixact and CommitTs to the oldest computed value.
1818  */
1819  TruncateCLOG(frozenXID, oldestxid_datoid);
1820  TruncateCommitTs(frozenXID);
1821  TruncateMultiXact(minMulti, minmulti_datoid);
1822 
1823  /*
1824  * Update the wrap limit for GetNewTransactionId and creation of new
1825  * MultiXactIds. Note: these functions will also signal the postmaster
1826  * for an(other) autovac cycle if needed. XXX should we avoid possibly
1827  * signaling twice?
1828  */
1829  SetTransactionIdLimit(frozenXID, oldestxid_datoid);
1830  SetMultiXactIdLimit(minMulti, minmulti_datoid, false);
1831 
1832  LWLockRelease(WrapLimitsVacuumLock);
1833 }
1834 
1835 
1836 /*
1837  * vacuum_rel() -- vacuum one heap relation
1838  *
1839  * relid identifies the relation to vacuum. If relation is supplied,
1840  * use the name therein for reporting any failure to open/lock the rel;
1841  * do not use it once we've successfully opened the rel, since it might
1842  * be stale.
1843  *
1844  * Returns true if it's okay to proceed with a requested ANALYZE
1845  * operation on this table.
1846  *
1847  * Doing one heap at a time incurs extra overhead, since we need to
1848  * check that the heap exists again just before we vacuum it. The
1849  * reason that we do this is so that vacuuming can be spread across
1850  * many small transactions. Otherwise, two-phase locking would require
1851  * us to lock the entire database during one pass of the vacuum cleaner.
1852  *
1853  * At entry and exit, we are not inside a transaction.
1854  */
1855 static bool
1856 vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params)
1857 {
1858  LOCKMODE lmode;
1859  Relation rel;
1860  LockRelId lockrelid;
1861  Oid toast_relid;
1862  Oid save_userid;
1863  int save_sec_context;
1864  int save_nestlevel;
1865 
1866  Assert(params != NULL);
1867 
1868  /* Begin a transaction for vacuuming this relation */
1870 
1871  if (!(params->options & VACOPT_FULL))
1872  {
1873  /*
1874  * In lazy vacuum, we can set the PROC_IN_VACUUM flag, which lets
1875  * other concurrent VACUUMs know that they can ignore this one while
1876  * determining their OldestXmin. (The reason we don't set it during a
1877  * full VACUUM is exactly that we may have to run user-defined
1878  * functions for functional indexes, and we want to make sure that if
1879  * they use the snapshot set above, any tuples it requires can't get
1880  * removed from other tables. An index function that depends on the
1881  * contents of other tables is arguably broken, but we won't break it
1882  * here by violating transaction semantics.)
1883  *
1884  * We also set the VACUUM_FOR_WRAPAROUND flag, which is passed down by
1885  * autovacuum; it's used to avoid canceling a vacuum that was invoked
1886  * in an emergency.
1887  *
1888  * Note: these flags remain set until CommitTransaction or
1889  * AbortTransaction. We don't want to clear them until we reset
1890  * MyProc->xid/xmin, otherwise GetOldestNonRemovableTransactionId()
1891  * might appear to go backwards, which is probably Not Good. (We also
1892  * set PROC_IN_VACUUM *before* taking our own snapshot, so that our
1893  * xmin doesn't become visible ahead of setting the flag.)
1894  */
1895  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
1897  if (params->is_wraparound)
1900  LWLockRelease(ProcArrayLock);
1901  }
1902 
1903  /*
1904  * Need to acquire a snapshot to prevent pg_subtrans from being truncated,
1905  * cutoff xids in local memory wrapping around, and to have updated xmin
1906  * horizons.
1907  */
1909 
1910  /*
1911  * Check for user-requested abort. Note we want this to be inside a
1912  * transaction, so xact.c doesn't issue useless WARNING.
1913  */
1915 
1916  /*
1917  * Determine the type of lock we want --- hard exclusive lock for a FULL
1918  * vacuum, but just ShareUpdateExclusiveLock for concurrent vacuum. Either
1919  * way, we can be sure that no other backend is vacuuming the same table.
1920  */
1921  lmode = (params->options & VACOPT_FULL) ?
1923 
1924  /* open the relation and get the appropriate lock on it */
1925  rel = vacuum_open_relation(relid, relation, params->options,
1926  params->log_min_duration >= 0, lmode);
1927 
1928  /* leave if relation could not be opened or locked */
1929  if (!rel)
1930  {
1933  return false;
1934  }
1935 
1936  /*
1937  * Check if relation needs to be skipped based on ownership. This check
1938  * happens also when building the relation list to vacuum for a manual
1939  * operation, and needs to be done additionally here as VACUUM could
1940  * happen across multiple transactions where relation ownership could have
1941  * changed in-between. Make sure to only generate logs for VACUUM in this
1942  * case.
1943  */
1945  rel->rd_rel,
1946  params->options & VACOPT_VACUUM))
1947  {
1948  relation_close(rel, lmode);
1951  return false;
1952  }
1953 
1954  /*
1955  * Check that it's of a vacuumable relkind.
1956  */
1957  if (rel->rd_rel->relkind != RELKIND_RELATION &&
1958  rel->rd_rel->relkind != RELKIND_MATVIEW &&
1959  rel->rd_rel->relkind != RELKIND_TOASTVALUE &&
1960  rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
1961  {
1962  ereport(WARNING,
1963  (errmsg("skipping \"%s\" --- cannot vacuum non-tables or special system tables",
1964  RelationGetRelationName(rel))));
1965  relation_close(rel, lmode);
1968  return false;
1969  }
1970 
1971  /*
1972  * Silently ignore tables that are temp tables of other backends ---
1973  * trying to vacuum these will lead to great unhappiness, since their
1974  * contents are probably not up-to-date on disk. (We don't throw a
1975  * warning here; it would just lead to chatter during a database-wide
1976  * VACUUM.)
1977  */
1978  if (RELATION_IS_OTHER_TEMP(rel))
1979  {
1980  relation_close(rel, lmode);
1983  return false;
1984  }
1985 
1986  /*
1987  * Silently ignore partitioned tables as there is no work to be done. The
1988  * useful work is on their child partitions, which have been queued up for
1989  * us separately.
1990  */
1991  if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
1992  {
1993  relation_close(rel, lmode);
1996  /* It's OK to proceed with ANALYZE on this table */
1997  return true;
1998  }
1999 
2000  /*
2001  * Get a session-level lock too. This will protect our access to the
2002  * relation across multiple transactions, so that we can vacuum the
2003  * relation's TOAST table (if any) secure in the knowledge that no one is
2004  * deleting the parent relation.
2005  *
2006  * NOTE: this cannot block, even if someone else is waiting for access,
2007  * because the lock manager knows that both lock requests are from the
2008  * same process.
2009  */
2010  lockrelid = rel->rd_lockInfo.lockRelId;
2011  LockRelationIdForSession(&lockrelid, lmode);
2012 
2013  /*
2014  * Set index_cleanup option based on index_cleanup reloption if it wasn't
2015  * specified in VACUUM command, or when running in an autovacuum worker
2016  */
2017  if (params->index_cleanup == VACOPTVALUE_UNSPECIFIED)
2018  {
2019  StdRdOptIndexCleanup vacuum_index_cleanup;
2020 
2021  if (rel->rd_options == NULL)
2022  vacuum_index_cleanup = STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO;
2023  else
2024  vacuum_index_cleanup =
2025  ((StdRdOptions *) rel->rd_options)->vacuum_index_cleanup;
2026 
2027  if (vacuum_index_cleanup == STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO)
2028  params->index_cleanup = VACOPTVALUE_AUTO;
2029  else if (vacuum_index_cleanup == STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON)
2031  else
2032  {
2033  Assert(vacuum_index_cleanup ==
2036  }
2037  }
2038 
2039  /*
2040  * Set truncate option based on truncate reloption if it wasn't specified
2041  * in VACUUM command, or when running in an autovacuum worker
2042  */
2043  if (params->truncate == VACOPTVALUE_UNSPECIFIED)
2044  {
2045  if (rel->rd_options == NULL ||
2046  ((StdRdOptions *) rel->rd_options)->vacuum_truncate)
2047  params->truncate = VACOPTVALUE_ENABLED;
2048  else
2049  params->truncate = VACOPTVALUE_DISABLED;
2050  }
2051 
2052  /*
2053  * Remember the relation's TOAST relation for later, if the caller asked
2054  * us to process it. In VACUUM FULL, though, the toast table is
2055  * automatically rebuilt by cluster_rel so we shouldn't recurse to it.
2056  */
2057  if ((params->options & VACOPT_PROCESS_TOAST) != 0 &&
2058  (params->options & VACOPT_FULL) == 0)
2059  toast_relid = rel->rd_rel->reltoastrelid;
2060  else
2061  toast_relid = InvalidOid;
2062 
2063  /*
2064  * Switch to the table owner's userid, so that any index functions are run
2065  * as that user. Also lock down security-restricted operations and
2066  * arrange to make GUC variable changes local to this command. (This is
2067  * unnecessary, but harmless, for lazy VACUUM.)
2068  */
2069  GetUserIdAndSecContext(&save_userid, &save_sec_context);
2070  SetUserIdAndSecContext(rel->rd_rel->relowner,
2071  save_sec_context | SECURITY_RESTRICTED_OPERATION);
2072  save_nestlevel = NewGUCNestLevel();
2073 
2074  /*
2075  * Do the actual work --- either FULL or "lazy" vacuum
2076  */
2077  if (params->options & VACOPT_FULL)
2078  {
2079  ClusterParams cluster_params = {0};
2080 
2081  /* close relation before vacuuming, but hold lock until commit */
2082  relation_close(rel, NoLock);
2083  rel = NULL;
2084 
2085  if ((params->options & VACOPT_VERBOSE) != 0)
2086  cluster_params.options |= CLUOPT_VERBOSE;
2087 
2088  /* VACUUM FULL is now a variant of CLUSTER; see cluster.c */
2089  cluster_rel(relid, InvalidOid, &cluster_params);
2090  }
2091  else
2092  table_relation_vacuum(rel, params, vac_strategy);
2093 
2094  /* Roll back any GUC changes executed by index functions */
2095  AtEOXact_GUC(false, save_nestlevel);
2096 
2097  /* Restore userid and security context */
2098  SetUserIdAndSecContext(save_userid, save_sec_context);
2099 
2100  /* all done with this class, but hold lock until commit */
2101  if (rel)
2102  relation_close(rel, NoLock);
2103 
2104  /*
2105  * Complete the transaction and free all temporary memory used.
2106  */
2109 
2110  /*
2111  * If the relation has a secondary toast rel, vacuum that too while we
2112  * still hold the session lock on the main table. Note however that
2113  * "analyze" will not get done on the toast table. This is good, because
2114  * the toaster always uses hardcoded index access and statistics are
2115  * totally unimportant for toast relations.
2116  */
2117  if (toast_relid != InvalidOid)
2118  vacuum_rel(toast_relid, NULL, params);
2119 
2120  /*
2121  * Now release the session-level lock on the main table.
2122  */
2123  UnlockRelationIdForSession(&lockrelid, lmode);
2124 
2125  /* Report that we really did it. */
2126  return true;
2127 }
2128 
2129 
2130 /*
2131  * Open all the vacuumable indexes of the given relation, obtaining the
2132  * specified kind of lock on each. Return an array of Relation pointers for
2133  * the indexes into *Irel, and the number of indexes into *nindexes.
2134  *
2135  * We consider an index vacuumable if it is marked insertable (indisready).
2136  * If it isn't, probably a CREATE INDEX CONCURRENTLY command failed early in
2137  * execution, and what we have is too corrupt to be processable. We will
2138  * vacuum even if the index isn't indisvalid; this is important because in a
2139  * unique index, uniqueness checks will be performed anyway and had better not
2140  * hit dangling index pointers.
2141  */
2142 void
2144  int *nindexes, Relation **Irel)
2145 {
2146  List *indexoidlist;
2147  ListCell *indexoidscan;
2148  int i;
2149 
2150  Assert(lockmode != NoLock);
2151 
2152  indexoidlist = RelationGetIndexList(relation);
2153 
2154  /* allocate enough memory for all indexes */
2155  i = list_length(indexoidlist);
2156 
2157  if (i > 0)
2158  *Irel = (Relation *) palloc(i * sizeof(Relation));
2159  else
2160  *Irel = NULL;
2161 
2162  /* collect just the ready indexes */
2163  i = 0;
2164  foreach(indexoidscan, indexoidlist)
2165  {
2166  Oid indexoid = lfirst_oid(indexoidscan);
2167  Relation indrel;
2168 
2169  indrel = index_open(indexoid, lockmode);
2170  if (indrel->rd_index->indisready)
2171  (*Irel)[i++] = indrel;
2172  else
2173  index_close(indrel, lockmode);
2174  }
2175 
2176  *nindexes = i;
2177 
2178  list_free(indexoidlist);
2179 }
2180 
2181 /*
2182  * Release the resources acquired by vac_open_indexes. Optionally release
2183  * the locks (say NoLock to keep 'em).
2184  */
2185 void
2186 vac_close_indexes(int nindexes, Relation *Irel, LOCKMODE lockmode)
2187 {
2188  if (Irel == NULL)
2189  return;
2190 
2191  while (nindexes--)
2192  {
2193  Relation ind = Irel[nindexes];
2194 
2195  index_close(ind, lockmode);
2196  }
2197  pfree(Irel);
2198 }
2199 
2200 /*
2201  * vacuum_delay_point --- check for interrupts and cost-based delay.
2202  *
2203  * This should be called in each major loop of VACUUM processing,
2204  * typically once per page processed.
2205  */
2206 void
2208 {
2209  double msec = 0;
2210 
2211  /* Always check for interrupts */
2213 
2215  return;
2216 
2217  /*
2218  * For parallel vacuum, the delay is computed based on the shared cost
2219  * balance. See compute_parallel_delay.
2220  */
2221  if (VacuumSharedCostBalance != NULL)
2222  msec = compute_parallel_delay();
2223  else if (VacuumCostBalance >= VacuumCostLimit)
2225 
2226  /* Nap if appropriate */
2227  if (msec > 0)
2228  {
2229  if (msec > VacuumCostDelay * 4)
2230  msec = VacuumCostDelay * 4;
2231 
2232  (void) WaitLatch(MyLatch,
2234  msec,
2237 
2238  VacuumCostBalance = 0;
2239 
2240  /* update balance values for workers */
2242 
2243  /* Might have gotten an interrupt while sleeping */
2245  }
2246 }
2247 
2248 /*
2249  * Computes the vacuum delay for parallel workers.
2250  *
2251  * The basic idea of a cost-based delay for parallel vacuum is to allow each
2252  * worker to sleep in proportion to the share of work it's done. We achieve this
2253  * by allowing all parallel vacuum workers including the leader process to
2254  * have a shared view of cost related parameters (mainly VacuumCostBalance).
2255  * We allow each worker to update it as and when it has incurred any cost and
2256  * then based on that decide whether it needs to sleep. We compute the time
2257  * to sleep for a worker based on the cost it has incurred
2258  * (VacuumCostBalanceLocal) and then reduce the VacuumSharedCostBalance by
2259  * that amount. This avoids putting to sleep those workers which have done less
2260  * I/O than other workers and therefore ensure that workers
2261  * which are doing more I/O got throttled more.
2262  *
2263  * We allow a worker to sleep only if it has performed I/O above a certain
2264  * threshold, which is calculated based on the number of active workers
2265  * (VacuumActiveNWorkers), and the overall cost balance is more than
2266  * VacuumCostLimit set by the system. Testing reveals that we achieve
2267  * the required throttling if we force a worker that has done more than 50%
2268  * of its share of work to sleep.
2269  */
2270 static double
2272 {
2273  double msec = 0;
2274  uint32 shared_balance;
2275  int nworkers;
2276 
2277  /* Parallel vacuum must be active */
2279 
2281 
2282  /* At least count itself */
2283  Assert(nworkers >= 1);
2284 
2285  /* Update the shared cost balance value atomically */
2287 
2288  /* Compute the total local balance for the current worker */
2290 
2291  if ((shared_balance >= VacuumCostLimit) &&
2292  (VacuumCostBalanceLocal > 0.5 * ((double) VacuumCostLimit / nworkers)))
2293  {
2294  /* Compute sleep time based on the local cost balance */
2298  }
2299 
2300  /*
2301  * Reset the local balance as we accumulated it into the shared value.
2302  */
2303  VacuumCostBalance = 0;
2304 
2305  return msec;
2306 }
2307 
2308 /*
2309  * A wrapper function of defGetBoolean().
2310  *
2311  * This function returns VACOPTVALUE_ENABLED and VACOPTVALUE_DISABLED instead
2312  * of true and false.
2313  */
2314 static VacOptValue
2316 {
2318 }
2319 
2320 /*
2321  * vac_bulkdel_one_index() -- bulk-deletion for index relation.
2322  *
2323  * Returns bulk delete stats derived from input stats
2324  */
2327  VacDeadItems *dead_items)
2328 {
2329  /* Do bulk deletion */
2330  istat = index_bulk_delete(ivinfo, istat, vac_tid_reaped,
2331  (void *) dead_items);
2332 
2333  ereport(ivinfo->message_level,
2334  (errmsg("scanned index \"%s\" to remove %d row versions",
2335  RelationGetRelationName(ivinfo->index),
2336  dead_items->num_items)));
2337 
2338  return istat;
2339 }
2340 
2341 /*
2342  * vac_cleanup_one_index() -- do post-vacuum cleanup for index relation.
2343  *
2344  * Returns bulk delete stats derived from input stats
2345  */
2348 {
2349  istat = index_vacuum_cleanup(ivinfo, istat);
2350 
2351  if (istat)
2352  ereport(ivinfo->message_level,
2353  (errmsg("index \"%s\" now contains %.0f row versions in %u pages",
2354  RelationGetRelationName(ivinfo->index),
2355  istat->num_index_tuples,
2356  istat->num_pages),
2357  errdetail("%.0f index row versions were removed.\n"
2358  "%u index pages were newly deleted.\n"
2359  "%u index pages are currently deleted, of which %u are currently reusable.",
2360  istat->tuples_removed,
2361  istat->pages_newly_deleted,
2362  istat->pages_deleted, istat->pages_free)));
2363 
2364  return istat;
2365 }
2366 
2367 /*
2368  * Returns the total required space for VACUUM's dead_items array given a
2369  * max_items value.
2370  */
2371 Size
2373 {
2374  Assert(max_items <= MAXDEADITEMS(MaxAllocSize));
2375 
2376  return offsetof(VacDeadItems, items) + sizeof(ItemPointerData) * max_items;
2377 }
2378 
2379 /*
2380  * vac_tid_reaped() -- is a particular tid deletable?
2381  *
2382  * This has the right signature to be an IndexBulkDeleteCallback.
2383  *
2384  * Assumes dead_items array is sorted (in ascending TID order).
2385  */
2386 static bool
2388 {
2389  VacDeadItems *dead_items = (VacDeadItems *) state;
2390  int64 litem,
2391  ritem,
2392  item;
2393  ItemPointer res;
2394 
2395  litem = itemptr_encode(&dead_items->items[0]);
2396  ritem = itemptr_encode(&dead_items->items[dead_items->num_items - 1]);
2397  item = itemptr_encode(itemptr);
2398 
2399  /*
2400  * Doing a simple bound check before bsearch() is useful to avoid the
2401  * extra cost of bsearch(), especially if dead items on the heap are
2402  * concentrated in a certain range. Since this function is called for
2403  * every index tuple, it pays to be really fast.
2404  */
2405  if (item < litem || item > ritem)
2406  return false;
2407 
2408  res = (ItemPointer) bsearch((void *) itemptr,
2409  (void *) dead_items->items,
2410  dead_items->num_items,
2411  sizeof(ItemPointerData),
2412  vac_cmp_itemptr);
2413 
2414  return (res != NULL);
2415 }
2416 
2417 /*
2418  * Comparator routines for use with qsort() and bsearch().
2419  */
2420 static int
2421 vac_cmp_itemptr(const void *left, const void *right)
2422 {
2423  BlockNumber lblk,
2424  rblk;
2425  OffsetNumber loff,
2426  roff;
2427 
2428  lblk = ItemPointerGetBlockNumber((ItemPointer) left);
2429  rblk = ItemPointerGetBlockNumber((ItemPointer) right);
2430 
2431  if (lblk < rblk)
2432  return -1;
2433  if (lblk > rblk)
2434  return 1;
2435 
2436  loff = ItemPointerGetOffsetNumber((ItemPointer) left);
2437  roff = ItemPointerGetOffsetNumber((ItemPointer) right);
2438 
2439  if (loff < roff)
2440  return -1;
2441  if (loff > roff)
2442  return 1;
2443 
2444  return 0;
2445 }
bool pg_database_ownercheck(Oid db_oid, Oid roleid)
Definition: aclchk.c:5589
bool pg_class_ownercheck(Oid class_oid, Oid roleid)
Definition: aclchk.c:5171
static uint32 pg_atomic_sub_fetch_u32(volatile pg_atomic_uint32 *ptr, int32 sub_)
Definition: atomics.h:401
static uint32 pg_atomic_add_fetch_u32(volatile pg_atomic_uint32 *ptr, int32 add_)
Definition: atomics.h:386
static uint32 pg_atomic_read_u32(volatile pg_atomic_uint32 *ptr)
Definition: atomics.h:241
void AutoVacuumUpdateDelay(void)
Definition: autovacuum.c:1779
int autovacuum_multixact_freeze_max_age
Definition: autovacuum.c:126
int autovacuum_freeze_max_age
Definition: autovacuum.c:125
bool IsAutoVacuumWorkerProcess(void)
Definition: autovacuum.c:3309
#define MAX_PARALLEL_WORKER_LIMIT
uint32 BlockNumber
Definition: block.h:31
@ BAS_VACUUM
Definition: bufmgr.h:33
#define NameStr(name)
Definition: c.h:681
unsigned int uint32
Definition: c.h:441
#define Min(x, y)
Definition: c.h:986
#define offsetof(type, field)
Definition: c.h:727
signed int int32
Definition: c.h:429
#define Max(x, y)
Definition: c.h:980
TransactionId MultiXactId
Definition: c.h:597
uint32 bits32
Definition: c.h:450
float float4
Definition: c.h:564
uint32 TransactionId
Definition: c.h:587
#define OidIsValid(objectId)
Definition: c.h:710
size_t Size
Definition: c.h:540
void TruncateCLOG(TransactionId oldestXact, Oid oldestxid_datoid)
Definition: clog.c:880
void cluster_rel(Oid tableOid, Oid indexOid, ClusterParams *params)
Definition: cluster.c:310
#define CLUOPT_VERBOSE
Definition: cluster.h:23
void analyze_rel(Oid relid, RangeVar *relation, VacuumParams *params, List *va_cols, bool in_outer_xact, BufferAccessStrategy bstrategy)
Definition: analyze.c:121
void AdvanceOldestCommitTsXid(TransactionId oldestXact)
Definition: commit_ts.c:908
void TruncateCommitTs(TransactionId oldestXact)
Definition: commit_ts.c:855
int64 TimestampTz
Definition: timestamp.h:39
int32 defGetInt32(DefElem *def)
Definition: define.c:163
bool defGetBoolean(DefElem *def)
Definition: define.c:108
char * defGetString(DefElem *def)
Definition: define.c:49
struct cursor * cur
Definition: ecpg.c:28
int errmsg_internal(const char *fmt,...)
Definition: elog.c:991
int errdetail(const char *fmt,...)
Definition: elog.c:1037
int errhint(const char *fmt,...)
Definition: elog.c:1151
int errcode(int sqlerrcode)
Definition: elog.c:693
int errmsg(const char *fmt,...)
Definition: elog.c:904
#define LOG
Definition: elog.h:25
#define PG_END_TRY()
Definition: elog.h:324
#define PG_TRY()
Definition: elog.h:299
#define WARNING
Definition: elog.h:30
#define PG_FINALLY()
Definition: elog.h:316
#define ERROR
Definition: elog.h:33
#define elog(elevel,...)
Definition: elog.h:218
#define ereport(elevel,...)
Definition: elog.h:143
BufferAccessStrategy GetAccessStrategy(BufferAccessStrategyType btype)
Definition: freelist.c:541
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:598
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:505
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:386
volatile sig_atomic_t InterruptPending
Definition: globals.c:30
int64 VacuumPageHit
Definition: globals.c:148
int VacuumCostLimit
Definition: globals.c:145
int64 VacuumPageMiss
Definition: globals.c:149
bool VacuumCostActive
Definition: globals.c:153
int64 VacuumPageDirty
Definition: globals.c:150
int VacuumCostBalance
Definition: globals.c:152
struct Latch * MyLatch
Definition: globals.c:58
double VacuumCostDelay
Definition: globals.c:146
Oid MyDatabaseId
Definition: globals.c:89
int NewGUCNestLevel(void)
Definition: guc.c:6467
void AtEOXact_GUC(bool isCommit, int nestLevel)
Definition: guc.c:6481
void heap_inplace_update(Relation relation, HeapTuple tuple)
Definition: heapam.c:5998
HeapTuple heap_getnext(TableScanDesc sscan, ScanDirection direction)
Definition: heapam.c:1296
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:680
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define GETSTRUCT(TUP)
Definition: htup_details.h:649
static int64 itemptr_encode(ItemPointer itemptr)
Definition: index.h:185
IndexBulkDeleteResult * index_vacuum_cleanup(IndexVacuumInfo *info, IndexBulkDeleteResult *istat)
Definition: indexam.c:712
void index_close(Relation relation, LOCKMODE lockmode)
Definition: indexam.c:158
IndexBulkDeleteResult * index_bulk_delete(IndexVacuumInfo *info, IndexBulkDeleteResult *istat, IndexBulkDeleteCallback callback, void *callback_state)
Definition: indexam.c:691
Relation index_open(Oid relationId, LOCKMODE lockmode)
Definition: indexam.c:132
int i
Definition: isn.c:73
#define ItemPointerGetBlockNumber(pointer)
Definition: itemptr.h:98
ItemPointerData * ItemPointer
Definition: itemptr.h:49
struct ItemPointerData ItemPointerData
#define ItemPointerGetOffsetNumber(pointer)
Definition: itemptr.h:117
void ResetLatch(Latch *latch)
Definition: latch.c:658
int WaitLatch(Latch *latch, int wakeEvents, long timeout, uint32 wait_event_info)
Definition: latch.c:451
#define WL_TIMEOUT
Definition: latch.h:128
#define WL_EXIT_ON_PM_DEATH
Definition: latch.h:130
#define WL_LATCH_SET
Definition: latch.h:125
Assert(fmt[strlen(fmt) - 1] !='\n')
List * lappend(List *list, void *datum)
Definition: list.c:336
void list_free(List *list)
Definition: list.c:1505
List * list_concat(List *list1, const List *list2)
Definition: list.c:540
bool ConditionalLockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:152
void UnlockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:228
void LockRelationIdForSession(LockRelId *relid, LOCKMODE lockmode)
Definition: lmgr.c:398
void UnlockRelationIdForSession(LockRelId *relid, LOCKMODE lockmode)
Definition: lmgr.c:411
void LockDatabaseFrozenIds(LOCKMODE lockmode)
Definition: lmgr.c:498
int LOCKMODE
Definition: lockdefs.h:26
#define NoLock
Definition: lockdefs.h:34
#define AccessExclusiveLock
Definition: lockdefs.h:43
#define AccessShareLock
Definition: lockdefs.h:36
#define ShareUpdateExclusiveLock
Definition: lockdefs.h:39
#define ExclusiveLock
Definition: lockdefs.h:42
#define RowExclusiveLock
Definition: lockdefs.h:38
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1196
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1800
@ LW_EXCLUSIVE
Definition: lwlock.h:104
VacuumRelation * makeVacuumRelation(RangeVar *relation, Oid oid, List *va_cols)
Definition: makefuncs.c:813
void pfree(void *pointer)
Definition: mcxt.c:1175
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:218
void * palloc(Size size)
Definition: mcxt.c:1068
MemoryContext PortalContext
Definition: mcxt.c:57
#define AllocSetContextCreate
Definition: memutils.h:173
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:197
#define MaxAllocSize
Definition: memutils.h:40
#define SECURITY_RESTRICTED_OPERATION
Definition: miscadmin.h:313
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:121
void GetUserIdAndSecContext(Oid *userid, int *sec_context)
Definition: miscinit.c:603
Oid GetUserId(void)
Definition: miscinit.c:492
void SetUserIdAndSecContext(Oid userid, int sec_context)
Definition: miscinit.c:610
bool MultiXactIdPrecedes(MultiXactId multi1, MultiXactId multi2)
Definition: multixact.c:3159
bool MultiXactIdPrecedesOrEquals(MultiXactId multi1, MultiXactId multi2)
Definition: multixact.c:3173
void SetMultiXactIdLimit(MultiXactId oldest_datminmxid, Oid oldest_datoid, bool is_startup)
Definition: multixact.c:2213
MultiXactId GetOldestMultiXactId(void)
Definition: multixact.c:2506
int MultiXactMemberFreezeThreshold(void)
Definition: multixact.c:2828
MultiXactId ReadNextMultiXactId(void)
Definition: multixact.c:723
void TruncateMultiXact(MultiXactId newOldestMulti, Oid newOldestMultiDB)
Definition: multixact.c:2944
#define MultiXactIdIsValid(multi)
Definition: multixact.h:28
#define FirstMultiXactId
Definition: multixact.h:25
Oid RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode, uint32 flags, RangeVarGetRelidCallback callback, void *callback_arg)
Definition: namespace.c:238
@ RVR_SKIP_LOCKED
Definition: namespace.h:73
uint16 OffsetNumber
Definition: off.h:24
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:110
static int verbose
#define ERRCODE_DATA_CORRUPTED
Definition: pg_basebackup.c:43
NameData relname
Definition: pg_class.h:38
FormData_pg_class * Form_pg_class
Definition: pg_class.h:153
TransactionId datfrozenxid
Definition: pg_database.h:56
TransactionId datminmxid
Definition: pg_database.h:59
FormData_pg_database * Form_pg_database
Definition: pg_database.h:87
FormData_pg_database
Definition: pg_database.h:80
List * find_all_inheritors(Oid parentrelId, LOCKMODE lockmode, List **numparents)
Definition: pg_inherits.c:256
#define lfirst(lc)
Definition: pg_list.h:169
#define lfirst_node(type, lc)
Definition: pg_list.h:172
static int list_length(const List *l)
Definition: pg_list.h:149
#define NIL
Definition: pg_list.h:65
#define lfirst_oid(lc)
Definition: pg_list.h:171
#define ERRCODE_UNDEFINED_TABLE
Definition: pgbench.c:81
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define InvalidOid
Definition: postgres_ext.h:36
unsigned int Oid
Definition: postgres_ext.h:31
#define PROC_IN_VACUUM
Definition: proc.h:55
#define PROC_VACUUM_FOR_WRAPAROUND
Definition: proc.h:57
TransactionId GetOldestNonRemovableTransactionId(Relation rel)
Definition: procarray.c:2021
static long analyze(struct nfa *nfa)
Definition: regc_nfa.c:3044
#define RelationGetRelid(relation)
Definition: rel.h:489
#define RelationGetRelationName(relation)
Definition: rel.h:523
#define RELATION_IS_OTHER_TEMP(relation)
Definition: rel.h:643
StdRdOptIndexCleanup
Definition: rel.h:314
@ STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO
Definition: rel.h:315
@ STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF
Definition: rel.h:316
@ STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON
Definition: rel.h:317
List * RelationGetIndexList(Relation relation)
Definition: relcache.c:4675
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
@ ForwardScanDirection
Definition: sdir.h:26
Snapshot GetTransactionSnapshot(void)
Definition: snapmgr.c:250
bool ActiveSnapshotSet(void)
Definition: snapmgr.c:815
bool TransactionIdLimitedForOldSnapshots(TransactionId recentXmin, Relation relation, TransactionId *limit_xid, TimestampTz *limit_ts)
Definition: snapmgr.c:1794
void PopActiveSnapshot(void)
Definition: snapmgr.c:776
void PushActiveSnapshot(Snapshot snap)
Definition: snapmgr.c:682
void SetOldSnapshotThresholdTimestamp(TimestampTz ts, TransactionId xlimit)
Definition: snapmgr.c:1715
static bool OldSnapshotThresholdActive(void)
Definition: snapmgr.h:101
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: relation.c:206
Relation try_relation_open(Oid relationId, LOCKMODE lockmode)
Definition: relation.c:89
PGPROC * MyProc
Definition: proc.c:68
PROC_HDR * ProcGlobal
Definition: proc.c:80
#define BTEqualStrategyNumber
Definition: stratnum.h:31
bits32 options
Definition: cluster.h:30
char * defname
Definition: parsenodes.h:765
int location
Definition: parsenodes.h:769
Node * arg
Definition: parsenodes.h:766
BlockNumber pages_deleted
Definition: genam.h:81
BlockNumber pages_newly_deleted
Definition: genam.h:80
BlockNumber pages_free
Definition: genam.h:82
BlockNumber num_pages
Definition: genam.h:76
double tuples_removed
Definition: genam.h:79
double num_index_tuples
Definition: genam.h:78
Relation index
Definition: genam.h:46
int message_level
Definition: genam.h:50
Definition: pg_list.h:51
LockRelId lockRelId
Definition: rel.h:45
Definition: rel.h:38
uint8 statusFlags
Definition: proc.h:227
int pgxactoff
Definition: proc.h:186
uint8 * statusFlags
Definition: proc.h:371
char * relname
Definition: primnodes.h:68
LockInfoData rd_lockInfo
Definition: rel.h:112
TriggerDesc * trigdesc
Definition: rel.h:115
Form_pg_index rd_index
Definition: rel.h:188
RuleLock * rd_rules
Definition: rel.h:113
bytea * rd_options
Definition: rel.h:171
Form_pg_class rd_rel
Definition: rel.h:109
ItemPointerData items[FLEXIBLE_ARRAY_MEMBER]
Definition: vacuum.h:247
int num_items
Definition: vacuum.h:244
int nworkers
Definition: vacuum.h:235
int freeze_table_age
Definition: vacuum.h:218
VacOptValue truncate
Definition: vacuum.h:228
bits32 options
Definition: vacuum.h:216
int freeze_min_age
Definition: vacuum.h:217
bool is_wraparound
Definition: vacuum.h:223
int multixact_freeze_min_age
Definition: vacuum.h:219
int multixact_freeze_table_age
Definition: vacuum.h:221
int log_min_duration
Definition: vacuum.h:224
VacOptValue index_cleanup
Definition: vacuum.h:227
RangeVar * relation
Definition: parsenodes.h:3728
List * options
Definition: parsenodes.h:3713
bool is_vacuumcmd
Definition: parsenodes.h:3715
List * rels
Definition: parsenodes.h:3714
Definition: regguts.h:318
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1221
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1173
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:179
@ RELOID
Definition: syscache.h:89
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
TableScanDesc table_beginscan_catalog(Relation relation, int nkeys, struct ScanKeyData *key)
Definition: tableam.c:112
static void table_endscan(TableScanDesc scan)
Definition: tableam.h:993
static void table_relation_vacuum(Relation rel, struct VacuumParams *params, BufferAccessStrategy bstrategy)
Definition: tableam.h:1677
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
bool TransactionIdPrecedesOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:319
static TransactionId ReadNextTransactionId(void)
Definition: transam.h:316
#define FirstNormalTransactionId
Definition: transam.h:34
#define TransactionIdIsValid(xid)
Definition: transam.h:41
#define TransactionIdIsNormal(xid)
Definition: transam.h:42
static bool vac_tid_reaped(ItemPointer itemptr, void *state)
Definition: vacuum.c:2387
IndexBulkDeleteResult * vac_bulkdel_one_index(IndexVacuumInfo *ivinfo, IndexBulkDeleteResult *istat, VacDeadItems *dead_items)
Definition: vacuum.c:2326
void ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
Definition: vacuum.c:107
static List * get_all_vacuum_rels(int options)
Definition: vacuum.c:884
pg_atomic_uint32 * VacuumActiveNWorkers
Definition: vacuum.c:84
static void vac_truncate_clog(TransactionId frozenXID, MultiXactId minMulti, TransactionId lastSaneFrozenXid, MultiXactId lastSaneMinMulti)
Definition: vacuum.c:1705
Size vac_max_items_to_alloc_size(int max_items)
Definition: vacuum.c:2372
static MemoryContext vac_context
Definition: vacuum.c:75
int vacuum_freeze_min_age
Definition: vacuum.c:66
static List * expand_vacuum_rel(VacuumRelation *vrel, int options)
Definition: vacuum.c:745
static double compute_parallel_delay(void)
Definition: vacuum.c:2271
static VacOptValue get_vacoptval_from_boolean(DefElem *def)
Definition: vacuum.c:2315
void vac_open_indexes(Relation relation, LOCKMODE lockmode, int *nindexes, Relation **Irel)
Definition: vacuum.c:2143
int VacuumCostBalanceLocal
Definition: vacuum.c:85
void vac_update_relstats(Relation relation, BlockNumber num_pages, double num_tuples, BlockNumber num_all_visible_pages, bool hasindex, TransactionId frozenxid, MultiXactId minmulti, bool *frozenxid_updated, bool *minmulti_updated, bool in_outer_xact)
Definition: vacuum.c:1324
void vacuum(List *relations, VacuumParams *params, BufferAccessStrategy bstrategy, bool isTopLevel)
Definition: vacuum.c:298
int vacuum_multixact_freeze_table_age
Definition: vacuum.c:69
bool vacuum_xid_failsafe_check(TransactionId relfrozenxid, MultiXactId relminmxid)
Definition: vacuum.c:1162
static BufferAccessStrategy vac_strategy
Definition: vacuum.c:76
int vacuum_freeze_table_age
Definition: vacuum.c:67
static bool vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params)
Definition: vacuum.c:1856
int vacuum_multixact_failsafe_age
Definition: vacuum.c:71
bool 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, MultiXactId *oldestMxact, TransactionId *freezeLimit, MultiXactId *multiXactCutoff)
Definition: vacuum.c:959
int vacuum_multixact_freeze_min_age
Definition: vacuum.c:68
Relation vacuum_open_relation(Oid relid, RangeVar *relation, bits32 options, bool verbose, LOCKMODE lmode)
Definition: vacuum.c:633
void vac_close_indexes(int nindexes, Relation *Irel, LOCKMODE lockmode)
Definition: vacuum.c:2186
void vacuum_delay_point(void)
Definition: vacuum.c:2207
bool vacuum_is_relation_owner(Oid relid, Form_pg_class reltuple, bits32 options)
Definition: vacuum.c:559
void vac_update_datfrozenxid(void)
Definition: vacuum.c:1491
pg_atomic_uint32 * VacuumSharedCostBalance
Definition: vacuum.c:83
int vacuum_failsafe_age
Definition: vacuum.c:70
double vac_estimate_reltuples(Relation relation, BlockNumber total_pages, BlockNumber scanned_pages, double scanned_tuples)
Definition: vacuum.c:1222
IndexBulkDeleteResult * vac_cleanup_one_index(IndexVacuumInfo *ivinfo, IndexBulkDeleteResult *istat)
Definition: vacuum.c:2347
static int vac_cmp_itemptr(const void *left, const void *right)
Definition: vacuum.c:2421
#define VACOPT_FREEZE
Definition: vacuum.h:186
#define VACOPT_SKIP_LOCKED
Definition: vacuum.h:188
#define VACOPT_VACUUM
Definition: vacuum.h:183
#define VACOPT_VERBOSE
Definition: vacuum.h:185
#define MAXDEADITEMS(avail_mem)
Definition: vacuum.h:250
#define VACOPT_FULL
Definition: vacuum.h:187
VacOptValue
Definition: vacuum.h:201
@ VACOPTVALUE_AUTO
Definition: vacuum.h:203
@ VACOPTVALUE_ENABLED
Definition: vacuum.h:205
@ VACOPTVALUE_UNSPECIFIED
Definition: vacuum.h:202
@ VACOPTVALUE_DISABLED
Definition: vacuum.h:204
#define VACOPT_PROCESS_TOAST
Definition: vacuum.h:189
#define VACOPT_DISABLE_PAGE_SKIPPING
Definition: vacuum.h:190
#define VACOPT_ANALYZE
Definition: vacuum.h:184
void SetTransactionIdLimit(TransactionId oldest_datfrozenxid, Oid oldest_datoid)
Definition: varsup.c:345
bool ForceTransactionIdLimitUpdate(void)
Definition: varsup.c:490
@ WAIT_EVENT_VACUUM_DELAY
Definition: wait_event.h:148
bool IsInTransactionBlock(bool isTopLevel)
Definition: xact.c:3575
void CommandCounterIncrement(void)
Definition: xact.c:1074
void PreventInTransactionBlock(bool isTopLevel, const char *stmtType)
Definition: xact.c:3462
void StartTransactionCommand(void)
Definition: xact.c:2925
void CommitTransactionCommand(void)
Definition: xact.c:3022