Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit fb0f5f0

Browse files
committed
Fix memory leak when de-toasting compressed values in VACUUM FULL/CLUSTER
VACUUM FULL and CLUSTER can be used to enforce the use of the existing compression method of a toastable column if a value currently stored is compressed with a method that does not match the column's defined method. The code in charge of decompressing and recompressing toast values at rewrite left around the detoasted values, causing an accumulation of memory allocated in TopTransactionContext. When processing large relations, this could cause the system to run out of memory. The detoasted values are not needed once their tuple is rewritten, and this commit ensures that the necessary cleanup happens. Issue introduced by bbe0a81. The comments of the area are reordered a bit while on it. Reported-by: Andres Freund Analyzed-by: Andres Freund Author: Michael Paquier Reviewed-by: Dilip Kumar Discussion: https://postgr.es/m/20210521211929.pcehg6f23icwstdb@alap3.anarazel.de
1 parent 0c6b92d commit fb0f5f0

File tree

1 file changed

+22
-9
lines changed

1 file changed

+22
-9
lines changed

src/backend/access/heap/heapam_handler.c

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2463,24 +2463,27 @@ reform_and_rewrite_tuple(HeapTuple tuple,
24632463
TupleDesc newTupDesc = RelationGetDescr(NewHeap);
24642464
HeapTuple copiedTuple;
24652465
int i;
2466+
bool values_free[MaxTupleAttributeNumber];
2467+
2468+
memset(values_free, 0, newTupDesc->natts * sizeof(bool));
24662469

24672470
heap_deform_tuple(tuple, oldTupDesc, values, isnull);
24682471

2469-
/* Be sure to null out any dropped columns */
24702472
for (i = 0; i < newTupDesc->natts; i++)
24712473
{
2474+
/* Be sure to null out any dropped columns */
24722475
if (TupleDescAttr(newTupDesc, i)->attisdropped)
24732476
isnull[i] = true;
2474-
2475-
/*
2476-
* Use this opportunity to force recompression of any data that's
2477-
* compressed with some TOAST compression method other than the one
2478-
* configured for the column. We don't actually need to perform the
2479-
* compression here; we just need to decompress. That will trigger
2480-
* recompression later on.
2481-
*/
24822477
else if (!isnull[i] && TupleDescAttr(newTupDesc, i)->attlen == -1)
24832478
{
2479+
/*
2480+
* Use this opportunity to force recompression of any data that's
2481+
* compressed with some TOAST compression method other than the
2482+
* one configured for the column. We don't actually need to
2483+
* perform the compression here; we just need to decompress. That
2484+
* will trigger recompression later on.
2485+
*/
2486+
24842487
struct varlena *new_value;
24852488
ToastCompressionId cmid;
24862489
char cmethod;
@@ -2507,7 +2510,10 @@ reform_and_rewrite_tuple(HeapTuple tuple,
25072510

25082511
/* if compression method doesn't match then detoast the value */
25092512
if (TupleDescAttr(newTupDesc, i)->attcompression != cmethod)
2513+
{
25102514
values[i] = PointerGetDatum(detoast_attr(new_value));
2515+
values_free[i] = true;
2516+
}
25112517
}
25122518
}
25132519

@@ -2516,6 +2522,13 @@ reform_and_rewrite_tuple(HeapTuple tuple,
25162522
/* The heap rewrite module does the rest */
25172523
rewrite_heap_tuple(rwstate, tuple, copiedTuple);
25182524

2525+
/* Free any value detoasted previously */
2526+
for (i = 0; i < newTupDesc->natts; i++)
2527+
{
2528+
if (values_free[i])
2529+
pfree(DatumGetPointer(values[i]));
2530+
}
2531+
25192532
heap_freetuple(copiedTuple);
25202533
}
25212534

0 commit comments

Comments
 (0)