Bug #10385 Stress: Memory not freed for other services to use on memory table deletion
Submitted: 5 May 2005 13:05 Modified: 5 May 2005 13:19
Reporter: Disha Email Updates:
Status: Not a Bug Impact on me:
None 
Category:MySQL Server Severity:S1 (Critical)
Version:5.0.4 Beta OS:Linux (Linux 9.x)
Assigned to: CPU Architecture:Any

[5 May 2005 13:05] Disha
Description:
Stress: Memory not freed for other services to use on memory table deletion.

On creating memory tables on heap, resident as well as swapped memory is utilized depending on the size of table created. 

Once this table is dropped or even if the database is dropped, the memory is not freed for other appications to use. It is blocked for mysqld process. That is, after dropping a memory table, and creating a new one of same size, does not require any additional memory space.

It is only when the Mysqld service is stopped, that the entire memory is freed.

However, the expected behaviour is that memory used by the memory table should be immediately released on dropping the table for other applications to use. 

How to repeat:
Setup:
The setup used has 4 gb of resident memory and 8 gb of swap memory.

Repro:
1. Check memory utilized by mysqld process using top or system monitor.
2. Create 3 memory tables, viz. tb1, tb2, tb3, each of which ocupies 2-3 gb of memory.
3. Check the memory utilized after table creation and population is complete.
4. Drop table tb3.
5. Check the memory utilized after table is dropped.
6. Stop mysqld service.
7. Check the memory utilized. 

Expected Result:
Memory utilized by mysqld after step 5 should be less than memory utilized after step 3. Alternatively, the memory after dropping the table should be shared for other applications to use.

Actual Result:
Memory utilized by mysqld after step 5 is same as the memory utilized after step 3. 
It is not released by other processes.

Additional Information
Following is the memory table creation script that is used:
set @@max_table_heap_size=4294967295//
create table tb4 (
f176 numeric (0) unsigned not null DEFAULT 9, 
f177 numeric (64) unsigned not null DEFAULT 9, 
f178 numeric (0) zerofill not null DEFAULT 9, 
f179 numeric (64) zerofill not null DEFAULT 9, 
f180 numeric (0) unsigned zerofill not null DEFAULT 9, 
f181 numeric (64) unsigned zerofill not null DEFAULT 9, 
f182 numeric (0,0) not null DEFAULT 9, 
f183 numeric (63,63) not null DEFAULT 9, 
f184 numeric (0,0) unsigned not null DEFAULT 9, 
f185 numeric (63,63) unsigned not null DEFAULT 9, 
f186 numeric (0,0) zerofill not null DEFAULT 9, 
f187 numeric (63,63) zerofill not null DEFAULT 9, 
f188 numeric (0,0) unsigned zerofill not null DEFAULT 9, 
f189 numeric (63,63) unsigned zerofill not null DEFAULT 9, 
f190 real not null DEFAULT 88.8, 
f191 real unsigned not null DEFAULT 88.8, 
f192 real zerofill not null DEFAULT 88.8, 
f193 real unsigned zerofill not null DEFAULT 88.8, 
f194 double not null DEFAULT 55.5, 
f195 double unsigned not null DEFAULT 55.5, 
f196 double zerofill not null DEFAULT 55.5, 
f197 double unsigned zerofill not null DEFAULT 55.5, 
f198 float, 
f199 float unsigned, 
f200 float zerofill, 
f201 float unsigned zerofill, 
f202 float(0), 
f203 float(23), 
f204 float(0) unsigned, 
f205 float(23) unsigned, 
f206 float(0) zerofill, 
f207 float(23) zerofill, 
f208 float(0) unsigned zerofill, 
f209 float(23) unsigned zerofill, 
f210 float(24), 
f211 float(53), 
f212 float(24) unsigned, 
f213 float(53) unsigned, 
f214 float(24) zerofill, 
f215 float(53) zerofill, 
f216 float(24) unsigned zerofill, 
f217 float(53) unsigned zerofill, 
f218 date, 
f219 time, 
f220 datetime, 
f221 timestamp, 
f222 year, 
f223 year(3), 
f224 year(4), 
f225 enum("1enum","2enum"), 
f226 set("1set","2set"),
f236 char(95) unicode,
f241 char(255) unicode,
f237 char(130) binary,
f238 varchar(2500) binary,
f239 varbinary(0),
f240 varchar(120) unicode
) engine = Memory;

This table populated with 500000 records creates a table of size 1.8 gb.
[5 May 2005 13:19] Hartmut Holzgraefe
I'm sorry, but this is how Unix memory allocation works: memory once allocated with malloc() is only free()d internally to be reused for future malloc() calls within the same
process but never returned to the operating system.

This is actually not as bad as it sounds as this unused memory is likely to be swapped out soon if memory is tight, so it just takes up swap space but not real memory.