How to Fix "max memory exceeded" in MySQL

Galaxy Glossary

How do I fix the MySQL “max memory exceeded” error?

“max memory exceeded” appears when MySQL’s calculated peak memory needs outstrip available RAM, risking crashes or OOM kills.

Sign up for the latest in SQL knowledge from the Galaxy Team!
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.

Description

Why does MySQL show “max memory exceeded”?

MySQL combines large global buffers with per-connection buffers. When many sessions open, per-thread allocations multiply. If the sum of global buffers plus (Max_used_connections × per-thread buffers) exceeds physical RAM, the server logs “max memory exceeded” and may crash.

How do I estimate peak memory quickly?

Run:

SHOW GLOBAL STATUS LIKE 'Max_used_connections';
SHOW VARIABLES WHERE Variable_name IN (
'innodb_buffer_pool_size','key_buffer_size',
'sort_buffer_size','join_buffer_size',
'read_buffer_size','tmp_table_size');

Add global buffers, then multiply each per-thread buffer by Max_used_connections. Compare with free -m or /proc/meminfo.

Which server variables control memory?

Global buffers

innodb_buffer_pool_size
key_buffer_size
query_cache_size -- removed in 8.0 but still seen in my.cnf

Per-connection buffers

sort_buffer_size
join_buffer_size
read_buffer_size
read_rnd_buffer_size
tmp_table_size / max_heap_table_size

How do I change these variables safely?

Edit my.cnf and restart, or issue at runtime:

SET GLOBAL innodb_buffer_pool_size = 6G;
SET GLOBAL sort_buffer_size = 2M;
SET GLOBAL tmp_table_size = 256M;
SET GLOBAL max_connections = 200;

Reduce per-thread buffers first—small changes free huge amounts when many sessions connect. Increase innodb_buffer_pool_size slowly while watching swap and Innodb_buffer_pool_reads.

How do I locate memory-hungry queries?

Enable the Performance Schema or slow_query_log with log_slow_extra = ON. Review performance_schema.events_statements_summary_by_digest for statements with high Sort_merge_passes, Created_tmp_disk_tables, or big current_allocated.

Example: ecommerce query that blew RAM

SELECT c.id, c.name,
SUM(o.total_amount) AS lifetime_value
FROM Customers c
JOIN Orders o ON o.customer_id = c.id
GROUP BY c.id, c.name
ORDER BY lifetime_value DESC;

On 50 M Orders, MySQL built a 1 GB temp table in memory and failed. Fixes: add INDEX Orders(customer_id), lower tmp_table_size to 256 MB so oversized temps spill to disk, and consider ORDER BY NULL when ordering is unnecessary.

Best practices to avoid “max memory exceeded”

  • Cap max_connections; rely on connection pooling.
  • Keep per-thread buffers ≤2 MB.
  • Size innodb_buffer_pool_size to 60-70 % of RAM, never 100 %.
  • Monitor MemAvailable and Max_used_connections daily.
  • Run mysqltuner or pt-variable-advisor monthly.

Common mistakes

Setting huge tmp_table_size

Developers increase temp-table memory hoping for speed. Under concurrency, each session allocates the full size, exhausting RAM. Keep it under 256 MB and optimize queries instead.

Ignoring Max_used_connections

Some teams tune memory for average load. A sudden traffic spike re-creates the high-connection scenario that first caused the error. Always plan for the recorded peak.

See also

MySQL manual: Memory Use

Why How to Fix "max memory exceeded" in MySQL is important

How to Fix "max memory exceeded" in MySQL Example Usage


-- Report high-value customers without blowing memory
SELECT c.id,
       c.name,
       SUM(o.total_amount) AS lifetime_value
FROM   Customers c
JOIN   Orders o ON o.customer_id = c.id
GROUP  BY c.id, c.name
HAVING SUM(o.total_amount) > 1000
ORDER  BY lifetime_value DESC
LIMIT  100;

How to Fix "max memory exceeded" in MySQL Syntax


# my.cnf snippet for memory control
innodb_buffer_pool_size = 6G          # Global buffer for InnoDB pages
key_buffer_size         = 64M         # MyISAM index cache
sort_buffer_size        = 2M          # Per-thread sort buffer
join_buffer_size        = 2M          # Per-thread join buffer
read_buffer_size        = 128K        # Sequential read buffer
read_rnd_buffer_size    = 256K        # Random read buffer
tmp_table_size          = 256M        # Memory temp tables size
max_heap_table_size     = 256M        # Upper bound for temp MEMORY tables
max_connections         = 200         # Limit connections to cap per-thread memory

-- Runtime change syntax
SET GLOBAL innodb_buffer_pool_size = <size>;
SET GLOBAL sort_buffer_size        = <size>;
SET GLOBAL join_buffer_size        = <size>;
SET GLOBAL tmp_table_size          = <size>;
SET GLOBAL max_connections         = <number>;

Common Mistakes

Frequently Asked Questions (FAQs)

What is the safest starting point for innodb_buffer_pool_size?

Allocate about 60 % of system RAM if MySQL is the only major service. Leave 30-40 % for the OS and connection buffers.

Will lowering tmp_table_size slow my queries?

Only if queries rely on large, unindexed temp tables. After indexing and rewriting queries, most workloads see no slowdown, and you gain stability.

How do I know which buffer is actually hitting its limit?

Monitor Created_tmp_memory_tables, Handler_read_rnd_next, and Sort_merge_passes. Rising values indicate the corresponding buffer is too small.

Want to learn about other SQL terms?