Skip to content

Commit 13d21b4

Browse files
committed
Fix per-relation memory leakage in autovacuum.
PgStat_StatTabEntry and AutoVacOpts structs were leaked until the end of the autovacuum worker's run, which is bad news if there are a lot of relations in the database. Note: pfree'ing the PgStat_StatTabEntry structs here seems a bit risky, because pgstat_fetch_stat_tabentry_ext does not guarantee anything about whether its result is long-lived. It appears okay so long as autovacuum forces PGSTAT_FETCH_CONSISTENCY_NONE, but I think that API could use a re-think. Also ensure that the VacuumRelation structure passed to vacuum() is in recoverable storage. Back-patch to v15 where we started to manage table statistics this way. (The AutoVacOpts leakage is probably older, but I'm not excited enough to worry about just that part.) Author: Tom Lane <tgl@sss.pgh.pa.us> Reviewed-by: Andres Freund <andres@anarazel.de> Discussion: https://postgr.es/m/285483.1746756246@sss.pgh.pa.us Backpatch-through: 15
1 parent 0e0174b commit 13d21b4

File tree

1 file changed

+32
-6
lines changed

1 file changed

+32
-6
lines changed

src/backend/postmaster/autovacuum.c

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2154,6 +2154,12 @@ do_autovacuum(void)
21542154
}
21552155
}
21562156
}
2157+
2158+
/* Release stuff to avoid per-relation leakage */
2159+
if (relopts)
2160+
pfree(relopts);
2161+
if (tabentry)
2162+
pfree(tabentry);
21572163
}
21582164

21592165
table_endscan(relScan);
@@ -2170,7 +2176,8 @@ do_autovacuum(void)
21702176
Form_pg_class classForm = (Form_pg_class) GETSTRUCT(tuple);
21712177
PgStat_StatTabEntry *tabentry;
21722178
Oid relid;
2173-
AutoVacOpts *relopts = NULL;
2179+
AutoVacOpts *relopts;
2180+
bool free_relopts = false;
21742181
bool dovacuum;
21752182
bool doanalyze;
21762183
bool wraparound;
@@ -2188,7 +2195,9 @@ do_autovacuum(void)
21882195
* main rel
21892196
*/
21902197
relopts = extract_autovac_opts(tuple, pg_class_desc);
2191-
if (relopts == NULL)
2198+
if (relopts)
2199+
free_relopts = true;
2200+
else
21922201
{
21932202
av_relation *hentry;
21942203
bool found;
@@ -2209,6 +2218,12 @@ do_autovacuum(void)
22092218
/* ignore analyze for toast tables */
22102219
if (dovacuum)
22112220
table_oids = lappend_oid(table_oids, relid);
2221+
2222+
/* Release stuff to avoid leakage */
2223+
if (free_relopts)
2224+
pfree(relopts);
2225+
if (tabentry)
2226+
pfree(tabentry);
22122227
}
22132228

22142229
table_endscan(relScan);
@@ -2572,6 +2587,8 @@ do_autovacuum(void)
25722587
VacuumCostLimit = stdVacuumCostLimit;
25732588
}
25742589

2590+
list_free(table_oids);
2591+
25752592
/*
25762593
* Perform additional work items, as requested by backends.
25772594
*/
@@ -2749,8 +2766,8 @@ perform_work_item(AutoVacuumWorkItem *workitem)
27492766
/*
27502767
* extract_autovac_opts
27512768
*
2752-
* Given a relation's pg_class tuple, return the AutoVacOpts portion of
2753-
* reloptions, if set; otherwise, return NULL.
2769+
* Given a relation's pg_class tuple, return a palloc'd copy of the
2770+
* AutoVacOpts portion of reloptions, if set; otherwise, return NULL.
27542771
*
27552772
* Note: callers do not have a relation lock on the table at this point,
27562773
* so the table could have been dropped, and its catalog rows gone, after
@@ -2799,6 +2816,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
27992816
autovac_table *tab = NULL;
28002817
bool wraparound;
28012818
AutoVacOpts *avopts;
2819+
bool free_avopts = false;
28022820

28032821
/* fetch the relation's relcache entry */
28042822
classTup = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relid));
@@ -2811,8 +2829,10 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
28112829
* main table reloptions if the toast table itself doesn't have.
28122830
*/
28132831
avopts = extract_autovac_opts(classTup, pg_class_desc);
2814-
if (classForm->relkind == RELKIND_TOASTVALUE &&
2815-
avopts == NULL && table_toast_map != NULL)
2832+
if (avopts)
2833+
free_avopts = true;
2834+
else if (classForm->relkind == RELKIND_TOASTVALUE &&
2835+
table_toast_map != NULL)
28162836
{
28172837
av_relation *hentry;
28182838
bool found;
@@ -2921,6 +2941,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
29212941
avopts->vacuum_cost_delay >= 0));
29222942
}
29232943

2944+
if (free_avopts)
2945+
pfree(avopts);
29242946
heap_freetuple(classTup);
29252947
return tab;
29262948
}
@@ -2952,6 +2974,10 @@ recheck_relation_needs_vacanalyze(Oid relid,
29522974
effective_multixact_freeze_max_age,
29532975
dovacuum, doanalyze, wraparound);
29542976

2977+
/* Release tabentry to avoid leakage */
2978+
if (tabentry)
2979+
pfree(tabentry);
2980+
29552981
/* ignore ANALYZE for toast tables */
29562982
if (classForm->relkind == RELKIND_TOASTVALUE)
29572983
*doanalyze = false;

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy