PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
autovacuum.c File Reference
#include "postgres.h"
#include <signal.h>
#include <sys/types.h>
#include <sys/time.h>
#include <unistd.h>
#include "access/heapam.h"
#include "access/htup_details.h"
#include "access/multixact.h"
#include "access/reloptions.h"
#include "access/transam.h"
#include "access/xact.h"
#include "catalog/dependency.h"
#include "catalog/namespace.h"
#include "catalog/pg_database.h"
#include "commands/dbcommands.h"
#include "commands/vacuum.h"
#include "lib/ilist.h"
#include "libpq/pqsignal.h"
#include "miscadmin.h"
#include "pgstat.h"
#include "postmaster/autovacuum.h"
#include "postmaster/fork_process.h"
#include "postmaster/postmaster.h"
#include "storage/bufmgr.h"
#include "storage/ipc.h"
#include "storage/latch.h"
#include "storage/lmgr.h"
#include "storage/pmsignal.h"
#include "storage/proc.h"
#include "storage/procsignal.h"
#include "storage/sinvaladt.h"
#include "tcop/tcopprot.h"
#include "utils/fmgroids.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/ps_status.h"
#include "utils/rel.h"
#include "utils/snapmgr.h"
#include "utils/syscache.h"
#include "utils/timeout.h"
#include "utils/timestamp.h"
#include "utils/tqual.h"
Include dependency graph for autovacuum.c:

Go to the source code of this file.

Data Structures

struct  avl_dbase
 
struct  avw_dbase
 
struct  av_relation
 
struct  autovac_table
 
struct  WorkerInfoData
 
struct  AutoVacuumShmemStruct
 

Macros

#define STATS_READ_DELAY   1000
 
#define MIN_AUTOVAC_SLEEPTIME   100.0 /* milliseconds */
 
#define MAX_AUTOVAC_SLEEPTIME   300 /* seconds */
 
#define MAX_AUTOVAC_ACTIV_LEN   (NAMEDATALEN * 2 + 56)
 

Typedefs

typedef struct avl_dbase avl_dbase
 
typedef struct avw_dbase avw_dbase
 
typedef struct av_relation av_relation
 
typedef struct autovac_table autovac_table
 
typedef struct WorkerInfoData WorkerInfoData
 
typedef struct WorkerInfoDataWorkerInfo
 

Enumerations

enum  AutoVacuumSignal { AutoVacForkFailed, AutoVacRebalance, AutoVacNumSignals }
 

Functions

NON_EXEC_STATIC void AutoVacWorkerMain (int argc, char *argv[]) pg_attribute_noreturn()
 
NON_EXEC_STATIC void AutoVacLauncherMain (int argc, char *argv[]) pg_attribute_noreturn()
 
static Oid do_start_worker (void)
 
static void launcher_determine_sleep (bool canlaunch, bool recursing, struct timeval *nap)
 
static void launch_worker (TimestampTz now)
 
static Listget_database_list (void)
 
static void rebuild_database_list (Oid newdb)
 
static int db_comparator (const void *a, const void *b)
 
static void autovac_balance_cost (void)
 
static void do_autovacuum (void)
 
static void FreeWorkerInfo (int code, Datum arg)
 
static autovac_tabletable_recheck_autovac (Oid relid, HTAB *table_toast_map, TupleDesc pg_class_desc, int effective_multixact_freeze_max_age)
 
static void relation_needs_vacanalyze (Oid relid, AutoVacOpts *relopts, Form_pg_class classForm, PgStat_StatTabEntry *tabentry, int effective_multixact_freeze_max_age, bool *dovacuum, bool *doanalyze, bool *wraparound)
 
static void autovacuum_do_vac_analyze (autovac_table *tab, BufferAccessStrategy bstrategy)
 
static AutoVacOptsextract_autovac_opts (HeapTuple tup, TupleDesc pg_class_desc)
 
static PgStat_StatTabEntryget_pgstat_tabentry_relid (Oid relid, bool isshared, PgStat_StatDBEntry *shared, PgStat_StatDBEntry *dbentry)
 
static void autovac_report_activity (autovac_table *tab)
 
static void av_sighup_handler (SIGNAL_ARGS)
 
static void avl_sigusr2_handler (SIGNAL_ARGS)
 
static void avl_sigterm_handler (SIGNAL_ARGS)
 
static void autovac_refresh_stats (void)
 
int StartAutoVacLauncher (void)
 
void AutoVacWorkerFailed (void)
 
int StartAutoVacWorker (void)
 
void AutoVacuumUpdateDelay (void)
 
bool AutoVacuumingActive (void)
 
void autovac_init (void)
 
bool IsAutoVacuumLauncherProcess (void)
 
bool IsAutoVacuumWorkerProcess (void)
 
Size AutoVacuumShmemSize (void)
 
void AutoVacuumShmemInit (void)
 

Variables

bool autovacuum_start_daemon = false
 
int autovacuum_max_workers
 
int autovacuum_work_mem = -1
 
int autovacuum_naptime
 
int autovacuum_vac_thresh
 
double autovacuum_vac_scale
 
int autovacuum_anl_thresh
 
double autovacuum_anl_scale
 
int autovacuum_freeze_max_age
 
int autovacuum_multixact_freeze_max_age
 
int autovacuum_vac_cost_delay
 
int autovacuum_vac_cost_limit
 
int Log_autovacuum_min_duration = -1
 
static bool am_autovacuum_launcher = false
 
static bool am_autovacuum_worker = false
 
static volatile sig_atomic_t got_SIGHUP = false
 
static volatile sig_atomic_t got_SIGUSR2 = false
 
static volatile sig_atomic_t got_SIGTERM = false
 
static TransactionId recentXid
 
static MultiXactId recentMulti
 
static int default_freeze_min_age
 
static int default_freeze_table_age
 
static int default_multixact_freeze_min_age
 
static int default_multixact_freeze_table_age
 
static MemoryContext AutovacMemCxt
 
static AutoVacuumShmemStructAutoVacuumShmem
 
static dlist_head DatabaseList = DLIST_STATIC_INIT(DatabaseList)
 
static MemoryContext DatabaseListCxt = NULL
 
static WorkerInfo MyWorkerInfo = NULL
 
int AutovacuumLauncherPid = 0
 

Macro Definition Documentation

#define MAX_AUTOVAC_ACTIV_LEN   (NAMEDATALEN * 2 + 56)

Referenced by autovac_report_activity().

#define MAX_AUTOVAC_SLEEPTIME   300 /* seconds */

Definition at line 132 of file autovacuum.c.

Referenced by launcher_determine_sleep().

#define MIN_AUTOVAC_SLEEPTIME   100.0 /* milliseconds */

Definition at line 131 of file autovacuum.c.

Referenced by launcher_determine_sleep(), and rebuild_database_list().

#define STATS_READ_DELAY   1000

Definition at line 128 of file autovacuum.c.

Referenced by autovac_refresh_stats().

Typedef Documentation

Definition at line 232 of file autovacuum.c.

Enumeration Type Documentation

Enumerator
AutoVacForkFailed 
AutoVacRebalance 
AutoVacNumSignals 

Definition at line 239 of file autovacuum.c.

