Thanks to visit codestin.com
Credit goes to doxygen.postgresql.org

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