Content-Length: 474236 | pFad | http://github.com/postgres/postgres/commit/e087b5b79452d4df9bca8e64d321d35b763b41c1

2E Fix per-relation memory leakage in autovacuum. · postgres/postgres@e087b5b · GitHub
Skip to content

Commit e087b5b

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 ee58de1 commit e087b5b

File tree

1 file changed

+40
-10
lines changed

1 file changed

+40
-10
lines changed

src/backend/postmaster/autovacuum.c

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2211,6 +2211,12 @@ do_autovacuum(void)
22112211
}
22122212
}
22132213
}
2214+
2215+
/* Release stuff to avoid per-relation leakage */
2216+
if (relopts)
2217+
pfree(relopts);
2218+
if (tabentry)
2219+
pfree(tabentry);
22142220
}
22152221

22162222
table_endscan(relScan);
@@ -2227,7 +2233,8 @@ do_autovacuum(void)
22272233
Form_pg_class classForm = (Form_pg_class) GETSTRUCT(tuple);
22282234
PgStat_StatTabEntry *tabentry;
22292235
Oid relid;
2230-
AutoVacOpts *relopts = NULL;
2236+
AutoVacOpts *relopts;
2237+
bool free_relopts = false;
22312238
bool dovacuum;
22322239
bool doanalyze;
22332240
bool wraparound;
@@ -2245,7 +2252,9 @@ do_autovacuum(void)
22452252
* main rel
22462253
*/
22472254
relopts = extract_autovac_opts(tuple, pg_class_desc);
2248-
if (relopts == NULL)
2255+
if (relopts)
2256+
free_relopts = true;
2257+
else
22492258
{
22502259
av_relation *hentry;
22512260
bool found;
@@ -2266,6 +2275,12 @@ do_autovacuum(void)
22662275
/* ignore analyze for toast tables */
22672276
if (dovacuum)
22682277
table_oids = lappend_oid(table_oids, relid);
2278+
2279+
/* Release stuff to avoid leakage */
2280+
if (free_relopts)
2281+
pfree(relopts);
2282+
if (tabentry)
2283+
pfree(tabentry);
22692284
}
22702285

22712286
table_endscan(relScan);
@@ -2637,6 +2652,8 @@ do_autovacuum(void)
26372652
pg_atomic_test_set_flag(&MyWorkerInfo->wi_dobalance);
26382653
}
26392654

2655+
list_free(table_oids);
2656+
26402657
/*
26412658
* Perform additional work items, as requested by backends.
26422659
*/
@@ -2818,8 +2835,8 @@ perform_work_item(AutoVacuumWorkItem *workitem)
28182835
/*
28192836
* extract_autovac_opts
28202837
*
2821-
* Given a relation's pg_class tuple, return the AutoVacOpts portion of
2822-
* reloptions, if set; otherwise, return NULL.
2838+
* Given a relation's pg_class tuple, return a palloc'd copy of the
2839+
* AutoVacOpts portion of reloptions, if set; otherwise, return NULL.
28232840
*
28242841
* Note: callers do not have a relation lock on the table at this point,
28252842
* so the table could have been dropped, and its catalog rows gone, after
@@ -2868,6 +2885,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
28682885
autovac_table *tab = NULL;
28692886
bool wraparound;
28702887
AutoVacOpts *avopts;
2888+
bool free_avopts = false;
28712889

28722890
/* fetch the relation's relcache entry */
28732891
classTup = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relid));
@@ -2880,8 +2898,10 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
28802898
* main table reloptions if the toast table itself doesn't have.
28812899
*/
28822900
avopts = extract_autovac_opts(classTup, pg_class_desc);
2883-
if (classForm->relkind == RELKIND_TOASTVALUE &&
2884-
avopts == NULL && table_toast_map != NULL)
2901+
if (avopts)
2902+
free_avopts = true;
2903+
else if (classForm->relkind == RELKIND_TOASTVALUE &&
2904+
table_toast_map != NULL)
28852905
{
28862906
av_relation *hentry;
28872907
bool found;
@@ -2983,6 +3003,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
29833003
avopts->vacuum_cost_delay >= 0));
29843004
}
29853005

3006+
if (free_avopts)
3007+
pfree(avopts);
29863008
heap_freetuple(classTup);
29873009
return tab;
29883010
}
@@ -3014,6 +3036,10 @@ recheck_relation_needs_vacanalyze(Oid relid,
30143036
effective_multixact_freeze_max_age,
30153037
dovacuum, doanalyze, wraparound);
30163038

3039+
/* Release tabentry to avoid leakage */
3040+
if (tabentry)
3041+
pfree(tabentry);
3042+
30173043
/* ignore ANALYZE for toast tables */
30183044
if (classForm->relkind == RELKIND_TOASTVALUE)
30193045
*doanalyze = false;
@@ -3236,18 +3262,22 @@ autovacuum_do_vac_analyze(autovac_table *tab, BufferAccessStrategy bstrategy)
32363262
VacuumRelation *rel;
32373263
List *rel_list;
32383264
MemoryContext vac_context;
3265+
MemoryContext old_context;
32393266

32403267
/* Let pgstat know what we're doing */
32413268
autovac_report_activity(tab);
32423269

3270+
/* Create a context that vacuum() can use as cross-transaction storage */
3271+
vac_context = AllocSetContextCreate(CurrentMemoryContext,
3272+
"Vacuum",
3273+
ALLOCSET_DEFAULT_SIZES);
3274+
32433275
/* Set up one VacuumRelation target, identified by OID, for vacuum() */
3276+
old_context = MemoryContextSwitchTo(vac_context);
32443277
rangevar = makeRangeVar(tab->at_nspname, tab->at_relname, -1);
32453278
rel = makeVacuumRelation(rangevar, tab->at_relid, NIL);
32463279
rel_list = list_make1(rel);
3247-
3248-
vac_context = AllocSetContextCreate(CurrentMemoryContext,
3249-
"Vacuum",
3250-
ALLOCSET_DEFAULT_SIZES);
3280+
MemoryContextSwitchTo(old_context);
32513281

32523282
vacuum(rel_list, &tab->at_params, bstrategy, vac_context, true);
32533283

0 commit comments

Comments
 (0)








ApplySandwichStrip

pFad - (p)hone/(F)rame/(a)nonymizer/(d)eclutterfier!      Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

Fetched URL: http://github.com/postgres/postgres/commit/e087b5b79452d4df9bca8e64d321d35b763b41c1

Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy