MySQL server memory usage troubleshooting tips

There are many blog posts already written on topics related to “MySQL server memory usage,” but nevertheless there are some who still get confused when troubleshooting issues associated with memory usage for MySQL. As a Percona support engineer, I’m seeing many issues regularly related to heavy server loads – OR OOM killer got invoked and killed MySQL server due to high Memory usage… OR with a question like: “I don’t know why mysql is taking so much memory. How do I find where exactly memory is allocated? please help!”

Checking MySQL Server Memory

There are many ways to check the memory consumption of MySQL. So, I’m just trying here to explain it by combining all the details that I know of in this post.

  • Check memory related Global/Session variables.

If you are using MyISAM then you need to check for Key_buffer_size, while using InnoDB, you can check innodb_buffer_pool_size,  innodb_additional_memory_pool_size, innodb_log_buffer_size,  innodb_sort_buffer_size (used only for sorting data while creating index in innodb, introduced from 5.6). max_connections, query_cache_size and table_cache are also important variables to check

We know that whenever a thread is connected to MySQL, it will need it’s own buffers when they are doing some complex operations like FTS,  sorting, creating temp tables, etc. So we also need to check the size of read_buffer_size, sort_buffer_size, read_rnd_buffer_size and tmp_table_size.

There is a very good quote from So it seems we have to understand the purpose for configuring any variable… either it is Global or Session level. I would like to explain more about that here.

For the Global variables like key_buffer_size, query_cache_size etc,  MySQL always allocates and initializes the specified amount of memory all at once when the server starts. But it’s not happened for those who are global default but can be set as per-session variables, i.e  For read_buffer_size, sort_buffer_size, join_buffer_size, MySQL doesn’t allocate any memory for these buffers until query needs. But when a query needs, it immediately allocates the entire chunk of memory specified. So if there are even small sorts, the full buffer size will be allocated which is just a waste of memory. Even some buffers can be used multiple times. For example, on queries that join several tables, join_buffer can be allocated once per joined table. Also, some complicated queries including sub-queries can use multiple sort_buffers at the same time which can lead to high memory consumption. In some scenario, the query didn’t even use sort_buffer whatever size is, as it selects by the primary key which will not allocate it. So it depends on the nature of your environment but I would say it’s always better to start with a safe variable value that can be larger than default if needed but not as large as it can consume all of the server’s memory.

One more thing,  not all per-thread memory allocation is configured by variables.  Some of the memory allocation per thread is done by MySQL itself for running complex processes/queries like “stored procedures” and it can take an unlimited amount of memory while running. And sometimes, optimizer can also take a lot of memory working with highly complex queries which generally we can’t control by any configuration parameter.

Even innodb_buffer_pool_size is not a hard limit, usually, innodb uses 10% more memory than the one specified. Many people do not recommend using both storage engine MyISAM and InnoDB at the same time on the production server. Because both have individual buffers which can eat all server memory.

For detailed information related to this topic, I would suggest reading this post from Peter Zaitsev titled “MySQL Server Memory Usage.”


Above one is from Native MySQL but if you’ll check the same with Percona Server you’ll get some more information.

This will give you information regarding how much memory is allocated by InnoDB. You can see here “Total Memory Allocated”, “Internal Hash Tables”, “Dictionary Memory Allocated”, “Buffer Pool Size” etc.

  • Profiling MySQL Memory usage with Valgrind Massif

Recently, I used this tool and surprisingly I got very good statistics about memory usage. Here the only problem is you have to shut down the mysql, start it with valgrind massif and after collecting statistics, you again have to shut down and normal start.

After getting the massif.out file, you have to read it with ms_print command. You will see a pretty nice graph and then statistics. i.e

You can see from the output that where memory is allocated, to which function, etc. You can use this tool to find memory leaks. You can get more information here on how to install and use it. Here’s another related post by Roel Van de Paar titled: “Profiling MySQL Memory Usage With Valgrind Massif.”

If possible Valgrind massif should not be used on busy production server as it can degrade the performance. Generally it’s used to find memory leak by creating mirror environment on test/stage server and run on it. It needs debug binary to run so it decreases performance a lot. So it can be used for investigating some cases but not for regular use.

  • Check Plot memory usage by monitoring ps output. 

This also useful when you want to check how much virtual(VSZ) and real memory (RSS) is used by mysqld. You can either simply run some bash script for monitoring it like

Or you can also check when needed from shell prompt with “ps aux | grep mysqld” command. 

  • Memory tables in MySQL 5.7

With MySQL 5.7, some very interesting memory statistics tables are introduced to check memory usage in performance_schema.  There is no any detailed documentation available yet but you can check some details here.

In P_S, there are five memory summary tables.

So with every event, you can get summarized memory consumption for a particular account, host, thread, and user. While checking more, I found that there are around 209 different events to check. I have just tried to check one event related to join buffer size.

Here, COUNT_ALLOC, COUNT_FREE are aggregate the number of calls to malloc-like and free-like functions. SUM_NUMBER_OF_BYTES_ALLOC and SUM_NUMBER_OF_BYTES_FREE are indicating the aggregate size of allocated and freed memory blocks. CURRENT_COUNT_USED is the aggregate number of currently allocated blocks that have not been freed yet. CURRENT_NUMBER_OF_BYTES_USED is the aggregate size of currently allocated memory blocks that have not been freed yet. LOW_ and HIGH_ are low and high water marks corresponding to the columns. 

If you are aware of these scripts then, these are giving a very good summary about overall server memory consumption as well as related to MySQL.

Like in output of pt-summary,

In output of pt-mysql-summary.


It is really important for us to know where MySQL allocates memory and how it affects the overall load on the MySQL server and performance. I have just tried here to describe a few ways but I still think that we should have some sort of script or something that can combine all of these results and gives us some truthful output of memory usage in MySQL.

More resources:




Free eBooks


Share this post

Comments (15)

  • shamim

    Nice article to capture the memory usage.
    I love using Valgrind Massif for memory stats and also the pt-summary as well.

    how many of the status for memory consumption that the percona server displayed above are configurable (ofcourse excluding the usual buffers and the caches we already can change)?

    While its good to know how much memory is being used behind the scenes, it would really help if we can configure/control it.

    January 26, 2014 at 9:28 am
  • Nilnandan Joshi

    Hi Shamim,

    Thanks. Can you please elaborate your question? Are you asking for P_S (Performance Schema) related memory usage or something else? If it’s P_S related which introduced from 5.6 then you can check with
    SHOW GLOBAL VARIABLES LIKE “performance_schema%”;

    Check more details in comments here about memory consumption and related variables for P_S.

    But still proper documentation is needed for the use of P_S in MySQL 5.6.

    January 27, 2014 at 4:50 am
    • Greg Hill

      Are you for hire? We would like someone with your skills to look at our Linux OpenSUSE system that is running Server version: 10.1.20-MariaDB openSUSE.
      It is an running software called Vicidial which uses Asterisk and Apache.
      Heaving disk activity, lots of simple inserts and updates taking place rapidly.
      We have it on Samsung SSD drives in a RAID 1.
      We have many servers without a RAID that run very well.
      The database in total is 25G, there about 5 tables all containing approximately 10 million records.
      One might suggest archiving but it was working fine before we upgraded the server.

      Very strange. There are 2 differences from other systems that work fine.
      1) RAID 1
      2) New Version of Vicidial Software (but there are not complaints on the forums for this upgrade).

      really need to be sure the my.cnf file is optimized.

      NOTE: We never see the CPU’s fully loaded, never see memory getting utilized.
      System has: Dual Zeon Hexcores with 32G of ram.

      Lost as to how it could be getting sluggish and have no sign of stress.

      Let me know if you or someone can take a look for an agreed fee.

      Thank you,

      February 16, 2017 at 9:44 pm
      • Nikki Morton

        Greg I’ve just sent you an email with contact information.

        Thank you,


        February 16, 2017 at 10:48 pm
        • Greg Hill

          Very good. Thank you.

          February 17, 2017 at 12:33 am
  • jo

    Please check this one to substantiate this further :

    August 1, 2014 at 2:59 pm
  • Pavan

    Hi Nilandan,

    I m begineer for sql database, please help me or guide me to learn and practice of sql database. i lm working in Datacenter for technical support issues.


    October 2, 2014 at 5:10 am
  • vikas

    I have website have 50 lakh data but my sql show 70% memory use
    please check screen shot

    May 3, 2015 at 1:05 pm
  • Rizal Mutaqien

    Nice article post ,Thank you 🙂

    July 11, 2015 at 2:49 pm
  • shailesh Chile

    Hi Nilnandan ,

    I have issue of MySQL Memory consumption.

    There is neither CPU load nor long queries but still memory consumption is 85 % .


    # * Basic Settings
    # Instead of skip-networking the default is now to listen only on
    # localhost which is more compatible and is not less secure.
    bind-address =
    # Fine Tuning
    key_buffer = 32M
    max_allowed_packet = 100M
    thread_stack = 192K
    thread_cache_size = 8
    #table_cache = 64
    #thread_concurrency = 10
    # Query Cache Configuration
    query_cache_limit = 1M
    query_cache_size = 16M

    log_error = /var/log/mysql/error.log
    # Here you can see queries with especially long duration
    log_slow_queries = /var/log/mysql/mysql-slow.log
    long_query_time = 10
    # The following can be used as easy to replay backup logs or for replication.
    # note: if you are setting up a replication slave, see README.Debian about
    # other settings you may need to change.
    #server-id = 1
    #log_bin = /var/log/mysql/mysql-bin.log
    expire_logs_days = 10
    max_binlog_size = 100M

    max_allowed_packet = 16M

    #no-auto-rehash # faster start of mysql but no tab completition

    key_buffer = 32M

    How can I resolved it.
    Thanks in advance.

    July 6, 2016 at 2:31 am
  • Romuald Brunet

    Hello, small correction on one of the the variables names

    The innodb_additional_memory_pool_size seems to actually be called innodb_additional_mem_pool_size (maybe this changed since 2014)

    December 14, 2016 at 4:47 am
  • Amit Patel

    Hi Nilnandan,
    I have one question, I have master DB with 128 GB RAM and 6 TB Flash Drive. Everything working fine but suddenly most of connections runs under “freeing item”, even simplest query also run under “freeing item.”. Sometime i get FAILED Connection also, and connected thread gradually after 2500 , application get getting connection timeout . Please help me in this issue, where i can search or digg for this issue.

    February 9, 2017 at 10:02 am
    • scott farrell

      mysql uses memory per thread, says my config is using 100m/thread. So 2500 threads you might be exhausting your RAM. Perhaps I have poor tuning.

      February 16, 2017 at 7:31 am
  • Kapil Panakanti

    Very nice article..
    We are facing some strange issue where in our mysql server is not starting and server status always remains starting but it not getting up.

    we are facing this as there was less memory on the machine, but when we increased the memory of the machine and started the service it is not getting started.

    any suggestions on this would be very much helpful.

    Thanks in advance.

    May 26, 2017 at 8:37 am
  • siddharth

    please check the configuration of your my.ini file and also and ibdata & iblog files..

    June 15, 2017 at 1:59 pm

Comments are closed.

Use Percona's Technical Forum to ask any follow-up questions on this blog topic.