[MDEV-14050] Memory not freed on memory table drop Created: 2017-10-11 Updated: 2020-08-25 Resolved: 2019-04-30 |
|
| Status: | Closed |
| Project: | MariaDB Server |
| Component/s: | Data Manipulation - Delete |
| Affects Version/s: | 10.2.9 |
| Fix Version/s: | 10.2.23, 10.3.14, 10.4.5 |
| Type: | Bug | Priority: | Critical |
| Reporter: | Silviu Dan Tanasie | Assignee: | Oleksandr Byelkin |
| Resolution: | Not a Bug | Votes: | 4 |
| Labels: | None | ||
| Environment: |
MariaDB 10.2.9 on Centos 7.4 |
||
| Attachments: |
|
| Description |
|
The issue is very simple. I have multiple tables using storage ENGINE MEMORY . These tables can range in size from 2Kb to 500Mb. They all have about 15 normal int columns with one BIG UNSIGNED INT column and HASH index on every column. I just updated from MariaDB 10.1.28 to MariaDB 10.2.9 and there is a major issue I have encountered: The server also have Replication enabled, but not on the database that uses MEMORY tables. Edit: After further investigation, it seems the memory is indeed freed but only after some time. Thus if you delete say a large number of tables and create a large number of tables in short time-span using Engine Memory, there is a high risk of running out of memory. |
| Comments |
| Comment by Elena Stepanova [ 2017-10-12 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
I can reproduce the difference, it seems to be related to 10.1 being linked with libjemalloc and 10.2 not.
Yes, the memory doesn't appear to be freed right away when I drop a table; but if I create a new one afterwards, the memory is reused, it's not allocated again. Thus, there is no danger of running out of memory, unless you have more existing tables than the machine can handle. Here is how it looks:
Could you please double-check that you actually have the extra consumption in the described scenario ("if you delete a large number of tables and create a large number of tables in short time-span"), and show the numbers? And if you do, please specify which version of jemalloc you have on the machine, and attach your cnf file(s). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Silviu Dan Tanasie [ 2017-10-16 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Thank you! Will do so. I can confirm I have the extra consumption. Ever since MariaDB 10.2 the mysql service will crash eventually if I delete and recreate a large number of tables using ENGINE MEMORY. System logs write that the OS ran out of memory and had to force close the mysql service in order to free up system memory. I know it's not because there are two many tables, because normally they occupy about 8 GB of RAM, the system has 16GB. If i drop them and recreate them, then MariaDB eats up about 16GB of RAM and the OS has to force restart it in order to avoid running out of memory. After MariaDB restart, if I recreate the tables, they will occupy 8GB of RAM, as the should. I will ran a test and give you the required information. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Silviu Dan Tanasie [ 2017-10-24 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
I have tried to reproduce the bug but it's very difficult. Mind you this table creation, dropping and recreation is done through PHP. However, dropping a table through mariadb console has the same effects and results from my tests. I have tried to use a simple memory table with 4 int colums: creating, dropping and recreating works as expected (no memory issues). *I have tried to export one of the existing tables and than drop it. Memory is not freed. Importing the table leads to additional memory usage. Dropping the table again afterwards frees the memory and importing it again is done at no extra memory usage. Right now this is what MariaDB reports and size for my memory tables:
Yet pmap for mysqld reports total 22006888K Other info:
As for the above tests:
At this point | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Elena Stepanova [ 2017-10-24 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
In regard to 20G reported by pmap, I'd expect most of those 20G would be various buffers, namely the InnoDB buffer pool, but also others. I think it also includes libraries. For the rest, which part of the output above you consider to be a leak? The last block with pmap results seems reasonable – you created three tables, the consumption grew three times. You dropped one table and created another one, the consumption didn't grow any further. For drop/import table, I'm not quite sure what you mean by import here, can you provide the exact commands that you used? | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Silviu Dan Tanasie [ 2017-10-28 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
I've finally been able to reproduce the bug but only when creating and dropping the tables via a PHP script. I'm using PHP 7.1. By manually running this script several times I was able to fill my server's memory to the point where it had to restart the mysql service (MariaDB).
This is the procedure: Server version: 10.2.9-MariaDB | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Alice Sherepa [ 2017-11-22 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
I could not reproduce the problem with test case provided. Memory grows up to some limit, but it should be expected, because the case needs a lot of memory. To move forward please confirm output of `SHOW GLOBAL VARIABLES` from the test server and provide exact output of memory growth as shown in `top -cbn1 | grep mysqld` during the test | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Silviu Dan Tanasie [ 2017-12-04 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Begining of test: 2035 mysql 20 0 3118012 381096 10484 S 0.0 1.2 0:00.28 /usr/sbin/mysqld First run: One minute wait Second run: 2 runs with 5 seconds wait them between them: One minute wait Sixth run: Another 4 runs with 5 seconds between them wait time (did not check mysqld usage between them): Another 5 runs with 5 seconds between them wait time (did not check mysqld usage between them): One minute wait Another 10 runs with 2 seconds between them wait time (did not check mysqld usage between them): Rerunning one more time: 2035 mysql 20 0 17.666g 0.014t 12156 S 0.0 47.7 19:09.73 /usr/sbin/mysqld Rerunning it 7-8 more times: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Silviu Dan Tanasie [ 2017-12-04 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
This is another test that I did with 600 temporary tables already loaded in memory. Server is a dual core HT machine with 32 GB of DDR4 RAM . We start at 25.3 % memory usage by mysql service: We now run the mentioned script once: Now let us wait 40 seconds and run the script again: ----------------------- Waited for 10 seconds after the previous script run and then run the script again. Memory is not cleared and the mysql memory usage grows to 47% Now, wait for 15 seconds and run the script again. Surprisingly, memory usage seems to remain stable at 57.8% : Now I wait for 1 minute before running the script again. Again the memory seems to be cleared and usage remains at 57.3%. http://imagizer.imageshack.com/img922/138/sVkixw.png Took another 10 second break and run the script again. This time memory usage remains at 65% after the script run. http://imagizer.imageshack.com/img922/2258/l1CyI6.png Took another 1 minute break and ran the script again. Memory usage now remains at 76.8%. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Silviu Dan Tanasie [ 2017-12-04 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Sorry for all the Global.txt edits, had some server information that needed to be removed. Should be good now. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Andrii Nikitin (Inactive) [ 2017-12-05 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
I can trigger the problem with concurrent load from bash (which also downloads and unpacks 10.2.11), I don't see how to write the same load from mtr . script: https://github.com/AndriiNikitin/bugs/blob/master/MDEV-14050.sh The logs show two numbers : combined size of all tables and memory usage, e.g. it starts with: meaning 11G of data+index and 16G memory usage, which looks good. Then memory usage steadily grows to be much more than size of tables: (You may see many errors like '2013 (HY000): Lost connection to MySQL server at 'handshake: reading inital communication packet', system error: 22' at start of bash script, which are caused by MDEV-14131 are safe to ignore in this test) All in my tests show that memory may grow up to twice more than size of memory tables, which of course is not effective, but may be explained by memory fragmentation. Minor notice is that memory usage with default table cache seems to cap at ~49G for handling ~24G of table data. Since:
I don't see any direct bug here. But of course it will be better if developers can look at the data and confirm conclusion | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Osiris Support [ 2018-06-26 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Hello, I encounter as well this issue with MariaDB 10.2.14, running on Red Hat Enterprise Linux Server release 6.2. I modified the PHP script of @Starchaser to open a new connection every time.
As our application runs several scripts in parallel creating temporary tables, we can not use MariaDB 10.2, it always ends up crashing. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Osiris Support [ 2018-07-23 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Hello,
We found this solution because we also had the problem mentioned in bug MDEV-13403 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Silviu Dan Tanasie [ 2018-07-25 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
This seems like a good workaround. Though the bug is still there. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Silviu Dan Tanasie [ 2018-11-26 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
As of MariaDB 10.3.11 this bug is still present. Any fix in sight? | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Hyeokjin Park [ 2018-12-24 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
we have same issue 10.2.18, jemalloc is usefull. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Valerii Kravchuk [ 2019-04-23 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Using jemalloc or tcmalloc is just a wokraround. Wee havee to understand what changed in 10.2+ comparing to 10.1 that made this visible. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Oleksandr Byelkin [ 2019-04-24 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
valerii, elenst mentioned that the difference is exactly in building 10.1 with jemalloc and 10.2 without (if I correctly understand the statement). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Valerii Kravchuk [ 2019-04-24 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
If building with jemalloc is a solution then why not to conitnue building with it by default (while having option to use other malloc libraries via LD_PRELOAD etc)? In any case, is there anything in the code that can be done so that memory is returned to OS properly no matter what malloc implementation is used? Like calling malloc_trim(0) as suggested in upstream https://bugs.mysql.com/bug.php?id=94647? | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Oleksandr Byelkin [ 2019-04-24 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
malloc_trim(0) looks good until next bugreport with question why temporary tables become slow... | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Oleksandr Byelkin [ 2019-04-24 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
I read and discussed it: so IMHO it is question of setup for special needs of the user (pre-load jemalloc) and there is no universal solution which will not touch most other customers. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Oleksandr Byelkin [ 2019-04-24 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Maybe the other solution is also to play with MALLOC_TRIM_THRESHOLD_ and MALLOC_TOP_PAD_ environment variables if jemalloc is not ok somehow. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Silviu Dan Tanasie [ 2019-04-24 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Hi, Unfortunately, jemalloc is not a stable solution or at least for us it is not. This is how our server configuration looks like now on Centos:
[mysqld] And this is memory usage: PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND The actual size of the in-memory tables is about 7GB. So mysql (MariaDB) is eating a lot more. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Oleksandr Byelkin [ 2019-04-24 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
How you measured size of in-memory tables footprint ("about 7GB")? | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Silviu Dan Tanasie [ 2019-04-24 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
I used SELECT table_schema "database_name", I know that only one database uses in-memory tables, in fact, it has ONLY in-memory tables. It's called "something_temp" and that database is reported to have 6634.7 MB. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Oleksandr Byelkin [ 2019-04-25 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
I checked the docs and there written that size is approximate so I checked what is not counted, about 14-15KB per table with 16 indexes by 1 index segment, i.e. not so much (actually I do not know if there is thouthands of tables it can be a lot) . But then I thought about allocation: we can not count memory management overhead. The only thing I can tell it proportional to number of tables and inversely proportional to record size. So most probably we have here big overhead due to memory fragmentation and just overhead of allocation (and using jemalloc is proof of it because they have better dealing with fragmentation). Other proof of this idea that if stop using heap tables memory will be returned eventually. So IMHO here we have problem of just out of resources for given load. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Silviu Dan Tanasie [ 2019-04-25 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Fortunately, I can help with a little bit more information.
Our workaround to this problem, that has never failed so far, is to have a job that restarts the MariaDB server once in a while and regenerate all the in-memory tables. If the MariaDB server is restarted, the memory is released. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Oleksandr Byelkin [ 2019-04-30 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
But you have not tried more memory or less table, it looks like the issue connected with memory fragmentation and so with intense use it just require much more memory than was allocated. I have not found memory leaks, or huge amount non-counted memory (limited size structures only). So I think it is just a memory fragmentation (which fought with different efficiency by different allocators but can not be removed with current approach of allocating memory for heap tables). Feel free to reopen bug if memory will not stop growing after increasing memory or decreasing volume of temporary data. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Silviu Dan Tanasie [ 2019-05-03 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Hi, Is there any way to check what memory management library MariaDB is using? The server is still crashing, albeit only once a week, with jemalloc. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Silviu Dan Tanasie [ 2019-09-19 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
It's time to finally put this issue to rest. The one solution that works is to edit the service file on Centos: /usr/lib/systemd/system/mariadb.service With this method, I was able to load my custom malloc library and finally, the memory allocation problem has gone away. For the future, I suggest to the MariaDB team to have more explicit features on using different memory allocation libraries. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Roope Pääkkönen (Inactive) [ 2019-09-20 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Small tip, if you edit that file in /usr/lib directly, it gets replaced when you update packages - instead you can run: systemctl edit mariadb and then add:
This will create an "override" to the systemd service definition, which will remain there over package upgrades, etc. I've also have had good experiences with using jemalloc w mariadb so far. |