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