240 {
241  AutoVacForkFailed, /* failed trying to start a worker */
242  AutoVacRebalance, /* rebalance the cost limits */
243  AutoVacNumSignals /* must be last */
AutoVacuumSignal
Definition: autovacuum.c:239

Function Documentation

static void autovac_balance_cost ( void  )
static

Definition at line 1730 of file autovacuum.c.

References autovacuum_vac_cost_delay, autovacuum_vac_cost_limit, AutoVacuumShmemStruct::av_runningWorkers, dlist_iter::cur, DEBUG2, dlist_container, dlist_foreach, elog, Max, Min, NULL, PGPROC::pid, VacuumCostDelay, VacuumCostLimit, WorkerInfoData::wi_cost_delay, WorkerInfoData::wi_cost_limit, WorkerInfoData::wi_cost_limit_base, WorkerInfoData::wi_dboid, WorkerInfoData::wi_dobalance, WorkerInfoData::wi_proc, and WorkerInfoData::wi_tableoid.

Referenced by AutoVacLauncherMain(), and do_autovacuum().

1731 {
1732  /*
1733  * The idea here is that we ration out I/O equally. The amount of I/O
1734  * that a worker can consume is determined by cost_limit/cost_delay, so we
1735  * try to equalize those ratios rather than the raw limit settings.
1736  *
1737  * note: in cost_limit, zero also means use value from elsewhere, because
1738  * zero is not a valid value.
1739  */
1740  int vac_cost_limit = (autovacuum_vac_cost_limit > 0 ?
1742  int vac_cost_delay = (autovacuum_vac_cost_delay >= 0 ?
1744  double cost_total;
1745  double cost_avail;
1746  dlist_iter iter;
1747 
1748  /* not set? nothing to do */
1749  if (vac_cost_limit <= 0 || vac_cost_delay <= 0)
1750  return;
1751 
1752  /* calculate the total base cost limit of participating active workers */
1753  cost_total = 0.0;
1755  {
1756  WorkerInfo worker = dlist_container(WorkerInfoData, wi_links, iter.cur);
1757 
1758  if (worker->wi_proc != NULL &&
1759  worker->wi_dobalance &&
1760  worker->wi_cost_limit_base > 0 && worker->wi_cost_delay > 0)
1761  cost_total +=
1762  (double) worker->wi_cost_limit_base / worker->wi_cost_delay;
1763  }
1764 
1765  /* there are no cost limits -- nothing to do */
1766  if (cost_total <= 0)
1767  return;
1768 
1769  /*
1770  * Adjust cost limit of each active worker to balance the total of cost
1771  * limit to autovacuum_vacuum_cost_limit.
1772  */
1773  cost_avail = (double) vac_cost_limit / vac_cost_delay;
1775  {
1776  WorkerInfo worker = dlist_container(WorkerInfoData, wi_links, iter.cur);
1777 
1778  if (worker->wi_proc != NULL &&
1779  worker->wi_dobalance &&
1780  worker->wi_cost_limit_base > 0 && worker->wi_cost_delay > 0)
1781  {
1782  int limit = (int)
1783  (cost_avail * worker->wi_cost_limit_base / cost_total);
1784 
1785  /*
1786  * We put a lower bound of 1 on the cost_limit, to avoid division-
1787  * by-zero in the vacuum code. Also, in case of roundoff trouble
1788  * in these calculations, let's be sure we don't ever set
1789  * cost_limit to more than the base value.
1790  */
1791  worker->wi_cost_limit = Max(Min(limit,
1792  worker->wi_cost_limit_base),
1793  1);
1794  }
1795 
1796  if (worker->wi_proc != NULL)
1797  elog(DEBUG2, "autovac_balance_cost(pid=%u db=%u, rel=%u, dobalance=%s cost_limit=%d, cost_limit_base=%d, cost_delay=%d)",
1798  worker->wi_proc->pid, worker->wi_dboid, worker->wi_tableoid,
1799  worker->wi_dobalance ? "yes" : "no",
1800  worker->wi_cost_limit, worker->wi_cost_limit_base,
1801  worker->wi_cost_delay);
1802  }
1803 }
#define dlist_foreach(iter, lhead)
Definition: ilist.h:507
#define Min(x, y)
Definition: c.h:801
int autovacuum_vac_cost_limit
Definition: autovacuum.c:123
#define dlist_container(type, membername, ptr)
Definition: ilist.h:477
int VacuumCostLimit
Definition: globals.c:131
#define DEBUG2
Definition: elog.h:24
int autovacuum_vac_cost_delay
Definition: autovacuum.c:122
int wi_cost_limit_base
Definition: autovacuum.c:229
dlist_node * cur
Definition: ilist.h:161
int VacuumCostDelay
Definition: globals.c:132
#define Max(x, y)
Definition: c.h:795
#define NULL
Definition: c.h:226
static AutoVacuumShmemStruct * AutoVacuumShmem
Definition: autovacuum.c:270
PGPROC * wi_proc
Definition: autovacuum.c:223
#define elog
Definition: elog.h:219
dlist_head av_runningWorkers
Definition: autovacuum.c:266
int pid
Definition: proc.h:98
void autovac_init ( void  )

Definition at line 2969 of file autovacuum.c.

References autovacuum_start_daemon, ereport, errhint(), errmsg(), pgstat_track_counts, and WARNING.

Referenced by PostmasterMain().

2970 {
2972  ereport(WARNING,
2973  (errmsg("autovacuum not started because of misconfiguration"),
2974  errhint("Enable the \"track_counts\" option.")));
2975 }
int errhint(const char *fmt,...)
Definition: elog.c:987
bool autovacuum_start_daemon
Definition: autovacuum.c:111
bool pgstat_track_counts
Definition: pgstat.c:110
#define ereport(elevel, rest)
Definition: elog.h:122
#define WARNING
Definition: elog.h:40
int errmsg(const char *fmt,...)
Definition: elog.c:797
static void autovac_refresh_stats ( void  )
static

Definition at line 3065 of file autovacuum.c.

References GetCurrentTimestamp(), IsAutoVacuumLauncherProcess(), pgstat_clear_snapshot(), STATS_READ_DELAY, and TimestampDifferenceExceeds().

Referenced by do_start_worker(), rebuild_database_list(), and table_recheck_autovac().

3066 {
3068  {
3069  static TimestampTz last_read = 0;
3070  TimestampTz current_time;
3071 
3072  current_time = GetCurrentTimestamp();
3073 
3074  if (!TimestampDifferenceExceeds(last_read, current_time,
3076  return;
3077 
3078  last_read = current_time;
3079  }
3080 
3082 }
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1688
#define STATS_READ_DELAY
Definition: autovacuum.c:128
bool TimestampDifferenceExceeds(TimestampTz start_time, TimestampTz stop_time, int msec)
Definition: timestamp.c:1821
double TimestampTz
Definition: timestamp.h:51
bool IsAutoVacuumLauncherProcess(void)
Definition: autovacuum.c:2983
void pgstat_clear_snapshot(void)
Definition: pgstat.c:5045
static void autovac_report_activity ( autovac_table tab)
static

Definition at line 2919 of file autovacuum.c.

References autovac_table::at_nspname, autovac_table::at_params, autovac_table::at_relname, autovac_table::at_vacoptions, VacuumParams::is_wraparound, MAX_AUTOVAC_ACTIV_LEN, pgstat_report_activity(), SetCurrentStatementStartTimestamp(), snprintf(), STATE_RUNNING, VACOPT_ANALYZE, and VACOPT_VACUUM.

Referenced by autovacuum_do_vac_analyze().

2920 {
2921 #define MAX_AUTOVAC_ACTIV_LEN (NAMEDATALEN * 2 + 56)
2922  char activity[MAX_AUTOVAC_ACTIV_LEN];
2923  int len;
2924 
2925  /* Report the command and possible options */
2926  if (tab->at_vacoptions & VACOPT_VACUUM)
2927  snprintf(activity, MAX_AUTOVAC_ACTIV_LEN,
2928  "autovacuum: VACUUM%s",
2929  tab->at_vacoptions & VACOPT_ANALYZE ? " ANALYZE" : "");
2930  else
2931  snprintf(activity, MAX_AUTOVAC_ACTIV_LEN,
2932  "autovacuum: ANALYZE");
2933 
2934  /*
2935  * Report the qualified name of the relation.
2936  */
2937  len = strlen(activity);
2938 
2939  snprintf(activity + len, MAX_AUTOVAC_ACTIV_LEN - len,
2940  " %s.%s%s", tab->at_nspname, tab->at_relname,
2941  tab->at_params.is_wraparound ? " (to prevent wraparound)" : "");
2942 
2943  /* Set statement_timestamp() to current time for pg_stat_activity */
2945 
2947 }
void pgstat_report_activity(BackendState state, const char *cmd_str)
Definition: pgstat.c:2805
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
char * at_relname
Definition: autovacuum.c:195
bool is_wraparound
Definition: vacuum.h:144
char * at_nspname
Definition: autovacuum.c:196
#define MAX_AUTOVAC_ACTIV_LEN
VacuumParams at_params
Definition: autovacuum.c:190
void SetCurrentStatementStartTimestamp(void)
Definition: xact.c:739
NON_EXEC_STATIC void AutoVacLauncherMain ( int  argc,
char *  argv[] 
)

Definition at line 407 of file autovacuum.c.

References AbortCurrentTransaction(), avl_dbase::adl_next_worker, ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate(), am_autovacuum_launcher, autovac_balance_cost(), AutoVacForkFailed, AutoVacRebalance, autovacuum_naptime, AutoVacuumingActive(), AutoVacuumShmemStruct::av_freeWorkers, AutoVacuumShmemStruct::av_launcherpid, av_sighup_handler(), AutoVacuumShmemStruct::av_signal, AutoVacuumShmemStruct::av_startingWorker, avl_sigterm_handler(), avl_sigusr2_handler(), BaseInit(), disable_all_timeouts(), dlist_init(), dlist_is_empty(), dlist_push_head(), dlist_tail_element, do_start_worker(), elog, EmitErrorReport(), ereport, errmsg(), error_context_stack, FloatExceptionHandler(), FlushErrorState(), GetCurrentTimestamp(), got_SIGHUP, got_SIGTERM, got_SIGUSR2, HOLD_INTERRUPTS, init_ps_display(), InitializeTimeouts(), InitPostgres(), InitProcess(), InitProcessing, InvalidOid, launch_worker(), launcher_determine_sleep(), LOG, LW_EXCLUSIVE, LW_SHARED, LWLockAcquire(), LWLockRelease(), MemoryContextResetAndDeleteChildren, MemoryContextSwitchTo(), Min, MyLatch, MyProcPid, NormalProcessing, NULL, PG_exception_stack, PG_SETMASK, pg_usleep(), PGC_S_OVERRIDE, PGC_SIGHUP, PGC_SUSET, pgstat_clear_snapshot(), PMSIGNAL_START_AUTOVAC_WORKER, PostAuthDelay, pqsignal(), proc_exit(), ProcessCatchupInterrupt(), ProcessConfigFile(), procsignal_sigusr1_handler(), QueryCancelPending, quickdie(), rebuild_database_list(), ResetLatch(), RESUME_INTERRUPTS, SendPostmasterSignal(), SetConfigOption(), SetProcessingMode, SIG_DFL, SIG_IGN, SIGCHLD, SIGHUP, SIGPIPE, SIGQUIT, SIGUSR1, SIGUSR2, StatementCancelHandler(), TimestampDifferenceExceeds(), TopMemoryContext, UnBlockSig, WAIT_EVENT_AUTOVACUUM_MAIN, WaitLatch(), waittime, WARNING, WorkerInfoData::wi_dboid, WorkerInfoData::wi_launchtime, WorkerInfoData::wi_links, WorkerInfoData::wi_proc, WorkerInfoData::wi_sharedrel, WorkerInfoData::wi_tableoid, WL_LATCH_SET, WL_POSTMASTER_DEATH, and WL_TIMEOUT.

Referenced by StartAutoVacLauncher().

408 {
409  sigjmp_buf local_sigjmp_buf;
410 
411  am_autovacuum_launcher = true;
412 
413  /* Identify myself via ps */
414  init_ps_display("autovacuum launcher process", "", "", "");
415 
416  ereport(LOG,
417  (errmsg("autovacuum launcher started")));
418 
419  if (PostAuthDelay)
420  pg_usleep(PostAuthDelay * 1000000L);
421 
423 
424  /*
425  * Set up signal handlers. We operate on databases much like a regular
426  * backend, so we use the same signal handling. See equivalent code in
427  * tcop/postgres.c.
428  */
431  pqsignal(SIGTERM, avl_sigterm_handler);
432 
434  InitializeTimeouts(); /* establishes SIGALRM handler */
435 
441 
442  /* Early initialization */
443  BaseInit();
444 
445  /*
446  * Create a per-backend PGPROC struct in shared memory, except in the
447  * EXEC_BACKEND case where this was done in SubPostmasterMain. We must do
448  * this before we can use LWLocks (and in the EXEC_BACKEND case we already
449  * had to do some stuff with LWLocks).
450  */
451 #ifndef EXEC_BACKEND
452  InitProcess();
453 #endif
454 
456 
458 
459  /*
460  * Create a memory context that we will do all our work in. We do this so
461  * that we can reset the context during error recovery and thereby avoid
462  * possible memory leaks.
463  */
465  "Autovacuum Launcher",
468 
469  /*
470  * If an exception is encountered, processing resumes here.
471  *
472  * This code is a stripped down version of PostgresMain error recovery.
473  */
474  if (sigsetjmp(local_sigjmp_buf, 1) != 0)
475  {
476  /* since not using PG_TRY, must reset error stack by hand */
478 
479  /* Prevents interrupts while cleaning up */
480  HOLD_INTERRUPTS();
481 
482  /* Forget any pending QueryCancel or timeout request */
483  disable_all_timeouts(false);
484  QueryCancelPending = false; /* second to avoid race condition */
485 
486  /* Report the error to the server log */
487  EmitErrorReport();
488 
489  /* Abort the current transaction in order to recover */
491 
492  /*
493  * Now return to normal top-level context and clear ErrorContext for
494  * next time.
495  */
497  FlushErrorState();
498 
499  /* Flush any leaked data in the top-level context */
501 
502  /* don't leave dangling pointers to freed memory */
505 
506  /*
507  * Make sure pgstat also considers our stat data as gone. Note: we
508  * mustn't use autovac_refresh_stats here.
509  */
511 
512  /* Now we can allow interrupts again */
514 
515  /* if in shutdown mode, no need for anything further; just go away */
516  if (got_SIGTERM)
517  goto shutdown;
518 
519  /*
520  * Sleep at least 1 second after any error. We don't want to be
521  * filling the error logs as fast as we can.
522  */
523  pg_usleep(1000000L);
524  }
525 
526  /* We can now handle ereport(ERROR) */
527  PG_exception_stack = &local_sigjmp_buf;
528 
529  /* must unblock signals before calling rebuild_database_list */
531 
532  /*
533  * Force zero_damaged_pages OFF in the autovac process, even if it is set
534  * in postgresql.conf. We don't really want such a dangerous option being
535  * applied non-interactively.
536  */
537  SetConfigOption("zero_damaged_pages", "false", PGC_SUSET, PGC_S_OVERRIDE);
538 
539  /*
540  * Force settable timeouts off to avoid letting these settings prevent
541  * regular maintenance from being executed.
542  */
543  SetConfigOption("statement_timeout", "0", PGC_SUSET, PGC_S_OVERRIDE);
544  SetConfigOption("lock_timeout", "0", PGC_SUSET, PGC_S_OVERRIDE);
545  SetConfigOption("idle_in_transaction_session_timeout", "0",
547 
548  /*
549  * Force default_transaction_isolation to READ COMMITTED. We don't want
550  * to pay the overhead of serializable mode, nor add any risk of causing
551  * deadlocks or delaying other transactions.
552  */
553  SetConfigOption("default_transaction_isolation", "read committed",
555 
556  /*
557  * In emergency mode, just start a worker (unless shutdown was requested)
558  * and go away.
559  */
560  if (!AutoVacuumingActive())
561  {
562  if (!got_SIGTERM)
563  do_start_worker();
564  proc_exit(0); /* done */
565  }
566 
568 
569  /*
570  * Create the initial database list. The invariant we want this list to
571  * keep is that it's ordered by decreasing next_time. As soon as an entry
572  * is updated to a higher time, it will be moved to the front (which is
573  * correct because the only operation is to add autovacuum_naptime to the
574  * entry, and time always increases).
575  */
577 
578  /* loop until shutdown request */
579  while (!got_SIGTERM)
580  {
581  struct timeval nap;
582  TimestampTz current_time = 0;
583  bool can_launch;
584  int rc;
585 
586  /*
587  * This loop is a bit different from the normal use of WaitLatch,
588  * because we'd like to sleep before the first launch of a child
589  * process. So it's WaitLatch, then ResetLatch, then check for
590  * wakening conditions.
591  */
592 
594  false, &nap);
595 
596  /*
597  * Wait until naptime expires or we get some type of signal (all the
598  * signal handlers will wake us by calling SetLatch).
599  */
600  rc = WaitLatch(MyLatch,
602  (nap.tv_sec * 1000L) + (nap.tv_usec / 1000L),
604 
606 
607  /* Process sinval catchup interrupts that happened while sleeping */
609 
610  /*
611  * Emergency bailout if postmaster has died. This is to avoid the
612  * necessity for manual cleanup of all postmaster children.
613  */
614  if (rc & WL_POSTMASTER_DEATH)
615  proc_exit(1);
616 
617  /* the normal shutdown case */
618  if (got_SIGTERM)
619  break;
620 
621  if (got_SIGHUP)
622  {
623  got_SIGHUP = false;
625 
626  /* shutdown requested in config file? */
627  if (!AutoVacuumingActive())
628  break;
629 
630  /* rebalance in case the default cost parameters changed */
631  LWLockAcquire(AutovacuumLock, LW_EXCLUSIVE);
633  LWLockRelease(AutovacuumLock);
634 
635  /* rebuild the list in case the naptime changed */
637  }
638 
639  /*
640  * a worker finished, or postmaster signalled failure to start a
641  * worker
642  */
643  if (got_SIGUSR2)
644  {
645  got_SIGUSR2 = false;
646 
647  /* rebalance cost limits, if needed */
649  {
650  LWLockAcquire(AutovacuumLock, LW_EXCLUSIVE);
653  LWLockRelease(AutovacuumLock);
654  }
655 
657  {
658  /*
659  * If the postmaster failed to start a new worker, we sleep
660  * for a little while and resend the signal. The new worker's
661  * state is still in memory, so this is sufficient. After
662  * that, we restart the main loop.
663  *
664  * XXX should we put a limit to the number of times we retry?
665  * I don't think it makes much sense, because a future start
666  * of a worker will continue to fail in the same way.
667  */
669  pg_usleep(1000000L); /* 1s */
671  continue;
672  }
673  }
674 
675  /*
676  * There are some conditions that we need to check before trying to
677  * start a worker. First, we need to make sure that there is a worker
678  * slot available. Second, we need to make sure that no other worker
679  * failed while starting up.
680  */
681 
682  current_time = GetCurrentTimestamp();
683  LWLockAcquire(AutovacuumLock, LW_SHARED);
684 
686 
688  {
689  int waittime;
691 
692  /*
693  * We can't launch another worker when another one is still
694  * starting up (or failed while doing so), so just sleep for a bit
695  * more; that worker will wake us up again as soon as it's ready.
696  * We will only wait autovacuum_naptime seconds (up to a maximum
697  * of 60 seconds) for this to happen however. Note that failure
698  * to connect to a particular database is not a problem here,
699  * because the worker removes itself from the startingWorker
700  * pointer before trying to connect. Problems detected by the
701  * postmaster (like fork() failure) are also reported and handled
702  * differently. The only problems that may cause this code to
703  * fire are errors in the earlier sections of AutoVacWorkerMain,
704  * before the worker removes the WorkerInfo from the
705  * startingWorker pointer.
706  */
707  waittime = Min(autovacuum_naptime, 60) * 1000;
708  if (TimestampDifferenceExceeds(worker->wi_launchtime, current_time,
709  waittime))
710  {
711  LWLockRelease(AutovacuumLock);
712  LWLockAcquire(AutovacuumLock, LW_EXCLUSIVE);
713 
714  /*
715  * No other process can put a worker in starting mode, so if
716  * startingWorker is still INVALID after exchanging our lock,
717  * we assume it's the same one we saw above (so we don't
718  * recheck the launch time).
719  */
721  {
723  worker->wi_dboid = InvalidOid;
724  worker->wi_tableoid = InvalidOid;
725  worker->wi_sharedrel = false;
726  worker->wi_proc = NULL;
727  worker->wi_launchtime = 0;
729  &worker->wi_links);
731  elog(WARNING, "worker took too long to start; canceled");
732  }
733  }
734  else
735  can_launch = false;
736  }
737  LWLockRelease(AutovacuumLock); /* either shared or exclusive */
738 
739  /* if we can't do anything, just go back to sleep */
740  if (!can_launch)
741  continue;
742 
743  /* We're OK to start a new worker */
744 
746  {
747  /*
748  * Special case when the list is empty: start a worker right away.
749  * This covers the initial case, when no database is in pgstats
750  * (thus the list is empty). Note that the constraints in
751  * launcher_determine_sleep keep us from starting workers too
752  * quickly (at most once every autovacuum_naptime when the list is
753  * empty).
754  */
755  launch_worker(current_time);
756  }
757  else
758  {
759  /*
760  * because rebuild_database_list constructs a list with most
761  * distant adl_next_worker first, we obtain our database from the
762  * tail of the list.
763  */
764  avl_dbase *avdb;
765 
766  avdb = dlist_tail_element(avl_dbase, adl_node, &DatabaseList);
767 
768  /*
769  * launch a worker if next_worker is right now or it is in the
770  * past
771  */
773  current_time, 0))
774  launch_worker(current_time);
775  }
776  }
777 
778  /* Normal exit from the autovac launcher is here */
779 shutdown:
780  ereport(LOG,
781  (errmsg("autovacuum launcher shutting down")));
783 
784  proc_exit(0); /* done */
785 }
void ProcessCatchupInterrupt(void)
Definition: sinval.c:177
void InitializeTimeouts(void)
Definition: timeout.c:340
int autovacuum_naptime
Definition: autovacuum.c:114
void AbortCurrentTransaction(void)
Definition: xact.c:2984
#define SIGUSR1
Definition: win32.h:211
TimestampTz adl_next_worker
Definition: autovacuum.c:160
int MyProcPid
Definition: globals.c:38
WorkerInfo av_startingWorker
Definition: autovacuum.c:267
static void autovac_balance_cost(void)
Definition: autovacuum.c:1730
sig_atomic_t av_signal[AutoVacNumSignals]
Definition: autovacuum.c:263
static bool am_autovacuum_launcher
Definition: autovacuum.c:135
#define WL_TIMEOUT
Definition: latch.h:127
void ProcessConfigFile(GucContext context)
dlist_head av_freeWorkers
Definition: autovacuum.c:265
int waittime
Definition: pg_standby.c:41
static void dlist_push_head(dlist_head *head, dlist_node *node)
Definition: ilist.h:300
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1688
TimestampTz wi_launchtime
Definition: autovacuum.c:224
static MemoryContext AutovacMemCxt
Definition: autovacuum.c:154
#define Min(x, y)
Definition: c.h:801
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
void proc_exit(int code)
Definition: ipc.c:99
static volatile sig_atomic_t got_SIGHUP
Definition: autovacuum.c:139
#define SetProcessingMode(mode)
Definition: miscadmin.h:371
void BaseInit(void)
Definition: postinit.c:517
dlist_node wi_links
Definition: autovacuum.c:220
void ResetLatch(volatile Latch *latch)
Definition: latch.c:462
#define LOG
Definition: elog.h:26
volatile bool QueryCancelPending
Definition: globals.c:30
bool TimestampDifferenceExceeds(TimestampTz start_time, TimestampTz stop_time, int msec)
Definition: timestamp.c:1821
#define SIGQUIT
Definition: win32.h:197
void FlushErrorState(void)
Definition: elog.c:1587
#define PG_SETMASK(mask)
Definition: pqsignal.h:19
void StatementCancelHandler(SIGNAL_ARGS)
Definition: postgres.c:2648
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1714
#define RESUME_INTERRUPTS()
Definition: miscadmin.h:116
ErrorContextCallback * error_context_stack
Definition: elog.c:88
void pg_usleep(long microsec)
Definition: signal.c:53
double TimestampTz
Definition: timestamp.h:51
int WaitLatch(volatile Latch *latch, int wakeEvents, long timeout, uint32 wait_event_info)
Definition: latch.c:301
#define SIG_IGN
Definition: win32.h:193
#define dlist_tail_element(type, membername, lhead)
Definition: ilist.h:496
void disable_all_timeouts(bool keep_indicators)
Definition: timeout.c:596
bool AutoVacuumingActive(void)
Definition: autovacuum.c:2955
Definition: guc.h:75
static volatile sig_atomic_t got_SIGTERM
Definition: autovacuum.c:141
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:145
void InitProcess(void)
Definition: proc.c:287
void SetConfigOption(const char *name, const char *value, GucContext context, GucSource source)
Definition: guc.c:6633
sigset_t UnBlockSig
Definition: pqsignal.c:22
static dlist_head DatabaseList
Definition: autovacuum.c:276
#define ereport(elevel, rest)
Definition: elog.h:122
MemoryContext TopMemoryContext
Definition: mcxt.c:43
Definition: guc.h:72
static void avl_sigusr2_handler(SIGNAL_ARGS)
Definition: autovacuum.c:1366
static void launcher_determine_sleep(bool canlaunch, bool recursing, struct timeval *nap)
Definition: autovacuum.c:795
#define WARNING
Definition: elog.h:40
#define MemoryContextResetAndDeleteChildren(ctx)
Definition: memutils.h:88
#define WL_POSTMASTER_DEATH
Definition: latch.h:128
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:440
int PostAuthDelay
Definition: postgres.c:97
void EmitErrorReport(void)
Definition: elog.c:1446
#define SIGPIPE
Definition: win32.h:201
#define SIGHUP
Definition: win32.h:196
#define InvalidOid
Definition: postgres_ext.h:36
static void dlist_init(dlist_head *head)
Definition: ilist.h:278
#define SIG_DFL
Definition: win32.h:191
pqsigfunc pqsignal(int signum, pqsigfunc handler)
Definition: signal.c:168
static volatile sig_atomic_t got_SIGUSR2
Definition: autovacuum.c:140
#define NULL
Definition: c.h:226
static bool dlist_is_empty(dlist_head *head)
Definition: ilist.h:289
void pgstat_clear_snapshot(void)
Definition: pgstat.c:5045
static AutoVacuumShmemStruct * AutoVacuumShmem
Definition: autovacuum.c:270
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1110
static void av_sighup_handler(SIGNAL_ARGS)
Definition: autovacuum.c:1354
sigjmp_buf * PG_exception_stack
Definition: elog.c:90
static void rebuild_database_list(Oid newdb)
Definition: autovacuum.c:879
void InitPostgres(const char *in_dbname, Oid dboid, const char *username, Oid useroid, char *out_dbname)
Definition: postinit.c:558
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define HOLD_INTERRUPTS()
Definition: miscadmin.h:114
static MemoryContext DatabaseListCxt
Definition: autovacuum.c:277
void FloatExceptionHandler(SIGNAL_ARGS)
Definition: postgres.c:2669
struct Latch * MyLatch
Definition: globals.c:51
PGPROC * wi_proc
Definition: autovacuum.c:223
static void launch_worker(TimestampTz now)
Definition: autovacuum.c:1295
void SendPostmasterSignal(PMSignalReason reason)
Definition: pmsignal.c:113
#define elog
Definition: elog.h:219
void procsignal_sigusr1_handler(SIGNAL_ARGS)
Definition: procsignal.c:260
#define SIGCHLD
Definition: win32.h:206
#define WL_LATCH_SET
Definition: latch.h:124
void quickdie(SIGNAL_ARGS)
Definition: postgres.c:2556
static Oid do_start_worker(void)
Definition: autovacuum.c:1080
#define SIGUSR2
Definition: win32.h:212
static void avl_sigterm_handler(SIGNAL_ARGS)
Definition: autovacuum.c:1378
void init_ps_display(const char *username, const char *dbname, const char *host_info, const char *initial_str)
Definition: ps_status.c:244
static void autovacuum_do_vac_analyze ( autovac_table tab,
BufferAccessStrategy  bstrategy 
)
static

Definition at line 2889 of file autovacuum.c.

References autovac_table::at_nspname, autovac_table::at_params, autovac_table::at_relid, autovac_table::at_relname, autovac_table::at_vacoptions, autovac_report_activity(), RangeVar::location, MemSet, NIL, RangeVar::relname, RangeVar::schemaname, and vacuum().

Referenced by do_autovacuum().

2890 {
2891  RangeVar rangevar;
2892 
2893  /* Set up command parameters --- use local variables instead of palloc */
2894  MemSet(&rangevar, 0, sizeof(rangevar));
2895 
2896  rangevar.schemaname = tab->at_nspname;
2897  rangevar.relname = tab->at_relname;
2898  rangevar.location = -1;
2899 
2900  /* Let pgstat know what we're doing */
2902 
2903  vacuum(tab->at_vacoptions, &rangevar, tab->at_relid, &tab->at_params, NIL,
2904  bstrategy, true);
2905 }
#define NIL
Definition: pg_list.h:69
#define MemSet(start, val, len)
Definition: c.h:852
char * schemaname
Definition: primnodes.h:66
int location
Definition: primnodes.h:72
char * relname
Definition: primnodes.h:67
char * at_relname
Definition: autovacuum.c:195
static void autovac_report_activity(autovac_table *tab)
Definition: autovacuum.c:2919
char * at_nspname
Definition: autovacuum.c:196
void vacuum(int options, RangeVar *relation, Oid relid, VacuumParams *params, List *va_cols, BufferAccessStrategy bstrategy, bool isTopLevel)
Definition: vacuum.c:148
VacuumParams at_params
Definition: autovacuum.c:190
bool AutoVacuumingActive ( void  )

Definition at line 2955 of file autovacuum.c.

References autovacuum_start_daemon, and pgstat_track_counts.

Referenced by AutoVacLauncherMain(), reaper(), relation_needs_vacanalyze(), and ServerLoop().

2956 {
2958  return false;
2959  return true;
2960 }
bool autovacuum_start_daemon
Definition: autovacuum.c:111
bool pgstat_track_counts
Definition: pgstat.c:110
void AutoVacuumShmemInit ( void  )

Definition at line 3019 of file autovacuum.c.

References Assert, autovacuum_max_workers, AutoVacuumShmemSize(), AutoVacuumShmemStruct::av_freeWorkers, AutoVacuumShmemStruct::av_launcherpid, AutoVacuumShmemStruct::av_runningWorkers, AutoVacuumShmemStruct::av_startingWorker, dlist_init(), dlist_push_head(), i, IsUnderPostmaster, MAXALIGN, NULL, ShmemInitStruct(), and WorkerInfoData::wi_links.

Referenced by CreateSharedMemoryAndSemaphores().

3020 {
3021  bool found;
3022 
3024  ShmemInitStruct("AutoVacuum Data",
3026  &found);
3027 
3028  if (!IsUnderPostmaster)
3029  {
3030  WorkerInfo worker;
3031  int i;
3032 
3033  Assert(!found);
3034 
3039 
3040  worker = (WorkerInfo) ((char *) AutoVacuumShmem +
3041  MAXALIGN(sizeof(AutoVacuumShmemStruct)));
3042 
3043  /* initialize the WorkerInfo free list */
3044  for (i = 0; i < autovacuum_max_workers; i++)
3046  &worker[i].wi_links);
3047  }
3048  else
3049  Assert(found);
3050 }
WorkerInfo av_startingWorker
Definition: autovacuum.c:267
dlist_head av_freeWorkers
Definition: autovacuum.c:265
static void dlist_push_head(dlist_head *head, dlist_node *node)
Definition: ilist.h:300
struct WorkerInfoData * WorkerInfo
Definition: autovacuum.c:232
dlist_node wi_links
Definition: autovacuum.c:220
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:372
bool IsUnderPostmaster
Definition: globals.c:100
Size AutoVacuumShmemSize(void)
Definition: autovacuum.c:3000
int autovacuum_max_workers
Definition: autovacuum.c:112
static void dlist_init(dlist_head *head)
Definition: ilist.h:278
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:670
static AutoVacuumShmemStruct * AutoVacuumShmem
Definition: autovacuum.c:270
#define MAXALIGN(LEN)
Definition: c.h:583
int i
dlist_head av_runningWorkers
Definition: autovacuum.c:266
Size AutoVacuumShmemSize ( void  )

Definition at line 3000 of file autovacuum.c.

References add_size(), autovacuum_max_workers, MAXALIGN, and mul_size().

Referenced by AutoVacuumShmemInit(), and CreateSharedMemoryAndSemaphores().

3001 {
3002  Size size;
3003 
3004  /*
3005  * Need the fixed struct and the array of WorkerInfoData.
3006  */
3007  size = sizeof(AutoVacuumShmemStruct);
3008  size = MAXALIGN(size);
3010  sizeof(WorkerInfoData)));
3011  return size;
3012 }
Size mul_size(Size s1, Size s2)
Definition: shmem.c:492
Size add_size(Size s1, Size s2)
Definition: shmem.c:475
int autovacuum_max_workers
Definition: autovacuum.c:112
size_t Size
Definition: c.h:352
#define MAXALIGN(LEN)
Definition: c.h:583
void AutoVacuumUpdateDelay ( void  )

Definition at line 1714 of file autovacuum.c.

References VacuumCostDelay, VacuumCostLimit, WorkerInfoData::wi_cost_delay, and WorkerInfoData::wi_cost_limit.

Referenced by do_autovacuum(), and vacuum_delay_point().

1715 {
1716  if (MyWorkerInfo)
1717  {
1720  }
1721 }
int VacuumCostLimit
Definition: globals.c:131
static WorkerInfo MyWorkerInfo
Definition: autovacuum.c:280
int VacuumCostDelay
Definition: globals.c:132
void AutoVacWorkerFailed ( void  )

Definition at line 1347 of file autovacuum.c.

References AutoVacForkFailed, and AutoVacuumShmemStruct::av_signal.

Referenced by StartAutovacuumWorker().

1348 {
1350 }
sig_atomic_t av_signal[AutoVacNumSignals]
Definition: autovacuum.c:263
static AutoVacuumShmemStruct * AutoVacuumShmem
Definition: autovacuum.c:270
NON_EXEC_STATIC void AutoVacWorkerMain ( int  argc,
char *  argv[] 
)

Definition at line 1469 of file autovacuum.c.

References am_autovacuum_worker, AutoVacuumShmemStruct::av_launcherpid, AutoVacuumShmemStruct::av_runningWorkers, av_sighup_handler(), AutoVacuumShmemStruct::av_startingWorker, BaseInit(), dbname, DEBUG1, die(), dlist_push_head(), do_autovacuum(), elog, EmitErrorReport(), ereport, errmsg(), FloatExceptionHandler(), FreeWorkerInfo(), HOLD_INTERRUPTS, init_ps_display(), InitializeTimeouts(), InitPostgres(), InitProcess(), InitProcessing, InvalidOid, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MyProc, NAMEDATALEN, NormalProcessing, NULL, OidIsValid, on_shmem_exit(), PG_exception_stack, PG_SETMASK, pg_usleep(), PGC_S_OVERRIDE, PGC_SUSET, pgstat_report_autovac(), PostAuthDelay, pqsignal(), proc_exit(), procsignal_sigusr1_handler(), quickdie(), ReadNewTransactionId(), ReadNextMultiXactId(), recentMulti, recentXid, set_ps_display(), SetConfigOption(), SetProcessingMode, SIG_DFL, SIG_IGN, SIGCHLD, SIGHUP, SIGPIPE, SIGQUIT, SIGUSR1, SIGUSR2, StatementCancelHandler(), synchronous_commit, SYNCHRONOUS_COMMIT_LOCAL_FLUSH, UnBlockSig, WARNING, WorkerInfoData::wi_dboid, WorkerInfoData::wi_links, and WorkerInfoData::wi_proc.

Referenced by StartAutoVacWorker().

1470 {
1471  sigjmp_buf local_sigjmp_buf;
1472  Oid dbid;
1473 
1474  am_autovacuum_worker = true;
1475 
1476  /* Identify myself via ps */
1477  init_ps_display("autovacuum worker process", "", "", "");
1478 
1480 
1481  /*
1482  * Set up signal handlers. We operate on databases much like a regular
1483  * backend, so we use the same signal handling. See equivalent code in
1484  * tcop/postgres.c.
1485  */
1487 
1488  /*
1489  * SIGINT is used to signal canceling the current table's vacuum; SIGTERM
1490  * means abort and exit cleanly, and SIGQUIT means abandon ship.
1491  */
1493  pqsignal(SIGTERM, die);
1495  InitializeTimeouts(); /* establishes SIGALRM handler */
1496 
1502 
1503  /* Early initialization */
1504  BaseInit();
1505 
1506  /*
1507  * Create a per-backend PGPROC struct in shared memory, except in the
1508  * EXEC_BACKEND case where this was done in SubPostmasterMain. We must do
1509  * this before we can use LWLocks (and in the EXEC_BACKEND case we already
1510  * had to do some stuff with LWLocks).
1511  */
1512 #ifndef EXEC_BACKEND
1513  InitProcess();
1514 #endif
1515 
1516  /*
1517  * If an exception is encountered, processing resumes here.
1518  *
1519  * See notes in postgres.c about the design of this coding.
1520  */
1521  if (sigsetjmp(local_sigjmp_buf, 1) != 0)
1522  {
1523  /* Prevents interrupts while cleaning up */
1524  HOLD_INTERRUPTS();
1525 
1526  /* Report the error to the server log */
1527  EmitErrorReport();
1528 
1529  /*
1530  * We can now go away. Note that because we called InitProcess, a
1531  * callback was registered to do ProcKill, which will clean up
1532  * necessary state.
1533  */
1534  proc_exit(0);
1535  }
1536 
1537  /* We can now handle ereport(ERROR) */
1538  PG_exception_stack = &local_sigjmp_buf;
1539 
1541 
1542  /*
1543  * Force zero_damaged_pages OFF in the autovac process, even if it is set
1544  * in postgresql.conf. We don't really want such a dangerous option being
1545  * applied non-interactively.
1546  */
1547  SetConfigOption("zero_damaged_pages", "false", PGC_SUSET, PGC_S_OVERRIDE);
1548 
1549  /*
1550  * Force settable timeouts off to avoid letting these settings prevent
1551  * regular maintenance from being executed.
1552  */
1553  SetConfigOption("statement_timeout", "0", PGC_SUSET, PGC_S_OVERRIDE);
1554  SetConfigOption("lock_timeout", "0", PGC_SUSET, PGC_S_OVERRIDE);
1555  SetConfigOption("idle_in_transaction_session_timeout", "0",
1557 
1558  /*
1559  * Force default_transaction_isolation to READ COMMITTED. We don't want
1560  * to pay the overhead of serializable mode, nor add any risk of causing
1561  * deadlocks or delaying other transactions.
1562  */
1563  SetConfigOption("default_transaction_isolation", "read committed",
1565 
1566  /*
1567  * Force synchronous replication off to allow regular maintenance even if
1568  * we are waiting for standbys to connect. This is important to ensure we
1569  * aren't blocked from performing anti-wraparound tasks.
1570  */
1572  SetConfigOption("synchronous_commit", "local",
1574 
1575  /*
1576  * Get the info about the database we're going to work on.
1577  */
1578  LWLockAcquire(AutovacuumLock, LW_EXCLUSIVE);
1579 
1580  /*
1581  * beware of startingWorker being INVALID; this should normally not
1582  * happen, but if a worker fails after forking and before this, the
1583  * launcher might have decided to remove it from the queue and start
1584  * again.
1585  */
1587  {
1589  dbid = MyWorkerInfo->wi_dboid;
1591 
1592  /* insert into the running list */
1595 
1596  /*
1597  * remove from the "starting" pointer, so that the launcher can start
1598  * a new worker if required
1599  */
1601  LWLockRelease(AutovacuumLock);
1602 
1604 
1605  /* wake up the launcher */
1606  if (AutoVacuumShmem->av_launcherpid != 0)
1608  }
1609  else
1610  {
1611  /* no worker entry for me, go away */
1612  elog(WARNING, "autovacuum worker started without a worker entry");
1613  dbid = InvalidOid;
1614  LWLockRelease(AutovacuumLock);
1615  }
1616 
1617  if (OidIsValid(dbid))
1618  {
1619  char dbname[NAMEDATALEN];
1620 
1621  /*
1622  * Report autovac startup to the stats collector. We deliberately do
1623  * this before InitPostgres, so that the last_autovac_time will get
1624  * updated even if the connection attempt fails. This is to prevent
1625  * autovac from getting "stuck" repeatedly selecting an unopenable
1626  * database, rather than making any progress on stuff it can connect
1627  * to.
1628  */
1629  pgstat_report_autovac(dbid);
1630 
1631  /*
1632  * Connect to the selected database
1633  *
1634  * Note: if we have selected a just-deleted database (due to using
1635  * stale stats info), we'll fail and exit here.
1636  */
1637  InitPostgres(NULL, dbid, NULL, InvalidOid, dbname);
1639  set_ps_display(dbname, false);
1640  ereport(DEBUG1,
1641  (errmsg("autovacuum: processing database \"%s\"", dbname)));
1642 
1643  if (PostAuthDelay)
1644  pg_usleep(PostAuthDelay * 1000000L);
1645 
1646  /* And do an appropriate amount of work */
1649  do_autovacuum();
1650  }
1651 
1652  /*
1653  * The launcher will be notified of my death in ProcKill, *if* we managed
1654  * to get a worker slot at all
1655  */
1656 
1657  /* All done, go away */
1658  proc_exit(0);
1659 }
static bool am_autovacuum_worker
Definition: autovacuum.c:136
void InitializeTimeouts(void)
Definition: timeout.c:340
#define SIGUSR1
Definition: win32.h:211
#define DEBUG1
Definition: elog.h:25
WorkerInfo av_startingWorker
Definition: autovacuum.c:267
static void dlist_push_head(dlist_head *head, dlist_node *node)
Definition: ilist.h:300
static void do_autovacuum(void)
Definition: autovacuum.c:1884
PGPROC * MyProc
Definition: proc.c:67
static MultiXactId recentMulti
Definition: autovacuum.c:145
void set_ps_display(const char *activity, bool force)
Definition: ps_status.c:326
void proc_exit(int code)
Definition: ipc.c:99
#define SetProcessingMode(mode)
Definition: miscadmin.h:371
void BaseInit(void)
Definition: postinit.c:517
dlist_node wi_links
Definition: autovacuum.c:220
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:533
#define SIGQUIT
Definition: win32.h:197
#define PG_SETMASK(mask)
Definition: pqsignal.h:19
void StatementCancelHandler(SIGNAL_ARGS)
Definition: postgres.c:2648
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1714
#define NAMEDATALEN
void pg_usleep(long microsec)
Definition: signal.c:53
#define SIG_IGN
Definition: win32.h:193
Definition: guc.h:75
void InitProcess(void)
Definition: proc.c:287
void on_shmem_exit(pg_on_exit_callback function, Datum arg)
Definition: ipc.c:348
void SetConfigOption(const char *name, const char *value, GucContext context, GucSource source)
Definition: guc.c:6633
TransactionId ReadNewTransactionId(void)
Definition: varsup.c:250
sigset_t UnBlockSig
Definition: pqsignal.c:22
static WorkerInfo MyWorkerInfo
Definition: autovacuum.c:280
int synchronous_commit
Definition: xact.c:82
#define ereport(elevel, rest)
Definition: elog.h:122
#define WARNING
Definition: elog.h:40
int PostAuthDelay
Definition: postgres.c:97
static TransactionId recentXid
Definition: autovacuum.c:144
void EmitErrorReport(void)
Definition: elog.c:1446
#define SIGPIPE
Definition: win32.h:201
#define SIGHUP
Definition: win32.h:196
#define InvalidOid
Definition: postgres_ext.h:36
#define SIG_DFL
Definition: win32.h:191
pqsigfunc pqsignal(int signum, pqsigfunc handler)
Definition: signal.c:168
#define NULL
Definition: c.h:226
char * dbname
Definition: streamutil.c:41
static void FreeWorkerInfo(int code, Datum arg)
Definition: autovacuum.c:1665
static AutoVacuumShmemStruct * AutoVacuumShmem
Definition: autovacuum.c:270
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1110
static void av_sighup_handler(SIGNAL_ARGS)
Definition: autovacuum.c:1354
sigjmp_buf * PG_exception_stack
Definition: elog.c:90
void InitPostgres(const char *in_dbname, Oid dboid, const char *username, Oid useroid, char *out_dbname)
Definition: postinit.c:558
int errmsg(const char *fmt,...)
Definition: elog.c:797
void die(SIGNAL_ARGS)
Definition: postgres.c:2617
#define HOLD_INTERRUPTS()
Definition: miscadmin.h:114
void FloatExceptionHandler(SIGNAL_ARGS)
Definition: postgres.c:2669
PGPROC * wi_proc
Definition: autovacuum.c:223
#define elog
Definition: elog.h:219
void procsignal_sigusr1_handler(SIGNAL_ARGS)
Definition: procsignal.c:260
dlist_head av_runningWorkers
Definition: autovacuum.c:266
#define SIGCHLD
Definition: win32.h:206
void pgstat_report_autovac(Oid dboid)
Definition: pgstat.c:1307
void quickdie(SIGNAL_ARGS)
Definition: postgres.c:2556
#define SIGUSR2
Definition: win32.h:212
void init_ps_display(const char *username, const char *dbname, const char *host_info, const char *initial_str)
Definition: ps_status.c:244
MultiXactId ReadNextMultiXactId(void)
Definition: multixact.c:721
static void av_sighup_handler ( SIGNAL_ARGS  )
static

Definition at line 1354 of file autovacuum.c.

References got_SIGHUP, MyLatch, and SetLatch().

Referenced by AutoVacLauncherMain(), and AutoVacWorkerMain().

1355 {
1356  int save_errno = errno;
1357 
1358  got_SIGHUP = true;
1359  SetLatch(MyLatch);
1360 
1361  errno = save_errno;
1362 }
static volatile sig_atomic_t got_SIGHUP
Definition: autovacuum.c:139
void SetLatch(volatile Latch *latch)
Definition: latch.c:380
struct Latch * MyLatch
Definition: globals.c:51
static void avl_sigterm_handler ( SIGNAL_ARGS  )
static

Definition at line 1378 of file autovacuum.c.

References got_SIGTERM, MyLatch, and SetLatch().

Referenced by AutoVacLauncherMain().

1379 {
1380  int save_errno = errno;
1381 
1382  got_SIGTERM = true;
1383  SetLatch(MyLatch);
1384 
1385  errno = save_errno;
1386 }
static volatile sig_atomic_t got_SIGTERM
Definition: autovacuum.c:141
void SetLatch(volatile Latch *latch)
Definition: latch.c:380
struct Latch * MyLatch
Definition: globals.c:51
static void avl_sigusr2_handler ( SIGNAL_ARGS  )
static

Definition at line 1366 of file autovacuum.c.

References got_SIGUSR2, MyLatch, and SetLatch().

Referenced by AutoVacLauncherMain().

1367 {
1368  int save_errno = errno;
1369 
1370  got_SIGUSR2 = true;
1371  SetLatch(MyLatch);
1372 
1373  errno = save_errno;
1374 }
static volatile sig_atomic_t got_SIGUSR2
Definition: autovacuum.c:140
void SetLatch(volatile Latch *latch)
Definition: latch.c:380
struct Latch * MyLatch
Definition: globals.c:51
static int db_comparator ( const void *  a,
const void *  b 
)
static

Definition at line 1060 of file autovacuum.c.

Referenced by rebuild_database_list().

1061 {
1062  if (((const avl_dbase *) a)->adl_score == ((const avl_dbase *) b)->adl_score)
1063  return 0;
1064  else
1065  return (((const avl_dbase *) a)->adl_score < ((const avl_dbase *) b)->adl_score) ? 1 : -1;
1066 }
static void do_autovacuum ( void  )
static

Definition at line 1884 of file autovacuum.c.

References AbortOutOfAnyTransaction(), AccessExclusiveLock, AccessShareLock, ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate(), Anum_pg_class_relkind, av_relation::ar_hasrelopts, av_relation::ar_relid, av_relation::ar_reloptions, autovac_table::at_datname, autovac_table::at_dobalance, autovac_table::at_nspname, autovac_table::at_relid, autovac_table::at_relname, autovac_table::at_sharedrel, autovac_table::at_vacoptions, autovac_table::at_vacuum_cost_delay, autovac_table::at_vacuum_cost_limit, autovac_balance_cost(), autovacuum_do_vac_analyze(), AutoVacuumUpdateDelay(), AutoVacuumShmemStruct::av_runningWorkers, BackendIdGetProc(), BAS_VACUUM, BTEqualStrategyNumber, CharGetDatum, CHECK_FOR_INTERRUPTS, CommitTransactionCommand(), ConditionalLockRelationOid(), CreateTupleDescCopy(), dlist_iter::cur, DATABASEOID, default_freeze_min_age, default_freeze_table_age, default_multixact_freeze_min_age, default_multixact_freeze_table_age, dlist_container, dlist_foreach, DROP_CASCADE, elog, EmitErrorReport(), HASHCTL::entrysize, ereport, errcontext, errmsg(), ERROR, extract_autovac_opts(), FlushErrorState(), ForwardScanDirection, get_database_name(), get_namespace_name(), get_pgstat_tabentry_relid(), get_rel_name(), get_rel_namespace(), GetAccessStrategy(), GETSTRUCT, GetTempNamespaceBackendId(), got_SIGHUP, HASH_BLOBS, hash_create(), HASH_ELEM, HASH_ENTER, HASH_FIND, hash_search(), heap_beginscan_catalog(), heap_close, heap_endscan(), heap_getnext(), heap_open(), HeapTupleGetOid, HeapTupleIsValid, HOLD_INTERRUPTS, InvalidBackendId, InvalidOid, HASHCTL::keysize, lappend_oid(), lfirst_oid, LOG, LW_EXCLUSIVE, LW_SHARED, LWLockAcquire(), LWLockRelease(), MemoryContextResetAndDeleteChildren, MemoryContextSwitchTo(), MemSet, MultiXactMemberFreezeThreshold(), MyBackendId, MyDatabaseId, NameStr, NIL, NULL, ObjectIdGetDatum, OidIsValid, PERFORM_DELETION_INTERNAL, PERFORM_DELETION_QUIETLY, PERFORM_DELETION_SKIP_EXTENSIONS, performDeletion(), pfree(), PG_CATCH, PG_END_TRY, PG_TRY, PGC_SIGHUP, pgstat_fetch_stat_dbentry(), pgstat_vacuum_stat(), PortalContext, ProcessConfigFile(), QueryCancelPending, relation_needs_vacanalyze(), RelationGetDescr, RelationRelationId, ReleaseSysCache(), RELKIND_MATVIEW, RELKIND_RELATION, RELKIND_TOASTVALUE, RELOID, RELPERSISTENCE_TEMP, RESUME_INTERRUPTS, ScanKeyInit(), SearchSysCache1, SearchSysCacheCopy1, StartTransactionCommand(), table_recheck_autovac(), TopMemoryContext, TopTransactionContext, UnlockRelationOid(), vac_update_datfrozenxid(), VACOPT_VACUUM, vacuum_freeze_min_age, vacuum_freeze_table_age, vacuum_multixact_freeze_min_age, vacuum_multixact_freeze_table_age, VacuumCostDelay, VacuumCostLimit, WorkerInfoData::wi_cost_delay, WorkerInfoData::wi_cost_limit, WorkerInfoData::wi_cost_limit_base, WorkerInfoData::wi_dboid, WorkerInfoData::wi_dobalance, WorkerInfoData::wi_sharedrel, and WorkerInfoData::wi_tableoid.

Referenced by AutoVacWorkerMain().

1885 {
1886  Relation classRel;
1887  HeapTuple tuple;
1888  HeapScanDesc relScan;
1889  Form_pg_database dbForm;
1890  List *table_oids = NIL;
1891  List *orphan_oids = NIL;
1892  HASHCTL ctl;
1893  HTAB *table_toast_map;
1894  ListCell *volatile cell;
1895  PgStat_StatDBEntry *shared;
1896  PgStat_StatDBEntry *dbentry;
1897  BufferAccessStrategy bstrategy;
1898  ScanKeyData key;
1899  TupleDesc pg_class_desc;
1900  int effective_multixact_freeze_max_age;
1901  bool did_vacuum = false;
1902  bool found_concurrent_worker = false;
1903 
1904  /*
1905  * StartTransactionCommand and CommitTransactionCommand will automatically
1906  * switch to other contexts. We need this one to keep the list of
1907  * relations to vacuum/analyze across transactions.
1908  */
1910  "AV worker",
1913 
1914  /*
1915  * may be NULL if we couldn't find an entry (only happens if we are
1916  * forcing a vacuum for anti-wrap purposes).
1917  */
1919 
1920  /* Start a transaction so our commands have one to play into. */
1922 
1923  /*
1924  * Clean up any dead statistics collector entries for this DB. We always
1925  * want to do this exactly once per DB-processing cycle, even if we find
1926  * nothing worth vacuuming in the database.
1927  */
1929 
1930  /*
1931  * Compute the multixact age for which freezing is urgent. This is
1932  * normally autovacuum_multixact_freeze_max_age, but may be less if we are
1933  * short of multixact member space.
1934  */
1935  effective_multixact_freeze_max_age = MultiXactMemberFreezeThreshold();
1936 
1937  /*
1938  * Find the pg_database entry and select the default freeze ages. We use
1939  * zero in template and nonconnectable databases, else the system-wide
1940  * default.
1941  */
1943  if (!HeapTupleIsValid(tuple))
1944  elog(ERROR, "cache lookup failed for database %u", MyDatabaseId);
1945  dbForm = (Form_pg_database) GETSTRUCT(tuple);
1946 
1947  if (dbForm->datistemplate || !dbForm->datallowconn)
1948  {
1953  }
1954  else
1955  {
1960  }
1961 
1962  ReleaseSysCache(tuple);
1963 
1964  /* StartTransactionCommand changed elsewhere */
1966 
1967  /* The database hash where pgstat keeps shared relations */
1969 
1971 
1972  /* create a copy so we can use it after closing pg_class */
1973  pg_class_desc = CreateTupleDescCopy(RelationGetDescr(classRel));
1974 
1975  /* create hash table for toast <-> main relid mapping */
1976  MemSet(&ctl, 0, sizeof(ctl));
1977  ctl.keysize = sizeof(Oid);
1978  ctl.entrysize = sizeof(av_relation);
1979 
1980  table_toast_map = hash_create("TOAST to main relid map",
1981  100,
1982  &ctl,
1983  HASH_ELEM | HASH_BLOBS);
1984 
1985  /*
1986  * Scan pg_class to determine which tables to vacuum.
1987  *
1988  * We do this in two passes: on the first one we collect the list of plain
1989  * relations and materialized views, and on the second one we collect
1990  * TOAST tables. The reason for doing the second pass is that during it we
1991  * want to use the main relation's pg_class.reloptions entry if the TOAST
1992  * table does not have any, and we cannot obtain it unless we know
1993  * beforehand what's the main table OID.
1994  *
1995  * We need to check TOAST tables separately because in cases with short,
1996  * wide tables there might be proportionally much more activity in the
1997  * TOAST table than in its parent.
1998  */
1999  relScan = heap_beginscan_catalog(classRel, 0, NULL);
2000 
2001  /*
2002  * On the first pass, we collect main tables to vacuum, and also the main
2003  * table relid to TOAST relid mapping.
2004  */
2005  while ((tuple = heap_getnext(relScan, ForwardScanDirection)) != NULL)
2006  {
2007  Form_pg_class classForm = (Form_pg_class) GETSTRUCT(tuple);
2008  PgStat_StatTabEntry *tabentry;
2009  AutoVacOpts *relopts;
2010  Oid relid;
2011  bool dovacuum;
2012  bool doanalyze;
2013  bool wraparound;
2014 
2015  if (classForm->relkind != RELKIND_RELATION &&
2016  classForm->relkind != RELKIND_MATVIEW)
2017  continue;
2018 
2019  relid = HeapTupleGetOid(tuple);
2020 
2021  /*
2022  * Check if it is a temp table (presumably, of some other backend's).
2023  * We cannot safely process other backends' temp tables.
2024  */
2025  if (classForm->relpersistence == RELPERSISTENCE_TEMP)
2026  {
2027  int backendID;
2028 
2029  backendID = GetTempNamespaceBackendId(classForm->relnamespace);
2030 
2031  /* We just ignore it if the owning backend is still active */
2032  if (backendID != InvalidBackendId &&
2033  (backendID == MyBackendId ||
2034  BackendIdGetProc(backendID) == NULL))
2035  {
2036  /*
2037  * The table seems to be orphaned -- although it might be that
2038  * the owning backend has already deleted it and exited; our
2039  * pg_class scan snapshot is not necessarily up-to-date
2040  * anymore, so we could be looking at a committed-dead entry.
2041  * Remember it so we can try to delete it later.
2042  */
2043  orphan_oids = lappend_oid(orphan_oids, relid);
2044  }
2045  continue;
2046  }
2047 
2048  /* Fetch reloptions and the pgstat entry for this table */
2049  relopts = extract_autovac_opts(tuple, pg_class_desc);
2050  tabentry = get_pgstat_tabentry_relid(relid, classForm->relisshared,
2051  shared, dbentry);
2052 
2053  /* Check if it needs vacuum or analyze */
2054  relation_needs_vacanalyze(relid, relopts, classForm, tabentry,
2055  effective_multixact_freeze_max_age,
2056  &dovacuum, &doanalyze, &wraparound);
2057 
2058  /* Relations that need work are added to table_oids */
2059  if (dovacuum || doanalyze)
2060  table_oids = lappend_oid(table_oids, relid);
2061 
2062  /*
2063  * Remember TOAST associations for the second pass. Note: we must do
2064  * this whether or not the table is going to be vacuumed, because we
2065  * don't automatically vacuum toast tables along the parent table.
2066  */
2067  if (OidIsValid(classForm->reltoastrelid))
2068  {
2069  av_relation *hentry;
2070  bool found;
2071 
2072  hentry = hash_search(table_toast_map,
2073  &classForm->reltoastrelid,
2074  HASH_ENTER, &found);
2075 
2076  if (!found)
2077  {
2078  /* hash_search already filled in the key */
2079  hentry->ar_relid = relid;
2080  hentry->ar_hasrelopts = false;
2081  if (relopts != NULL)
2082  {
2083  hentry->ar_hasrelopts = true;
2084  memcpy(&hentry->ar_reloptions, relopts,
2085  sizeof(AutoVacOpts));
2086  }
2087  }
2088  }
2089  }
2090 
2091  heap_endscan(relScan);
2092 
2093  /* second pass: check TOAST tables */
2094  ScanKeyInit(&key,
2096  BTEqualStrategyNumber, F_CHAREQ,
2098 
2099  relScan = heap_beginscan_catalog(classRel, 1, &key);
2100  while ((tuple = heap_getnext(relScan, ForwardScanDirection)) != NULL)
2101  {
2102  Form_pg_class classForm = (Form_pg_class) GETSTRUCT(tuple);
2103  PgStat_StatTabEntry *tabentry;
2104  Oid relid;
2105  AutoVacOpts *relopts = NULL;
2106  bool dovacuum;
2107  bool doanalyze;
2108  bool wraparound;
2109 
2110  /*
2111  * We cannot safely process other backends' temp tables, so skip 'em.
2112  */
2113  if (classForm->relpersistence == RELPERSISTENCE_TEMP)
2114  continue;
2115 
2116  relid = HeapTupleGetOid(tuple);
2117 
2118  /*
2119  * fetch reloptions -- if this toast table does not have them, try the
2120  * main rel
2121  */
2122  relopts = extract_autovac_opts(tuple, pg_class_desc);
2123  if (relopts == NULL)
2124  {
2125  av_relation *hentry;
2126  bool found;
2127 
2128  hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
2129  if (found && hentry->ar_hasrelopts)
2130  relopts = &hentry->ar_reloptions;
2131  }
2132 
2133  /* Fetch the pgstat entry for this table */
2134  tabentry = get_pgstat_tabentry_relid(relid, classForm->relisshared,
2135  shared, dbentry);
2136 
2137  relation_needs_vacanalyze(relid, relopts, classForm, tabentry,
2138  effective_multixact_freeze_max_age,
2139  &dovacuum, &doanalyze, &wraparound);
2140 
2141  /* ignore analyze for toast tables */
2142  if (dovacuum)
2143  table_oids = lappend_oid(table_oids, relid);
2144  }
2145 
2146  heap_endscan(relScan);
2147  heap_close(classRel, AccessShareLock);
2148 
2149  /*
2150  * Recheck orphan temporary tables, and if they still seem orphaned, drop
2151  * them. We'll eat a transaction per dropped table, which might seem
2152  * excessive, but we should only need to do anything as a result of a
2153  * previous backend crash, so this should not happen often enough to
2154  * justify "optimizing". Using separate transactions ensures that we
2155  * don't bloat the lock table if there are many temp tables to be dropped,
2156  * and it ensures that we don't lose work if a deletion attempt fails.
2157  */
2158  foreach(cell, orphan_oids)
2159  {
2160  Oid relid = lfirst_oid(cell);
2161  Form_pg_class classForm;
2162  int backendID;
2163  ObjectAddress object;
2164 
2165  /*
2166  * Check for user-requested abort.
2167  */
2169 
2170  /*
2171  * Try to lock the table. If we can't get the lock immediately,
2172  * somebody else is using (or dropping) the table, so it's not our
2173  * concern anymore. Having the lock prevents race conditions below.
2174  */
2176  continue;
2177 
2178  /*
2179  * Re-fetch the pg_class tuple and re-check whether it still seems to
2180  * be an orphaned temp table. If it's not there or no longer the same
2181  * relation, ignore it.
2182  */
2183  tuple = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relid));
2184  if (!HeapTupleIsValid(tuple))
2185  {
2186  /* be sure to drop useless lock so we don't bloat lock table */
2188  continue;
2189  }
2190  classForm = (Form_pg_class) GETSTRUCT(tuple);
2191 
2192  /*
2193  * Make all the same tests made in the loop above. In event of OID
2194  * counter wraparound, the pg_class entry we have now might be
2195  * completely unrelated to the one we saw before.
2196  */
2197  if (!((classForm->relkind == RELKIND_RELATION ||
2198  classForm->relkind == RELKIND_MATVIEW) &&
2199  classForm->relpersistence == RELPERSISTENCE_TEMP))
2200  {
2202  continue;
2203  }
2204  backendID = GetTempNamespaceBackendId(classForm->relnamespace);
2205  if (!(backendID != InvalidBackendId &&
2206  (backendID == MyBackendId ||
2207  BackendIdGetProc(backendID) == NULL)))
2208  {
2210  continue;
2211  }
2212 
2213  /* OK, let's delete it */
2214  ereport(LOG,
2215  (errmsg("autovacuum: dropping orphan temp table \"%s.%s.%s\"",
2217  get_namespace_name(classForm->relnamespace),
2218  NameStr(classForm->relname))));
2219 
2220  object.classId = RelationRelationId;
2221  object.objectId = relid;
2222  object.objectSubId = 0;
2223  performDeletion(&object, DROP_CASCADE,
2227 
2228  /*
2229  * To commit the deletion, end current transaction and start a new
2230  * one. Note this also releases the lock we took.
2231  */
2234 
2235  /* StartTransactionCommand changed current memory context */
2237  }
2238 
2239  /*
2240  * Create a buffer access strategy object for VACUUM to use. We want to
2241  * use the same one across all the vacuum operations we perform, since the
2242  * point is for VACUUM not to blow out the shared cache.
2243  */
2244  bstrategy = GetAccessStrategy(BAS_VACUUM);
2245 
2246  /*
2247  * create a memory context to act as fake PortalContext, so that the
2248  * contexts created in the vacuum code are cleaned up for each table.
2249  */
2251  "Autovacuum Portal",
2253 
2254  /*
2255  * Perform operations on collected tables.
2256  */
2257  foreach(cell, table_oids)
2258  {
2259  Oid relid = lfirst_oid(cell);
2260  autovac_table *tab;
2261  bool skipit;
2262  int stdVacuumCostDelay;
2263  int stdVacuumCostLimit;
2264  dlist_iter iter;
2265 
2267 
2268  /*
2269  * Check for config changes before processing each collected table.
2270  */
2271  if (got_SIGHUP)
2272  {
2273  got_SIGHUP = false;
2275 
2276  /*
2277  * You might be tempted to bail out if we see autovacuum is now
2278  * disabled. Must resist that temptation -- this might be a
2279  * for-wraparound emergency worker, in which case that would be
2280  * entirely inappropriate.
2281  */
2282  }
2283 
2284  /*
2285  * hold schedule lock from here until we're sure that this table still
2286  * needs vacuuming. We also need the AutovacuumLock to walk the
2287  * worker array, but we'll let go of that one quickly.
2288  */
2289  LWLockAcquire(AutovacuumScheduleLock, LW_EXCLUSIVE);
2290  LWLockAcquire(AutovacuumLock, LW_SHARED);
2291 
2292  /*
2293  * Check whether the table is being vacuumed concurrently by another
2294  * worker.
2295  */
2296  skipit = false;
2298  {
2299  WorkerInfo worker = dlist_container(WorkerInfoData, wi_links, iter.cur);
2300 
2301  /* ignore myself */
2302  if (worker == MyWorkerInfo)
2303  continue;
2304 
2305  /* ignore workers in other databases (unless table is shared) */
2306  if (!worker->wi_sharedrel && worker->wi_dboid != MyDatabaseId)
2307  continue;
2308 
2309  if (worker->wi_tableoid == relid)
2310  {
2311  skipit = true;
2312  found_concurrent_worker = true;
2313  break;
2314  }
2315  }
2316  LWLockRelease(AutovacuumLock);
2317  if (skipit)
2318  {
2319  LWLockRelease(AutovacuumScheduleLock);
2320  continue;
2321  }
2322 
2323  /*
2324  * Check whether pgstat data still says we need to vacuum this table.
2325  * It could have changed if something else processed the table while
2326  * we weren't looking.
2327  *
2328  * Note: we have a special case in pgstat code to ensure that the
2329  * stats we read are as up-to-date as possible, to avoid the problem
2330  * that somebody just finished vacuuming this table. The window to
2331  * the race condition is not closed but it is very small.
2332  */
2334  tab = table_recheck_autovac(relid, table_toast_map, pg_class_desc,
2335  effective_multixact_freeze_max_age);
2336  if (tab == NULL)
2337  {
2338  /* someone else vacuumed the table, or it went away */
2339  LWLockRelease(AutovacuumScheduleLock);
2340  continue;
2341  }
2342 
2343  /*
2344  * Ok, good to go. Store the table in shared memory before releasing
2345  * the lock so that other workers don't vacuum it concurrently.
2346  */
2347  MyWorkerInfo->wi_tableoid = relid;
2349  LWLockRelease(AutovacuumScheduleLock);
2350 
2351  /*
2352  * Remember the prevailing values of the vacuum cost GUCs. We have to
2353  * restore these at the bottom of the loop, else we'll compute wrong
2354  * values in the next iteration of autovac_balance_cost().
2355  */
2356  stdVacuumCostDelay = VacuumCostDelay;
2357  stdVacuumCostLimit = VacuumCostLimit;
2358 
2359  /* Must hold AutovacuumLock while mucking with cost balance info */
2360  LWLockAcquire(AutovacuumLock, LW_EXCLUSIVE);
2361 
2362  /* advertise my cost delay parameters for the balancing algorithm */
2367 
2368  /* do a balance */
2370 
2371  /* set the active cost parameters from the result of that */
2373 
2374  /* done */
2375  LWLockRelease(AutovacuumLock);
2376 
2377  /* clean up memory before each iteration */
2379 
2380  /*
2381  * Save the relation name for a possible error message, to avoid a
2382  * catalog lookup in case of an error. If any of these return NULL,
2383  * then the relation has been dropped since last we checked; skip it.
2384  * Note: they must live in a long-lived memory context because we call
2385  * vacuum and analyze in different transactions.
2386  */
2387 
2388  tab->at_relname = get_rel_name(tab->at_relid);
2391  if (!tab->at_relname || !tab->at_nspname || !tab->at_datname)
2392  goto deleted;
2393 
2394  /*
2395  * We will abort vacuuming the current table if something errors out,
2396  * and continue with the next one in schedule; in particular, this
2397  * happens if we are interrupted with SIGINT.
2398  */
2399  PG_TRY();
2400  {
2401  /* have at it */
2403  autovacuum_do_vac_analyze(tab, bstrategy);
2404 
2405  /*
2406  * Clear a possible query-cancel signal, to avoid a late reaction
2407  * to an automatically-sent signal because of vacuuming the
2408  * current table (we're done with it, so it would make no sense to
2409  * cancel at this point.)
2410  */
2411  QueryCancelPending = false;
2412  }
2413  PG_CATCH();
2414  {
2415  /*
2416  * Abort the transaction, start a new one, and proceed with the
2417  * next table in our list.
2418  */
2419  HOLD_INTERRUPTS();
2420  if (tab->at_vacoptions & VACOPT_VACUUM)
2421  errcontext("automatic vacuum of table \"%s.%s.%s\"",
2422  tab->at_datname, tab->at_nspname, tab->at_relname);
2423  else
2424  errcontext("automatic analyze of table \"%s.%s.%s\"",
2425  tab->at_datname, tab->at_nspname, tab->at_relname);
2426  EmitErrorReport();
2427 
2428  /* this resets the PGXACT flags too */
2430  FlushErrorState();
2432 
2433  /* restart our transaction for the following operations */
2436  }
2437  PG_END_TRY();
2438 
2439  did_vacuum = true;
2440 
2441  /* the PGXACT flags are reset at the next end of transaction */
2442 
2443  /* be tidy */
2444 deleted:
2445  if (tab->at_datname != NULL)
2446  pfree(tab->at_datname);
2447  if (tab->at_nspname != NULL)
2448  pfree(tab->at_nspname);
2449  if (tab->at_relname != NULL)
2450  pfree(tab->at_relname);
2451  pfree(tab);
2452 
2453  /*
2454  * Remove my info from shared memory. We could, but intentionally
2455  * don't, clear wi_cost_limit and friends --- this is on the
2456  * assumption that we probably have more to do with similar cost
2457  * settings, so we don't want to give up our share of I/O for a very
2458  * short interval and thereby thrash the global balance.
2459  */
2460  LWLockAcquire(AutovacuumLock, LW_EXCLUSIVE);
2462  MyWorkerInfo->wi_sharedrel = false;
2463  LWLockRelease(AutovacuumLock);
2464 
2465  /* restore vacuum cost GUCs for the next iteration */
2466  VacuumCostDelay = stdVacuumCostDelay;
2467  VacuumCostLimit = stdVacuumCostLimit;
2468  }
2469 
2470  /*
2471  * We leak table_toast_map here (among other things), but since we're
2472  * going away soon, it's not a problem.
2473  */
2474 
2475  /*
2476  * Update pg_database.datfrozenxid, and truncate pg_clog if possible. We
2477  * only need to do this once, not after each table.
2478  *
2479  * Even if we didn't vacuum anything, it may still be important to do
2480  * this, because one indirect effect of vac_update_datfrozenxid() is to
2481  * update ShmemVariableCache->xidVacLimit. That might need to be done
2482  * even if we haven't vacuumed anything, because relations with older
2483  * relfrozenxid values or other databases with older datfrozenxid values
2484  * might have been dropped, allowing xidVacLimit to advance.
2485  *
2486  * However, it's also important not to do this blindly in all cases,
2487  * because when autovacuum=off this will restart the autovacuum launcher.
2488  * If we're not careful, an infinite loop can result, where workers find
2489  * no work to do and restart the launcher, which starts another worker in
2490  * the same database that finds no work to do. To prevent that, we skip
2491  * this if (1) we found no work to do and (2) we skipped at least one
2492  * table due to concurrent autovacuum activity. In that case, the other
2493  * worker has already done it, or will do so when it finishes.
2494  */
2495  if (did_vacuum || !found_concurrent_worker)
2497 
2498  /* Finally close out the last transaction. */
2500 }
BufferAccessStrategy GetAccessStrategy(BufferAccessStrategyType btype)
Definition: freelist.c:525
#define NIL
Definition: pg_list.h:69
bool ConditionalLockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:138
static int default_freeze_table_age
Definition: autovacuum.c:149
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:141
BackendId MyBackendId
Definition: globals.c:72
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
static void autovac_balance_cost(void)
Definition: autovacuum.c:1730
MemoryContext TopTransactionContext
Definition: mcxt.c:48
int vacuum_multixact_freeze_table_age
Definition: vacuum.c:60
void heap_endscan(HeapScanDesc scan)
Definition: heapam.c:1581
int at_vacuum_cost_delay
Definition: autovacuum.c:191
#define HASH_ELEM
Definition: hsearch.h:87
void ProcessConfigFile(GucContext context)
void vac_update_datfrozenxid(void)
Definition: vacuum.c:892
static int default_multixact_freeze_min_age
Definition: autovacuum.c:150
#define RelationGetDescr(relation)
Definition: rel.h:425
void UnlockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:182
FormData_pg_database * Form_pg_database
Definition: pg_database.h:57
#define dlist_foreach(iter, lhead)
Definition: ilist.h:507
void CommitTransactionCommand(void)
Definition: xact.c:2745
#define RelationRelationId
Definition: pg_class.h:29
static MemoryContext AutovacMemCxt
Definition: autovacuum.c:154
Oid get_rel_namespace(Oid relid)
Definition: lsyscache.c:1718
#define RELKIND_MATVIEW
Definition: pg_class.h:167
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define AccessShareLock
Definition: lockdefs.h:36
Size entrysize
Definition: hsearch.h:73
#define MemSet(start, val, len)
Definition: c.h:852
static volatile sig_atomic_t got_SIGHUP
Definition: autovacuum.c:139
PgStat_StatDBEntry * pgstat_fetch_stat_dbentry(Oid dbid)
Definition: pgstat.c:2285
int GetTempNamespaceBackendId(Oid namespaceId)
Definition: namespace.c:3029
#define heap_close(r, l)
Definition: heapam.h:97
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:885
char * at_datname
Definition: autovacuum.c:197
#define LOG
Definition: elog.h:26
unsigned int Oid
Definition: postgres_ext.h:31
volatile bool QueryCancelPending
Definition: globals.c:30
List * lappend_oid(List *list, Oid datum)
Definition: list.c:164
#define OidIsValid(objectId)
Definition: c.h:533
void AbortOutOfAnyTransaction(void)
Definition: xact.c:4220
void FlushErrorState(void)
Definition: elog.c:1587
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:149
MemoryContext PortalContext
Definition: mcxt.c:52
bool at_sharedrel
Definition: autovacuum.c:194
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1714
#define RESUME_INTERRUPTS()
Definition: miscadmin.h:116
#define Anum_pg_class_relkind
Definition: pg_class.h:118
int at_vacuum_cost_limit
Definition: autovacuum.c:192
Definition: dynahash.c:193
char * at_relname
Definition: autovacuum.c:195
#define dlist_container(type, membername, ptr)
Definition: ilist.h:477
void pfree(void *pointer)
Definition: mcxt.c:992
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
int VacuumCostLimit
Definition: globals.c:131
int vacuum_multixact_freeze_min_age
Definition: vacuum.c:59
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:145
char * get_database_name(Oid dbid)
Definition: dbcommands.c:2049
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3006
static AutoVacOpts * extract_autovac_opts(HeapTuple tup, TupleDesc pg_class_desc)
Definition: autovacuum.c:2509
void performDeletion(const ObjectAddress *object, DropBehavior behavior, int flags)
Definition: dependency.c:301
static PgStat_StatTabEntry * get_pgstat_tabentry_relid(Oid relid, bool isshared, PgStat_StatDBEntry *shared, PgStat_StatDBEntry *dbentry)
Definition: autovacuum.c:2535
static WorkerInfo MyWorkerInfo
Definition: autovacuum.c:280
HeapScanDesc heap_beginscan_catalog(Relation relation, int nkeys, ScanKey key)
Definition: heapam.c:1402
static void relation_needs_vacanalyze(Oid relid, AutoVacOpts *relopts, Form_pg_class classForm, PgStat_StatTabEntry *tabentry, int effective_multixact_freeze_max_age, bool *dovacuum, bool *doanalyze, bool *wraparound)
Definition: autovacuum.c:2744
#define ereport(elevel, rest)
Definition: elog.h:122
void pgstat_vacuum_stat(void)
Definition: pgstat.c:946
int MultiXactMemberFreezeThreshold(void)
Definition: multixact.c:2812
int wi_cost_limit_base
Definition: autovacuum.c:229
MemoryContext TopMemoryContext
Definition: mcxt.c:43
Definition: guc.h:72
#define MemoryContextResetAndDeleteChildren(ctx)
Definition: memutils.h:88
#define HASH_BLOBS
Definition: hsearch.h:88
char * at_nspname
Definition: autovacuum.c:196
#define InvalidBackendId
Definition: backendid.h:23
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:440
#define RELKIND_TOASTVALUE
Definition: pg_class.h:163
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:301
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1083
Oid MyDatabaseId
Definition: globals.c:76
HeapTuple heap_getnext(HeapScanDesc scan, ScanDirection direction)
Definition: heapam.c:1781
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1287
Size keysize
Definition: hsearch.h:72
dlist_node * cur
Definition: ilist.h:161
void EmitErrorReport(void)
Definition: elog.c:1446
#define InvalidOid
Definition: postgres_ext.h:36
int VacuumCostDelay
Definition: globals.c:132
#define PG_CATCH()
Definition: elog.h:293
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:226
#define PERFORM_DELETION_QUIETLY
Definition: dependency.h:175
void StartTransactionCommand(void)
Definition: xact.c:2675
static AutoVacuumShmemStruct * AutoVacuumShmem
Definition: autovacuum.c:270
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1110
int vacuum_freeze_min_age
Definition: vacuum.c:57
int vacuum_freeze_table_age
Definition: vacuum.c:58
#define CharGetDatum(X)
Definition: postgres.h:424
FormData_pg_class * Form_pg_class
Definition: pg_class.h:95
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:158
AutoVacOpts ar_reloptions
Definition: autovacuum.c:181
#define AccessExclusiveLock
Definition: lockdefs.h:46
static void autovacuum_do_vac_analyze(autovac_table *tab, BufferAccessStrategy bstrategy)
Definition: autovacuum.c:2889
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define HOLD_INTERRUPTS()
Definition: miscadmin.h:114
#define errcontext
Definition: elog.h:164
#define NameStr(name)
Definition: c.h:494
struct av_relation av_relation
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
void AutoVacuumUpdateDelay(void)
Definition: autovacuum.c:1714
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:97
#define elog
Definition: elog.h:219
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:695
#define RELPERSISTENCE_TEMP
Definition: pg_class.h:172
dlist_head av_runningWorkers
Definition: autovacuum.c:266
#define PG_TRY()
Definition: elog.h:284
#define PERFORM_DELETION_SKIP_EXTENSIONS
Definition: dependency.h:177
#define RELKIND_RELATION
Definition: pg_class.h:160
bool ar_hasrelopts
Definition: autovacuum.c:180
Definition: pg_list.h:45
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1694
static int default_multixact_freeze_table_age
Definition: autovacuum.c:151
static int default_freeze_min_age
Definition: autovacuum.c:148
#define PG_END_TRY()
Definition: elog.h:300
#define BTEqualStrategyNumber
Definition: stratnum.h:31
bool at_dobalance
Definition: autovacuum.c:193
#define lfirst_oid(lc)
Definition: pg_list.h:108
static autovac_table * table_recheck_autovac(Oid relid, HTAB *table_toast_map, TupleDesc pg_class_desc, int effective_multixact_freeze_max_age)
Definition: autovacuum.c:2562
#define PERFORM_DELETION_INTERNAL
Definition: dependency.h:173
PGPROC * BackendIdGetProc(int backendID)
Definition: sinvaladt.c:377
static Oid do_start_worker ( void  )
static

Definition at line 1080 of file autovacuum.c.

References avl_dbase::adl_datid, avl_dbase::adl_next_worker, avw_dbase::adw_datid, avw_dbase::adw_entry, avw_dbase::adw_frozenxid, avw_dbase::adw_minmulti, ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate(), autovac_refresh_stats(), autovacuum_freeze_max_age, autovacuum_naptime, AutoVacuumShmemStruct::av_freeWorkers, AutoVacuumShmemStruct::av_startingWorker, dlist_iter::cur, CurrentMemoryContext, dblist, dlist_container, dlist_is_empty(), dlist_pop_head_node(), dlist_reverse_foreach, FirstMultiXactId, FirstNormalTransactionId, get_database_list(), GetCurrentTimestamp(), InvalidOid, PgStat_StatDBEntry::last_autovac_time, lfirst, LW_EXCLUSIVE, LW_SHARED, LWLockAcquire(), LWLockRelease(), MemoryContextDelete(), MemoryContextSwitchTo(), MultiXactIdPrecedes(), MultiXactMemberFreezeThreshold(), NULL, pgstat_fetch_stat_dbentry(), PMSIGNAL_START_AUTOVAC_WORKER, ReadNewTransactionId(), ReadNextMultiXactId(), rebuild_database_list(), recentMulti, recentXid, SendPostmasterSignal(), TimestampDifferenceExceeds(), TransactionIdPrecedes(), WorkerInfoData::wi_dboid, WorkerInfoData::wi_launchtime, and WorkerInfoData::wi_proc.

Referenced by AutoVacLauncherMain(), and launch_worker().

1081 {
1082  List *dblist;
1083  ListCell *cell;
1084  TransactionId xidForceLimit;
1085  MultiXactId multiForceLimit;
1086  bool for_xid_wrap;
1087  bool for_multi_wrap;
1088  avw_dbase *avdb;
1089  TimestampTz current_time;
1090  bool skipit = false;
1091  Oid retval = InvalidOid;
1092  MemoryContext tmpcxt,
1093  oldcxt;
1094 
1095  /* return quickly when there are no free workers */
1096  LWLockAcquire(AutovacuumLock, LW_SHARED);
1098  {
1099  LWLockRelease(AutovacuumLock);
1100  return InvalidOid;
1101  }
1102  LWLockRelease(AutovacuumLock);
1103 
1104  /*
1105  * Create and switch to a temporary context to avoid leaking the memory
1106  * allocated for the database list.
1107  */
1109  "Start worker tmp cxt",
1111  oldcxt = MemoryContextSwitchTo(tmpcxt);
1112 
1113  /* use fresh stats */
1115 
1116  /* Get a list of databases */
1117  dblist = get_database_list();
1118 
1119  /*
1120  * Determine the oldest datfrozenxid/relfrozenxid that we will allow to
1121  * pass without forcing a vacuum. (This limit can be tightened for
1122  * particular tables, but not loosened.)
1123  */
1125  xidForceLimit = recentXid - autovacuum_freeze_max_age;
1126  /* ensure it's a "normal" XID, else TransactionIdPrecedes misbehaves */
1127  /* this can cause the limit to go backwards by 3, but that's OK */
1128  if (xidForceLimit < FirstNormalTransactionId)
1129  xidForceLimit -= FirstNormalTransactionId;
1130 
1131  /* Also determine the oldest datminmxid we will consider. */
1133  multiForceLimit = recentMulti - MultiXactMemberFreezeThreshold();
1134  if (multiForceLimit < FirstMultiXactId)
1135  multiForceLimit -= FirstMultiXactId;
1136 
1137  /*
1138  * Choose a database to connect to. We pick the database that was least
1139  * recently auto-vacuumed, or one that needs vacuuming to prevent Xid
1140  * wraparound-related data loss. If any db at risk of Xid wraparound is
1141  * found, we pick the one with oldest datfrozenxid, independently of
1142  * autovacuum times; similarly we pick the one with the oldest datminmxid
1143  * if any is in MultiXactId wraparound. Note that those in Xid wraparound
1144  * danger are given more priority than those in multi wraparound danger.
1145  *
1146  * Note that a database with no stats entry is not considered, except for
1147  * Xid wraparound purposes. The theory is that if no one has ever
1148  * connected to it since the stats were last initialized, it doesn't need
1149  * vacuuming.
1150  *
1151  * XXX This could be improved if we had more info about whether it needs
1152  * vacuuming before connecting to it. Perhaps look through the pgstats
1153  * data for the database's tables? One idea is to keep track of the
1154  * number of new and dead tuples per database in pgstats. However it
1155  * isn't clear how to construct a metric that measures that and not cause
1156  * starvation for less busy databases.
1157  */
1158  avdb = NULL;
1159  for_xid_wrap = false;
1160  for_multi_wrap = false;
1161  current_time = GetCurrentTimestamp();
1162  foreach(cell, dblist)
1163  {
1164  avw_dbase *tmp = lfirst(cell);
1165  dlist_iter iter;
1166 
1167  /* Check to see if this one is at risk of wraparound */
1168  if (TransactionIdPrecedes(tmp->adw_frozenxid, xidForceLimit))
1169  {
1170  if (avdb == NULL ||
1172  avdb->adw_frozenxid))
1173  avdb = tmp;
1174  for_xid_wrap = true;
1175  continue;
1176  }
1177  else if (for_xid_wrap)
1178  continue; /* ignore not-at-risk DBs */
1179  else if (MultiXactIdPrecedes(tmp->adw_minmulti, multiForceLimit))
1180  {
1181  if (avdb == NULL ||
1183  avdb = tmp;
1184  for_multi_wrap = true;
1185  continue;
1186  }
1187  else if (for_multi_wrap)
1188  continue; /* ignore not-at-risk DBs */
1189 
1190  /* Find pgstat entry if any */
1192 
1193  /*
1194  * Skip a database with no pgstat entry; it means it hasn't seen any
1195  * activity.
1196  */
1197  if (!tmp->adw_entry)
1198  continue;
1199 
1200  /*
1201  * Also, skip a database that appears on the database list as having
1202  * been processed recently (less than autovacuum_naptime seconds ago).
1203  * We do this so that we don't select a database which we just
1204  * selected, but that pgstat hasn't gotten around to updating the last
1205  * autovacuum time yet.
1206  */
1207  skipit = false;
1208 
1210  {
1211  avl_dbase *dbp = dlist_container(avl_dbase, adl_node, iter.cur);
1212 
1213  if (dbp->adl_datid == tmp->adw_datid)
1214  {
1215  /*
1216  * Skip this database if its next_worker value falls between
1217  * the current time and the current time plus naptime.
1218  */
1220  current_time, 0) &&
1221  !TimestampDifferenceExceeds(current_time,
1222  dbp->adl_next_worker,
1223  autovacuum_naptime * 1000))
1224  skipit = true;
1225 
1226  break;
1227  }
1228  }
1229  if (skipit)
1230  continue;
1231 
1232  /*
1233  * Remember the db with oldest autovac time. (If we are here, both
1234  * tmp->entry and db->entry must be non-null.)
1235  */
1236  if (avdb == NULL ||
1238  avdb = tmp;
1239  }
1240 
1241  /* Found a database -- process it */
1242  if (avdb != NULL)
1243  {
1244  WorkerInfo worker;
1245  dlist_node *wptr;
1246 
1247  LWLockAcquire(AutovacuumLock, LW_EXCLUSIVE);
1248 
1249  /*
1250  * Get a worker entry from the freelist. We checked above, so there
1251  * really should be a free slot.
1252  */
1254 
1255  worker = dlist_container(WorkerInfoData, wi_links, wptr);
1256  worker->wi_dboid = avdb->adw_datid;
1257  worker->wi_proc = NULL;
1258  worker->wi_launchtime = GetCurrentTimestamp();
1259 
1261 
1262  LWLockRelease(AutovacuumLock);
1263 
1265 
1266  retval = avdb->adw_datid;
1267  }
1268  else if (skipit)
1269  {
1270  /*
1271  * If we skipped all databases on the list, rebuild it, because it
1272  * probably contains a dropped database.
1273  */
1275  }
1276 
1277  MemoryContextSwitchTo(oldcxt);
1278  MemoryContextDelete(tmpcxt);
1279 
1280  return retval;
1281 }
int autovacuum_naptime
Definition: autovacuum.c:114
TimestampTz adl_next_worker
Definition: autovacuum.c:160
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:200
MultiXactId adw_minmulti
Definition: autovacuum.c:171
WorkerInfo av_startingWorker
Definition: autovacuum.c:267
dlist_head av_freeWorkers
Definition: autovacuum.c:265
uint32 TransactionId
Definition: c.h:393
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1688
TimestampTz wi_launchtime
Definition: autovacuum.c:224
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
static MultiXactId recentMulti
Definition: autovacuum.c:145
static void autovac_refresh_stats(void)
Definition: autovacuum.c:3065
PgStat_StatDBEntry * pgstat_fetch_stat_dbentry(Oid dbid)
Definition: pgstat.c:2285
unsigned int Oid
Definition: postgres_ext.h:31
bool TimestampDifferenceExceeds(TimestampTz start_time, TimestampTz stop_time, int msec)
Definition: timestamp.c:1821
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1714
#define dlist_container(type, membername, ptr)
Definition: ilist.h:477
double TimestampTz
Definition: timestamp.h:51
#define FirstNormalTransactionId
Definition: transam.h:34
int autovacuum_freeze_max_age
Definition: autovacuum.c:119
static List * get_database_list(void)
Definition: autovacuum.c:1818
Oid adl_datid
Definition: autovacuum.c:159
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:145
_stringlist * dblist
Definition: pg_regress.c:70
TimestampTz last_autovac_time
Definition: pgstat.h:587
TransactionId ReadNewTransactionId(void)
Definition: varsup.c:250
#define FirstMultiXactId
Definition: multixact.h:24
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
static dlist_head DatabaseList
Definition: autovacuum.c:276
int MultiXactMemberFreezeThreshold(void)
Definition: multixact.c:2812
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
TransactionId adw_frozenxid
Definition: autovacuum.c:170
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:440
PgStat_StatDBEntry * adw_entry
Definition: autovacuum.c:172
Oid adw_datid
Definition: autovacuum.c:168
static TransactionId recentXid
Definition: autovacuum.c:144
dlist_node * cur
Definition: ilist.h:161
#define InvalidOid
Definition: postgres_ext.h:36
TransactionId MultiXactId
Definition: c.h:403
#define NULL
Definition: c.h:226
#define lfirst(lc)
Definition: pg_list.h:106
static bool dlist_is_empty(dlist_head *head)
Definition: ilist.h:289
static AutoVacuumShmemStruct * AutoVacuumShmem
Definition: autovacuum.c:270
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1110
bool MultiXactIdPrecedes(MultiXactId multi1, MultiXactId multi2)
Definition: multixact.c:3135
static void rebuild_database_list(Oid newdb)
Definition: autovacuum.c:879
static dlist_node * dlist_pop_head_node(dlist_head *head)
Definition: ilist.h:368
PGPROC * wi_proc
Definition: autovacuum.c:223
void SendPostmasterSignal(PMSignalReason reason)
Definition: pmsignal.c:113
Definition: pg_list.h:45
#define dlist_reverse_foreach(iter, lhead)
Definition: ilist.h:538
MultiXactId ReadNextMultiXactId(void)
Definition: multixact.c:721
static AutoVacOpts * extract_autovac_opts ( HeapTuple  tup,
TupleDesc  pg_class_desc 
)
static

Definition at line 2509 of file autovacuum.c.

References Assert, av, extractRelOptions(), GETSTRUCT, NULL, palloc(), pfree(), RELKIND_MATVIEW, RELKIND_RELATION, and RELKIND_TOASTVALUE.

Referenced by do_autovacuum(), and table_recheck_autovac().

2510 {
2511  bytea *relopts;
2512  AutoVacOpts *av;
2513 
2514  Assert(((Form_pg_class) GETSTRUCT(tup))->relkind == RELKIND_RELATION ||
2515  ((Form_pg_class) GETSTRUCT(tup))->relkind == RELKIND_MATVIEW ||
2516  ((Form_pg_class) GETSTRUCT(tup))->relkind == RELKIND_TOASTVALUE);
2517 
2518  relopts = extractRelOptions(tup, pg_class_desc, NULL);
2519  if (relopts == NULL)
2520  return NULL;
2521 
2522  av = palloc(sizeof(AutoVacOpts));
2523  memcpy(av, &(((StdRdOptions *) relopts)->autovacuum), sizeof(AutoVacOpts));
2524  pfree(relopts);
2525 
2526  return av;
2527 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define RELKIND_MATVIEW
Definition: pg_class.h:167
void pfree(void *pointer)
Definition: mcxt.c:992
struct @18::@19 av[32]
#define RELKIND_TOASTVALUE
Definition: pg_class.h:163
bytea * extractRelOptions(HeapTuple tuple, TupleDesc tupdesc, amoptions_function amoptions)
Definition: reloptions.c:910
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:670
FormData_pg_class * Form_pg_class
Definition: pg_class.h:95
void * palloc(Size size)
Definition: mcxt.c:891
Definition: c.h:434
#define RELKIND_RELATION
Definition: pg_class.h:160
static void FreeWorkerInfo ( int  code,
Datum  arg 
)
static

Definition at line 1665 of file autovacuum.c.

References AutoVacRebalance, AutovacuumLauncherPid, AutoVacuumShmemStruct::av_freeWorkers, AutoVacuumShmemStruct::av_launcherpid, AutoVacuumShmemStruct::av_signal, dlist_delete(), dlist_push_head(), InvalidOid, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), NULL, WorkerInfoData::wi_cost_delay, WorkerInfoData::wi_cost_limit, WorkerInfoData::wi_cost_limit_base, WorkerInfoData::wi_dboid, WorkerInfoData::wi_dobalance, WorkerInfoData::wi_launchtime, WorkerInfoData::wi_links, WorkerInfoData::wi_proc, WorkerInfoData::wi_sharedrel, and WorkerInfoData::wi_tableoid.

Referenced by AutoVacWorkerMain().

1666 {
1667  if (MyWorkerInfo != NULL)
1668  {
1669  LWLockAcquire(AutovacuumLock, LW_EXCLUSIVE);
1670 
1671  /*
1672  * Wake the launcher up so that he can launch a new worker immediately
1673  * if required. We only save the launcher's PID in local memory here;
1674  * the actual signal will be sent when the PGPROC is recycled. Note
1675  * that we always do this, so that the launcher can rebalance the cost
1676  * limit setting of the remaining workers.
1677  *
1678  * We somewhat ignore the risk that the launcher changes its PID
1679  * between us reading it and the actual kill; we expect ProcKill to be
1680  * called shortly after us, and we assume that PIDs are not reused too
1681  * quickly after a process exits.
1682  */
1684 
1688  MyWorkerInfo->wi_sharedrel = false;
1691  MyWorkerInfo->wi_dobalance = false;
1697  /* not mine anymore */
1698  MyWorkerInfo = NULL;
1699 
1700  /*
1701  * now that we're inactive, cause a rebalancing of the surviving
1702  * workers
1703  */
1705  LWLockRelease(AutovacuumLock);
1706  }
1707 }
sig_atomic_t av_signal[AutoVacNumSignals]
Definition: autovacuum.c:263
dlist_head av_freeWorkers
Definition: autovacuum.c:265
static void dlist_push_head(dlist_head *head, dlist_node *node)
Definition: ilist.h:300
TimestampTz wi_launchtime
Definition: autovacuum.c:224
dlist_node wi_links
Definition: autovacuum.c:220
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1714
int AutovacuumLauncherPid
Definition: autovacuum.c:283
static WorkerInfo MyWorkerInfo
Definition: autovacuum.c:280
static void dlist_delete(dlist_node *node)
Definition: ilist.h:358
int wi_cost_limit_base
Definition: autovacuum.c:229
#define InvalidOid
Definition: postgres_ext.h:36
#define NULL
Definition: c.h:226
static AutoVacuumShmemStruct * AutoVacuumShmem
Definition: autovacuum.c:270
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1110
PGPROC * wi_proc
Definition: autovacuum.c:223
static List * get_database_list ( void  )
static

Definition at line 1818 of file autovacuum.c.

References AccessShareLock, avw_dbase::adw_datid, avw_dbase::adw_entry, avw_dbase::adw_frozenxid, avw_dbase::adw_minmulti, avw_dbase::adw_name, CommitTransactionCommand(), CurrentMemoryContext, DatabaseRelationId, dblist, ForwardScanDirection, GETSTRUCT, GetTransactionSnapshot(), heap_beginscan_catalog(), heap_close, heap_endscan(), heap_getnext(), heap_open(), HeapTupleGetOid, HeapTupleIsValid, lappend(), MemoryContextSwitchTo(), NameStr, NIL, NULL, palloc(), pstrdup(), and StartTransactionCommand().

Referenced by do_start_worker(), and rebuild_database_list().

1819 {
1820  List *dblist = NIL;
1821  Relation rel;
1822  HeapScanDesc scan;
1823  HeapTuple tup;
1824  MemoryContext resultcxt;
1825 
1826  /* This is the context that we will allocate our output data in */
1827  resultcxt = CurrentMemoryContext;
1828 
1829  /*
1830  * Start a transaction so we can access pg_database, and get a snapshot.
1831  * We don't have a use for the snapshot itself, but we're interested in
1832  * the secondary effect that it sets RecentGlobalXmin. (This is critical
1833  * for anything that reads heap pages, because HOT may decide to prune
1834  * them even if the process doesn't attempt to modify any tuples.)
1835  */
1837  (void) GetTransactionSnapshot();
1838 
1840  scan = heap_beginscan_catalog(rel, 0, NULL);
1841 
1842  while (HeapTupleIsValid(tup = heap_getnext(scan, ForwardScanDirection)))
1843  {
1844  Form_pg_database pgdatabase = (Form_pg_database) GETSTRUCT(tup);
1845  avw_dbase *avdb;
1846  MemoryContext oldcxt;
1847 
1848  /*
1849  * Allocate our results in the caller's context, not the
1850  * transaction's. We do this inside the loop, and restore the original
1851  * context at the end, so that leaky things like heap_getnext() are
1852  * not called in a potentially long-lived context.
1853  */
1854  oldcxt = MemoryContextSwitchTo(resultcxt);
1855 
1856  avdb = (avw_dbase *) palloc(sizeof(avw_dbase));
1857 
1858  avdb->adw_datid = HeapTupleGetOid(tup);
1859  avdb->adw_name = pstrdup(NameStr(pgdatabase->datname));
1860  avdb->adw_frozenxid = pgdatabase->datfrozenxid;
1861  avdb->adw_minmulti = pgdatabase->datminmxid;
1862  /* this gets set later: */
1863  avdb->adw_entry = NULL;
1864 
1865  dblist = lappend(dblist, avdb);
1866  MemoryContextSwitchTo(oldcxt);
1867  }
1868 
1869  heap_endscan(scan);
1871 
1873 
1874  return dblist;
1875 }
#define NIL
Definition: pg_list.h:69
MultiXactId adw_minmulti
Definition: autovacuum.c:171
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
void heap_endscan(HeapScanDesc scan)
Definition: heapam.c:1581
FormData_pg_database * Form_pg_database
Definition: pg_database.h:57
char * pstrdup(const char *in)
Definition: mcxt.c:1165
#define DatabaseRelationId
Definition: pg_database.h:29
void CommitTransactionCommand(void)
Definition: xact.c:2745
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define AccessShareLock
Definition: lockdefs.h:36
#define heap_close(r, l)
Definition: heapam.h:97
Snapshot GetTransactionSnapshot(void)
Definition: snapmgr.c:300
_stringlist * dblist
Definition: pg_regress.c:70
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
HeapScanDesc heap_beginscan_catalog(Relation relation, int nkeys, ScanKey key)
Definition: heapam.c:1402
char * adw_name
Definition: autovacuum.c:169
List * lappend(List *list, void *datum)
Definition: list.c:128
TransactionId adw_frozenxid
Definition: autovacuum.c:170
PgStat_StatDBEntry * adw_entry
Definition: autovacuum.c:172
Oid adw_datid
Definition: autovacuum.c:168
HeapTuple heap_getnext(HeapScanDesc scan, ScanDirection direction)
Definition: heapam.c:1781
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1287
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:226
void StartTransactionCommand(void)
Definition: xact.c:2675
void * palloc(Size size)
Definition: mcxt.c:891
#define NameStr(name)
Definition: c.h:494
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:695
Definition: pg_list.h:45
static PgStat_StatTabEntry * get_pgstat_tabentry_relid ( Oid  relid,
bool  isshared,
PgStat_StatDBEntry shared,
PgStat_StatDBEntry dbentry 
)
static

Definition at line 2535 of file autovacuum.c.

References HASH_FIND, hash_search(), NULL, PointerIsValid, and PgStat_StatDBEntry::tables.

Referenced by do_autovacuum(), and table_recheck_autovac().

2537 {
2538  PgStat_StatTabEntry *tabentry = NULL;
2539 
2540  if (isshared)
2541  {
2542  if (PointerIsValid(shared))
2543  tabentry = hash_search(shared->tables, &relid,
2544  HASH_FIND, NULL);
2545  }
2546  else if (PointerIsValid(dbentry))
2547  tabentry = hash_search(dbentry->tables, &relid,
2548  HASH_FIND, NULL);
2549 
2550  return tabentry;
2551 }
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:885
#define NULL
Definition: c.h:226
#define PointerIsValid(pointer)
Definition: c.h:521
bool IsAutoVacuumLauncherProcess ( void  )

Definition at line 2983 of file autovacuum.c.

References am_autovacuum_launcher.

Referenced by autovac_refresh_stats(), backend_read_statsfile(), InitPostgres(), InitProcess(), and ProcKill().

2984 {
2985  return am_autovacuum_launcher;
2986 }
static bool am_autovacuum_launcher
Definition: autovacuum.c:135
static void launch_worker ( TimestampTz  now)
static

Definition at line 1295 of file autovacuum.c.

References avl_dbase::adl_datid, avl_dbase::adl_next_worker, autovacuum_naptime, dlist_iter::cur, dlist_container, dlist_foreach, dlist_move_head(), do_start_worker(), OidIsValid, rebuild_database_list(), and TimestampTzPlusMilliseconds.

Referenced by AutoVacLauncherMain().

1296 {
1297  Oid dbid;
1298  dlist_iter iter;
1299 
1300  dbid = do_start_worker();
1301  if (OidIsValid(dbid))
1302  {
1303  bool found = false;
1304 
1305  /*
1306  * Walk the database list and update the corresponding entry. If the
1307  * database is not on the list, we'll recreate the list.
1308  */
1309  dlist_foreach(iter, &DatabaseList)
1310  {
1311  avl_dbase *avdb = dlist_container(avl_dbase, adl_node, iter.cur);
1312 
1313  if (avdb->adl_datid == dbid)
1314  {
1315  found = true;
1316 
1317  /*
1318  * add autovacuum_naptime seconds to the current time, and use
1319  * that as the new "next_worker" field for this database.
1320  */
1321  avdb->adl_next_worker =
1323 
1325  break;
1326  }
1327  }
1328 
1329  /*
1330  * If the database was not present in the database list, we rebuild
1331  * the list. It's possible that the database does not get into the
1332  * list anyway, for example if it's a database that doesn't have a
1333  * pgstat entry, but this is not a problem because we don't want to
1334  * schedule workers regularly into those in any case.
1335  */
1336  if (!found)
1337  rebuild_database_list(dbid);
1338  }
1339 }
int autovacuum_naptime
Definition: autovacuum.c:114
TimestampTz adl_next_worker
Definition: autovacuum.c:160
#define dlist_foreach(iter, lhead)
Definition: ilist.h:507
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:533
#define dlist_container(type, membername, ptr)
Definition: ilist.h:477
Oid adl_datid
Definition: autovacuum.c:159
static dlist_head DatabaseList
Definition: autovacuum.c:276
dlist_node * cur
Definition: ilist.h:161
#define TimestampTzPlusMilliseconds(tz, ms)
Definition: timestamp.h:80
static void dlist_move_head(dlist_head *head, dlist_node *node)
Definition: ilist.h:385
static void rebuild_database_list(Oid newdb)
Definition: autovacuum.c:879
static Oid do_start_worker(void)
Definition: autovacuum.c:1080
Datum now(PG_FUNCTION_ARGS)
Definition: timestamp.c:1652
static void launcher_determine_sleep ( bool  canlaunch,
bool  recursing,
struct timeval *  nap 
)
static

Definition at line 795 of file autovacuum.c.

References avl_dbase::adl_next_worker, autovacuum_naptime, dlist_is_empty(), dlist_tail_element, GetCurrentTimestamp(), InvalidOid, MAX_AUTOVAC_SLEEPTIME, MIN_AUTOVAC_SLEEPTIME, rebuild_database_list(), and TimestampDifference().

Referenced by AutoVacLauncherMain().

796 {
797  /*
798  * We sleep until the next scheduled vacuum. We trust that when the
799  * database list was built, care was taken so that no entries have times
800  * in the past; if the first entry has too close a next_worker value, or a
801  * time in the past, we will sleep a small nominal time.
802  */
803  if (!canlaunch)
804  {
805  nap->tv_sec = autovacuum_naptime;
806  nap->tv_usec = 0;
807  }
808  else if (!dlist_is_empty(&DatabaseList))
809  {
810  TimestampTz current_time = GetCurrentTimestamp();
811  TimestampTz next_wakeup;
812  avl_dbase *avdb;
813  long secs;
814  int usecs;
815 
816  avdb = dlist_tail_element(avl_dbase, adl_node, &DatabaseList);
817 
818  next_wakeup = avdb->adl_next_worker;
819  TimestampDifference(current_time, next_wakeup, &secs, &usecs);
820 
821  nap->tv_sec = secs;
822  nap->tv_usec = usecs;
823  }
824  else
825  {
826  /* list is empty, sleep for whole autovacuum_naptime seconds */
827  nap->tv_sec = autovacuum_naptime;
828  nap->tv_usec = 0;
829  }
830 
831  /*
832  * If the result is exactly zero, it means a database had an entry with
833  * time in the past. Rebuild the list so that the databases are evenly
834  * distributed again, and recalculate the time to sleep. This can happen
835  * if there are more tables needing vacuum than workers, and they all take
836  * longer to vacuum than autovacuum_naptime.
837  *
838  * We only recurse once. rebuild_database_list should always return times
839  * in the future, but it seems best not to trust too much on that.
840  */
841  if (nap->tv_sec == 0 && nap->tv_usec == 0 && !recursing)
842  {
844  launcher_determine_sleep(canlaunch, true, nap);
845  return;
846  }
847 
848  /* The smallest time we'll allow the launcher to sleep. */
849  if (nap->tv_sec <= 0 && nap->tv_usec <= MIN_AUTOVAC_SLEEPTIME * 1000)
850  {
851  nap->tv_sec = 0;
852  nap->tv_usec = MIN_AUTOVAC_SLEEPTIME * 1000;
853  }
854 
855  /*
856  * If the sleep time is too large, clamp it to an arbitrary maximum (plus
857  * any fractional seconds, for simplicity). This avoids an essentially
858  * infinite sleep in strange cases like the system clock going backwards a
859  * few years.
860  */
861  if (nap->tv_sec > MAX_AUTOVAC_SLEEPTIME)
862  nap->tv_sec = MAX_AUTOVAC_SLEEPTIME;
863 }
int autovacuum_naptime
Definition: autovacuum.c:114
TimestampTz adl_next_worker
Definition: autovacuum.c:160
#define MAX_AUTOVAC_SLEEPTIME
Definition: autovacuum.c:132
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1688
#define MIN_AUTOVAC_SLEEPTIME
Definition: autovacuum.c:131
double TimestampTz
Definition: timestamp.h:51
#define dlist_tail_element(type, membername, lhead)
Definition: ilist.h:496
static dlist_head DatabaseList
Definition: autovacuum.c:276
static void launcher_determine_sleep(bool canlaunch, bool recursing, struct timeval *nap)
Definition: autovacuum.c:795
#define InvalidOid
Definition: postgres_ext.h:36
static bool dlist_is_empty(dlist_head *head)
Definition: ilist.h:289
static void rebuild_database_list(Oid newdb)
Definition: autovacuum.c:879
void TimestampDifference(TimestampTz start_time, TimestampTz stop_time, long *secs, int *microsecs)
Definition: timestamp.c:1791
static void rebuild_database_list ( Oid  newdb)
static

Definition at line 879 of file autovacuum.c.

References avl_dbase::adl_datid, avl_dbase::adl_next_worker, avl_dbase::adl_node, avl_dbase::adl_score, avw_dbase::adw_datid, ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate(), autovac_refresh_stats(), autovacuum_naptime, dlist_iter::cur, db_comparator(), dblist, dlist_container, dlist_foreach, dlist_init(), dlist_push_head(), HASHCTL::entrysize, get_database_list(), GetCurrentTimestamp(), HASH_BLOBS, HASH_CONTEXT, hash_create(), HASH_ELEM, HASH_ENTER, hash_search(), hash_seq_init(), hash_seq_search(), HASHCTL::hcxt, i, HASHCTL::keysize, lfirst, MemoryContextDelete(), MemoryContextSwitchTo(), MIN_AUTOVAC_SLEEPTIME, NULL, OidIsValid, palloc(), pgstat_fetch_stat_dbentry(), qsort, and TimestampTzPlusMilliseconds.

Referenced by AutoVacLauncherMain(), do_start_worker(), launch_worker(), and launcher_determine_sleep().

880 {
881  List *dblist;
882  ListCell *cell;
883  MemoryContext newcxt;
884  MemoryContext oldcxt;
885  MemoryContext tmpcxt;
886  HASHCTL hctl;
887  int score;
888  int nelems;
889  HTAB *dbhash;
890  dlist_iter iter;
891 
892  /* use fresh stats */
894 
896  "AV dblist",
898  tmpcxt = AllocSetContextCreate(newcxt,
899  "tmp AV dblist",
901  oldcxt = MemoryContextSwitchTo(tmpcxt);
902 
903  /*
904  * Implementing this is not as simple as it sounds, because we need to put
905  * the new database at the end of the list; next the databases that were
906  * already on the list, and finally (at the tail of the list) all the
907  * other databases that are not on the existing list.
908  *
909  * To do this, we build an empty hash table of scored databases. We will
910  * start with the lowest score (zero) for the new database, then
911  * increasing scores for the databases in the existing list, in order, and
912  * lastly increasing scores for all databases gotten via
913  * get_database_list() that are not already on the hash.
914  *
915  * Then we will put all the hash elements into an array, sort the array by
916  * score, and finally put the array elements into the new doubly linked
917  * list.
918  */
919  hctl.keysize = sizeof(Oid);
920  hctl.entrysize = sizeof(avl_dbase);
921  hctl.hcxt = tmpcxt;
922  dbhash = hash_create("db hash", 20, &hctl, /* magic number here FIXME */
924 
925  /* start by inserting the new database */
926  score = 0;
927  if (OidIsValid(newdb))
928  {
929  avl_dbase *db;
930  PgStat_StatDBEntry *entry;
931 
932  /* only consider this database if it has a pgstat entry */
933  entry = pgstat_fetch_stat_dbentry(newdb);
934  if (entry != NULL)
935  {
936  /* we assume it isn't found because the hash was just created */
937  db = hash_search(dbhash, &newdb, HASH_ENTER, NULL);
938 
939  /* hash_search already filled in the key */
940  db->adl_score = score++;
941  /* next_worker is filled in later */
942  }
943  }
944 
945  /* Now insert the databases from the existing list */
947  {
948  avl_dbase *avdb = dlist_container(avl_dbase, adl_node, iter.cur);
949  avl_dbase *db;
950  bool found;
951  PgStat_StatDBEntry *entry;
952 
953  /*
954  * skip databases with no stat entries -- in particular, this gets rid
955  * of dropped databases
956  */
957  entry = pgstat_fetch_stat_dbentry(avdb->adl_datid);
958  if (entry == NULL)
959  continue;
960 
961  db = hash_search(dbhash, &(avdb->adl_datid), HASH_ENTER, &found);
962 
963  if (!found)
964  {
965  /* hash_search already filled in the key */
966  db->adl_score = score++;
967  /* next_worker is filled in later */
968  }
969  }
970 
971  /* finally, insert all qualifying databases not previously inserted */
972  dblist = get_database_list();
973  foreach(cell, dblist)
974  {
975  avw_dbase *avdb = lfirst(cell);
976  avl_dbase *db;
977  bool found;
978  PgStat_StatDBEntry *entry;
979 
980  /* only consider databases with a pgstat entry */
981  entry = pgstat_fetch_stat_dbentry(avdb->adw_datid);
982  if (entry == NULL)
983  continue;
984 
985  db = hash_search(dbhash, &(avdb->adw_datid), HASH_ENTER, &found);
986  /* only update the score if the database was not already on the hash */
987  if (!found)
988  {
989  /* hash_search already filled in the key */
990  db->adl_score = score++;
991  /* next_worker is filled in later */
992  }
993  }
994  nelems = score;
995 
996  /* from here on, the allocated memory belongs to the new list */
997  MemoryContextSwitchTo(newcxt);
999 
1000  if (nelems > 0)
1001  {
1002  TimestampTz current_time;
1003  int millis_increment;
1004  avl_dbase *dbary;
1005  avl_dbase *db;
1006  HASH_SEQ_STATUS seq;
1007  int i;
1008 
1009  /* put all the hash elements into an array */
1010  dbary = palloc(nelems * sizeof(avl_dbase));
1011 
1012  i = 0;
1013  hash_seq_init(&seq, dbhash);
1014  while ((db = hash_seq_search(&seq)) != NULL)
1015  memcpy(&(dbary[i++]), db, sizeof(avl_dbase));
1016 
1017  /* sort the array */
1018  qsort(dbary, nelems, sizeof(avl_dbase), db_comparator);
1019 
1020  /*
1021  * Determine the time interval between databases in the schedule. If
1022  * we see that the configured naptime would take us to sleep times
1023  * lower than our min sleep time (which launcher_determine_sleep is
1024  * coded not to allow), silently use a larger naptime (but don't touch
1025  * the GUC variable).
1026  */
1027  millis_increment = 1000.0 * autovacuum_naptime / nelems;
1028  if (millis_increment <= MIN_AUTOVAC_SLEEPTIME)
1029  millis_increment = MIN_AUTOVAC_SLEEPTIME * 1.1;
1030 
1031  current_time = GetCurrentTimestamp();
1032 
1033  /*
1034  * move the elements from the array into the dllist, setting the
1035  * next_worker while walking the array
1036  */
1037  for (i = 0; i < nelems; i++)
1038  {
1039  avl_dbase *db = &(dbary[i]);
1040 
1041  current_time = TimestampTzPlusMilliseconds(current_time,
1042  millis_increment);
1043  db->adl_next_worker = current_time;
1044 
1045  /* later elements should go closer to the head of the list */
1047  }
1048  }
1049 
1050  /* all done, clean up memory */
1051  if (DatabaseListCxt != NULL)
1053  MemoryContextDelete(tmpcxt);
1054  DatabaseListCxt = newcxt;
1055  MemoryContextSwitchTo(oldcxt);
1056 }
int autovacuum_naptime
Definition: autovacuum.c:114
TimestampTz adl_next_worker
Definition: autovacuum.c:160
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:200
#define HASH_CONTEXT
Definition: hsearch.h:93
#define HASH_ELEM
Definition: hsearch.h:87
MemoryContext hcxt
Definition: hsearch.h:78
static void dlist_push_head(dlist_head *head, dlist_node *node)
Definition: ilist.h:300
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1688
#define dlist_foreach(iter, lhead)
Definition: ilist.h:507
int adl_score
Definition: autovacuum.c:161
static MemoryContext AutovacMemCxt
Definition: autovacuum.c:154
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Size entrysize
Definition: hsearch.h:73
struct avl_dbase avl_dbase
static void autovac_refresh_stats(void)
Definition: autovacuum.c:3065
PgStat_StatDBEntry * pgstat_fetch_stat_dbentry(Oid dbid)
Definition: pgstat.c:2285
#define MIN_AUTOVAC_SLEEPTIME
Definition: autovacuum.c:131
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:885
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:533
Definition: dynahash.c:193
#define dlist_container(type, membername, ptr)
Definition: ilist.h:477
double TimestampTz
Definition: timestamp.h:51
static List * get_database_list(void)
Definition: autovacuum.c:1818
Oid adl_datid
Definition: autovacuum.c:159
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:145
_stringlist * dblist
Definition: pg_regress.c:70
static dlist_head DatabaseList
Definition: autovacuum.c:276
static int db_comparator(const void *a, const void *b)
Definition: autovacuum.c:1060
#define HASH_BLOBS
Definition: hsearch.h:88
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:440
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:301
Oid adw_datid
Definition: autovacuum.c:168
Size keysize
Definition: hsearch.h:72
dlist_node * cur
Definition: ilist.h:161
#define TimestampTzPlusMilliseconds(tz, ms)
Definition: timestamp.h:80
static void dlist_init(dlist_head *head)
Definition: ilist.h:278
#define NULL
Definition: c.h:226
#define lfirst(lc)
Definition: pg_list.h:106
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1353
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1343
dlist_node adl_node
Definition: autovacuum.c:162
void * palloc(Size size)
Definition: mcxt.c:891
static MemoryContext DatabaseListCxt
Definition: autovacuum.c:277
int i
#define qsort(a, b, c, d)
Definition: port.h:440
Definition: pg_list.h:45
static void relation_needs_vacanalyze ( Oid  relid,
AutoVacOpts relopts,
Form_pg_class  classForm,
PgStat_StatTabEntry tabentry,
int  effective_multixact_freeze_max_age,
bool dovacuum,
bool doanalyze,
bool wraparound 
)
static

Definition at line 2744 of file autovacuum.c.

References AutoVacOpts::analyze_scale_factor, AutoVacOpts::analyze_threshold, AssertArg, autovacuum_anl_scale, autovacuum_anl_thresh, autovacuum_freeze_max_age, autovacuum_vac_scale, autovacuum_vac_thresh, AutoVacuumingActive(), PgStat_StatTabEntry::changes_since_analyze, DEBUG3, elog, AutoVacOpts::enabled, FirstMultiXactId, FirstNormalTransactionId, AutoVacOpts::freeze_max_age, Min, AutoVacOpts::multixact_freeze_max_age, MultiXactIdPrecedes(), PgStat_StatTabEntry::n_dead_tuples, NameStr, NULL, OidIsValid, PointerIsValid, recentMulti, recentXid, StatisticRelationId, TransactionIdIsNormal, TransactionIdPrecedes(), AutoVacOpts::vacuum_scale_factor, and AutoVacOpts::vacuum_threshold.

Referenced by do_autovacuum(), and table_recheck_autovac().

2753 {
2754  bool force_vacuum;
2755  bool av_enabled;
2756  float4 reltuples; /* pg_class.reltuples */
2757 
2758  /* constants from reloptions or GUC variables */
2759  int vac_base_thresh,
2760  anl_base_thresh;
2761  float4 vac_scale_factor,
2762  anl_scale_factor;
2763 
2764  /* thresholds calculated from above constants */
2765  float4 vacthresh,
2766  anlthresh;
2767 
2768  /* number of vacuum (resp. analyze) tuples at this time */
2769  float4 vactuples,
2770  anltuples;
2771 
2772  /* freeze parameters */
2773  int freeze_max_age;
2774  int multixact_freeze_max_age;
2775  TransactionId xidForceLimit;
2776  MultiXactId multiForceLimit;
2777 
2778  AssertArg(classForm != NULL);
2779  AssertArg(OidIsValid(relid));
2780 
2781  /*
2782  * Determine vacuum/analyze equation parameters. We have two possible
2783  * sources: the passed reloptions (which could be a main table or a toast
2784  * table), or the autovacuum GUC variables.
2785  */
2786 
2787  /* -1 in autovac setting means use plain vacuum_cost_delay */
2788  vac_scale_factor = (relopts && relopts->vacuum_scale_factor >= 0)
2789  ? relopts->vacuum_scale_factor
2791 
2792  vac_base_thresh = (relopts && relopts->vacuum_threshold >= 0)
2793  ? relopts->vacuum_threshold
2795 
2796  anl_scale_factor = (relopts && relopts->analyze_scale_factor >= 0)
2797  ? relopts->analyze_scale_factor
2799 
2800  anl_base_thresh = (relopts && relopts->analyze_threshold >= 0)
2801  ? relopts->analyze_threshold
2803 
2804  freeze_max_age = (relopts && relopts->freeze_max_age >= 0)
2807 
2808  multixact_freeze_max_age = (relopts && relopts->multixact_freeze_max_age >= 0)
2809  ? Min(relopts->multixact_freeze_max_age, effective_multixact_freeze_max_age)
2810  : effective_multixact_freeze_max_age;
2811 
2812  av_enabled = (relopts ? relopts->enabled : true);
2813 
2814  /* Force vacuum if table is at risk of wraparound */
2815  xidForceLimit = recentXid - freeze_max_age;
2816  if (xidForceLimit < FirstNormalTransactionId)
2817  xidForceLimit -= FirstNormalTransactionId;
2818  force_vacuum = (TransactionIdIsNormal(classForm->relfrozenxid) &&
2819  TransactionIdPrecedes(classForm->relfrozenxid,
2820  xidForceLimit));
2821  if (!force_vacuum)
2822  {
2823  multiForceLimit = recentMulti - multixact_freeze_max_age;
2824  if (multiForceLimit < FirstMultiXactId)
2825  multiForceLimit -= FirstMultiXactId;
2826  force_vacuum = MultiXactIdPrecedes(classForm->relminmxid,
2827  multiForceLimit);
2828  }
2829  *wraparound = force_vacuum;
2830 
2831  /* User disabled it in pg_class.reloptions? (But ignore if at risk) */
2832  if (!av_enabled && !force_vacuum)
2833  {
2834  *doanalyze = false;
2835  *dovacuum = false;
2836  return;
2837  }
2838 
2839  /*
2840  * If we found the table in the stats hash, and autovacuum is currently
2841  * enabled, make a threshold-based decision whether to vacuum and/or
2842  * analyze. If autovacuum is currently disabled, we must be here for
2843  * anti-wraparound vacuuming only, so don't vacuum (or analyze) anything
2844  * that's not being forced.
2845  */
2846  if (PointerIsValid(tabentry) && AutoVacuumingActive())
2847  {
2848  reltuples = classForm->reltuples;
2849  vactuples = tabentry->n_dead_tuples;
2850  anltuples = tabentry->changes_since_analyze;
2851 
2852  vacthresh = (float4) vac_base_thresh + vac_scale_factor * reltuples;
2853  anlthresh = (float4) anl_base_thresh + anl_scale_factor * reltuples;
2854 
2855  /*
2856  * Note that we don't need to take special consideration for stat
2857  * reset, because if that happens, the last vacuum and analyze counts
2858  * will be reset too.
2859  */
2860  elog(DEBUG3, "%s: vac: %.0f (threshold %.0f), anl: %.0f (threshold %.0f)",
2861  NameStr(classForm->relname),
2862  vactuples, vacthresh, anltuples, anlthresh);
2863 
2864  /* Determine if this table needs vacuum or analyze. */
2865  *dovacuum = force_vacuum || (vactuples > vacthresh);
2866  *doanalyze = (anltuples > anlthresh);
2867  }
2868  else
2869  {
2870  /*
2871  * Skip a table not found in stat hash, unless we have to force vacuum
2872  * for anti-wrap purposes. If it's not acted upon, there's no need to
2873  * vacuum it.
2874  */
2875  *dovacuum = force_vacuum;
2876  *doanalyze = false;
2877  }
2878 
2879  /* ANALYZE refuses to work with pg_statistic */
2880  if (relid == StatisticRelationId)
2881  *doanalyze = false;
2882 }
double autovacuum_anl_scale
Definition: autovacuum.c:118
uint32 TransactionId
Definition: c.h:393
#define DEBUG3
Definition: elog.h:23
float8 vacuum_scale_factor
Definition: rel.h:268
#define Min(x, y)
Definition: c.h:801
static MultiXactId recentMulti
Definition: autovacuum.c:145
#define OidIsValid(objectId)
Definition: c.h:533
#define FirstNormalTransactionId
Definition: transam.h:34
bool AutoVacuumingActive(void)
Definition: autovacuum.c:2955
int autovacuum_freeze_max_age
Definition: autovacuum.c:119
PgStat_Counter n_dead_tuples
Definition: pgstat.h:630
int analyze_threshold
Definition: rel.h:258
int autovacuum_vac_thresh
Definition: autovacuum.c:115
#define FirstMultiXactId
Definition: multixact.h:24
#define AssertArg(condition)
Definition: c.h:672
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
float float4
Definition: c.h:376
int vacuum_threshold
Definition: rel.h:257
#define StatisticRelationId
Definition: pg_statistic.h:29
static TransactionId recentXid
Definition: autovacuum.c:144
PgStat_Counter changes_since_analyze
Definition: pgstat.h:631
double autovacuum_vac_scale
Definition: autovacuum.c:116
float8 analyze_scale_factor
Definition: rel.h:269
TransactionId MultiXactId
Definition: c.h:403
int freeze_max_age
Definition: rel.h:262
#define NULL
Definition: c.h:226
bool enabled
Definition: rel.h:256
bool MultiXactIdPrecedes(MultiXactId multi1, MultiXactId multi2)
Definition: multixact.c:3135
#define NameStr(name)
Definition: c.h:494
int multixact_freeze_max_age
Definition: rel.h:265
#define elog
Definition: elog.h:219
#define TransactionIdIsNormal(xid)
Definition: transam.h:42
#define PointerIsValid(pointer)
Definition: c.h:521
int autovacuum_anl_thresh
Definition: autovacuum.c:117
int StartAutoVacLauncher ( void  )

Definition at line 369 of file autovacuum.c.

References AutoVacLauncherMain(), AutoVacPID, ClosePostmasterPorts(), ereport, errmsg(), fork_process(), InitPostmasterChild(), LOG, and NULL.

Referenced by reaper(), and ServerLoop().

370 {
371  pid_t AutoVacPID;
372 
373 #ifdef EXEC_BACKEND
374  switch ((AutoVacPID = avlauncher_forkexec()))
375 #else
376  switch ((AutoVacPID = fork_process()))
377 #endif
378  {
379  case -1:
380  ereport(LOG,
381  (errmsg("could not fork autovacuum launcher process: %m")));
382  return 0;
383 
384 #ifndef EXEC_BACKEND
385  case 0:
386  /* in postmaster child ... */
388 
389  /* Close the postmaster's sockets */
390  ClosePostmasterPorts(false);
391 
393  break;
394 #endif
395  default:
396  return (int) AutoVacPID;
397  }
398 
399  /* shouldn't get here */
400  return 0;
401 }
void InitPostmasterChild(void)
Definition: miscinit.c:175
NON_EXEC_STATIC void AutoVacLauncherMain(int argc, char *argv[]) pg_attribute_noreturn()
Definition: autovacuum.c:407
pid_t fork_process(void)
Definition: fork_process.c:31
#define LOG
Definition: elog.h:26
void ClosePostmasterPorts(bool am_syslogger)
Definition: postmaster.c:2414
#define ereport(elevel, rest)
Definition: elog.h:122
#define NULL
Definition: c.h:226
static pid_t AutoVacPID
Definition: postmaster.c:252
int errmsg(const char *fmt,...)
Definition: elog.c:797
int StartAutoVacWorker ( void  )

Definition at line 1431 of file autovacuum.c.

References AutoVacWorkerMain(), ClosePostmasterPorts(), ereport, errmsg(), fork_process(), InitPostmasterChild(), LOG, and NULL.

Referenced by StartAutovacuumWorker().

1432 {
1433  pid_t worker_pid;
1434 
1435 #ifdef EXEC_BACKEND
1436  switch ((worker_pid = avworker_forkexec()))
1437 #else
1438  switch ((worker_pid = fork_process()))
1439 #endif
1440  {
1441  case -1:
1442  ereport(LOG,
1443  (errmsg("could not fork autovacuum worker process: %m")));
1444  return 0;
1445 
1446 #ifndef EXEC_BACKEND
1447  case 0:
1448  /* in postmaster child ... */
1450 
1451  /* Close the postmaster's sockets */
1452  ClosePostmasterPorts(false);
1453 
1454  AutoVacWorkerMain(0, NULL);
1455  break;
1456 #endif
1457  default:
1458  return (int) worker_pid;
1459  }
1460 
1461  /* shouldn't get here */
1462  return 0;
1463 }
void InitPostmasterChild(void)
Definition: miscinit.c:175
pid_t fork_process(void)
Definition: fork_process.c:31
#define LOG
Definition: elog.h:26
NON_EXEC_STATIC void AutoVacWorkerMain(int argc, char *argv[]) pg_attribute_noreturn()
Definition: autovacuum.c:1469
void ClosePostmasterPorts(bool am_syslogger)
Definition: postmaster.c:2414
#define ereport(elevel, rest)
Definition: elog.h:122
#define NULL
Definition: c.h:226
int errmsg(const char *fmt,...)
Definition: elog.c:797
static autovac_table * table_recheck_autovac ( Oid  relid,
HTAB table_toast_map,
TupleDesc  pg_class_desc,
int  effective_multixact_freeze_max_age 
)
static

Definition at line 2562 of file autovacuum.c.

References av_relation::ar_hasrelopts, av_relation::ar_reloptions, autovac_table::at_datname, autovac_table::at_dobalance, autovac_table::at_nspname, autovac_table::at_params, autovac_table::at_relid, autovac_table::at_relname, autovac_table::at_sharedrel, autovac_table::at_vacoptions, autovac_table::at_vacuum_cost_delay, autovac_table::at_vacuum_cost_limit, autovac_refresh_stats(), autovacuum_vac_cost_delay, autovacuum_vac_cost_limit, default_freeze_min_age, default_freeze_table_age, default_multixact_freeze_min_age, default_multixact_freeze_table_age, extract_autovac_opts(), VacuumParams::freeze_min_age, AutoVacOpts::freeze_min_age, VacuumParams::freeze_table_age, AutoVacOpts::freeze_table_age, get_pgstat_tabentry_relid(), GETSTRUCT, HASH_FIND, hash_search(), heap_freetuple(), HeapTupleIsValid, InvalidOid, VacuumParams::is_wraparound, Log_autovacuum_min_duration, VacuumParams::log_min_duration, AutoVacOpts::log_min_duration, VacuumParams::multixact_freeze_min_age, AutoVacOpts::multixact_freeze_min_age, VacuumParams::multixact_freeze_table_age, AutoVacOpts::multixact_freeze_table_age, MyDatabaseId, NULL, ObjectIdGetDatum, palloc(), pgstat_fetch_stat_dbentry(), relation_needs_vacanalyze(), RELKIND_TOASTVALUE, RELOID, SearchSysCacheCopy1, VACOPT_ANALYZE, VACOPT_NOWAIT, VACOPT_SKIPTOAST, VACOPT_VACUUM, AutoVacOpts::vacuum_cost_delay, AutoVacOpts::vacuum_cost_limit, VacuumCostDelay, and VacuumCostLimit.

Referenced by do_autovacuum().

2565 {
2566  Form_pg_class classForm;
2567  HeapTuple classTup;
2568  bool dovacuum;
2569  bool doanalyze;
2570  autovac_table *tab = NULL;
2571  PgStat_StatTabEntry *tabentry;
2572  PgStat_StatDBEntry *shared;
2573  PgStat_StatDBEntry *dbentry;
2574  bool wraparound;
2575  AutoVacOpts *avopts;
2576 
2577  /* use fresh stats */
2579 
2582 
2583  /* fetch the relation's relcache entry */
2584  classTup = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relid));
2585  if (!HeapTupleIsValid(classTup))
2586  return NULL;
2587  classForm = (Form_pg_class) GETSTRUCT(classTup);
2588 
2589  /*
2590  * Get the applicable reloptions. If it is a TOAST table, try to get the
2591  * main table reloptions if the toast table itself doesn't have.
2592  */
2593  avopts = extract_autovac_opts(classTup, pg_class_desc);
2594  if (classForm->relkind == RELKIND_TOASTVALUE &&
2595  avopts == NULL && table_toast_map != NULL)
2596  {
2597  av_relation *hentry;
2598  bool found;
2599 
2600  hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
2601  if (found && hentry->ar_hasrelopts)
2602  avopts = &hentry->ar_reloptions;
2603  }
2604 
2605  /* fetch the pgstat table entry */
2606  tabentry = get_pgstat_tabentry_relid(relid, classForm->relisshared,
2607  shared, dbentry);
2608 
2609  relation_needs_vacanalyze(relid, avopts, classForm, tabentry,
2610  effective_multixact_freeze_max_age,
2611  &dovacuum, &doanalyze, &wraparound);
2612 
2613  /* ignore ANALYZE for toast tables */
2614  if (classForm->relkind == RELKIND_TOASTVALUE)
2615  doanalyze = false;
2616 
2617  /* OK, it needs something done */
2618  if (doanalyze || dovacuum)
2619  {
2620  int freeze_min_age;
2621  int freeze_table_age;
2622  int multixact_freeze_min_age;
2623  int multixact_freeze_table_age;
2624  int vac_cost_limit;
2625  int vac_cost_delay;
2626  int log_min_duration;
2627 
2628  /*
2629  * Calculate the vacuum cost parameters and the freeze ages. If there
2630  * are options set in pg_class.reloptions, use them; in the case of a
2631  * toast table, try the main table too. Otherwise use the GUC
2632  * defaults, autovacuum's own first and plain vacuum second.
2633  */
2634 
2635  /* -1 in autovac setting means use plain vacuum_cost_delay */
2636  vac_cost_delay = (avopts && avopts->vacuum_cost_delay >= 0)
2637  ? avopts->vacuum_cost_delay
2638  : (autovacuum_vac_cost_delay >= 0)
2640  : VacuumCostDelay;
2641 
2642  /* 0 or -1 in autovac setting means use plain vacuum_cost_limit */
2643  vac_cost_limit = (avopts && avopts->vacuum_cost_limit > 0)
2644  ? avopts->vacuum_cost_limit
2647  : VacuumCostLimit;
2648 
2649  /* -1 in autovac setting means use log_autovacuum_min_duration */
2650  log_min_duration = (avopts && avopts->log_min_duration >= 0)
2651  ? avopts->log_min_duration
2653 
2654  /* these do not have autovacuum-specific settings */
2655  freeze_min_age = (avopts && avopts->freeze_min_age >= 0)
2656  ? avopts->freeze_min_age
2658 
2659  freeze_table_age = (avopts && avopts->freeze_table_age >= 0)
2660  ? avopts->freeze_table_age
2662 
2663  multixact_freeze_min_age = (avopts &&
2664  avopts->multixact_freeze_min_age >= 0)
2665  ? avopts->multixact_freeze_min_age
2667 
2668  multixact_freeze_table_age = (avopts &&
2669  avopts->multixact_freeze_table_age >= 0)
2670  ? avopts->multixact_freeze_table_age
2672 
2673  tab = palloc(sizeof(autovac_table));
2674  tab->at_relid = relid;
2675  tab->at_sharedrel = classForm->relisshared;
2677  (dovacuum ? VACOPT_VACUUM : 0) |
2678  (doanalyze ? VACOPT_ANALYZE : 0) |
2679  (!wraparound ? VACOPT_NOWAIT : 0);
2680  tab->at_params.freeze_min_age = freeze_min_age;
2681  tab->at_params.freeze_table_age = freeze_table_age;
2682  tab->at_params.multixact_freeze_min_age = multixact_freeze_min_age;
2683  tab->at_params.multixact_freeze_table_age = multixact_freeze_table_age;
2684  tab->at_params.is_wraparound = wraparound;
2685  tab->at_params.log_min_duration = log_min_duration;
2686  tab->at_vacuum_cost_limit = vac_cost_limit;
2687  tab->at_vacuum_cost_delay = vac_cost_delay;
2688  tab->at_relname = NULL;
2689  tab->at_nspname = NULL;
2690  tab->at_datname = NULL;
2691 
2692  /*
2693  * If any of the cost delay parameters has been set individually for
2694  * this table, disable the balancing algorithm.
2695  */
2696  tab->at_dobalance =
2697  !(avopts && (avopts->vacuum_cost_limit > 0 ||
2698  avopts->vacuum_cost_delay > 0));
2699  }
2700 
2701  heap_freetuple(classTup);
2702 
2703  return tab;
2704 }
int vacuum_cost_delay
Definition: rel.h:259
int multixact_freeze_table_age
Definition: vacuum.h:142
static int default_freeze_table_age
Definition: autovacuum.c:149
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
int at_vacuum_cost_delay
Definition: autovacuum.c:191
static int default_multixact_freeze_min_age
Definition: autovacuum.c:150
int freeze_min_age
Definition: rel.h:261
static void autovac_refresh_stats(void)
Definition: autovacuum.c:3065
PgStat_StatDBEntry * pgstat_fetch_stat_dbentry(Oid dbid)
Definition: pgstat.c:2285
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:885
char * at_datname
Definition: autovacuum.c:197
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1374
int freeze_table_age
Definition: vacuum.h:139
int autovacuum_vac_cost_limit
Definition: autovacuum.c:123
bool at_sharedrel
Definition: autovacuum.c:194
int freeze_table_age
Definition: rel.h:263
int at_vacuum_cost_limit
Definition: autovacuum.c:192
char * at_relname
Definition: autovacuum.c:195
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
int VacuumCostLimit
Definition: globals.c:131
int freeze_min_age
Definition: vacuum.h:138
bool is_wraparound
Definition: vacuum.h:144
static AutoVacOpts * extract_autovac_opts(HeapTuple tup, TupleDesc pg_class_desc)
Definition: autovacuum.c:2509
static PgStat_StatTabEntry * get_pgstat_tabentry_relid(Oid relid, bool isshared, PgStat_StatDBEntry *shared, PgStat_StatDBEntry *dbentry)
Definition: autovacuum.c:2535
static void relation_needs_vacanalyze(Oid relid, AutoVacOpts *relopts, Form_pg_class classForm, PgStat_StatTabEntry *tabentry, int effective_multixact_freeze_max_age, bool *dovacuum, bool *doanalyze, bool *wraparound)
Definition: autovacuum.c:2744
int autovacuum_vac_cost_delay
Definition: autovacuum.c:122
char * at_nspname
Definition: autovacuum.c:196
int multixact_freeze_table_age
Definition: rel.h:266
#define RELKIND_TOASTVALUE
Definition: pg_class.h:163
Oid MyDatabaseId
Definition: globals.c:76
#define InvalidOid
Definition: postgres_ext.h:36
int VacuumCostDelay
Definition: globals.c:132
VacuumParams at_params
Definition: autovacuum.c:190
int vacuum_cost_limit
Definition: rel.h:260
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:226
int multixact_freeze_min_age
Definition: rel.h:264
int log_min_duration
Definition: vacuum.h:145
int log_min_duration
Definition: rel.h:267
int Log_autovacuum_min_duration
Definition: autovacuum.c:125
FormData_pg_class * Form_pg_class
Definition: pg_class.h:95
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:158
AutoVacOpts ar_reloptions
Definition: autovacuum.c:181
void * palloc(Size size)
Definition: mcxt.c:891
bool ar_hasrelopts
Definition: autovacuum.c:180
static int default_multixact_freeze_table_age
Definition: autovacuum.c:151
int multixact_freeze_min_age
Definition: vacuum.h:140
static int default_freeze_min_age
Definition: autovacuum.c:148
bool at_dobalance
Definition: autovacuum.c:193

Variable Documentation

bool am_autovacuum_launcher = false
static

Definition at line 135 of file autovacuum.c.

Referenced by AutoVacLauncherMain(), and IsAutoVacuumLauncherProcess().

bool am_autovacuum_worker = false
static

Definition at line 136 of file autovacuum.c.

Referenced by AutoVacWorkerMain(), and IsAutoVacuumWorkerProcess().

MemoryContext AutovacMemCxt
static

Definition at line 154 of file autovacuum.c.

double autovacuum_anl_scale

Definition at line 118 of file autovacuum.c.

Referenced by relation_needs_vacanalyze().

int autovacuum_anl_thresh

Definition at line 117 of file autovacuum.c.

Referenced by relation_needs_vacanalyze().

int autovacuum_freeze_max_age
int autovacuum_multixact_freeze_max_age

Definition at line 120 of file autovacuum.c.

Referenced by MultiXactMemberFreezeThreshold(), and SetMultiXactIdLimit().

int autovacuum_naptime
bool autovacuum_start_daemon = false

Definition at line 111 of file autovacuum.c.

Referenced by autovac_init(), and AutoVacuumingActive().

int autovacuum_vac_cost_delay

Definition at line 122 of file autovacuum.c.

Referenced by autovac_balance_cost(), and table_recheck_autovac().

int autovacuum_vac_cost_limit

Definition at line 123 of file autovacuum.c.

Referenced by autovac_balance_cost(), and table_recheck_autovac().

double autovacuum_vac_scale

Definition at line 116 of file autovacuum.c.

Referenced by relation_needs_vacanalyze().

int autovacuum_vac_thresh

Definition at line 115 of file autovacuum.c.

Referenced by relation_needs_vacanalyze().

int autovacuum_work_mem = -1

Definition at line 113 of file autovacuum.c.

Referenced by ginInsertCleanup(), and lazy_space_alloc().

int AutovacuumLauncherPid = 0

Definition at line 283 of file autovacuum.c.

Referenced by FreeWorkerInfo(), and ProcKill().

AutoVacuumShmemStruct* AutoVacuumShmem
static

Definition at line 270 of file autovacuum.c.

dlist_head DatabaseList = DLIST_STATIC_INIT(DatabaseList)
static

Definition at line 276 of file autovacuum.c.

MemoryContext DatabaseListCxt = NULL
static

Definition at line 277 of file autovacuum.c.

int default_freeze_min_age
static

Definition at line 148 of file autovacuum.c.

Referenced by do_autovacuum(), and table_recheck_autovac().

int default_freeze_table_age
static

Definition at line 149 of file autovacuum.c.

Referenced by do_autovacuum(), and table_recheck_autovac().

int default_multixact_freeze_min_age
static

Definition at line 150 of file autovacuum.c.

Referenced by do_autovacuum(), and table_recheck_autovac().

int default_multixact_freeze_table_age
static

Definition at line 151 of file autovacuum.c.

Referenced by do_autovacuum(), and table_recheck_autovac().

volatile sig_atomic_t got_SIGHUP = false
static

Definition at line 139 of file autovacuum.c.

Referenced by AutoVacLauncherMain(), av_sighup_handler(), and do_autovacuum().

volatile sig_atomic_t got_SIGTERM = false
static

Definition at line 141 of file autovacuum.c.

Referenced by ApplyLoop(), AutoVacLauncherMain(), and avl_sigterm_handler().

volatile sig_atomic_t got_SIGUSR2 = false
static

Definition at line 140 of file autovacuum.c.

Referenced by AutoVacLauncherMain(), and avl_sigusr2_handler().

int Log_autovacuum_min_duration = -1

Definition at line 125 of file autovacuum.c.

Referenced by table_recheck_autovac().

WorkerInfo MyWorkerInfo = NULL
static

Definition at line 280 of file autovacuum.c.

MultiXactId recentMulti
static

Definition at line 145 of file autovacuum.c.

Referenced by AutoVacWorkerMain(), do_start_worker(), and relation_needs_vacanalyze().

TransactionId recentXid
static

Definition at line 144 of file autovacuum.c.

Referenced by AutoVacWorkerMain(), do_start_worker(), and relation_needs_vacanalyze().