PostgreSQL Source Code git master
Loading...
Searching...
No Matches
autovacuum.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * autovacuum.c
4 *
5 * PostgreSQL Integrated Autovacuum Daemon
6 *
7 * The autovacuum system is structured in two different kinds of processes: the
8 * autovacuum launcher and the autovacuum worker. The launcher is an
9 * always-running process, started by the postmaster when the autovacuum GUC
10 * parameter is set. The launcher schedules autovacuum workers to be started
11 * when appropriate. The workers are the processes which execute the actual
12 * vacuuming; they connect to a database as determined in the launcher, and
13 * once connected they examine the catalogs to select the tables to vacuum.
14 *
15 * The autovacuum launcher cannot start the worker processes by itself,
16 * because doing so would cause robustness issues (namely, failure to shut
17 * them down on exceptional conditions, and also, since the launcher is
18 * connected to shared memory and is thus subject to corruption there, it is
19 * not as robust as the postmaster). So it leaves that task to the postmaster.
20 *
21 * There is an autovacuum shared memory area, where the launcher stores
22 * information about the database it wants vacuumed. When it wants a new
23 * worker to start, it sets a flag in shared memory and sends a signal to the
24 * postmaster. Then postmaster knows nothing more than it must start a worker;
25 * so it forks a new child, which turns into a worker. This new process
26 * connects to shared memory, and there it can inspect the information that the
27 * launcher has set up.
28 *
29 * If the fork() call fails in the postmaster, it sets a flag in the shared
30 * memory area, and sends a signal to the launcher. The launcher, upon
31 * noticing the flag, can try starting the worker again by resending the
32 * signal. Note that the failure can only be transient (fork failure due to
33 * high load, memory pressure, too many processes, etc); more permanent
34 * problems, like failure to connect to a database, are detected later in the
35 * worker and dealt with just by having the worker exit normally. The launcher
36 * will launch a new worker again later, per schedule.
37 *
38 * When the worker is done vacuuming it sends SIGUSR2 to the launcher. The
39 * launcher then wakes up and is able to launch another worker, if the schedule
40 * is so tight that a new worker is needed immediately. At this time the
41 * launcher can also balance the settings for the various remaining workers'
42 * cost-based vacuum delay feature.
43 *
44 * Note that there can be more than one worker in a database concurrently.
45 * They will store the table they are currently vacuuming in shared memory, so
46 * that other workers avoid being blocked waiting for the vacuum lock for that
47 * table. They will also fetch the last time the table was vacuumed from
48 * pgstats just before vacuuming each table, to avoid vacuuming a table that
49 * was just finished being vacuumed by another worker and thus is no longer
50 * noted in shared memory. However, there is a small window (due to not yet
51 * holding the relation lock) during which a worker may choose a table that was
52 * already vacuumed; this is a bug in the current design.
53 *
54 * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
55 * Portions Copyright (c) 1994, Regents of the University of California
56 *
57 *
58 * IDENTIFICATION
59 * src/backend/postmaster/autovacuum.c
60 *
61 *-------------------------------------------------------------------------
62 */
63#include "postgres.h"
64
65#include <math.h>
66#include <signal.h>
67#include <sys/time.h>
68#include <unistd.h>
69
70#include "access/heapam.h"
71#include "access/htup_details.h"
72#include "access/multixact.h"
73#include "access/reloptions.h"
74#include "access/tableam.h"
75#include "access/transam.h"
76#include "access/xact.h"
77#include "catalog/dependency.h"
78#include "catalog/namespace.h"
79#include "catalog/pg_database.h"
81#include "commands/vacuum.h"
82#include "common/int.h"
83#include "funcapi.h"
84#include "lib/ilist.h"
85#include "libpq/pqsignal.h"
86#include "miscadmin.h"
87#include "nodes/makefuncs.h"
88#include "pgstat.h"
92#include "storage/aio_subsys.h"
93#include "storage/bufmgr.h"
94#include "storage/ipc.h"
95#include "storage/fd.h"
96#include "storage/latch.h"
97#include "storage/lmgr.h"
98#include "storage/pmsignal.h"
99#include "storage/proc.h"
100#include "storage/procsignal.h"
101#include "storage/smgr.h"
102#include "storage/subsystems.h"
103#include "tcop/tcopprot.h"
104#include "utils/fmgroids.h"
105#include "utils/fmgrprotos.h"
106#include "utils/guc_hooks.h"
108#include "utils/lsyscache.h"
109#include "utils/memutils.h"
110#include "utils/ps_status.h"
111#include "utils/rel.h"
112#include "utils/snapmgr.h"
113#include "utils/syscache.h"
114#include "utils/timeout.h"
115#include "utils/timestamp.h"
116#include "utils/tuplestore.h"
117#include "utils/wait_event.h"
118
119
120/*
121 * GUC parameters
122 */
144
147
148/* the minimum allowed time between two awakenings of the launcher */
149#define MIN_AUTOVAC_SLEEPTIME 100.0 /* milliseconds */
150#define MAX_AUTOVAC_SLEEPTIME 300 /* seconds */
151
152/*
153 * Variables to save the cost-related storage parameters for the current
154 * relation being vacuumed by this autovacuum worker. Using these, we can
155 * ensure we don't overwrite the values of vacuum_cost_delay and
156 * vacuum_cost_limit after reloading the configuration file. They are
157 * initialized to "invalid" values to indicate that no cost-related storage
158 * parameters were specified and will be set in do_autovacuum() after checking
159 * the storage parameters in table_recheck_autovac().
160 */
163
164/* Flags set by signal handlers */
165static volatile sig_atomic_t got_SIGUSR2 = false;
166
167/* Comparison points for determining whether freeze_max_age is exceeded */
170
171/* Default freeze ages to use for autovacuum (varies by database) */
176
177/* Memory context for long-lived data */
179
180/* struct to keep track of databases in launcher */
188
189/* struct to keep track of databases in worker */
198
199/* struct to keep track of tables to vacuum and/or analyze, in 1st pass */
200typedef struct av_relation
201{
202 Oid ar_toastrelid; /* hash key - must be first */
205 AutoVacOpts ar_reloptions; /* copy of AutoVacOpts from the main table's
206 * reloptions, or NULL if none */
208
209/* struct to keep track of tables to vacuum and/or analyze, after rechecking */
221
222/*-------------
223 * This struct holds information about a single worker's whereabouts. We keep
224 * an array of these in shared memory, sized according to
225 * autovacuum_worker_slots.
226 *
227 * wi_links entry into free list or running list
228 * wi_dboid OID of the database this worker is supposed to work on
229 * wi_tableoid OID of the table currently being vacuumed, if any
230 * wi_sharedrel flag indicating whether table is marked relisshared
231 * wi_proc pointer to PGPROC of the running worker, NULL if not started
232 * wi_launchtime Time at which this worker was launched
233 * wi_dobalance Whether this worker should be included in balance calculations
234 *
235 * All fields are protected by AutovacuumLock, except for wi_tableoid and
236 * wi_sharedrel which are protected by AutovacuumScheduleLock (note these
237 * two fields are read-only for everyone except that worker itself).
238 *-------------
239 */
250
252
253/*
254 * Possible signals received by the launcher from remote processes. These are
255 * stored atomically in shared memory so that other processes can set them
256 * without locking.
257 */
258typedef enum
259{
260 AutoVacForkFailed, /* failed trying to start a worker */
261 AutoVacRebalance, /* rebalance the cost limits */
263
264#define AutoVacNumSignals (AutoVacRebalance + 1)
265
266/*
267 * Autovacuum workitem array, stored in AutoVacuumShmem->av_workItems. This
268 * list is mostly protected by AutovacuumLock, except that if an item is
269 * marked 'active' other processes must not modify the work-identifying
270 * members.
271 */
281
282#define NUM_WORKITEMS 256
283
284/*-------------
285 * The main autovacuum shmem struct. On shared memory we store this main
286 * struct and the array of WorkerInfo structs. This struct keeps:
287 *
288 * av_signal set by other processes to indicate various conditions
289 * av_launcherpid the PID of the autovacuum launcher
290 * av_freeWorkers the WorkerInfo freelist
291 * av_runningWorkers the WorkerInfo non-free queue
292 * av_startingWorker pointer to WorkerInfo currently being started (cleared by
293 * the worker itself as soon as it's up and running)
294 * av_workItems work item array
295 * av_nworkersForBalance the number of autovacuum workers to use when
296 * calculating the per worker cost limit
297 *
298 * This struct is protected by AutovacuumLock, except for av_signal and parts
299 * of the worker list (see above).
300 *-------------
301 */
312
314
315static void AutoVacuumShmemRequest(void *arg);
316static void AutoVacuumShmemInit(void *arg);
317
322
323/*
324 * the database list (of avl_dbase elements) in the launcher, and the context
325 * that contains it
326 */
329
330/*
331 * This struct is used by relation_needs_vacanalyze() to return the table's
332 * score (i.e., the maximum of the component scores) as well as the component
333 * scores themselves.
334 */
335typedef struct
336{
337 double max; /* maximum of all values below */
338 double xid; /* transaction ID component */
339 double mxid; /* multixact ID component */
340 double vac; /* vacuum component */
341 double vac_ins; /* vacuum insert component */
342 double anl; /* analyze component */
344
345/*
346 * This struct is used to track and sort the list of tables to process.
347 */
348typedef struct
349{
351 double score;
353
354/*
355 * Dummy pointer to persuade Valgrind that we've not leaked the array of
356 * avl_dbase structs. Make it global to ensure the compiler doesn't
357 * optimize it away.
358 */
359#ifdef USE_VALGRIND
362#endif
363
364/* Pointer to my own WorkerInfo, valid on each worker */
366
367static Oid do_start_worker(void);
368static void ProcessAutoVacLauncherInterrupts(void);
369pg_noreturn static void AutoVacLauncherShutdown(void);
370static void launcher_determine_sleep(bool canlaunch, bool recursing,
371 struct timeval *nap);
372static void launch_worker(TimestampTz now);
373static List *get_database_list(void);
374static void rebuild_database_list(Oid newdb);
375static int db_comparator(const void *a, const void *b);
377
378static void do_autovacuum(void);
379static void FreeWorkerInfo(int code, Datum arg);
380
387 int elevel,
388 bool *dovacuum, bool *doanalyze, bool *wraparound,
390
392 BufferAccessStrategy bstrategy);
396static void autovac_report_activity(autovac_table *tab);
398 const char *nspname, const char *relname);
400static bool av_worker_available(void);
401static void check_av_worker_gucs(void);
402
403
404
405/********************************************************************
406 * AUTOVACUUM LAUNCHER CODE
407 ********************************************************************/
408
409/*
410 * Main entry point for the autovacuum launcher process.
411 */
412void
414{
416
418
419 /* Release postmaster's working memory context */
421 {
424 }
425
427
429 (errmsg_internal("autovacuum launcher started")));
430
431 if (PostAuthDelay)
432 pg_usleep(PostAuthDelay * 1000000L);
433
435
436 /*
437 * Set up signal handlers. We operate on databases much like a regular
438 * backend, so we use the same signal handling. See equivalent code in
439 * tcop/postgres.c.
440 */
444 /* SIGQUIT handler was already set up by InitPostmasterChild */
445
446 InitializeTimeouts(); /* establishes SIGALRM handler */
447
453
454 /*
455 * Create a per-backend PGPROC struct in shared memory. We must do this
456 * before we can use LWLocks or access any shared memory.
457 */
458 InitProcess();
459
460 /* Early initialization */
461 BaseInit();
462
464
466
467 /*
468 * Create a memory context that we will do all our work in. We do this so
469 * that we can reset the context during error recovery and thereby avoid
470 * possible memory leaks.
471 */
473 "Autovacuum Launcher",
476
477 /*
478 * If an exception is encountered, processing resumes here.
479 *
480 * This code is a stripped down version of PostgresMain error recovery.
481 *
482 * Note that we use sigsetjmp(..., 1), so that the prevailing signal mask
483 * (to wit, BlockSig) will be restored when longjmp'ing to here. Thus,
484 * signals other than SIGQUIT will be blocked until we complete error
485 * recovery. It might seem that this policy makes the HOLD_INTERRUPTS()
486 * call redundant, but it is not since InterruptPending might be set
487 * already.
488 */
489 if (sigsetjmp(local_sigjmp_buf, 1) != 0)
490 {
491 /* since not using PG_TRY, must reset error stack by hand */
493
494 /* Prevents interrupts while cleaning up */
496
497 /* Forget any pending QueryCancel or timeout request */
499 QueryCancelPending = false; /* second to avoid race condition */
500
501 /* Report the error to the server log */
503
504 /* Abort the current transaction in order to recover */
506
507 /*
508 * Release any other resources, for the case where we were not in a
509 * transaction.
510 */
515 /* this is probably dead code, but let's be safe: */
518 AtEOXact_Buffers(false);
520 AtEOXact_Files(false);
521 AtEOXact_HashTables(false);
522
523 /*
524 * Now return to normal top-level context and clear ErrorContext for
525 * next time.
526 */
529
530 /* Flush any leaked data in the top-level context */
532
533 /* don't leave dangling pointers to freed memory */
536
537 /* Now we can allow interrupts again */
539
540 /* if in shutdown mode, no need for anything further; just go away */
543
544 /*
545 * Sleep at least 1 second after any error. We don't want to be
546 * filling the error logs as fast as we can.
547 */
548 pg_usleep(1000000L);
549 }
550
551 /* We can now handle ereport(ERROR) */
553
554 /* must unblock signals before calling rebuild_database_list */
556
557 /*
558 * Set always-secure search path. Launcher doesn't connect to a database,
559 * so this has no effect.
560 */
561 SetConfigOption("search_path", "", PGC_SUSET, PGC_S_OVERRIDE);
562
563 /*
564 * Force zero_damaged_pages OFF in the autovac process, even if it is set
565 * in postgresql.conf. We don't really want such a dangerous option being
566 * applied non-interactively.
567 */
568 SetConfigOption("zero_damaged_pages", "false", PGC_SUSET, PGC_S_OVERRIDE);
569
570 /*
571 * Force settable timeouts off to avoid letting these settings prevent
572 * regular maintenance from being executed.
573 */
574 SetConfigOption("statement_timeout", "0", PGC_SUSET, PGC_S_OVERRIDE);
575 SetConfigOption("transaction_timeout", "0", PGC_SUSET, PGC_S_OVERRIDE);
576 SetConfigOption("lock_timeout", "0", PGC_SUSET, PGC_S_OVERRIDE);
577 SetConfigOption("idle_in_transaction_session_timeout", "0",
579
580 /*
581 * Force default_transaction_isolation to READ COMMITTED. We don't want
582 * to pay the overhead of serializable mode, nor add any risk of causing
583 * deadlocks or delaying other transactions.
584 */
585 SetConfigOption("default_transaction_isolation", "read committed",
587
588 /*
589 * Even when system is configured to use a different fetch consistency,
590 * for autovac we always want fresh stats.
591 */
592 SetConfigOption("stats_fetch_consistency", "none", PGC_SUSET, PGC_S_OVERRIDE);
593
594 /*
595 * In emergency mode, just start a worker (unless shutdown was requested)
596 * and go away.
597 */
598 if (!AutoVacuumingActive())
599 {
602 proc_exit(0); /* done */
603 }
604
606
607 /*
608 * Create the initial database list. The invariant we want this list to
609 * keep is that it's ordered by decreasing next_worker. As soon as an
610 * entry is updated to a higher time, it will be moved to the front (which
611 * is correct because the only operation is to add autovacuum_naptime to
612 * the entry, and time always increases).
613 */
615
616 /* loop until shutdown request */
618 {
619 struct timeval nap;
621 bool can_launch;
622
623 /*
624 * This loop is a bit different from the normal use of WaitLatch,
625 * because we'd like to sleep before the first launch of a child
626 * process. So it's WaitLatch, then ResetLatch, then check for
627 * wakening conditions.
628 */
629
631
632 /*
633 * Wait until naptime expires or we get some type of signal (all the
634 * signal handlers will wake us by calling SetLatch).
635 */
638 (nap.tv_sec * 1000L) + (nap.tv_usec / 1000L),
640
642
644
645 /*
646 * a worker finished, or postmaster signaled failure to start a worker
647 */
648 if (got_SIGUSR2)
649 {
650 got_SIGUSR2 = false;
651
652 /* rebalance cost limits, if needed */
654 {
659 }
660
662 {
663 /*
664 * If the postmaster failed to start a new worker, we sleep
665 * for a little while and resend the signal. The new worker's
666 * state is still in memory, so this is sufficient. After
667 * that, we restart the main loop.
668 *
669 * XXX should we put a limit to the number of times we retry?
670 * I don't think it makes much sense, because a future start
671 * of a worker will continue to fail in the same way.
672 */
674 pg_usleep(1000000L); /* 1s */
676 continue;
677 }
678 }
679
680 /*
681 * There are some conditions that we need to check before trying to
682 * start a worker. First, we need to make sure that there is a worker
683 * slot available. Second, we need to make sure that no other worker
684 * failed while starting up.
685 */
686
689
691
693 {
694 int waittime;
696
697 /*
698 * We can't launch another worker when another one is still
699 * starting up (or failed while doing so), so just sleep for a bit
700 * more; that worker will wake us up again as soon as it's ready.
701 * We will only wait autovacuum_naptime seconds (up to a maximum
702 * of 60 seconds) for this to happen however. Note that failure
703 * to connect to a particular database is not a problem here,
704 * because the worker removes itself from the startingWorker
705 * pointer before trying to connect. Problems detected by the
706 * postmaster (like fork() failure) are also reported and handled
707 * differently. The only problems that may cause this code to
708 * fire are errors in the earlier sections of AutoVacWorkerMain,
709 * before the worker removes the WorkerInfo from the
710 * startingWorker pointer.
711 */
712 waittime = Min(autovacuum_naptime, 60) * 1000;
714 waittime))
715 {
718
719 /*
720 * No other process can put a worker in starting mode, so if
721 * startingWorker is still INVALID after exchanging our lock,
722 * we assume it's the same one we saw above (so we don't
723 * recheck the launch time).
724 */
726 {
728 worker->wi_dboid = InvalidOid;
729 worker->wi_tableoid = InvalidOid;
730 worker->wi_sharedrel = false;
731 worker->wi_proc = NULL;
732 worker->wi_launchtime = 0;
734 &worker->wi_links);
737 errmsg("autovacuum worker took too long to start; canceled"));
738 }
739 }
740 else
741 can_launch = false;
742 }
743 LWLockRelease(AutovacuumLock); /* either shared or exclusive */
744
745 /* if we can't do anything, just go back to sleep */
746 if (!can_launch)
747 continue;
748
749 /* We're OK to start a new worker */
750
752 {
753 /*
754 * Special case when the list is empty: start a worker right away.
755 * This covers the initial case, when no database is in pgstats
756 * (thus the list is empty). Note that the constraints in
757 * launcher_determine_sleep keep us from starting workers too
758 * quickly (at most once every autovacuum_naptime when the list is
759 * empty).
760 */
762 }
763 else
764 {
765 /*
766 * because rebuild_database_list constructs a list with most
767 * distant adl_next_worker first, we obtain our database from the
768 * tail of the list.
769 */
771
773
774 /*
775 * launch a worker if next_worker is right now or it is in the
776 * past
777 */
778 if (TimestampDifferenceExceeds(avdb->adl_next_worker,
779 current_time, 0))
781 }
782 }
783
785}
786
787/*
788 * Process any new interrupts.
789 */
790static void
792{
793 /* the normal shutdown case */
796
798 {
800
801 ConfigReloadPending = false;
803
804 /* shutdown requested in config file? */
805 if (!AutoVacuumingActive())
807
808 /*
809 * If autovacuum_max_workers changed, emit a WARNING if
810 * autovacuum_worker_slots < autovacuum_max_workers. If it didn't
811 * change, skip this to avoid too many repeated log messages.
812 */
815
816 /* rebuild the list in case the naptime changed */
818 }
819
820 /* Process barrier events */
823
824 /* Perform logging of memory contexts of this process */
827
828 /* Process sinval catchup interrupts that happened while sleeping */
830}
831
832/*
833 * Perform a normal exit from the autovac launcher.
834 */
835static void
837{
839 (errmsg_internal("autovacuum launcher shutting down")));
841
842 proc_exit(0); /* done */
843}
844
845/*
846 * Determine the time to sleep, based on the database list.
847 *
848 * The "canlaunch" parameter indicates whether we can start a worker right now,
849 * for example due to the workers being all busy. If this is false, we will
850 * cause a long sleep, which will be interrupted when a worker exits.
851 */
852static void
853launcher_determine_sleep(bool canlaunch, bool recursing, struct timeval *nap)
854{
855 /*
856 * We sleep until the next scheduled vacuum. We trust that when the
857 * database list was built, care was taken so that no entries have times
858 * in the past; if the first entry has too close a next_worker value, or a
859 * time in the past, we will sleep a small nominal time.
860 */
861 if (!canlaunch)
862 {
863 nap->tv_sec = autovacuum_naptime;
864 nap->tv_usec = 0;
865 }
866 else if (!dlist_is_empty(&DatabaseList))
867 {
871 long secs;
872 int usecs;
873
875
876 next_wakeup = avdb->adl_next_worker;
878
879 nap->tv_sec = secs;
880 nap->tv_usec = usecs;
881 }
882 else
883 {
884 /* list is empty, sleep for whole autovacuum_naptime seconds */
885 nap->tv_sec = autovacuum_naptime;
886 nap->tv_usec = 0;
887 }
888
889 /*
890 * If the result is exactly zero, it means a database had an entry with
891 * time in the past. Rebuild the list so that the databases are evenly
892 * distributed again, and recalculate the time to sleep. This can happen
893 * if there are more tables needing vacuum than workers, and they all take
894 * longer to vacuum than autovacuum_naptime.
895 *
896 * We only recurse once. rebuild_database_list should always return times
897 * in the future, but it seems best not to trust too much on that.
898 */
899 if (nap->tv_sec == 0 && nap->tv_usec == 0 && !recursing)
900 {
903 return;
904 }
905
906 /* The smallest time we'll allow the launcher to sleep. */
907 if (nap->tv_sec <= 0 && nap->tv_usec <= MIN_AUTOVAC_SLEEPTIME * 1000)
908 {
909 nap->tv_sec = 0;
910 nap->tv_usec = MIN_AUTOVAC_SLEEPTIME * 1000;
911 }
912
913 /*
914 * If the sleep time is too large, clamp it to an arbitrary maximum (plus
915 * any fractional seconds, for simplicity). This avoids an essentially
916 * infinite sleep in strange cases like the system clock going backwards a
917 * few years.
918 */
919 if (nap->tv_sec > MAX_AUTOVAC_SLEEPTIME)
920 nap->tv_sec = MAX_AUTOVAC_SLEEPTIME;
921}
922
923/*
924 * Build an updated DatabaseList. It must only contain databases that appear
925 * in pgstats, and must be sorted by next_worker from highest to lowest,
926 * distributed regularly across the next autovacuum_naptime interval.
927 *
928 * Receives the Oid of the database that made this list be generated (we call
929 * this the "new" database, because when the database was already present on
930 * the list, we expect that this function is not called at all). The
931 * preexisting list, if any, will be used to preserve the order of the
932 * databases in the autovacuum_naptime period. The new database is put at the
933 * end of the interval. The actual values are not saved, which should not be
934 * much of a problem.
935 */
936static void
938{
939 List *dblist;
940 ListCell *cell;
944 HASHCTL hctl;
945 int score;
946 int nelems;
947 HTAB *dbhash;
948 dlist_iter iter;
949
951 "Autovacuum database list",
954 "Autovacuum database list (tmp)",
957
958 /*
959 * Implementing this is not as simple as it sounds, because we need to put
960 * the new database at the end of the list; next the databases that were
961 * already on the list, and finally (at the tail of the list) all the
962 * other databases that are not on the existing list.
963 *
964 * To do this, we build an empty hash table of scored databases. We will
965 * start with the lowest score (zero) for the new database, then
966 * increasing scores for the databases in the existing list, in order, and
967 * lastly increasing scores for all databases gotten via
968 * get_database_list() that are not already on the hash.
969 *
970 * Then we will put all the hash elements into an array, sort the array by
971 * score, and finally put the array elements into the new doubly linked
972 * list.
973 */
974 hctl.keysize = sizeof(Oid);
975 hctl.entrysize = sizeof(avl_dbase);
976 hctl.hcxt = tmpcxt;
977 dbhash = hash_create("autovacuum db hash", 20, &hctl, /* magic number here
978 * FIXME */
980
981 /* start by inserting the new database */
982 score = 0;
983 if (OidIsValid(newdb))
984 {
985 avl_dbase *db;
986 PgStat_StatDBEntry *entry;
987
988 /* only consider this database if it has a pgstat entry */
990 if (entry != NULL)
991 {
992 /* we assume it isn't found because the hash was just created */
994
995 /* hash_search already filled in the key */
996 db->adl_score = score++;
997 /* next_worker is filled in later */
998 }
999 }
1000
1001 /* Now insert the databases from the existing list */
1003 {
1004 avl_dbase *avdb = dlist_container(avl_dbase, adl_node, iter.cur);
1005 avl_dbase *db;
1006 bool found;
1007 PgStat_StatDBEntry *entry;
1008
1009 /*
1010 * skip databases with no stat entries -- in particular, this gets rid
1011 * of dropped databases
1012 */
1013 entry = pgstat_fetch_stat_dbentry(avdb->adl_datid);
1014 if (entry == NULL)
1015 continue;
1016
1017 db = hash_search(dbhash, &(avdb->adl_datid), HASH_ENTER, &found);
1018
1019 if (!found)
1020 {
1021 /* hash_search already filled in the key */
1022 db->adl_score = score++;
1023 /* next_worker is filled in later */
1024 }
1025 }
1026
1027 /* finally, insert all qualifying databases not previously inserted */
1029 foreach(cell, dblist)
1030 {
1031 avw_dbase *avdb = lfirst(cell);
1032 avl_dbase *db;
1033 bool found;
1034 PgStat_StatDBEntry *entry;
1035
1036 /* only consider databases with a pgstat entry */
1037 entry = pgstat_fetch_stat_dbentry(avdb->adw_datid);
1038 if (entry == NULL)
1039 continue;
1040
1041 db = hash_search(dbhash, &(avdb->adw_datid), HASH_ENTER, &found);
1042 /* only update the score if the database was not already on the hash */
1043 if (!found)
1044 {
1045 /* hash_search already filled in the key */
1046 db->adl_score = score++;
1047 /* next_worker is filled in later */
1048 }
1049 }
1050 nelems = score;
1051
1052 /* from here on, the allocated memory belongs to the new list */
1055
1056 if (nelems > 0)
1057 {
1059 int millis_increment;
1061 avl_dbase *db;
1063 int i;
1064
1065 /* put all the hash elements into an array */
1066 dbary = palloc(nelems * sizeof(avl_dbase));
1067 /* keep Valgrind quiet */
1068#ifdef USE_VALGRIND
1070#endif
1071
1072 i = 0;
1074 while ((db = hash_seq_search(&seq)) != NULL)
1075 memcpy(&(dbary[i++]), db, sizeof(avl_dbase));
1076
1077 /* sort the array */
1078 qsort(dbary, nelems, sizeof(avl_dbase), db_comparator);
1079
1080 /*
1081 * Determine the time interval between databases in the schedule. If
1082 * we see that the configured naptime would take us to sleep times
1083 * lower than our min sleep time (which launcher_determine_sleep is
1084 * coded not to allow), silently use a larger naptime (but don't touch
1085 * the GUC variable).
1086 */
1087 millis_increment = 1000.0 * autovacuum_naptime / nelems;
1090
1092
1093 /*
1094 * move the elements from the array into the dlist, setting the
1095 * next_worker while walking the array
1096 */
1097 for (i = 0; i < nelems; i++)
1098 {
1099 db = &(dbary[i]);
1100
1104
1105 /* later elements should go closer to the head of the list */
1107 }
1108 }
1109
1110 /* all done, clean up memory */
1111 if (DatabaseListCxt != NULL)
1116}
1117
1118/* qsort comparator for avl_dbase, using adl_score */
1119static int
1120db_comparator(const void *a, const void *b)
1121{
1122 return pg_cmp_s32(((const avl_dbase *) a)->adl_score,
1123 ((const avl_dbase *) b)->adl_score);
1124}
1125
1126/*
1127 * do_start_worker
1128 *
1129 * Bare-bones procedure for starting an autovacuum worker from the launcher.
1130 * It determines what database to work on, sets up shared memory stuff and
1131 * signals postmaster to start the worker. It fails gracefully if invoked when
1132 * autovacuum_workers are already active.
1133 *
1134 * Return value is the OID of the database that the worker is going to process,
1135 * or InvalidOid if no worker was actually started.
1136 */
1137static Oid
1139{
1140 List *dblist;
1141 ListCell *cell;
1144 bool for_xid_wrap;
1145 bool for_multi_wrap;
1146 avw_dbase *avdb;
1148 bool skipit = false;
1149 Oid retval = InvalidOid;
1151 oldcxt;
1152
1153 /* return quickly when there are no free workers */
1155 if (!av_worker_available())
1156 {
1158 return InvalidOid;
1159 }
1161
1162 /*
1163 * Create and switch to a temporary context to avoid leaking the memory
1164 * allocated for the database list.
1165 */
1167 "Autovacuum start worker (tmp)",
1170
1171 /* Get a list of databases */
1173
1174 /*
1175 * Determine the oldest datfrozenxid/relfrozenxid that we will allow to
1176 * pass without forcing a vacuum. (This limit can be tightened for
1177 * particular tables, but not loosened.)
1178 */
1181 /* ensure it's a "normal" XID, else TransactionIdPrecedes misbehaves */
1182 /* this can cause the limit to go backwards by 3, but that's OK */
1185
1186 /* Also determine the oldest datminmxid we will consider. */
1191
1192 /*
1193 * Choose a database to connect to. We pick the database that was least
1194 * recently auto-vacuumed, or one that needs vacuuming to prevent Xid
1195 * wraparound-related data loss. If any db at risk of Xid wraparound is
1196 * found, we pick the one with oldest datfrozenxid, independently of
1197 * autovacuum times; similarly we pick the one with the oldest datminmxid
1198 * if any is in MultiXactId wraparound. Note that those in Xid wraparound
1199 * danger are given more priority than those in multi wraparound danger.
1200 *
1201 * Note that a database with no stats entry is not considered, except for
1202 * Xid wraparound purposes. The theory is that if no one has ever
1203 * connected to it since the stats were last initialized, it doesn't need
1204 * vacuuming.
1205 *
1206 * XXX This could be improved if we had more info about whether it needs
1207 * vacuuming before connecting to it. Perhaps look through the pgstats
1208 * data for the database's tables? One idea is to keep track of the
1209 * number of new and dead tuples per database in pgstats. However it
1210 * isn't clear how to construct a metric that measures that and not cause
1211 * starvation for less busy databases.
1212 */
1213 avdb = NULL;
1214 for_xid_wrap = false;
1215 for_multi_wrap = false;
1217 foreach(cell, dblist)
1218 {
1219 avw_dbase *tmp = lfirst(cell);
1220 dlist_iter iter;
1221
1222 /* Check to see if this one is at risk of wraparound */
1224 {
1225 if (avdb == NULL ||
1227 avdb->adw_frozenxid))
1228 avdb = tmp;
1229 for_xid_wrap = true;
1230 continue;
1231 }
1232 else if (for_xid_wrap)
1233 continue; /* ignore not-at-risk DBs */
1235 {
1236 if (avdb == NULL ||
1237 MultiXactIdPrecedes(tmp->adw_minmulti, avdb->adw_minmulti))
1238 avdb = tmp;
1239 for_multi_wrap = true;
1240 continue;
1241 }
1242 else if (for_multi_wrap)
1243 continue; /* ignore not-at-risk DBs */
1244
1245 /* Find pgstat entry if any */
1247
1248 /*
1249 * Skip a database with no pgstat entry; it means it hasn't seen any
1250 * activity.
1251 */
1252 if (!tmp->adw_entry)
1253 continue;
1254
1255 /*
1256 * Also, skip a database that appears on the database list as having
1257 * been processed recently (less than autovacuum_naptime seconds ago).
1258 * We do this so that we don't select a database which we just
1259 * selected, but that pgstat hasn't gotten around to updating the last
1260 * autovacuum time yet.
1261 */
1262 skipit = false;
1263
1265 {
1266 avl_dbase *dbp = dlist_container(avl_dbase, adl_node, iter.cur);
1267
1268 if (dbp->adl_datid == tmp->adw_datid)
1269 {
1270 /*
1271 * Skip this database if its next_worker value falls between
1272 * the current time and the current time plus naptime.
1273 */
1274 if (!TimestampDifferenceExceeds(dbp->adl_next_worker,
1275 current_time, 0) &&
1277 dbp->adl_next_worker,
1278 autovacuum_naptime * 1000))
1279 skipit = true;
1280
1281 break;
1282 }
1283 }
1284 if (skipit)
1285 continue;
1286
1287 /*
1288 * Remember the db with oldest autovac time. (If we are here, both
1289 * tmp->entry and db->entry must be non-null.)
1290 */
1291 if (avdb == NULL ||
1292 tmp->adw_entry->last_autovac_time < avdb->adw_entry->last_autovac_time)
1293 avdb = tmp;
1294 }
1295
1296 /* Found a database -- process it */
1297 if (avdb != NULL)
1298 {
1299 WorkerInfo worker;
1301
1303
1304 /*
1305 * Get a worker entry from the freelist. We checked above, so there
1306 * really should be a free slot.
1307 */
1309
1310 worker = dlist_container(WorkerInfoData, wi_links, wptr);
1311 worker->wi_dboid = avdb->adw_datid;
1312 worker->wi_proc = NULL;
1314
1316
1318
1320
1321 retval = avdb->adw_datid;
1322 }
1323 else if (skipit)
1324 {
1325 /*
1326 * If we skipped all databases on the list, rebuild it, because it
1327 * probably contains a dropped database.
1328 */
1330 }
1331
1334
1335 return retval;
1336}
1337
1338/*
1339 * launch_worker
1340 *
1341 * Wrapper for starting a worker from the launcher. Besides actually starting
1342 * it, update the database list to reflect the next time that another one will
1343 * need to be started on the selected database. The actual database choice is
1344 * left to do_start_worker.
1345 *
1346 * This routine is also expected to insert an entry into the database list if
1347 * the selected database was previously absent from the list.
1348 */
1349static void
1351{
1352 Oid dbid;
1353 dlist_iter iter;
1354
1355 dbid = do_start_worker();
1356 if (OidIsValid(dbid))
1357 {
1358 bool found = false;
1359
1360 /*
1361 * Walk the database list and update the corresponding entry. If the
1362 * database is not on the list, we'll recreate the list.
1363 */
1365 {
1366 avl_dbase *avdb = dlist_container(avl_dbase, adl_node, iter.cur);
1367
1368 if (avdb->adl_datid == dbid)
1369 {
1370 found = true;
1371
1372 /*
1373 * add autovacuum_naptime seconds to the current time, and use
1374 * that as the new "next_worker" field for this database.
1375 */
1376 avdb->adl_next_worker =
1378
1380 break;
1381 }
1382 }
1383
1384 /*
1385 * If the database was not present in the database list, we rebuild
1386 * the list. It's possible that the database does not get into the
1387 * list anyway, for example if it's a database that doesn't have a
1388 * pgstat entry, but this is not a problem because we don't want to
1389 * schedule workers regularly into those in any case.
1390 */
1391 if (!found)
1393 }
1394}
1395
1396/*
1397 * Called from postmaster to signal a failure to fork a process to become
1398 * worker. The postmaster should kill(SIGUSR2) the launcher shortly
1399 * after calling this function.
1400 */
1401void
1406
1407/* SIGUSR2: a worker is up and running, or just finished, or failed to fork */
1408static void
1414
1415
1416/********************************************************************
1417 * AUTOVACUUM WORKER CODE
1418 ********************************************************************/
1419
1420/*
1421 * Main entry point for autovacuum worker processes.
1422 */
1423void
1425{
1427 Oid dbid;
1428
1430
1431 /* Release postmaster's working memory context */
1433 {
1436 }
1437
1439
1441
1442 /*
1443 * Set up signal handlers. We operate on databases much like a regular
1444 * backend, so we use the same signal handling. See equivalent code in
1445 * tcop/postgres.c.
1446 */
1448
1449 /*
1450 * SIGINT is used to signal canceling the current table's vacuum; SIGTERM
1451 * means abort and exit cleanly, and SIGQUIT means abandon ship.
1452 */
1455 /* SIGQUIT handler was already set up by InitPostmasterChild */
1456
1457 InitializeTimeouts(); /* establishes SIGALRM handler */
1458
1464
1465 /*
1466 * Create a per-backend PGPROC struct in shared memory. We must do this
1467 * before we can use LWLocks or access any shared memory.
1468 */
1469 InitProcess();
1470
1471 /* Early initialization */
1472 BaseInit();
1473
1474 /*
1475 * If an exception is encountered, processing resumes here.
1476 *
1477 * Unlike most auxiliary processes, we don't attempt to continue
1478 * processing after an error; we just clean up and exit. The autovac
1479 * launcher is responsible for spawning another worker later.
1480 *
1481 * Note that we use sigsetjmp(..., 1), so that the prevailing signal mask
1482 * (to wit, BlockSig) will be restored when longjmp'ing to here. Thus,
1483 * signals other than SIGQUIT will be blocked until we exit. It might
1484 * seem that this policy makes the HOLD_INTERRUPTS() call redundant, but
1485 * it is not since InterruptPending might be set already.
1486 */
1487 if (sigsetjmp(local_sigjmp_buf, 1) != 0)
1488 {
1489 /* since not using PG_TRY, must reset error stack by hand */
1491
1492 /* Prevents interrupts while cleaning up */
1494
1495 /* Report the error to the server log */
1497
1498 /*
1499 * We can now go away. Note that because we called InitProcess, a
1500 * callback was registered to do ProcKill, which will clean up
1501 * necessary state.
1502 */
1503 proc_exit(0);
1504 }
1505
1506 /* We can now handle ereport(ERROR) */
1508
1510
1511 /*
1512 * Set always-secure search path, so malicious users can't redirect user
1513 * code (e.g. pg_index.indexprs). (That code runs in a
1514 * SECURITY_RESTRICTED_OPERATION sandbox, so malicious users could not
1515 * take control of the entire autovacuum worker in any case.)
1516 */
1517 SetConfigOption("search_path", "", PGC_SUSET, PGC_S_OVERRIDE);
1518
1519 /*
1520 * Force zero_damaged_pages OFF in the autovac process, even if it is set
1521 * in postgresql.conf. We don't really want such a dangerous option being
1522 * applied non-interactively.
1523 */
1524 SetConfigOption("zero_damaged_pages", "false", PGC_SUSET, PGC_S_OVERRIDE);
1525
1526 /*
1527 * Force settable timeouts off to avoid letting these settings prevent
1528 * regular maintenance from being executed.
1529 */
1530 SetConfigOption("statement_timeout", "0", PGC_SUSET, PGC_S_OVERRIDE);
1531 SetConfigOption("transaction_timeout", "0", PGC_SUSET, PGC_S_OVERRIDE);
1532 SetConfigOption("lock_timeout", "0", PGC_SUSET, PGC_S_OVERRIDE);
1533 SetConfigOption("idle_in_transaction_session_timeout", "0",
1535
1536 /*
1537 * Force default_transaction_isolation to READ COMMITTED. We don't want
1538 * to pay the overhead of serializable mode, nor add any risk of causing
1539 * deadlocks or delaying other transactions.
1540 */
1541 SetConfigOption("default_transaction_isolation", "read committed",
1543
1544 /*
1545 * Force synchronous replication off to allow regular maintenance even if
1546 * we are waiting for standbys to connect. This is important to ensure we
1547 * aren't blocked from performing anti-wraparound tasks.
1548 */
1550 SetConfigOption("synchronous_commit", "local",
1552
1553 /*
1554 * Even when system is configured to use a different fetch consistency,
1555 * for autovac we always want fresh stats.
1556 */
1557 SetConfigOption("stats_fetch_consistency", "none", PGC_SUSET, PGC_S_OVERRIDE);
1558
1559 /*
1560 * Get the info about the database we're going to work on.
1561 */
1563
1564 /*
1565 * beware of startingWorker being INVALID; this should normally not
1566 * happen, but if a worker fails after forking and before this, the
1567 * launcher might have decided to remove it from the queue and start
1568 * again.
1569 */
1571 {
1573 dbid = MyWorkerInfo->wi_dboid;
1575
1576 /* insert into the running list */
1579
1580 /*
1581 * remove from the "starting" pointer, so that the launcher can start
1582 * a new worker if required
1583 */
1586
1588
1589 /* wake up the launcher */
1592 }
1593 else
1594 {
1595 /* no worker entry for me, go away */
1596 elog(WARNING, "autovacuum worker started without a worker entry");
1597 dbid = InvalidOid;
1599 }
1600
1601 if (OidIsValid(dbid))
1602 {
1603 char dbname[NAMEDATALEN];
1604
1605 /*
1606 * Report autovac startup to the cumulative stats system. We
1607 * deliberately do this before InitPostgres, so that the
1608 * last_autovac_time will get updated even if the connection attempt
1609 * fails. This is to prevent autovac from getting "stuck" repeatedly
1610 * selecting an unopenable database, rather than making any progress
1611 * on stuff it can connect to.
1612 */
1614
1615 /*
1616 * Connect to the selected database, specifying no particular user,
1617 * and ignoring datallowconn. Collect the database's name for
1618 * display.
1619 *
1620 * Note: if we have selected a just-deleted database (due to using
1621 * stale stats info), we'll fail and exit here.
1622 */
1625 dbname);
1629 (errmsg_internal("autovacuum: processing database \"%s\"", dbname)));
1630
1631 if (PostAuthDelay)
1632 pg_usleep(PostAuthDelay * 1000000L);
1633
1634 /* And do an appropriate amount of work */
1637 do_autovacuum();
1638 }
1639
1640 /* All done, go away */
1641 proc_exit(0);
1642}
1643
1644/*
1645 * Return a WorkerInfo to the free list
1646 */
1647static void
1649{
1650 if (MyWorkerInfo != NULL)
1651 {
1653
1657 MyWorkerInfo->wi_sharedrel = false;
1663 /* not mine anymore */
1665
1666 /*
1667 * now that we're inactive, cause a rebalancing of the surviving
1668 * workers
1669 */
1672 }
1673}
1674
1675/*
1676 * Update vacuum cost-based delay-related parameters for autovacuum workers and
1677 * backends executing VACUUM or ANALYZE using the value of relevant GUCs and
1678 * global state. This must be called during setup for vacuum and after every
1679 * config reload to ensure up-to-date values.
1680 */
1681void
1683{
1684 if (MyWorkerInfo)
1685 {
1688 else if (autovacuum_vac_cost_delay >= 0)
1690 else
1691 /* fall back to VacuumCostDelay */
1693
1695 }
1696 else
1697 {
1698 /* Must be explicit VACUUM or ANALYZE or parallel autovacuum worker */
1701 }
1702
1703 /*
1704 * If configuration changes are allowed to impact VacuumCostActive, make
1705 * sure it is updated.
1706 */
1709 else if (vacuum_cost_delay > 0)
1710 VacuumCostActive = true;
1711 else
1712 {
1713 VacuumCostActive = false;
1715 }
1716
1717 /*
1718 * Since the cost logging requires a lock, avoid rendering the log message
1719 * in case we are using a message level where the log wouldn't be emitted.
1720 */
1722 {
1723 Oid dboid,
1724 tableoid;
1725
1727
1729 dboid = MyWorkerInfo->wi_dboid;
1730 tableoid = MyWorkerInfo->wi_tableoid;
1732
1733 elog(DEBUG2,
1734 "Autovacuum VacuumUpdateCosts(db=%u, rel=%u, dobalance=%s, cost_limit=%d, cost_delay=%g active=%s failsafe=%s)",
1735 dboid, tableoid, pg_atomic_unlocked_test_flag(&MyWorkerInfo->wi_dobalance) ? "no" : "yes",
1737 vacuum_cost_delay > 0 ? "yes" : "no",
1738 VacuumFailsafeActive ? "yes" : "no");
1739 }
1740}
1741
1742/*
1743 * Update vacuum_cost_limit with the correct value for an autovacuum worker,
1744 * given the value of other relevant cost limit parameters and the number of
1745 * workers across which the limit must be balanced. Autovacuum workers must
1746 * call this regularly in case av_nworkersForBalance has been updated by
1747 * another worker or by the autovacuum launcher. They must also call it after a
1748 * config reload.
1749 */
1750void
1752{
1753 if (!MyWorkerInfo)
1754 return;
1755
1756 /*
1757 * note: in cost_limit, zero also means use value from elsewhere, because
1758 * zero is not a valid value.
1759 */
1760
1763 else
1764 {
1766
1769 else
1771
1772 /* Only balance limit if no cost-related storage parameters specified */
1774 return;
1775
1777
1779
1780 /* There is at least 1 autovac worker (this worker) */
1781 if (nworkers_for_balance <= 0)
1782 elog(ERROR, "nworkers_for_balance must be > 0");
1783
1785 }
1786}
1787
1788/*
1789 * autovac_recalculate_workers_for_balance
1790 * Recalculate the number of workers to consider, given cost-related
1791 * storage parameters and the current number of active workers.
1792 *
1793 * Caller must hold the AutovacuumLock in at least shared mode to access
1794 * worker->wi_proc.
1795 */
1796static void
1823
1824/*
1825 * get_database_list
1826 * Return a list of all databases found in pg_database.
1827 *
1828 * The list and associated data is allocated in the caller's memory context,
1829 * which is in charge of ensuring that it's properly cleaned up afterwards.
1830 *
1831 * Note: this is the only function in which the autovacuum launcher uses a
1832 * transaction. Although we aren't attached to any particular database and
1833 * therefore can't access most catalogs, we do have enough infrastructure
1834 * to do a seqscan on pg_database.
1835 */
1836static List *
1838{
1839 List *dblist = NIL;
1840 Relation rel;
1841 TableScanDesc scan;
1842 HeapTuple tup;
1844
1845 /* This is the context that we will allocate our output data in */
1847
1848 /*
1849 * Start a transaction so we can access pg_database.
1850 */
1852
1854 scan = table_beginscan_catalog(rel, 0, NULL);
1855
1857 {
1859 avw_dbase *avdb;
1861
1862 /*
1863 * If database has partially been dropped, we can't, nor need to,
1864 * vacuum it.
1865 */
1867 {
1868 elog(DEBUG2,
1869 "autovacuum: skipping invalid database \"%s\"",
1870 NameStr(pgdatabase->datname));
1871 continue;
1872 }
1873
1874 /*
1875 * Allocate our results in the caller's context, not the
1876 * transaction's. We do this inside the loop, and restore the original
1877 * context at the end, so that leaky things like heap_getnext() are
1878 * not called in a potentially long-lived context.
1879 */
1881
1883
1884 avdb->adw_datid = pgdatabase->oid;
1885 avdb->adw_name = pstrdup(NameStr(pgdatabase->datname));
1886 avdb->adw_frozenxid = pgdatabase->datfrozenxid;
1887 avdb->adw_minmulti = pgdatabase->datminmxid;
1888 /* this gets set later: */
1889 avdb->adw_entry = NULL;
1890
1893 }
1894
1895 table_endscan(scan);
1897
1899
1900 /* Be sure to restore caller's memory context */
1902
1903 return dblist;
1904}
1905
1906/*
1907 * List comparator for TableToProcess. Note that this sorts the tables based
1908 * on their scores in descending order.
1909 */
1910static int
1912{
1915
1916 return (t2->score < t1->score) ? -1 : (t2->score > t1->score) ? 1 : 0;
1917}
1918
1919/*
1920 * Process a database table-by-table
1921 *
1922 * Note that CHECK_FOR_INTERRUPTS is supposed to be used in certain spots in
1923 * order not to ignore shutdown commands for too long.
1924 */
1925static void
1927{
1929 HeapTuple tuple;
1933 List *orphan_oids = NIL;
1934 HASHCTL ctl;
1936 ListCell *volatile cell;
1937 BufferAccessStrategy bstrategy;
1938 ScanKeyData key;
1941 bool did_vacuum = false;
1942 bool found_concurrent_worker = false;
1943 int i;
1944
1945 /*
1946 * StartTransactionCommand and CommitTransactionCommand will automatically
1947 * switch to other contexts. We need this one to keep the list of
1948 * relations to vacuum/analyze across transactions.
1949 */
1951 "Autovacuum worker",
1954
1955 /* Start a transaction so our commands have one to play into. */
1957
1958 /*
1959 * This injection point is put in a transaction block to work with a wait
1960 * that uses a condition variable.
1961 */
1962 INJECTION_POINT("autovacuum-worker-start", NULL);
1963
1964 /*
1965 * Compute the multixact age for which freezing is urgent. This is
1966 * normally autovacuum_multixact_freeze_max_age, but may be less if
1967 * multixact members are bloated.
1968 */
1970
1971 /*
1972 * Find the pg_database entry and select the default freeze ages. We use
1973 * zero in template and nonconnectable databases, else the system-wide
1974 * default.
1975 */
1977 if (!HeapTupleIsValid(tuple))
1978 elog(ERROR, "cache lookup failed for database %u", MyDatabaseId);
1980
1981 if (dbForm->datistemplate || !dbForm->datallowconn)
1982 {
1987 }
1988 else
1989 {
1994 }
1995
1996 ReleaseSysCache(tuple);
1997
1998 /* StartTransactionCommand changed elsewhere */
2000
2002
2003 /* create a copy so we can use it after closing pg_class */
2005
2006 /* create hash table for toast <-> main relid mapping */
2007 ctl.keysize = sizeof(Oid);
2008 ctl.entrysize = sizeof(av_relation);
2009
2010 table_toast_map = hash_create("TOAST to main relid map",
2011 100,
2012 &ctl,
2014
2015 /*
2016 * Scan pg_class to determine which tables to vacuum.
2017 *
2018 * We do this in two passes: on the first one we collect the list of plain
2019 * relations and materialized views, and on the second one we collect
2020 * TOAST tables. The reason for doing the second pass is that during it we
2021 * want to use the main relation's pg_class.reloptions entry if the TOAST
2022 * table does not have any, and we cannot obtain it unless we know
2023 * beforehand what's the main table OID.
2024 *
2025 * We need to check TOAST tables separately because in cases with short,
2026 * wide tables there might be proportionally much more activity in the
2027 * TOAST table than in its parent.
2028 */
2030
2031 /*
2032 * On the first pass, we collect main tables to vacuum, and also the main
2033 * table relid to TOAST relid mapping.
2034 */
2035 while ((tuple = heap_getnext(relScan, ForwardScanDirection)) != NULL)
2036 {
2039 Oid relid;
2040 bool dovacuum;
2041 bool doanalyze;
2042 bool wraparound;
2044
2045 if (classForm->relkind != RELKIND_RELATION &&
2046 classForm->relkind != RELKIND_MATVIEW)
2047 continue;
2048
2049 relid = classForm->oid;
2050
2051 /*
2052 * Check if it is a temp table (presumably, of some other backend's).
2053 * We cannot safely process other backends' temp tables.
2054 */
2055 if (classForm->relpersistence == RELPERSISTENCE_TEMP)
2056 {
2057 /*
2058 * We just ignore it if the owning backend is still active and
2059 * using the temporary schema. Also, for safety, ignore it if the
2060 * namespace doesn't exist or isn't a temp namespace after all.
2061 */
2063 {
2064 /*
2065 * The table seems to be orphaned -- although it might be that
2066 * the owning backend has already deleted it and exited; our
2067 * pg_class scan snapshot is not necessarily up-to-date
2068 * anymore, so we could be looking at a committed-dead entry.
2069 * Remember it so we can try to delete it later.
2070 */
2072 }
2073 continue;
2074 }
2075
2076 /* Fetch reloptions and the pgstat entry for this table */
2078
2079 /* Check if it needs vacuum or analyze */
2082 DEBUG3,
2084 &scores);
2085
2086 /* Relations that need work are added to tables_to_process */
2087 if (dovacuum || doanalyze)
2088 {
2090
2091 table->oid = relid;
2092 table->score = scores.max;
2094 }
2095
2096 /*
2097 * Remember TOAST associations for the second pass. Note: we must do
2098 * this whether or not the table is going to be vacuumed, because we
2099 * don't automatically vacuum toast tables along the parent table.
2100 */
2101 if (OidIsValid(classForm->reltoastrelid))
2102 {
2104 bool found;
2105
2107 &classForm->reltoastrelid,
2108 HASH_ENTER, &found);
2109
2110 if (!found)
2111 {
2112 /* hash_search already filled in the key */
2113 hentry->ar_relid = relid;
2114 hentry->ar_hasrelopts = false;
2115 if (relopts != NULL)
2116 {
2117 hentry->ar_hasrelopts = true;
2118 memcpy(&hentry->ar_reloptions, relopts,
2119 sizeof(AutoVacOpts));
2120 }
2121 }
2122 }
2123
2124 /* Release stuff to avoid per-relation leakage */
2125 if (relopts)
2126 pfree(relopts);
2127 }
2128
2130
2131 /* second pass: check TOAST tables */
2132 ScanKeyInit(&key,
2136
2138 while ((tuple = heap_getnext(relScan, ForwardScanDirection)) != NULL)
2139 {
2141 Oid relid;
2143 bool free_relopts = false;
2144 bool dovacuum;
2145 bool doanalyze;
2146 bool wraparound;
2148
2149 /*
2150 * We cannot safely process other backends' temp tables, so skip 'em.
2151 */
2152 if (classForm->relpersistence == RELPERSISTENCE_TEMP)
2153 continue;
2154
2155 relid = classForm->oid;
2156
2157 /*
2158 * fetch reloptions -- if this toast table does not have them, try the
2159 * main rel
2160 */
2162 if (relopts)
2163 free_relopts = true;
2164 else
2165 {
2167 bool found;
2168
2169 hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
2170 if (found && hentry->ar_hasrelopts)
2171 relopts = &hentry->ar_reloptions;
2172 }
2173
2176 DEBUG3,
2178 &scores);
2179
2180 /* ignore analyze for toast tables */
2181 if (dovacuum)
2182 {
2184
2185 table->oid = relid;
2186 table->score = scores.max;
2188 }
2189
2190 /* Release stuff to avoid leakage */
2191 if (free_relopts)
2192 pfree(relopts);
2193 }
2194
2197
2198 /*
2199 * Recheck orphan temporary tables, and if they still seem orphaned, drop
2200 * them. We'll eat a transaction per dropped table, which might seem
2201 * excessive, but we should only need to do anything as a result of a
2202 * previous backend crash, so this should not happen often enough to
2203 * justify "optimizing". Using separate transactions ensures that we
2204 * don't bloat the lock table if there are many temp tables to be dropped,
2205 * and it ensures that we don't lose work if a deletion attempt fails.
2206 */
2207 foreach(cell, orphan_oids)
2208 {
2209 Oid relid = lfirst_oid(cell);
2211 ObjectAddress object;
2212
2213 /*
2214 * Check for user-requested abort.
2215 */
2217
2218 /*
2219 * Try to lock the table. If we can't get the lock immediately,
2220 * somebody else is using (or dropping) the table, so it's not our
2221 * concern anymore. Having the lock prevents race conditions below.
2222 */
2224 continue;
2225
2226 /*
2227 * Re-fetch the pg_class tuple and re-check whether it still seems to
2228 * be an orphaned temp table. If it's not there or no longer the same
2229 * relation, ignore it.
2230 */
2232 if (!HeapTupleIsValid(tuple))
2233 {
2234 /* be sure to drop useless lock so we don't bloat lock table */
2236 continue;
2237 }
2239
2240 /*
2241 * Make all the same tests made in the loop above. In event of OID
2242 * counter wraparound, the pg_class entry we have now might be
2243 * completely unrelated to the one we saw before.
2244 */
2245 if (!((classForm->relkind == RELKIND_RELATION ||
2246 classForm->relkind == RELKIND_MATVIEW) &&
2247 classForm->relpersistence == RELPERSISTENCE_TEMP))
2248 {
2250 continue;
2251 }
2252
2254 {
2256 continue;
2257 }
2258
2259 /*
2260 * Try to lock the temp namespace, too. Even though we have lock on
2261 * the table itself, there's a risk of deadlock against an incoming
2262 * backend trying to clean out the temp namespace, in case this table
2263 * has dependencies (such as sequences) that the backend's
2264 * performDeletion call might visit in a different order. If we can
2265 * get AccessShareLock on the namespace, that's sufficient to ensure
2266 * we're not running concurrently with RemoveTempRelations. If we
2267 * can't, back off and let RemoveTempRelations do its thing.
2268 */
2270 classForm->relnamespace, 0,
2272 {
2274 continue;
2275 }
2276
2277 /* OK, let's delete it */
2278 ereport(LOG,
2279 (errmsg("autovacuum: dropping orphan temp table \"%s.%s.%s\"",
2281 get_namespace_name(classForm->relnamespace),
2282 NameStr(classForm->relname))));
2283
2284 /*
2285 * Deletion might involve TOAST table access, so ensure we have a
2286 * valid snapshot.
2287 */
2289
2290 object.classId = RelationRelationId;
2291 object.objectId = relid;
2292 object.objectSubId = 0;
2297
2298 /*
2299 * To commit the deletion, end current transaction and start a new
2300 * one. Note this also releases the locks we took.
2301 */
2305
2306 /* StartTransactionCommand changed current memory context */
2308 }
2309
2310 /*
2311 * In case list_sort() would modify the list even when all the scores are
2312 * 0.0, skip sorting if all the weight parameters are set to 0.0. This is
2313 * probably not necessary, but we want to ensure folks have a guaranteed
2314 * escape hatch from the scoring system.
2315 */
2316 if (autovacuum_freeze_score_weight != 0.0 ||
2322
2323 /*
2324 * Optionally, create a buffer access strategy object for VACUUM to use.
2325 * We use the same BufferAccessStrategy object for all tables VACUUMed by
2326 * this worker to prevent autovacuum from blowing out shared buffers.
2327 *
2328 * VacuumBufferUsageLimit being set to 0 results in
2329 * GetAccessStrategyWithSize returning NULL, effectively meaning we can
2330 * use up to all of shared buffers.
2331 *
2332 * If we later enter failsafe mode on any of the tables being vacuumed, we
2333 * will cease use of the BufferAccessStrategy only for that table.
2334 *
2335 * XXX should we consider adding code to adjust the size of this if
2336 * VacuumBufferUsageLimit changes?
2337 */
2339
2340 /*
2341 * create a memory context to act as fake PortalContext, so that the
2342 * contexts created in the vacuum code are cleaned up for each table.
2343 */
2345 "Autovacuum Portal",
2347
2348 /*
2349 * Perform operations on collected tables.
2350 */
2352 {
2353 Oid relid = table->oid;
2355 autovac_table *tab;
2356 bool isshared;
2357 bool skipit;
2358 dlist_iter iter;
2359
2361
2362 /*
2363 * Check for config changes before processing each collected table.
2364 */
2366 {
2367 ConfigReloadPending = false;
2369
2370 /*
2371 * You might be tempted to bail out if we see autovacuum is now
2372 * disabled. Must resist that temptation -- this might be a
2373 * for-wraparound emergency worker, in which case that would be
2374 * entirely inappropriate.
2375 */
2376 }
2377
2378 /*
2379 * Find out whether the table is shared or not. (It's slightly
2380 * annoying to fetch the syscache entry just for this, but in typical
2381 * cases it adds little cost because table_recheck_autovac would
2382 * refetch the entry anyway. We could buy that back by copying the
2383 * tuple here and passing it to table_recheck_autovac, but that
2384 * increases the odds of that function working with stale data.)
2385 */
2388 continue; /* somebody deleted the rel, forget it */
2391
2392 /*
2393 * Hold schedule lock from here until we've claimed the table. We
2394 * also need the AutovacuumLock to walk the worker array, but that one
2395 * can just be a shared lock.
2396 */
2399
2400 /*
2401 * Check whether the table is being vacuumed concurrently by another
2402 * worker.
2403 */
2404 skipit = false;
2406 {
2407 WorkerInfo worker = dlist_container(WorkerInfoData, wi_links, iter.cur);
2408
2409 /* ignore myself */
2410 if (worker == MyWorkerInfo)
2411 continue;
2412
2413 /* ignore workers in other databases (unless table is shared) */
2414 if (!worker->wi_sharedrel && worker->wi_dboid != MyDatabaseId)
2415 continue;
2416
2417 if (worker->wi_tableoid == relid)
2418 {
2419 skipit = true;
2421 break;
2422 }
2423 }
2425 if (skipit)
2426 {
2428 continue;
2429 }
2430
2431 /*
2432 * Store the table's OID in shared memory before releasing the
2433 * schedule lock, so that other workers don't try to vacuum it
2434 * concurrently. (We claim it here so as not to hold
2435 * AutovacuumScheduleLock while rechecking the stats.)
2436 */
2437 MyWorkerInfo->wi_tableoid = relid;
2438 MyWorkerInfo->wi_sharedrel = isshared;
2440
2441 /*
2442 * Check whether pgstat data still says we need to vacuum this table.
2443 * It could have changed if something else processed the table while
2444 * we weren't looking. This doesn't entirely close the race condition,
2445 * but it is very small.
2446 */
2450 if (tab == NULL)
2451 {
2452 /* someone else vacuumed the table, or it went away */
2455 MyWorkerInfo->wi_sharedrel = false;
2457 continue;
2458 }
2459
2460 /*
2461 * Save the cost-related storage parameter values in global variables
2462 * for reference when updating vacuum_cost_delay and vacuum_cost_limit
2463 * during vacuuming this table.
2464 */
2467
2468 /*
2469 * We only expect this worker to ever set the flag, so don't bother
2470 * checking the return value. We shouldn't have to retry.
2471 */
2472 if (tab->at_dobalance)
2474 else
2476
2480
2481 /*
2482 * We wait until this point to update cost delay and cost limit
2483 * values, even though we reloaded the configuration file above, so
2484 * that we can take into account the cost-related storage parameters.
2485 */
2487
2488
2489 /* clean up memory before each iteration */
2491
2492 /*
2493 * Save the relation name for a possible error message, to avoid a
2494 * catalog lookup in case of an error. If any of these return NULL,
2495 * then the relation has been dropped since last we checked; skip it.
2496 * Note: they must live in a long-lived memory context because we call
2497 * vacuum and analyze in different transactions.
2498 */
2499
2500 tab->at_relname = get_rel_name(tab->at_relid);
2503 if (!tab->at_relname || !tab->at_nspname || !tab->at_datname)
2504 goto deleted;
2505
2506 /*
2507 * We will abort vacuuming the current table if something errors out,
2508 * and continue with the next one in schedule; in particular, this
2509 * happens if we are interrupted with SIGINT.
2510 */
2511 PG_TRY();
2512 {
2513 /* Use PortalContext for any per-table allocations */
2515
2516 /* have at it */
2517 autovacuum_do_vac_analyze(tab, bstrategy);
2518
2519 /*
2520 * Clear a possible query-cancel signal, to avoid a late reaction
2521 * to an automatically-sent signal because of vacuuming the
2522 * current table (we're done with it, so it would make no sense to
2523 * cancel at this point.)
2524 */
2525 QueryCancelPending = false;
2526 }
2527 PG_CATCH();
2528 {
2529 /*
2530 * Abort the transaction, start a new one, and proceed with the
2531 * next table in our list.
2532 */
2534 if (tab->at_params.options & VACOPT_VACUUM)
2535 errcontext("automatic vacuum of table \"%s.%s.%s\"",
2536 tab->at_datname, tab->at_nspname, tab->at_relname);
2537 else
2538 errcontext("automatic analyze of table \"%s.%s.%s\"",
2539 tab->at_datname, tab->at_nspname, tab->at_relname);
2541
2542 /* this resets ProcGlobal->statusFlags[i] too */
2546
2547 /* restart our transaction for the following operations */
2550 }
2551 PG_END_TRY();
2552
2553 /* Make sure we're back in AutovacMemCxt */
2555
2556 did_vacuum = true;
2557
2558 /* ProcGlobal->statusFlags[i] are reset at the next end of xact */
2559
2560 /* be tidy */
2561deleted:
2562 if (tab->at_datname != NULL)
2563 pfree(tab->at_datname);
2564 if (tab->at_nspname != NULL)
2565 pfree(tab->at_nspname);
2566 if (tab->at_relname != NULL)
2567 pfree(tab->at_relname);
2568 pfree(tab);
2569
2570 /*
2571 * Remove my info from shared memory. We set wi_dobalance on the
2572 * assumption that we are more likely than not to vacuum a table with
2573 * no cost-related storage parameters next, so we want to claim our
2574 * share of I/O as soon as possible to avoid thrashing the global
2575 * balance.
2576 */
2579 MyWorkerInfo->wi_sharedrel = false;
2582 }
2583
2585
2586 /*
2587 * Perform additional work items, as requested by backends.
2588 */
2590 for (i = 0; i < NUM_WORKITEMS; i++)
2591 {
2593
2594 if (!workitem->avw_used)
2595 continue;
2596 if (workitem->avw_active)
2597 continue;
2598 if (workitem->avw_database != MyDatabaseId)
2599 continue;
2600
2601 /* claim this one, and release lock while performing it */
2602 workitem->avw_active = true;
2604
2607 if (ActiveSnapshotSet()) /* transaction could have aborted */
2609
2610 /*
2611 * Check for config changes before acquiring lock for further jobs.
2612 */
2615 {
2616 ConfigReloadPending = false;
2619 }
2620
2622
2623 /* and mark it done */
2624 workitem->avw_active = false;
2625 workitem->avw_used = false;
2626 }
2628
2629 /*
2630 * We leak table_toast_map here (among other things), but since we're
2631 * going away soon, it's not a problem normally. But when using Valgrind,
2632 * release some stuff to reduce complaints about leaked storage.
2633 */
2634#ifdef USE_VALGRIND
2637 if (bstrategy)
2638 pfree(bstrategy);
2639#endif
2640
2641 /* Run the rest in xact context, mainly to avoid Valgrind leak warnings */
2643
2644 /*
2645 * Update pg_database.datfrozenxid, and truncate pg_xact if possible. We
2646 * only need to do this once, not after each table.
2647 *
2648 * Even if we didn't vacuum anything, it may still be important to do
2649 * this, because one indirect effect of vac_update_datfrozenxid() is to
2650 * update TransamVariables->xidVacLimit. That might need to be done even
2651 * if we haven't vacuumed anything, because relations with older
2652 * relfrozenxid values or other databases with older datfrozenxid values
2653 * might have been dropped, allowing xidVacLimit to advance.
2654 *
2655 * However, it's also important not to do this blindly in all cases,
2656 * because when autovacuum=off this will restart the autovacuum launcher.
2657 * If we're not careful, an infinite loop can result, where workers find
2658 * no work to do and restart the launcher, which starts another worker in
2659 * the same database that finds no work to do. To prevent that, we skip
2660 * this if (1) we found no work to do and (2) we skipped at least one
2661 * table due to concurrent autovacuum activity. In that case, the other
2662 * worker has already done it, or will do so when it finishes.
2663 */
2666
2667 /* Finally close out the last transaction. */
2669}
2670
2671/*
2672 * Execute a previously registered work item.
2673 */
2674static void
2676{
2677 char *cur_datname = NULL;
2678 char *cur_nspname = NULL;
2679 char *cur_relname = NULL;
2680
2681 /*
2682 * Note we do not store table info in MyWorkerInfo, since this is not
2683 * vacuuming proper.
2684 */
2685
2686 /*
2687 * Save the relation name for a possible error message, to avoid a catalog
2688 * lookup in case of an error. If any of these return NULL, then the
2689 * relation has been dropped since last we checked; skip it.
2690 */
2692
2693 cur_relname = get_rel_name(workitem->avw_relation);
2696 if (!cur_relname || !cur_nspname || !cur_datname)
2697 goto deleted2;
2698
2700
2701 /* clean up memory before each work item */
2703
2704 /*
2705 * We will abort the current work item if something errors out, and
2706 * continue with the next one; in particular, this happens if we are
2707 * interrupted with SIGINT. Note that this means that the work item list
2708 * can be lossy.
2709 */
2710 PG_TRY();
2711 {
2712 /* Use PortalContext for any per-work-item allocations */
2714
2715 /*
2716 * Have at it. Functions called here are responsible for any required
2717 * user switch and sandbox.
2718 */
2719 switch (workitem->avw_type)
2720 {
2723 ObjectIdGetDatum(workitem->avw_relation),
2724 Int64GetDatum((int64) workitem->avw_blockNumber));
2725 break;
2726 default:
2727 elog(WARNING, "unrecognized work item found: type %d",
2728 workitem->avw_type);
2729 break;
2730 }
2731
2732 /*
2733 * Clear a possible query-cancel signal, to avoid a late reaction to
2734 * an automatically-sent signal because of vacuuming the current table
2735 * (we're done with it, so it would make no sense to cancel at this
2736 * point.)
2737 */
2738 QueryCancelPending = false;
2739 }
2740 PG_CATCH();
2741 {
2742 /*
2743 * Abort the transaction, start a new one, and proceed with the next
2744 * table in our list.
2745 */
2747 errcontext("processing work entry for relation \"%s.%s.%s\"",
2748 cur_datname, cur_nspname, cur_relname);
2750
2751 /* this resets ProcGlobal->statusFlags[i] too */
2755
2756 /* restart our transaction for the following operations */
2759 }
2760 PG_END_TRY();
2761
2762 /* Make sure we're back in AutovacMemCxt */
2764
2765 /* We intentionally do not set did_vacuum here */
2766
2767 /* be tidy */
2768deleted2:
2769 if (cur_datname)
2771 if (cur_nspname)
2773 if (cur_relname)
2774 pfree(cur_relname);
2775}
2776
2777/*
2778 * extract_autovac_opts
2779 *
2780 * Given a relation's pg_class tuple, return a palloc'd copy of the
2781 * AutoVacOpts portion of reloptions, if set; otherwise, return NULL.
2782 *
2783 * Note: callers do not have a relation lock on the table at this point,
2784 * so the table could have been dropped, and its catalog rows gone, after
2785 * we acquired the pg_class row. If pg_class had a TOAST table, this would
2786 * be a risk; fortunately, it doesn't.
2787 */
2788static AutoVacOpts *
2790{
2791 bytea *relopts;
2792 AutoVacOpts *av;
2793
2795 ((Form_pg_class) GETSTRUCT(tup))->relkind == RELKIND_MATVIEW ||
2797
2799 if (relopts == NULL)
2800 return NULL;
2801
2803 memcpy(av, &(((StdRdOptions *) relopts)->autovacuum), sizeof(AutoVacOpts));
2804 pfree(relopts);
2805
2806 return av;
2807}
2808
2809
2810/*
2811 * table_recheck_autovac
2812 *
2813 * Recheck whether a table still needs vacuum or analyze. Return value is a
2814 * valid autovac_table pointer if it does, NULL otherwise.
2815 *
2816 * Note that the returned autovac_table does not have the name fields set.
2817 */
2818static autovac_table *
2822{
2825 bool dovacuum;
2826 bool doanalyze;
2827 autovac_table *tab = NULL;
2828 bool wraparound;
2830 bool free_avopts = false;
2832
2833 /* fetch the relation's relcache entry */
2836 return NULL;
2838
2839 /*
2840 * Get the applicable reloptions. If it is a TOAST table, try to get the
2841 * main table reloptions if the toast table itself doesn't have.
2842 */
2844 if (avopts)
2845 free_avopts = true;
2846 else if (classForm->relkind == RELKIND_TOASTVALUE &&
2848 {
2850 bool found;
2851
2852 hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
2853 if (found && hentry->ar_hasrelopts)
2854 avopts = &hentry->ar_reloptions;
2855 }
2856
2859 DEBUG3,
2861 &scores);
2862
2863 /* OK, it needs something done */
2864 if (doanalyze || dovacuum)
2865 {
2866 int freeze_min_age;
2867 int freeze_table_age;
2868 int multixact_freeze_min_age;
2869 int multixact_freeze_table_age;
2870 int log_vacuum_min_duration;
2871 int log_analyze_min_duration;
2872
2873 /*
2874 * Calculate the vacuum cost parameters and the freeze ages. If there
2875 * are options set in pg_class.reloptions, use them; in the case of a
2876 * toast table, try the main table too. Otherwise use the GUC
2877 * defaults, autovacuum's own first and plain vacuum second.
2878 */
2879
2880 /* -1 in autovac setting means use log_autovacuum_min_duration */
2881 log_vacuum_min_duration = (avopts && avopts->log_vacuum_min_duration >= 0)
2882 ? avopts->log_vacuum_min_duration
2884
2885 /* -1 in autovac setting means use log_autoanalyze_min_duration */
2886 log_analyze_min_duration = (avopts && avopts->log_analyze_min_duration >= 0)
2887 ? avopts->log_analyze_min_duration
2889
2890 /* these do not have autovacuum-specific settings */
2891 freeze_min_age = (avopts && avopts->freeze_min_age >= 0)
2892 ? avopts->freeze_min_age
2894
2895 freeze_table_age = (avopts && avopts->freeze_table_age >= 0)
2896 ? avopts->freeze_table_age
2898
2899 multixact_freeze_min_age = (avopts &&
2900 avopts->multixact_freeze_min_age >= 0)
2901 ? avopts->multixact_freeze_min_age
2903
2904 multixact_freeze_table_age = (avopts &&
2905 avopts->multixact_freeze_table_age >= 0)
2906 ? avopts->multixact_freeze_table_age
2908
2910 tab->at_relid = relid;
2911
2912 /*
2913 * Select VACUUM options. Note we don't say VACOPT_PROCESS_TOAST, so
2914 * that vacuum() skips toast relations. Also note we tell vacuum() to
2915 * skip vac_update_datfrozenxid(); we'll do that separately.
2916 */
2917 tab->at_params.options =
2921 (doanalyze ? VACOPT_ANALYZE : 0) |
2923
2924 /*
2925 * index_cleanup and truncate are unspecified at first in autovacuum.
2926 * They will be filled in with usable values using their reloptions
2927 * (or reloption defaults) later.
2928 */
2931 tab->at_params.freeze_min_age = freeze_min_age;
2932 tab->at_params.freeze_table_age = freeze_table_age;
2933 tab->at_params.multixact_freeze_min_age = multixact_freeze_min_age;
2934 tab->at_params.multixact_freeze_table_age = multixact_freeze_table_age;
2936 tab->at_params.log_vacuum_min_duration = log_vacuum_min_duration;
2937 tab->at_params.log_analyze_min_duration = log_analyze_min_duration;
2939
2940 /* Determine the number of parallel vacuum workers to use */
2941 tab->at_params.nworkers = 0;
2942 if (avopts)
2943 {
2944 if (avopts->autovacuum_parallel_workers == 0)
2945 {
2946 /*
2947 * Disable parallel vacuum, if the reloption sets the parallel
2948 * degree as zero.
2949 */
2950 tab->at_params.nworkers = -1;
2951 }
2952 else if (avopts->autovacuum_parallel_workers > 0)
2953 tab->at_params.nworkers = avopts->autovacuum_parallel_workers;
2954
2955 /*
2956 * autovacuum_parallel_workers == -1 falls through, keep
2957 * nworkers=0
2958 */
2959 }
2960
2961 /*
2962 * Later, in vacuum_rel(), we check reloptions for any
2963 * vacuum_max_eager_freeze_failure_rate override.
2964 */
2967 avopts->vacuum_cost_limit : 0;
2969 avopts->vacuum_cost_delay : -1;
2970 tab->at_relname = NULL;
2971 tab->at_nspname = NULL;
2972 tab->at_datname = NULL;
2973
2974 /*
2975 * If any of the cost delay parameters has been set individually for
2976 * this table, disable the balancing algorithm.
2977 */
2978 tab->at_dobalance =
2979 !(avopts && (avopts->vacuum_cost_limit > 0 ||
2980 avopts->vacuum_cost_delay >= 0));
2981 }
2982
2983 if (free_avopts)
2984 pfree(avopts);
2986 return tab;
2987}
2988
2989/*
2990 * relation_needs_vacanalyze
2991 *
2992 * Check whether a relation needs to be vacuumed or analyzed; return each into
2993 * "dovacuum" and "doanalyze", respectively. Also return whether the vacuum is
2994 * being forced because of Xid or multixact wraparound.
2995 *
2996 * relopts is a pointer to the AutoVacOpts options (either for itself in the
2997 * case of a plain table, or for either itself or its parent table in the case
2998 * of a TOAST table), NULL if none.
2999 *
3000 * A table needs to be vacuumed if the number of dead tuples exceeds a
3001 * threshold. This threshold is calculated as
3002 *
3003 * threshold = vac_base_thresh + vac_scale_factor * reltuples
3004 * if (threshold > vac_max_thresh)
3005 * threshold = vac_max_thresh;
3006 *
3007 * For analyze, the analysis done is that the number of tuples inserted,
3008 * deleted and updated since the last analyze exceeds a threshold calculated
3009 * in the same fashion as above. Note that the cumulative stats system stores
3010 * the number of tuples (both live and dead) that there were as of the last
3011 * analyze. This is asymmetric to the VACUUM case.
3012 *
3013 * We also force vacuum if the table's relfrozenxid is more than freeze_max_age
3014 * transactions back, and if its relminmxid is more than
3015 * multixact_freeze_max_age multixacts back.
3016 *
3017 * A table whose autovacuum_enabled option is false is
3018 * automatically skipped (unless we have to vacuum it due to freeze_max_age).
3019 * Thus autovacuum can be disabled for specific tables. Also, when the cumulative
3020 * stats system does not have data about a table, it will be skipped.
3021 *
3022 * A table whose vac_base_thresh value is < 0 takes the base value from the
3023 * autovacuum_vacuum_threshold GUC variable. Similarly, a vac_scale_factor
3024 * value < 0 is substituted with the value of
3025 * autovacuum_vacuum_scale_factor GUC variable. Ditto for analyze.
3026 *
3027 * This function also returns scores that can be used to sort the list of
3028 * tables to process. The idea is to have autovacuum prioritize tables that
3029 * are furthest beyond their thresholds (e.g., a table nearing transaction ID
3030 * wraparound should be vacuumed first). This prioritization scheme is
3031 * certainly far from perfect; there are simply too many possibilities for any
3032 * scoring technique to work across all workloads, and the situation might
3033 * change significantly between the time we calculate the score and the time
3034 * that autovacuum processes it. However, we have attempted to develop
3035 * something that is expected to work for a large portion of workloads with
3036 * reasonable parameter settings.
3037 *
3038 * The autovacuum table score is calculated as the maximum of the ratios of
3039 * each of the table's relevant values to its threshold. For example, if the
3040 * number of inserted tuples is 100, and the insert threshold for the table is
3041 * 80, the insert score is 1.25. If all other scores are below that value, the
3042 * returned score will be 1.25. The other criteria considered for the score
3043 * are the table ages (both relfrozenxid and relminmxid) compared to the
3044 * corresponding freeze-max-age setting, the number of updated/deleted tuples
3045 * compared to the vacuum threshold, and the number of inserted/updated/deleted
3046 * tuples compared to the analyze threshold.
3047 *
3048 * One exception to the previous paragraph is for tables nearing wraparound,
3049 * i.e., those that have surpassed the effective failsafe ages. In that case,
3050 * the relfrozen/relminmxid-based score is scaled aggressively so that the
3051 * table has a decent chance of sorting to the front of the list.
3052 *
3053 * To adjust how strongly each component contributes to the score, the
3054 * following parameters can be adjusted from their default of 1.0 to anywhere
3055 * between 0.0 and 10.0 (inclusive). Setting all of these to 0.0 restores
3056 * pre-v19 prioritization behavior:
3057 *
3058 * autovacuum_freeze_score_weight
3059 * autovacuum_multixact_freeze_score_weight
3060 * autovacuum_vacuum_score_weight
3061 * autovacuum_vacuum_insert_score_weight
3062 * autovacuum_analyze_score_weight
3063 *
3064 * The autovacuum table score is returned in scores->max. The component scores
3065 * are also returned in the "scores" argument via the other members of the
3066 * AutoVacuumScores struct.
3067 */
3068static void
3073 int elevel,
3074 /* output params below */
3075 bool *dovacuum,
3076 bool *doanalyze,
3077 bool *wraparound,
3079{
3081 bool force_vacuum;
3082 bool av_enabled;
3083 bool may_free = false;
3084
3085 /* constants from reloptions or GUC variables */
3086 int vac_base_thresh,
3093
3094 /* thresholds calculated from above constants */
3097 anlthresh;
3098
3099 /* number of vacuum (resp. analyze) tuples at this time */
3101 instuples,
3102 anltuples;
3103
3104 /* freeze parameters */
3105 int freeze_max_age;
3106 int multixact_freeze_max_age;
3108 TransactionId relfrozenxid;
3109 MultiXactId relminmxid;
3115
3117 float4 reltuples = classForm->reltuples;
3118 int32 relpages = classForm->relpages;
3119 int32 relallfrozen = classForm->relallfrozen;
3120
3121 Assert(classForm != NULL);
3122 Assert(OidIsValid(relid));
3123
3124 memset(scores, 0, sizeof(AutoVacuumScores));
3125 *dovacuum = false;
3126 *doanalyze = false;
3127
3128 /*
3129 * Determine vacuum/analyze equation parameters. We have two possible
3130 * sources: the passed reloptions (which could be a main table or a toast
3131 * table), or the autovacuum GUC variables.
3132 */
3133
3134 /* -1 in autovac setting means use plain vacuum_scale_factor */
3135 vac_scale_factor = (relopts && relopts->vacuum_scale_factor >= 0)
3136 ? relopts->vacuum_scale_factor
3138
3139 vac_base_thresh = (relopts && relopts->vacuum_threshold >= 0)
3140 ? relopts->vacuum_threshold
3142
3143 /* -1 is used to disable max threshold */
3144 vac_max_thresh = (relopts && relopts->vacuum_max_threshold >= -1)
3145 ? relopts->vacuum_max_threshold
3147
3148 vac_ins_scale_factor = (relopts && relopts->vacuum_ins_scale_factor >= 0)
3149 ? relopts->vacuum_ins_scale_factor
3151
3152 /* -1 is used to disable insert vacuums */
3153 vac_ins_base_thresh = (relopts && relopts->vacuum_ins_threshold >= -1)
3154 ? relopts->vacuum_ins_threshold
3156
3157 anl_scale_factor = (relopts && relopts->analyze_scale_factor >= 0)
3158 ? relopts->analyze_scale_factor
3160
3161 anl_base_thresh = (relopts && relopts->analyze_threshold >= 0)
3162 ? relopts->analyze_threshold
3164
3165 freeze_max_age = (relopts && relopts->freeze_max_age >= 0)
3166 ? Min(relopts->freeze_max_age, autovacuum_freeze_max_age)
3168
3169 multixact_freeze_max_age = (relopts && relopts->multixact_freeze_max_age >= 0)
3170 ? Min(relopts->multixact_freeze_max_age, effective_multixact_freeze_max_age)
3172
3173 av_enabled = (relopts ? relopts->enabled : true);
3175
3176 relfrozenxid = classForm->relfrozenxid;
3177 relminmxid = classForm->relminmxid;
3178
3179 /* Force vacuum if table is at risk of wraparound */
3180 xidForceLimit = recentXid - freeze_max_age;
3183 force_vacuum = (TransactionIdIsNormal(relfrozenxid) &&
3184 TransactionIdPrecedes(relfrozenxid, xidForceLimit));
3185 if (!force_vacuum)
3186 {
3187 multiForceLimit = recentMulti - multixact_freeze_max_age;
3190 force_vacuum = MultiXactIdIsValid(relminmxid) &&
3192 }
3194
3195 /*
3196 * To calculate the (M)XID age portion of the score, divide the age by its
3197 * respective *_freeze_max_age parameter.
3198 */
3199 xid_age = TransactionIdIsNormal(relfrozenxid) ? recentXid - relfrozenxid : 0;
3200 mxid_age = MultiXactIdIsValid(relminmxid) ? recentMulti - relminmxid : 0;
3201
3202 scores->xid = (double) xid_age / freeze_max_age;
3203 scores->mxid = (double) mxid_age / multixact_freeze_max_age;
3204
3205 /*
3206 * To ensure tables are given increased priority once they begin
3207 * approaching wraparound, we scale the score aggressively if the ages
3208 * surpass vacuum_failsafe_age or vacuum_multixact_failsafe_age.
3209 *
3210 * As in vacuum_xid_failsafe_check(), the effective failsafe age is no
3211 * less than 105% the value of the respective *_freeze_max_age parameter.
3212 * Note that per-table settings could result in a low score even if the
3213 * table surpasses the failsafe settings. However, this is a strange
3214 * enough corner case that we don't bother trying to handle it.
3215 *
3216 * We further adjust the effective failsafe ages with the weight
3217 * parameters so that increasing them lowers the ages at which we begin
3218 * scaling aggressively.
3219 */
3224
3229
3231 scores->xid = pow(scores->xid, Max(1.0, (double) xid_age / 100000000));
3233 scores->mxid = pow(scores->mxid, Max(1.0, (double) mxid_age / 100000000));
3234
3237
3238 scores->max = Max(scores->xid, scores->mxid);
3239 if (force_vacuum)
3240 *dovacuum = true;
3241
3242 /*
3243 * If we found stats for the table, and autovacuum is currently enabled,
3244 * make a threshold-based decision whether to vacuum and/or analyze. If
3245 * autovacuum is currently disabled, we must be here for anti-wraparound
3246 * vacuuming only, so don't vacuum (or analyze) anything that's not being
3247 * forced.
3248 */
3250 relid, &may_free);
3251 if (!tabentry)
3252 return;
3253
3254 vactuples = tabentry->dead_tuples;
3255 instuples = tabentry->ins_since_vacuum;
3256 anltuples = tabentry->mod_since_analyze;
3257
3258 /* If the table hasn't yet been vacuumed, take reltuples as zero */
3259 if (reltuples < 0)
3260 reltuples = 0;
3261
3262 /*
3263 * If we have data for relallfrozen, calculate the unfrozen percentage of
3264 * the table to modify insert scale factor. This helps us decide whether
3265 * or not to vacuum an insert-heavy table based on the number of inserts
3266 * to the more "active" part of the table.
3267 */
3268 if (relpages > 0 && relallfrozen > 0)
3269 {
3270 /*
3271 * It could be the stats were updated manually and relallfrozen >
3272 * relpages. Clamp relallfrozen to relpages to avoid nonsensical
3273 * calculations.
3274 */
3275 relallfrozen = Min(relallfrozen, relpages);
3276 pcnt_unfrozen = 1 - ((float4) relallfrozen / relpages);
3277 }
3278
3282
3284 vac_ins_scale_factor * reltuples * pcnt_unfrozen;
3286
3287 /* Determine if this table needs vacuum, and update the score. */
3288 scores->vac = (double) vactuples / Max(vacthresh, 1);
3290 scores->max = Max(scores->max, scores->vac);
3292 *dovacuum = true;
3293
3294 if (vac_ins_base_thresh >= 0)
3295 {
3296 scores->vac_ins = (double) instuples / Max(vacinsthresh, 1);
3298 scores->max = Max(scores->max, scores->vac_ins);
3300 *dovacuum = true;
3301 }
3302
3303 /*
3304 * Determine if this table needs analyze, and update the score. Note that
3305 * we don't analyze TOAST tables and pg_statistic.
3306 */
3307 if (relid != StatisticRelationId &&
3308 classForm->relkind != RELKIND_TOASTVALUE)
3309 {
3310 scores->anl = (double) anltuples / Max(anlthresh, 1);
3312 scores->max = Max(scores->max, scores->anl);
3314 *doanalyze = true;
3315 }
3316
3317 if (vac_ins_base_thresh >= 0)
3318 elog(elevel, "%s: vac: %.0f (thresh %.0f, score %.2f), ins: %.0f (thresh %.0f, score %.2f), anl: %.0f (thresh %.0f, score %.2f), xid score: %.2f, mxid score: %.2f",
3319 NameStr(classForm->relname),
3320 vactuples, vacthresh, scores->vac,
3321 instuples, vacinsthresh, scores->vac_ins,
3322 anltuples, anlthresh, scores->anl,
3323 scores->xid, scores->mxid);
3324 else
3325 elog(elevel, "%s: vac: %.0f (thresh %.0f, score %.2f), ins: (disabled), anl: %.0f (thresh %.0f, score %.2f), xid score: %.2f, mxid score: %.2f",
3326 NameStr(classForm->relname),
3327 vactuples, vacthresh, scores->vac,
3328 anltuples, anlthresh, scores->anl,
3329 scores->xid, scores->mxid);
3330
3331 /* Avoid leaking pgstat entries until the end of autovacuum. */
3332 if (may_free)
3333 pfree(tabentry);
3334}
3335
3336/*
3337 * autovacuum_do_vac_analyze
3338 * Vacuum and/or analyze the specified table
3339 *
3340 * We expect the caller to have switched into a memory context that won't
3341 * disappear at transaction commit.
3342 */
3343static void
3345{
3347 VacuumRelation *rel;
3348 List *rel_list;
3351
3352 /* Let pgstat know what we're doing */
3354
3355 /* Create a context that vacuum() can use as cross-transaction storage */
3357 "Vacuum",
3359
3360 /* Set up one VacuumRelation target, identified by OID, for vacuum() */
3362 rangevar = makeRangeVar(tab->at_nspname, tab->at_relname, -1);
3364 rel_list = list_make1(rel);
3366
3367 vacuum(rel_list, &tab->at_params, bstrategy, vac_context, true);
3368
3370}
3371
3372/*
3373 * autovac_report_activity
3374 * Report to pgstat what autovacuum is doing
3375 *
3376 * We send a SQL string corresponding to what the user would see if the
3377 * equivalent command was to be issued manually.
3378 *
3379 * Note we assume that we are going to report the next command as soon as we're
3380 * done with the current one, and exit right after the last one, so we don't
3381 * bother to report "<IDLE>" or some such.
3382 */
3383static void
3385{
3386#define MAX_AUTOVAC_ACTIV_LEN (NAMEDATALEN * 2 + 56)
3388 int len;
3389
3390 /* Report the command and possible options */
3391 if (tab->at_params.options & VACOPT_VACUUM)
3393 "autovacuum: VACUUM%s",
3394 tab->at_params.options & VACOPT_ANALYZE ? " ANALYZE" : "");
3395 else
3397 "autovacuum: ANALYZE");
3398
3399 /*
3400 * Report the qualified name of the relation.
3401 */
3402 len = strlen(activity);
3403
3405 " %s.%s%s", tab->at_nspname, tab->at_relname,
3406 tab->at_params.is_wraparound ? " (to prevent wraparound)" : "");
3407
3408 /* Set statement_timestamp() to current time for pg_stat_activity */
3410
3412}
3413
3414/*
3415 * autovac_report_workitem
3416 * Report to pgstat that autovacuum is processing a work item
3417 */
3418static void
3420 const char *nspname, const char *relname)
3421{
3422 char activity[MAX_AUTOVAC_ACTIV_LEN + 12 + 2];
3423 char blk[12 + 2];
3424 int len;
3425
3426 switch (workitem->avw_type)
3427 {
3430 "autovacuum: BRIN summarize");
3431 break;
3432 }
3433
3434 /*
3435 * Report the qualified name of the relation, and the block number if any
3436 */
3437 len = strlen(activity);
3438
3439 if (BlockNumberIsValid(workitem->avw_blockNumber))
3440 snprintf(blk, sizeof(blk), " %u", workitem->avw_blockNumber);
3441 else
3442 blk[0] = '\0';
3443
3445 " %s.%s%s", nspname, relname, blk);
3446
3447 /* Set statement_timestamp() to current time for pg_stat_activity */
3449
3451}
3452
3453/*
3454 * AutoVacuumingActive
3455 * Check GUC vars and report whether the autovacuum process should be
3456 * running.
3457 */
3458bool
3460{
3462 return false;
3463 return true;
3464}
3465
3466/*
3467 * Request one work item to the next autovacuum run processing our database.
3468 * Return false if the request can't be recorded.
3469 */
3470bool
3472 BlockNumber blkno)
3473{
3474 int i;
3475 bool result = false;
3476
3478
3479 /*
3480 * Locate an unused work item and fill it with the given data.
3481 */
3482 for (i = 0; i < NUM_WORKITEMS; i++)
3483 {
3485
3486 if (workitem->avw_used)
3487 continue;
3488
3489 workitem->avw_used = true;
3490 workitem->avw_active = false;
3491 workitem->avw_type = type;
3492 workitem->avw_database = MyDatabaseId;
3493 workitem->avw_relation = relationId;
3494 workitem->avw_blockNumber = blkno;
3495 result = true;
3496
3497 /* done */
3498 break;
3499 }
3500
3502
3503 return result;
3504}
3505
3506/*
3507 * autovac_init
3508 * This is called at postmaster initialization.
3509 *
3510 * All we do here is annoy the user if he got it wrong.
3511 */
3512void
3514{
3516 return;
3517 else if (!pgstat_track_counts)
3519 (errmsg("autovacuum not started because of misconfiguration"),
3520 errhint("Enable the \"track_counts\" option.")));
3521 else
3523}
3524
3525/*
3526 * AutoVacuumShmemRequest
3527 * Register shared memory space needed for autovacuum
3528 */
3529static void
3531{
3532 Size size;
3533
3534 /*
3535 * Need the fixed struct and the array of WorkerInfoData.
3536 */
3537 size = sizeof(AutoVacuumShmemStruct);
3538 size = MAXALIGN(size);
3540 sizeof(WorkerInfoData)));
3541
3542 ShmemRequestStruct(.name = "AutoVacuum Data",
3543 .size = size,
3544 .ptr = (void **) &AutoVacuumShmem,
3545 );
3546}
3547
3548/*
3549 * AutoVacuumShmemInit
3550 * Initialize autovacuum-related shared memory
3551 */
3552static void
3554{
3555 WorkerInfo worker;
3556
3563
3564 worker = (WorkerInfo) ((char *) AutoVacuumShmem +
3566
3567 /* initialize the WorkerInfo free list */
3568 for (int i = 0; i < autovacuum_worker_slots; i++)
3569 {
3571 &worker[i].wi_links);
3572 pg_atomic_init_flag(&worker[i].wi_dobalance);
3573 }
3574
3576}
3577
3578/*
3579 * GUC check_hook for autovacuum_work_mem
3580 */
3581bool
3583{
3584 /*
3585 * -1 indicates fallback.
3586 *
3587 * If we haven't yet changed the boot_val default of -1, just let it be.
3588 * Autovacuum will look to maintenance_work_mem instead.
3589 */
3590 if (*newval == -1)
3591 return true;
3592
3593 /*
3594 * We clamp manually-set values to at least 64kB. Since
3595 * maintenance_work_mem is always set to at least this value, do the same
3596 * here.
3597 */
3598 if (*newval < 64)
3599 *newval = 64;
3600
3601 return true;
3602}
3603
3604/*
3605 * Returns whether there is a free autovacuum worker slot available.
3606 */
3607static bool
3620
3621/*
3622 * Emits a WARNING if autovacuum_worker_slots < autovacuum_max_workers.
3623 */
3624static void
3626{
3630 errmsg("\"autovacuum_max_workers\" (%d) should be less than or equal to \"autovacuum_worker_slots\" (%d)",
3632 errdetail("The server will only start up to \"autovacuum_worker_slots\" (%d) autovacuum workers at a given time.",
3634}
3635
3636/*
3637 * pg_stat_get_autovacuum_scores
3638 *
3639 * Returns current autovacuum scores for all relevant tables in the current
3640 * database.
3641 */
3642Datum
3644{
3646 Relation rel;
3647 TableScanDesc scan;
3648 HeapTuple tup;
3649 ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
3650
3651 InitMaterializedSRF(fcinfo, 0);
3652
3653 /* some prerequisite initialization */
3657
3658 /* scan pg_class */
3660 scan = table_beginscan_catalog(rel, 0, NULL);
3661 while ((tup = heap_getnext(scan, ForwardScanDirection)) != NULL)
3662 {
3665 bool dovacuum;
3666 bool doanalyze;
3667 bool wraparound;
3669 Datum vals[10];
3670 bool nulls[10] = {false};
3671
3672 /* skip ineligible entries */
3673 if (form->relkind != RELKIND_RELATION &&
3674 form->relkind != RELKIND_MATVIEW &&
3675 form->relkind != RELKIND_TOASTVALUE)
3676 continue;
3677 if (form->relpersistence == RELPERSISTENCE_TEMP)
3678 continue;
3679
3683 LOG_NEVER,
3685 &scores);
3686 if (avopts)
3687 pfree(avopts);
3688
3689 vals[0] = ObjectIdGetDatum(form->oid);
3690 vals[1] = Float8GetDatum(scores.max);
3691 vals[2] = Float8GetDatum(scores.xid);
3692 vals[3] = Float8GetDatum(scores.mxid);
3693 vals[4] = Float8GetDatum(scores.vac);
3694 vals[5] = Float8GetDatum(scores.vac_ins);
3695 vals[6] = Float8GetDatum(scores.anl);
3696 vals[7] = BoolGetDatum(dovacuum);
3697 vals[8] = BoolGetDatum(doanalyze);
3698 vals[9] = BoolGetDatum(wraparound);
3699
3700 tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, vals, nulls);
3701 }
3702 table_endscan(scan);
3704
3705 return (Datum) 0;
3706}
void pgaio_error_cleanup(void)
Definition aio.c:1175
static void pg_atomic_clear_flag(volatile pg_atomic_flag *ptr)
Definition atomics.h:205
static void pg_atomic_init_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition atomics.h:219
static bool pg_atomic_test_set_flag(volatile pg_atomic_flag *ptr)
Definition atomics.h:181
static bool pg_atomic_unlocked_test_flag(volatile pg_atomic_flag *ptr)
Definition atomics.h:194
static void pg_atomic_write_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition atomics.h:274
static uint32 pg_atomic_read_u32(volatile pg_atomic_uint32 *ptr)
Definition atomics.h:237
static void pg_atomic_init_flag(volatile pg_atomic_flag *ptr)
Definition atomics.h:168
static Oid do_start_worker(void)
static void launcher_determine_sleep(bool canlaunch, bool recursing, struct timeval *nap)
Definition autovacuum.c:853
int autovacuum_worker_slots
Definition autovacuum.c:124
void VacuumUpdateCosts(void)
void AutoVacLauncherMain(const void *startup_data, size_t startup_data_len)
Definition autovacuum.c:413
static volatile sig_atomic_t got_SIGUSR2
Definition autovacuum.c:165
static void avl_sigusr2_handler(SIGNAL_ARGS)
int autovacuum_multixact_freeze_max_age
Definition autovacuum.c:136
static bool av_worker_available(void)
static int default_multixact_freeze_table_age
Definition autovacuum.c:175
int autovacuum_naptime
Definition autovacuum.c:127
double autovacuum_vac_scale
Definition autovacuum.c:130
void AutoVacWorkerMain(const void *startup_data, size_t startup_data_len)
static void FreeWorkerInfo(int code, Datum arg)
Datum pg_stat_get_autovacuum_scores(PG_FUNCTION_ARGS)
int Log_autovacuum_min_duration
Definition autovacuum.c:145
int autovacuum_anl_thresh
Definition autovacuum.c:133
static TransactionId recentXid
Definition autovacuum.c:168
#define NUM_WORKITEMS
Definition autovacuum.c:282
static List * get_database_list(void)
bool check_autovacuum_work_mem(int *newval, void **extra, GucSource source)
static void autovac_report_activity(autovac_table *tab)
static void AutoVacuumShmemInit(void *arg)
static int default_multixact_freeze_min_age
Definition autovacuum.c:174
const ShmemCallbacks AutoVacuumShmemCallbacks
Definition autovacuum.c:318
static void do_autovacuum(void)
int autovacuum_vac_cost_limit
Definition autovacuum.c:143
static double av_storage_param_cost_delay
Definition autovacuum.c:161
bool AutoVacuumRequestWork(AutoVacuumWorkItemType type, Oid relationId, BlockNumber blkno)
bool AutoVacuumingActive(void)
static int TableToProcessComparator(const ListCell *a, const ListCell *b)
int autovacuum_max_workers
Definition autovacuum.c:125
int autovacuum_freeze_max_age
Definition autovacuum.c:135
static int db_comparator(const void *a, const void *b)
static int av_storage_param_cost_limit
Definition autovacuum.c:162
double autovacuum_vac_cost_delay
Definition autovacuum.c:142
static pg_noreturn void AutoVacLauncherShutdown(void)
Definition autovacuum.c:836
#define AutoVacNumSignals
Definition autovacuum.c:264
int autovacuum_vac_thresh
Definition autovacuum.c:128
AutoVacuumSignal
Definition autovacuum.c:259
@ AutoVacRebalance
Definition autovacuum.c:261
@ AutoVacForkFailed
Definition autovacuum.c:260
static void launch_worker(TimestampTz now)
static dlist_head DatabaseList
Definition autovacuum.c:327
static void rebuild_database_list(Oid newdb)
Definition autovacuum.c:937
static AutoVacuumShmemStruct * AutoVacuumShmem
Definition autovacuum.c:313
double autovacuum_analyze_score_weight
Definition autovacuum.c:141
int autovacuum_work_mem
Definition autovacuum.c:126
double autovacuum_vacuum_insert_score_weight
Definition autovacuum.c:140
static void check_av_worker_gucs(void)
static void relation_needs_vacanalyze(Oid relid, AutoVacOpts *relopts, Form_pg_class classForm, int effective_multixact_freeze_max_age, int elevel, bool *dovacuum, bool *doanalyze, bool *wraparound, AutoVacuumScores *scores)
double autovacuum_vacuum_score_weight
Definition autovacuum.c:139
#define MIN_AUTOVAC_SLEEPTIME
Definition autovacuum.c:149
#define MAX_AUTOVAC_ACTIV_LEN
double autovacuum_anl_scale
Definition autovacuum.c:134
int autovacuum_vac_ins_thresh
Definition autovacuum.c:131
#define MAX_AUTOVAC_SLEEPTIME
Definition autovacuum.c:150
static MemoryContext DatabaseListCxt
Definition autovacuum.c:328
void AutoVacWorkerFailed(void)
struct WorkerInfoData * WorkerInfo
Definition autovacuum.c:251
double autovacuum_multixact_freeze_score_weight
Definition autovacuum.c:138
bool autovacuum_start_daemon
Definition autovacuum.c:123
static void perform_work_item(AutoVacuumWorkItem *workitem)
static void AutoVacuumShmemRequest(void *arg)
double autovacuum_vac_ins_scale
Definition autovacuum.c:132
static MultiXactId recentMulti
Definition autovacuum.c:169
static int default_freeze_min_age
Definition autovacuum.c:172
static void autovac_recalculate_workers_for_balance(void)
int autovacuum_vac_max_thresh
Definition autovacuum.c:129
void AutoVacuumUpdateCostLimit(void)
static WorkerInfo MyWorkerInfo
Definition autovacuum.c:365
static void autovac_report_workitem(AutoVacuumWorkItem *workitem, const char *nspname, const char *relname)
void autovac_init(void)
static autovac_table * table_recheck_autovac(Oid relid, HTAB *table_toast_map, TupleDesc pg_class_desc, int effective_multixact_freeze_max_age)
static MemoryContext AutovacMemCxt
Definition autovacuum.c:178
double autovacuum_freeze_score_weight
Definition autovacuum.c:137
static void ProcessAutoVacLauncherInterrupts(void)
Definition autovacuum.c:791
static AutoVacOpts * extract_autovac_opts(HeapTuple tup, TupleDesc pg_class_desc)
static int default_freeze_table_age
Definition autovacuum.c:173
static void autovacuum_do_vac_analyze(autovac_table *tab, BufferAccessStrategy bstrategy)
int Log_autoanalyze_min_duration
Definition autovacuum.c:146
AutoVacuumWorkItemType
Definition autovacuum.h:24
@ AVW_BRINSummarizeRange
Definition autovacuum.h:25
sigset_t UnBlockSig
Definition pqsignal.c:22
void TimestampDifference(TimestampTz start_time, TimestampTz stop_time, long *secs, int *microsecs)
Definition timestamp.c:1715
bool TimestampDifferenceExceeds(TimestampTz start_time, TimestampTz stop_time, int msec)
Definition timestamp.c:1775
TimestampTz GetCurrentTimestamp(void)
Definition timestamp.c:1639
Datum now(PG_FUNCTION_ARGS)
Definition timestamp.c:1603
void pgstat_report_activity(BackendState state, const char *cmd_str)
@ STATE_RUNNING
uint32 BlockNumber
Definition block.h:31
static bool BlockNumberIsValid(BlockNumber blockNumber)
Definition block.h:71
Datum brin_summarize_range(PG_FUNCTION_ARGS)
Definition brin.c:1386
void AtEOXact_Buffers(bool isCommit)
Definition bufmgr.c:4199
void UnlockBuffers(void)
Definition bufmgr.c:5852
@ BAS_VACUUM
Definition bufmgr.h:40
#define NameStr(name)
Definition c.h:835
#define Min(x, y)
Definition c.h:1091
#define MAXALIGN(LEN)
Definition c.h:896
#define pg_noreturn
Definition c.h:190
#define Max(x, y)
Definition c.h:1085
#define SIGNAL_ARGS
Definition c.h:1450
#define Assert(condition)
Definition c.h:943
int64_t int64
Definition c.h:621
TransactionId MultiXactId
Definition c.h:746
int32_t int32
Definition c.h:620
uint32_t uint32
Definition c.h:624
float float4
Definition c.h:713
uint32 TransactionId
Definition c.h:736
#define OidIsValid(objectId)
Definition c.h:858
size_t Size
Definition c.h:689
uint32 result
memcpy(sums, checksumBaseOffsets, sizeof(checksumBaseOffsets))
int64 TimestampTz
Definition timestamp.h:39
bool database_is_invalid_form(Form_pg_database datform)
void performDeletion(const ObjectAddress *object, DropBehavior behavior, int flags)
Definition dependency.c:279
#define PERFORM_DELETION_SKIP_EXTENSIONS
Definition dependency.h:96
#define PERFORM_DELETION_QUIETLY
Definition dependency.h:94
#define PERFORM_DELETION_INTERNAL
Definition dependency.h:92
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition dynahash.c:889
void AtEOXact_HashTables(bool isCommit)
Definition dynahash.c:1864
HTAB * hash_create(const char *tabname, int64 nelem, const HASHCTL *info, int flags)
Definition dynahash.c:360
void hash_destroy(HTAB *hashp)
Definition dynahash.c:802
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition dynahash.c:1352
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition dynahash.c:1317
Datum arg
Definition elog.c:1322
void EmitErrorReport(void)
Definition elog.c:1882
ErrorContextCallback * error_context_stack
Definition elog.c:99
void FlushErrorState(void)
Definition elog.c:2062
bool message_level_is_interesting(int elevel)
Definition elog.c:284
int errcode(int sqlerrcode)
Definition elog.c:874
sigjmp_buf * PG_exception_stack
Definition elog.c:101
#define LOG
Definition elog.h:32
#define errcontext
Definition elog.h:200
int errhint(const char *fmt,...) pg_attribute_printf(1
#define DEBUG3
Definition elog.h:29
int errdetail(const char *fmt,...) pg_attribute_printf(1
int int errmsg_internal(const char *fmt,...) pg_attribute_printf(1
#define PG_TRY(...)
Definition elog.h:374
#define WARNING
Definition elog.h:37
#define DEBUG2
Definition elog.h:30
#define PG_END_TRY(...)
Definition elog.h:399
#define DEBUG1
Definition elog.h:31
#define ERROR
Definition elog.h:40
#define PG_CATCH(...)
Definition elog.h:384
#define elog(elevel,...)
Definition elog.h:228
#define LOG_NEVER
Definition elog.h:26
#define ereport(elevel,...)
Definition elog.h:152
void AtEOXact_Files(bool isCommit)
Definition fd.c:3214
#define palloc_object(type)
Definition fe_memutils.h:74
#define DirectFunctionCall2(func, arg1, arg2)
Definition fmgr.h:686
#define PG_FUNCTION_ARGS
Definition fmgr.h:193
BufferAccessStrategy GetAccessStrategyWithSize(BufferAccessStrategyType btype, int ring_size_kb)
Definition freelist.c:511
void InitMaterializedSRF(FunctionCallInfo fcinfo, uint32 flags)
Definition funcapi.c:76
volatile sig_atomic_t LogMemoryContextPending
Definition globals.c:41
volatile sig_atomic_t ProcSignalBarrierPending
Definition globals.c:40
int VacuumCostLimit
Definition globals.c:157
int MyProcPid
Definition globals.c:49
bool VacuumCostActive
Definition globals.c:161
int VacuumCostBalance
Definition globals.c:160
volatile sig_atomic_t QueryCancelPending
Definition globals.c:33
int VacuumBufferUsageLimit
Definition globals.c:152
struct Latch * MyLatch
Definition globals.c:65
double VacuumCostDelay
Definition globals.c:158
Oid MyDatabaseId
Definition globals.c:96
void ProcessConfigFile(GucContext context)
Definition guc-file.l:120
void SetConfigOption(const char *name, const char *value, GucContext context, GucSource source)
Definition guc.c:4234
#define newval
GucSource
Definition guc.h:112
@ PGC_S_OVERRIDE
Definition guc.h:123
@ PGC_SUSET
Definition guc.h:78
@ PGC_SIGHUP
Definition guc.h:75
HeapTuple heap_getnext(TableScanDesc sscan, ScanDirection direction)
Definition heapam.c:1435
void heap_freetuple(HeapTuple htup)
Definition heaptuple.c:1372
@ HASH_FIND
Definition hsearch.h:108
@ HASH_ENTER
Definition hsearch.h:109
#define HASH_CONTEXT
Definition hsearch.h:97
#define HASH_ELEM
Definition hsearch.h:90
#define HASH_BLOBS
Definition hsearch.h:92
#define HeapTupleIsValid(tuple)
Definition htup.h:78
static void * GETSTRUCT(const HeapTupleData *tuple)
#define dlist_foreach(iter, lhead)
Definition ilist.h:623
static void dlist_init(dlist_head *head)
Definition ilist.h:314
static void dlist_delete(dlist_node *node)
Definition ilist.h:405
static uint32 dclist_count(const dclist_head *head)
Definition ilist.h:932
#define dlist_reverse_foreach(iter, lhead)
Definition ilist.h:654
#define dlist_tail_element(type, membername, lhead)
Definition ilist.h:612
static void dlist_push_head(dlist_head *head, dlist_node *node)
Definition ilist.h:347
static bool dlist_is_empty(const dlist_head *head)
Definition ilist.h:336
static dlist_node * dclist_pop_head_node(dclist_head *head)
Definition ilist.h:789
static void dclist_push_head(dclist_head *head, dlist_node *node)
Definition ilist.h:693
static void dclist_init(dclist_head *head)
Definition ilist.h:671
static void dlist_move_head(dlist_head *head, dlist_node *node)
Definition ilist.h:467
#define DLIST_STATIC_INIT(name)
Definition ilist.h:281
#define dlist_container(type, membername, ptr)
Definition ilist.h:593
#define INJECTION_POINT(name, arg)
static int pg_cmp_s32(int32 a, int32 b)
Definition int.h:713
void SignalHandlerForShutdownRequest(SIGNAL_ARGS)
Definition interrupt.c:104
volatile sig_atomic_t ShutdownRequestPending
Definition interrupt.c:28
volatile sig_atomic_t ConfigReloadPending
Definition interrupt.c:27
void SignalHandlerForConfigReload(SIGNAL_ARGS)
Definition interrupt.c:61
void on_shmem_exit(pg_on_exit_callback function, Datum arg)
Definition ipc.c:372
void proc_exit(int code)
Definition ipc.c:105
int b
Definition isn.c:74
int a
Definition isn.c:73
int i
Definition isn.c:77
void SetLatch(Latch *latch)
Definition latch.c:290
void ResetLatch(Latch *latch)
Definition latch.c:374
int WaitLatch(Latch *latch, int wakeEvents, long timeout, uint32 wait_event_info)
Definition latch.c:172
List * lappend(List *list, void *datum)
Definition list.c:339
void list_sort(List *list, list_sort_comparator cmp)
Definition list.c:1674
List * lappend_oid(List *list, Oid datum)
Definition list.c:375
void list_free_deep(List *list)
Definition list.c:1560
bool ConditionalLockRelationOid(Oid relid, LOCKMODE lockmode)
Definition lmgr.c:151
void UnlockRelationOid(Oid relid, LOCKMODE lockmode)
Definition lmgr.c:229
bool ConditionalLockDatabaseObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition lmgr.c:1032
#define AccessExclusiveLock
Definition lockdefs.h:43
#define AccessShareLock
Definition lockdefs.h:36
char * get_rel_name(Oid relid)
Definition lsyscache.c:2148
char * get_database_name(Oid dbid)
Definition lsyscache.c:1312
Oid get_rel_namespace(Oid relid)
Definition lsyscache.c:2172
char * get_namespace_name(Oid nspid)
Definition lsyscache.c:3588
bool LWLockHeldByMe(LWLock *lock)
Definition lwlock.c:1885
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition lwlock.c:1150
void LWLockRelease(LWLock *lock)
Definition lwlock.c:1767
void LWLockReleaseAll(void)
Definition lwlock.c:1866
@ LW_SHARED
Definition lwlock.h:105
@ LW_EXCLUSIVE
Definition lwlock.h:104
VacuumRelation * makeVacuumRelation(RangeVar *relation, Oid oid, List *va_cols)
Definition makefuncs.c:907
RangeVar * makeRangeVar(char *schemaname, char *relname, int location)
Definition makefuncs.c:473
void MemoryContextReset(MemoryContext context)
Definition mcxt.c:403
MemoryContext TopTransactionContext
Definition mcxt.c:171
char * pstrdup(const char *in)
Definition mcxt.c:1781
void pfree(void *pointer)
Definition mcxt.c:1616
MemoryContext TopMemoryContext
Definition mcxt.c:166
void * palloc(Size size)
Definition mcxt.c:1387
MemoryContext CurrentMemoryContext
Definition mcxt.c:160
MemoryContext PostmasterContext
Definition mcxt.c:168
void ProcessLogMemoryContextInterrupt(void)
Definition mcxt.c:1340
void MemoryContextDelete(MemoryContext context)
Definition mcxt.c:472
MemoryContext PortalContext
Definition mcxt.c:175
#define AllocSetContextCreate
Definition memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition memutils.h:160
#define RESUME_INTERRUPTS()
Definition miscadmin.h:138
@ NormalProcessing
Definition miscadmin.h:490
@ InitProcessing
Definition miscadmin.h:489
#define GetProcessingMode()
Definition miscadmin.h:499
#define CHECK_FOR_INTERRUPTS()
Definition miscadmin.h:125
#define HOLD_INTERRUPTS()
Definition miscadmin.h:136
#define SetProcessingMode(mode)
Definition miscadmin.h:501
#define INIT_PG_OVERRIDE_ALLOW_CONNS
Definition miscadmin.h:518
bool MultiXactIdPrecedes(MultiXactId multi1, MultiXactId multi2)
Definition multixact.c:2865
int MultiXactMemberFreezeThreshold(void)
Definition multixact.c:2590
MultiXactId ReadNextMultiXactId(void)
Definition multixact.c:679
#define MultiXactIdIsValid(multi)
Definition multixact.h:29
#define FirstMultiXactId
Definition multixact.h:26
TempNamespaceStatus checkTempNamespaceStatus(Oid namespaceId)
Definition namespace.c:3801
@ TEMP_NAMESPACE_IDLE
Definition namespace.h:66
static char * errmsg
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:124
@ DROP_CASCADE
NameData relname
Definition pg_class.h:40
FormData_pg_class * Form_pg_class
Definition pg_class.h:160
#define NAMEDATALEN
const void size_t len
END_CATALOG_STRUCT typedef FormData_pg_database * Form_pg_database
#define lfirst(lc)
Definition pg_list.h:172
#define NIL
Definition pg_list.h:68
#define list_make1(x1)
Definition pg_list.h:244
#define foreach_ptr(type, var, lst)
Definition pg_list.h:501
#define lfirst_oid(lc)
Definition pg_list.h:174
static const struct lconv_member_info table[]
_stringlist * dblist
Definition pg_regress.c:99
static rewind_source * source
Definition pg_rewind.c:89
#define die(msg)
bool pgstat_track_counts
Definition pgstat.c:204
void pgstat_report_autovac(Oid dboid)
PgStat_StatDBEntry * pgstat_fetch_stat_dbentry(Oid dboid)
PgStat_StatTabEntry * pgstat_fetch_stat_tabentry_ext(bool shared, Oid reloid, bool *may_free)
void SendPostmasterSignal(PMSignalReason reason)
Definition pmsignal.c:164
@ PMSIGNAL_START_AUTOVAC_WORKER
Definition pmsignal.h:40
#define pqsignal
Definition port.h:547
#define snprintf
Definition port.h:260
#define qsort(a, b, c, d)
Definition port.h:495
int PostAuthDelay
Definition postgres.c:105
void FloatExceptionHandler(SIGNAL_ARGS)
Definition postgres.c:3070
void StatementCancelHandler(SIGNAL_ARGS)
Definition postgres.c:3053
static Datum Int64GetDatum(int64 X)
Definition postgres.h:413
static Datum BoolGetDatum(bool X)
Definition postgres.h:112
static Datum ObjectIdGetDatum(Oid X)
Definition postgres.h:252
uint64_t Datum
Definition postgres.h:70
static Datum Float8GetDatum(float8 X)
Definition postgres.h:502
static Datum CharGetDatum(char X)
Definition postgres.h:132
#define InvalidOid
unsigned int Oid
void BaseInit(void)
Definition postinit.c:616
void InitPostgres(const char *in_dbname, Oid dboid, const char *username, Oid useroid, uint32 flags, char *out_dbname)
Definition postinit.c:719
static int fb(int x)
void ProcessProcSignalBarrier(void)
Definition procsignal.c:503
void procsignal_sigusr1_handler(SIGNAL_ARGS)
Definition procsignal.c:688
void init_ps_display(const char *fixed_part)
Definition ps_status.c:286
static void set_ps_display(const char *activity)
Definition ps_status.h:40
tree ctl
Definition radixtree.h:1838
#define RelationGetDescr(relation)
Definition rel.h:542
bytea * extractRelOptions(HeapTuple tuple, TupleDesc tupdesc, amoptions_function amoptions)
void ReleaseAuxProcessResources(bool isCommit)
Definition resowner.c:1016
ResourceOwner AuxProcessResourceOwner
Definition resowner.c:176
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition scankey.c:76
@ ForwardScanDirection
Definition sdir.h:28
struct @10::@11 av[32]
Size add_size(Size s1, Size s2)
Definition shmem.c:1048
Size mul_size(Size s1, Size s2)
Definition shmem.c:1063
#define ShmemRequestStruct(...)
Definition shmem.h:176
void pg_usleep(long microsec)
Definition signal.c:53
void ProcessCatchupInterrupt(void)
Definition sinval.c:173
void AtEOXact_SMgr(void)
Definition smgr.c:1017
Snapshot GetTransactionSnapshot(void)
Definition snapmgr.c:272
void PushActiveSnapshot(Snapshot snapshot)
Definition snapmgr.c:682
bool ActiveSnapshotSet(void)
Definition snapmgr.c:812
void PopActiveSnapshot(void)
Definition snapmgr.c:775
PGPROC * MyProc
Definition proc.c:71
void InitProcess(void)
Definition proc.c:392
#define BTEqualStrategyNumber
Definition stratnum.h:31
char * dbname
Definition streamutil.c:49
dclist_head av_freeWorkers
Definition autovacuum.c:306
WorkerInfo av_startingWorker
Definition autovacuum.c:308
sig_atomic_t av_signal[AutoVacNumSignals]
Definition autovacuum.c:304
AutoVacuumWorkItem av_workItems[NUM_WORKITEMS]
Definition autovacuum.c:309
pg_atomic_uint32 av_nworkersForBalance
Definition autovacuum.c:310
dlist_head av_runningWorkers
Definition autovacuum.c:307
BlockNumber avw_blockNumber
Definition autovacuum.c:279
AutoVacuumWorkItemType avw_type
Definition autovacuum.c:274
Size keysize
Definition hsearch.h:69
Size entrysize
Definition hsearch.h:70
MemoryContext hcxt
Definition hsearch.h:81
Definition pg_list.h:54
Definition proc.h:179
TimestampTz last_autovac_time
Definition pgstat.h:378
ShmemRequestCallback request_fn
Definition shmem.h:133
int nworkers
Definition vacuum.h:250
int freeze_table_age
Definition vacuum.h:220
VacOptValue truncate
Definition vacuum.h:235
int freeze_min_age
Definition vacuum.h:219
int log_vacuum_min_duration
Definition vacuum.h:226
uint32 options
Definition vacuum.h:218
bool is_wraparound
Definition vacuum.h:225
int multixact_freeze_min_age
Definition vacuum.h:221
int multixact_freeze_table_age
Definition vacuum.h:223
Oid toast_parent
Definition vacuum.h:236
VacOptValue index_cleanup
Definition vacuum.h:234
int log_analyze_min_duration
Definition vacuum.h:230
double max_eager_freeze_failure_rate
Definition vacuum.h:243
TimestampTz wi_launchtime
Definition autovacuum.c:246
dlist_node wi_links
Definition autovacuum.c:242
PGPROC * wi_proc
Definition autovacuum.c:245
pg_atomic_flag wi_dobalance
Definition autovacuum.c:247
double at_storage_param_vac_cost_delay
Definition autovacuum.c:214
int at_storage_param_vac_cost_limit
Definition autovacuum.c:215
char * at_nspname
Definition autovacuum.c:218
char * at_relname
Definition autovacuum.c:217
char * at_datname
Definition autovacuum.c:219
VacuumParams at_params
Definition autovacuum.c:213
bool ar_hasrelopts
Definition autovacuum.c:204
AutoVacOpts ar_reloptions
Definition autovacuum.c:205
Oid ar_toastrelid
Definition autovacuum.c:202
Oid adl_datid
Definition autovacuum.c:183
dlist_node adl_node
Definition autovacuum.c:186
int adl_score
Definition autovacuum.c:185
TimestampTz adl_next_worker
Definition autovacuum.c:184
PgStat_StatDBEntry * adw_entry
Definition autovacuum.c:196
Oid adw_datid
Definition autovacuum.c:192
TransactionId adw_frozenxid
Definition autovacuum.c:194
char * adw_name
Definition autovacuum.c:193
MultiXactId adw_minmulti
Definition autovacuum.c:195
dlist_node * cur
Definition ilist.h:179
Definition c.h:776
void ReleaseSysCache(HeapTuple tuple)
Definition syscache.c:265
HeapTuple SearchSysCache1(SysCacheIdentifier cacheId, Datum key1)
Definition syscache.c:221
#define SearchSysCacheCopy1(cacheId, key1)
Definition syscache.h:91
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:1061
void disable_all_timeouts(bool keep_indicators)
Definition timeout.c:751
void InitializeTimeouts(void)
Definition timeout.c:470
static TransactionId ReadNextTransactionId(void)
Definition transam.h:375
#define FirstNormalTransactionId
Definition transam.h:34
#define TransactionIdIsNormal(xid)
Definition transam.h:42
static bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition transam.h:263
void FreeTupleDesc(TupleDesc tupdesc)
Definition tupdesc.c:560
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition tupdesc.c:242
void tuplestore_putvalues(Tuplestorestate *state, TupleDesc tdesc, const Datum *values, const bool *isnull)
Definition tuplestore.c:785
#define TimestampTzPlusMilliseconds(tz, ms)
Definition timestamp.h:85
void vacuum(List *relations, const VacuumParams *params, BufferAccessStrategy bstrategy, MemoryContext vac_context, bool isTopLevel)
Definition vacuum.c:494
int vacuum_freeze_min_age
Definition vacuum.c:76
double vacuum_max_eager_freeze_failure_rate
Definition vacuum.c:82
double vacuum_cost_delay
Definition vacuum.c:92
int vacuum_multixact_freeze_table_age
Definition vacuum.c:79
int vacuum_freeze_table_age
Definition vacuum.c:77
int vacuum_multixact_failsafe_age
Definition vacuum.c:81
int vacuum_multixact_freeze_min_age
Definition vacuum.c:78
void vac_update_datfrozenxid(void)
Definition vacuum.c:1609
bool VacuumFailsafeActive
Definition vacuum.c:111
int vacuum_cost_limit
Definition vacuum.c:93
int vacuum_failsafe_age
Definition vacuum.c:80
#define VACOPT_SKIP_LOCKED
Definition vacuum.h:184
#define VACOPT_VACUUM
Definition vacuum.h:179
#define VACOPT_SKIP_DATABASE_STATS
Definition vacuum.h:188
@ VACOPTVALUE_UNSPECIFIED
Definition vacuum.h:201
#define VACOPT_PROCESS_MAIN
Definition vacuum.h:185
#define VACOPT_ANALYZE
Definition vacuum.h:180
static void pgstat_report_wait_end(void)
Definition wait_event.h:83
const char * type
const char * name
#define WL_TIMEOUT
#define WL_EXIT_ON_PM_DEATH
#define WL_LATCH_SET
#define SIGCHLD
Definition win32_port.h:168
#define SIGHUP
Definition win32_port.h:158
#define SIGPIPE
Definition win32_port.h:163
#define kill(pid, sig)
Definition win32_port.h:490
#define SIGUSR1
Definition win32_port.h:170
#define SIGUSR2
Definition win32_port.h:171
int synchronous_commit
Definition xact.c:89
void StartTransactionCommand(void)
Definition xact.c:3109
void SetCurrentStatementStartTimestamp(void)
Definition xact.c:916
void CommitTransactionCommand(void)
Definition xact.c:3207
void AbortOutOfAnyTransaction(void)
Definition xact.c:4913
void AbortCurrentTransaction(void)
Definition xact.c:3501
@ SYNCHRONOUS_COMMIT_LOCAL_FLUSH
Definition xact.h:72
Datum xid_age(PG_FUNCTION_ARGS)
Definition xid.c:117
Datum mxid_age(PG_FUNCTION_ARGS)
Definition xid.c:133