Strange memory management when using full-text indexes
Description
Environment
AFFECTED CS IDs
Attachments
Smart Checklist
Activity

Julia Vural March 4, 2025 at 9:02 PM
It appears that this issue is no longer being worked on, so we are closing it for housekeeping purposes. If you believe the issue still exists, please open a new ticket after confirming it's present in the latest release.

Satya Bodapati October 23, 2024 at 8:53 AM
FYI: blogpost link:

Yura Sorokin March 15, 2019 at 3:09 PM
Idea (2) - jemalloc works like a charm

Yura Sorokin March 15, 2019 at 2:58 PM
Here are a few few ideas, which we can verify.
1. Pre-allocating memory_heap object inside 'fts_query_phrase_search()' with a big memory block(32/64/128 MB) upon creation.
2. Try different memory allocator like jemalloc (may have other side effects).
3. There can be kernel tuning settings for memory releasing background thread (needs investigation).

Yura Sorokin March 15, 2019 at 2:43 PM
Deeper InnoDB FTS code analysis and checks revealed no actual memory leaks.
The problem seems to be in memory fragmentation and in how this fragmented memory is released to the OS upon calling 'free()' libc function.
Each call to 'fts_query_phrase_search()' creates an InnoDB memory heap object which grows up to 80 MB in this case and have a big number of memory blocks ('mem_block_t'). Memory in those blocks is very often wasted as this heap is used for constantly growing 'ib_vector' objects and every time 'ib_vector_push()' is called and vector runs out of its capacity, a new memory is requested from the heap_allocator which in turns ends up with allocating a new memory block for the heap by calling 'malloc()'.
Digging into how standard libc memory allocator works, it looks like 'free()' function MAY but DON'T HAVE to immediately release memory to the kernel. It may reuse the most recently deleted block (or several blocks) for the next allocation(s). Moreover, releasing memory to the kernel is still just an async request. On modern kernels, the memory is actually released by a background thread. The fact that having 2 CPU cores instead of 1 drastically improves memory consumption can be an explained by the fact that in this case that memory releasing background thread now can be run on its own CPU core and be much more productive and therefore catch up with allocation requests coming from mysqld.
See https://unix.stackexchange.com/questions/53447/does-free-unmap-the-memory-of-a-process).
Details
Details
Assignee

Reporter

Labels
Upstream Bug URL
Time tracking
Sprint
Affects versions
Priority
Smart Checklist
Open Smart Checklist
Smart Checklist

Percona Server does not release memory after executing query that required full-text index.
Tested against 5.7.24-26, this issue is not reproducible with upstream or PS 8. This is reproducible with thread_cache_size=0.
Steps to reproduce:
1. Create a test table.
2. Populate it with data:
3. Start monitoring memory usage (pidstat -p pid -r 1 1000, for example)
4. Start select query in a loop:
5. Check current MySQL memory usage
- It starts growing:
and finally, it reaches a maximum point after it is not released back even if queries from point 3 are finished already:
What's interesting, executing the same amount of 'dummy' queries:
caused MySQL to release back its memory: