100 #include "utils/fmgroids.h"
101 #include "utils/fmgrprotos.h"
136 #define MIN_AUTOVAC_SLEEPTIME 100.0
137 #define MAX_AUTOVAC_SLEEPTIME 300
252 #define AutoVacNumSignals (AutoVacRebalance + 1)
270 #define NUM_WORKITEMS 256
320 struct timeval *nap);
332 int effective_multixact_freeze_max_age);
335 int effective_multixact_freeze_max_age,
336 bool *dovacuum,
bool *doanalyze,
bool *wraparound);
340 int effective_multixact_freeze_max_age,
341 bool *dovacuum,
bool *doanalyze,
bool *wraparound);
350 const char *nspname,
const char *
relname);
365 sigjmp_buf local_sigjmp_buf;
367 Assert(startup_data_len == 0);
424 "Autovacuum Launcher",
440 if (sigsetjmp(local_sigjmp_buf, 1) != 0)
589 (nap.tv_sec * 1000L) + (nap.tv_usec / 1000L),
590 WAIT_EVENT_AUTOVACUUM_MAIN);
688 errmsg(
"autovacuum worker took too long to start; canceled"));
821 nap->tv_usec = usecs;
840 if (nap->tv_sec == 0 && nap->tv_usec == 0 && !recursing)
892 "Autovacuum database list",
895 "Autovacuum database list (tmp)",
918 dbhash =
hash_create(
"autovacuum db hash", 20, &hctl,
1000 int millis_increment;
1012 memcpy(&(dbary[
i++]), db,
sizeof(
avl_dbase));
1034 for (
i = 0;
i < nelems;
i++)
1082 bool for_multi_wrap;
1085 bool skipit =
false;
1104 "Autovacuum start worker (tmp)",
1151 for_xid_wrap =
false;
1152 for_multi_wrap =
false;
1166 for_xid_wrap =
true;
1169 else if (for_xid_wrap)
1176 for_multi_wrap =
true;
1179 else if (for_multi_wrap)
1363 sigjmp_buf local_sigjmp_buf;
1366 Assert(startup_data_len == 0);
1425 if (sigsetjmp(local_sigjmp_buf, 1) != 0)
1534 elog(
WARNING,
"autovacuum worker started without a worker entry");
1687 "Autovacuum VacuumUpdateCosts(db=%u, rel=%u, dobalance=%s, cost_limit=%d, cost_delay=%g active=%s failsafe=%s)",
1718 int nworkers_for_balance;
1734 if (nworkers_for_balance <= 0)
1735 elog(
ERROR,
"nworkers_for_balance must be > 0");
1753 int orig_nworkers_for_balance;
1754 int nworkers_for_balance = 0;
1758 orig_nworkers_for_balance =
1765 if (worker->
wi_proc == NULL ||
1769 nworkers_for_balance++;
1772 if (nworkers_for_balance != orig_nworkers_for_balance)
1774 nworkers_for_balance);
1831 "autovacuum: skipping invalid database \"%s\"",
1832 NameStr(pgdatabase->datname));
1884 HTAB *table_toast_map;
1889 int effective_multixact_freeze_max_age;
1890 bool did_vacuum =
false;
1891 bool found_concurrent_worker =
false;
1900 "Autovacuum worker",
1930 if (dbForm->datistemplate || !dbForm->datallowconn)
1956 ctl.keysize =
sizeof(
Oid);
1959 table_toast_map =
hash_create(
"TOAST to main relid map",
1994 if (classForm->relkind != RELKIND_RELATION &&
1995 classForm->relkind != RELKIND_MATVIEW)
1998 relid = classForm->oid;
2004 if (classForm->relpersistence == RELPERSISTENCE_TEMP)
2032 effective_multixact_freeze_max_age,
2033 &dovacuum, &doanalyze, &wraparound);
2036 if (dovacuum || doanalyze)
2050 &classForm->reltoastrelid,
2058 if (relopts != NULL)
2072 Anum_pg_class_relkind,
2090 if (classForm->relpersistence == RELPERSISTENCE_TEMP)
2093 relid = classForm->oid;
2100 if (relopts == NULL)
2115 effective_multixact_freeze_max_age,
2116 &dovacuum, &doanalyze, &wraparound);
2135 foreach(cell, orphan_oids)
2173 if (!((classForm->relkind == RELKIND_RELATION ||
2174 classForm->relkind == RELKIND_MATVIEW) &&
2175 classForm->relpersistence == RELPERSISTENCE_TEMP))
2198 classForm->relnamespace, 0,
2207 (
errmsg(
"autovacuum: dropping orphan temp table \"%s.%s.%s\"",
2210 NameStr(classForm->relname))));
2212 object.classId = RelationRelationId;
2213 object.objectId = relid;
2214 object.objectSubId = 0;
2253 "Autovacuum Portal",
2259 foreach(cell, table_oids)
2328 found_concurrent_worker =
true;
2357 effective_multixact_freeze_max_age);
2443 errcontext(
"automatic vacuum of table \"%s.%s.%s\"",
2446 errcontext(
"automatic analyze of table \"%s.%s.%s\"",
2557 if (did_vacuum || !found_concurrent_worker)
2570 char *cur_datname = NULL;
2571 char *cur_nspname = NULL;
2572 char *cur_relname = NULL;
2589 if (!cur_relname || !cur_nspname || !cur_datname)
2620 elog(
WARNING,
"unrecognized work item found: type %d",
2640 errcontext(
"processing work entry for relation \"%s.%s.%s\"",
2641 cur_datname, cur_nspname, cur_relname);
2692 if (relopts == NULL)
2714 int effective_multixact_freeze_max_age)
2735 if (classForm->relkind == RELKIND_TOASTVALUE &&
2736 avopts == NULL && table_toast_map != NULL)
2747 effective_multixact_freeze_max_age,
2748 &dovacuum, &doanalyze, &wraparound);
2751 if (doanalyze || dovacuum)
2754 int freeze_table_age;
2755 int multixact_freeze_min_age;
2756 int multixact_freeze_table_age;
2757 int log_min_duration;
2780 multixact_freeze_min_age = (avopts &&
2785 multixact_freeze_table_age = (avopts &&
2855 int effective_multixact_freeze_max_age,
2867 effective_multixact_freeze_max_age,
2868 dovacuum, doanalyze, wraparound);
2871 if (classForm->relkind == RELKIND_TOASTVALUE)
2917 int effective_multixact_freeze_max_age,
2928 int vac_base_thresh,
2929 vac_ins_base_thresh,
2932 vac_ins_scale_factor,
2947 int multixact_freeze_max_age;
2952 Assert(classForm != NULL);
2993 : effective_multixact_freeze_max_age;
2995 av_enabled = (relopts ? relopts->
enabled :
true);
2998 xidForceLimit =
recentXid - freeze_max_age;
3001 relfrozenxid = classForm->relfrozenxid;
3008 multiForceLimit =
recentMulti - multixact_freeze_max_age;
3014 *wraparound = force_vacuum;
3017 if (!av_enabled && !force_vacuum)
3033 reltuples = classForm->reltuples;
3042 vacthresh = (
float4) vac_base_thresh + vac_scale_factor * reltuples;
3043 vacinsthresh = (
float4) vac_ins_base_thresh + vac_ins_scale_factor * reltuples;
3044 anlthresh = (
float4) anl_base_thresh + anl_scale_factor * reltuples;
3051 if (vac_ins_base_thresh >= 0)
3052 elog(
DEBUG3,
"%s: vac: %.0f (threshold %.0f), ins: %.0f (threshold %.0f), anl: %.0f (threshold %.0f)",
3054 vactuples, vacthresh, instuples, vacinsthresh, anltuples, anlthresh);
3056 elog(
DEBUG3,
"%s: vac: %.0f (threshold %.0f), ins: (disabled), anl: %.0f (threshold %.0f)",
3058 vactuples, vacthresh, anltuples, anlthresh);
3061 *dovacuum = force_vacuum || (vactuples > vacthresh) ||
3062 (vac_ins_base_thresh >= 0 && instuples > vacinsthresh);
3063 *doanalyze = (anltuples > anlthresh);
3072 *dovacuum = force_vacuum;
3077 if (relid == StatisticRelationId)
3127 #define MAX_AUTOVAC_ACTIV_LEN (NAMEDATALEN * 2 + 56)
3134 "autovacuum: VACUUM%s",
3138 "autovacuum: ANALYZE");
3143 len = strlen(activity);
3161 const char *nspname,
const char *
relname)
3171 "autovacuum: BRIN summarize");
3178 len = strlen(activity);
3186 " %s.%s%s", nspname,
relname, blk);
3216 bool result =
false;
3258 (
errmsg(
"autovacuum not started because of misconfiguration"),
3259 errhint(
"Enable the \"track_counts\" option.")));
static void pg_atomic_clear_flag(volatile pg_atomic_flag *ptr)
static void pg_atomic_init_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
static bool pg_atomic_test_set_flag(volatile pg_atomic_flag *ptr)
static bool pg_atomic_unlocked_test_flag(volatile pg_atomic_flag *ptr)
static void pg_atomic_write_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
static uint32 pg_atomic_read_u32(volatile pg_atomic_uint32 *ptr)
static void pg_atomic_init_flag(volatile pg_atomic_flag *ptr)
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 Oid do_start_worker(void)
static void launcher_determine_sleep(bool canlaunch, bool recursing, struct timeval *nap)
static autovac_table * table_recheck_autovac(Oid relid, HTAB *table_toast_map, TupleDesc pg_class_desc, int effective_multixact_freeze_max_age)
void VacuumUpdateCosts(void)
static volatile sig_atomic_t got_SIGUSR2
static void avl_sigusr2_handler(SIGNAL_ARGS)
int autovacuum_multixact_freeze_max_age
static int default_multixact_freeze_table_age
static void HandleAutoVacLauncherInterrupts(void)
double autovacuum_vac_scale
static void FreeWorkerInfo(int code, Datum arg)
int AutovacuumLauncherPid
int Log_autovacuum_min_duration
int autovacuum_anl_thresh
struct av_relation av_relation
static TransactionId recentXid
struct AutoVacuumWorkItem AutoVacuumWorkItem
Size AutoVacuumShmemSize(void)
struct autovac_table autovac_table
void AutoVacuumShmemInit(void)
bool check_autovacuum_work_mem(int *newval, void **extra, GucSource source)
static void autovac_report_activity(autovac_table *tab)
static int default_multixact_freeze_min_age
static AutoVacOpts * extract_autovac_opts(HeapTuple tup, TupleDesc pg_class_desc)
static void do_autovacuum(void)
int autovacuum_vac_cost_limit
static double av_storage_param_cost_delay
bool AutoVacuumRequestWork(AutoVacuumWorkItemType type, Oid relationId, BlockNumber blkno)
bool AutoVacuumingActive(void)
int autovacuum_max_workers
int autovacuum_freeze_max_age
static int db_comparator(const void *a, const void *b)
static int av_storage_param_cost_limit
double autovacuum_vac_cost_delay
static void AutoVacLauncherShutdown(void)
#define AutoVacNumSignals
struct avl_dbase avl_dbase
int autovacuum_vac_thresh
struct avw_dbase avw_dbase
static void launch_worker(TimestampTz now)
struct WorkerInfoData WorkerInfoData
static dlist_head DatabaseList
static void rebuild_database_list(Oid newdb)
static AutoVacuumShmemStruct * AutoVacuumShmem
#define MIN_AUTOVAC_SLEEPTIME
#define MAX_AUTOVAC_ACTIV_LEN
void AutoVacWorkerMain(char *startup_data, size_t startup_data_len)
double autovacuum_anl_scale
int autovacuum_vac_ins_thresh
#define MAX_AUTOVAC_SLEEPTIME
static MemoryContext DatabaseListCxt
void AutoVacWorkerFailed(void)
struct WorkerInfoData * WorkerInfo
static List * get_database_list(void)
bool autovacuum_start_daemon
static void perform_work_item(AutoVacuumWorkItem *workitem)
double autovacuum_vac_ins_scale
static MultiXactId recentMulti
static int default_freeze_min_age
static void autovac_recalculate_workers_for_balance(void)
void AutoVacuumUpdateCostLimit(void)
static WorkerInfo MyWorkerInfo
static void autovac_report_workitem(AutoVacuumWorkItem *workitem, const char *nspname, const char *relname)
static void recheck_relation_needs_vacanalyze(Oid relid, AutoVacOpts *avopts, Form_pg_class classForm, int effective_multixact_freeze_max_age, bool *dovacuum, bool *doanalyze, bool *wraparound)
static MemoryContext AutovacMemCxt
static int default_freeze_table_age
static void autovacuum_do_vac_analyze(autovac_table *tab, BufferAccessStrategy bstrategy)
void AutoVacLauncherMain(char *startup_data, size_t startup_data_len) pg_attribute_noreturn()
void TimestampDifference(TimestampTz start_time, TimestampTz stop_time, long *secs, int *microsecs)
bool TimestampDifferenceExceeds(TimestampTz start_time, TimestampTz stop_time, int msec)
TimestampTz GetCurrentTimestamp(void)
Datum now(PG_FUNCTION_ARGS)
void pgstat_report_activity(BackendState state, const char *cmd_str)
static bool BlockNumberIsValid(BlockNumber blockNumber)
Datum brin_summarize_range(PG_FUNCTION_ARGS)
void AtEOXact_Buffers(bool isCommit)
#define Assert(condition)
#define pg_attribute_noreturn()
TransactionId MultiXactId
#define PointerIsValid(pointer)
#define OidIsValid(objectId)
char * get_database_name(Oid dbid)
bool database_is_invalid_form(Form_pg_database datform)
void performDeletion(const ObjectAddress *object, DropBehavior behavior, int flags)
#define PERFORM_DELETION_SKIP_EXTENSIONS
#define PERFORM_DELETION_QUIETLY
#define PERFORM_DELETION_INTERNAL
void AtEOXact_HashTables(bool isCommit)
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
void * hash_seq_search(HASH_SEQ_STATUS *status)
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
int errmsg_internal(const char *fmt,...)
void EmitErrorReport(void)
ErrorContextCallback * error_context_stack
void FlushErrorState(void)
int errhint(const char *fmt,...)
bool message_level_is_interesting(int elevel)
int errmsg(const char *fmt,...)
sigjmp_buf * PG_exception_stack
#define ereport(elevel,...)
void AtEOXact_Files(bool isCommit)
Datum Int64GetDatum(int64 X)
#define DirectFunctionCall2(func, arg1, arg2)
BufferAccessStrategy GetAccessStrategyWithSize(BufferAccessStrategyType btype, int ring_size_kb)
volatile sig_atomic_t LogMemoryContextPending
volatile sig_atomic_t ProcSignalBarrierPending
volatile sig_atomic_t QueryCancelPending
int VacuumBufferUsageLimit
void SetConfigOption(const char *name, const char *value, GucContext context, GucSource source)
void ProcessConfigFile(GucContext context)
HeapTuple heap_getnext(TableScanDesc sscan, ScanDirection direction)
void heap_freetuple(HeapTuple htup)
#define HeapTupleIsValid(tuple)
#define dlist_foreach(iter, lhead)
static void dlist_init(dlist_head *head)
static void dlist_delete(dlist_node *node)
#define dlist_reverse_foreach(iter, lhead)
static dlist_node * dlist_pop_head_node(dlist_head *head)
#define dlist_tail_element(type, membername, lhead)
static void dlist_push_head(dlist_head *head, dlist_node *node)
static bool dlist_is_empty(const dlist_head *head)
static void dlist_move_head(dlist_head *head, dlist_node *node)
#define DLIST_STATIC_INIT(name)
#define dlist_container(type, membername, ptr)
#define INJECTION_POINT(name)
static int pg_cmp_s32(int32 a, int32 b)
void SignalHandlerForShutdownRequest(SIGNAL_ARGS)
volatile sig_atomic_t ShutdownRequestPending
volatile sig_atomic_t ConfigReloadPending
void SignalHandlerForConfigReload(SIGNAL_ARGS)
void on_shmem_exit(pg_on_exit_callback function, Datum arg)
void SetLatch(Latch *latch)
void ResetLatch(Latch *latch)
int WaitLatch(Latch *latch, int wakeEvents, long timeout, uint32 wait_event_info)
#define WL_EXIT_ON_PM_DEATH
List * lappend(List *list, void *datum)
List * lappend_oid(List *list, Oid datum)
bool ConditionalLockRelationOid(Oid relid, LOCKMODE lockmode)
void UnlockRelationOid(Oid relid, LOCKMODE lockmode)
bool ConditionalLockDatabaseObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
#define AccessExclusiveLock
char * get_namespace_name(Oid nspid)
Oid get_rel_namespace(Oid relid)
char * get_rel_name(Oid relid)
bool LWLockHeldByMe(LWLock *lock)
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
void LWLockRelease(LWLock *lock)
void LWLockReleaseAll(void)
VacuumRelation * makeVacuumRelation(RangeVar *relation, Oid oid, List *va_cols)
RangeVar * makeRangeVar(char *schemaname, char *relname, int location)
void MemoryContextReset(MemoryContext context)
char * pstrdup(const char *in)
void pfree(void *pointer)
MemoryContext TopMemoryContext
MemoryContext CurrentMemoryContext
MemoryContext PostmasterContext
void ProcessLogMemoryContextInterrupt(void)
void MemoryContextDelete(MemoryContext context)
MemoryContext PortalContext
#define AllocSetContextCreate
#define ALLOCSET_DEFAULT_SIZES
#define RESUME_INTERRUPTS()
#define GetProcessingMode()
#define CHECK_FOR_INTERRUPTS()
#define HOLD_INTERRUPTS()
#define SetProcessingMode(mode)
BackendType MyBackendType
bool MultiXactIdPrecedes(MultiXactId multi1, MultiXactId multi2)
int MultiXactMemberFreezeThreshold(void)
MultiXactId ReadNextMultiXactId(void)
#define MultiXactIdIsValid(multi)
TempNamespaceStatus checkTempNamespaceStatus(Oid namespaceId)
FormData_pg_class * Form_pg_class
FormData_pg_database * Form_pg_database
static rewind_source * source
void pgstat_report_autovac(Oid dboid)
PgStat_StatDBEntry * pgstat_fetch_stat_dbentry(Oid dboid)
PgStat_StatTabEntry * pgstat_fetch_stat_tabentry_ext(bool shared, Oid reloid)
void SendPostmasterSignal(PMSignalReason reason)
@ PMSIGNAL_START_AUTOVAC_WORKER
pqsigfunc pqsignal(int signo, pqsigfunc func)
#define qsort(a, b, c, d)
void FloatExceptionHandler(SIGNAL_ARGS)
void StatementCancelHandler(SIGNAL_ARGS)
static Datum ObjectIdGetDatum(Oid X)
static Datum CharGetDatum(char X)
void InitPostgres(const char *in_dbname, Oid dboid, const char *username, Oid useroid, bits32 flags, char *out_dbname)
void ProcessProcSignalBarrier(void)
void procsignal_sigusr1_handler(SIGNAL_ARGS)
void init_ps_display(const char *fixed_part)
static void set_ps_display(const char *activity)
MemoryContextSwitchTo(old_ctx)
#define RelationGetDescr(relation)
bytea * extractRelOptions(HeapTuple tuple, TupleDesc tupdesc, amoptions_function amoptions)
void ReleaseAuxProcessResources(bool isCommit)
ResourceOwner AuxProcessResourceOwner
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Size add_size(Size s1, Size s2)
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Size mul_size(Size s1, Size s2)
void pg_usleep(long microsec)
void ProcessCatchupInterrupt(void)
static pg_noinline void Size size
Snapshot GetTransactionSnapshot(void)
#define BTEqualStrategyNumber
int multixact_freeze_max_age
float8 vacuum_scale_factor
float8 vacuum_ins_scale_factor
int multixact_freeze_table_age
int multixact_freeze_min_age
float8 analyze_scale_factor
dlist_head av_freeWorkers
WorkerInfo av_startingWorker
sig_atomic_t av_signal[AutoVacNumSignals]
AutoVacuumWorkItem av_workItems[NUM_WORKITEMS]
pg_atomic_uint32 av_nworkersForBalance
dlist_head av_runningWorkers
BlockNumber avw_blockNumber
AutoVacuumWorkItemType avw_type
TimestampTz last_autovac_time
PgStat_Counter ins_since_vacuum
PgStat_Counter mod_since_analyze
PgStat_Counter dead_tuples
int multixact_freeze_min_age
int multixact_freeze_table_age
VacOptValue index_cleanup
TimestampTz wi_launchtime
pg_atomic_flag wi_dobalance
double at_storage_param_vac_cost_delay
int at_storage_param_vac_cost_limit
AutoVacOpts ar_reloptions
TimestampTz adl_next_worker
PgStat_StatDBEntry * adw_entry
TransactionId adw_frozenxid
void ReleaseSysCache(HeapTuple tuple)
HeapTuple SearchSysCache1(int cacheId, Datum key1)
#define SearchSysCacheCopy1(cacheId, key1)
void table_close(Relation relation, LOCKMODE lockmode)
Relation table_open(Oid relationId, LOCKMODE lockmode)
TableScanDesc table_beginscan_catalog(Relation relation, int nkeys, struct ScanKeyData *key)
static void table_endscan(TableScanDesc scan)
void disable_all_timeouts(bool keep_indicators)
void InitializeTimeouts(void)
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
static TransactionId ReadNextTransactionId(void)
#define FirstNormalTransactionId
#define TransactionIdIsNormal(xid)
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
#define TimestampTzPlusMilliseconds(tz, ms)
int vacuum_freeze_min_age
void vacuum(List *relations, VacuumParams *params, BufferAccessStrategy bstrategy, MemoryContext vac_context, bool isTopLevel)
int vacuum_multixact_freeze_table_age
int vacuum_freeze_table_age
int vacuum_multixact_freeze_min_age
void vac_update_datfrozenxid(void)
bool VacuumFailsafeActive
#define VACOPT_SKIP_LOCKED
#define VACOPT_SKIP_DATABASE_STATS
@ VACOPTVALUE_UNSPECIFIED
#define VACOPT_PROCESS_MAIN
static void pgstat_report_wait_end(void)
void StartTransactionCommand(void)
void SetCurrentStatementStartTimestamp(void)
void CommitTransactionCommand(void)
void AbortOutOfAnyTransaction(void)
void AbortCurrentTransaction(void)
@ SYNCHRONOUS_COMMIT_LOCAL_FLUSH