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