How to Configure MySQL Memory Limits to Prevent Excessive RAM Usage (166% of Installed RAM)


2 views

When MySQL Tuner reports that your MySQL instance could potentially use 166% of installed RAM (like the 426.8M shown in your case), it's indicating that your configuration allows MySQL to allocate more memory than your system physically possesses. This occurs because MySQL's various buffers and caches can collectively request memory that exceeds physical limits.

These are the primary configuration options that impact MySQL's memory usage:


# In your my.cnf or my.ini file under [mysqld] section
key_buffer_size = 16M
query_cache_size = 16M
tmp_table_size = 32M
max_heap_table_size = 32M
innodb_buffer_pool_size = 128M
innodb_log_buffer_size = 8M
max_connections = 100

Use this formula to estimate total potential memory usage:


Total Memory = 
(key_buffer_size) +
(query_cache_size) +
(tmp_table_size * max_connections) +
(innodb_buffer_pool_size) +
(innodb_log_buffer_size) +
(max_heap_table_size * max_connections)

For a system with 256MB RAM (similar to your reported case):


[mysqld]
# Global settings
key_buffer_size = 16M
query_cache_size = 8M
query_cache_limit = 1M
max_connections = 50

# Per-connection settings
thread_stack = 192K
thread_cache_size = 8

# Temp tables
tmp_table_size = 16M
max_heap_table_size = 16M

# InnoDB settings
innodb_buffer_pool_size = 64M
innodb_log_buffer_size = 4M
innodb_flush_log_at_trx_commit = 2

After making changes, restart MySQL and check:


SHOW VARIABLES LIKE '%size%';
SHOW STATUS LIKE 'Memory%';

Use this query to monitor current memory usage:


SELECT 
  (SELECT @@key_buffer_size) +
  (SELECT @@query_cache_size) +
  (SELECT @@innodb_buffer_pool_size) +
  (SELECT @@innodb_log_buffer_size) +
  (SELECT @@max_connections * (@@read_buffer_size + 
                               @@read_rnd_buffer_size + 
                               @@sort_buffer_size + 
                               @@join_buffer_size + 
                               @@binlog_cache_size + 
                               @@thread_stack)) AS total_configured_memory;

If MySQL gets killed by the OOM killer, add these protective measures:


# In /etc/security/limits.conf
mysql hard as 500000
mysql soft as 500000

# In /etc/sysctl.conf
vm.overcommit_memory = 2
vm.overcommit_ratio = 80

When MySQL Tuner reports your MySQL instance could potentially use 166% of installed RAM (like the 426.8M vs installed RAM in your case), this indicates critical configuration issues. The database is configured to allocate more memory than physically available, which will lead to swapping and severe performance degradation.

These are the primary variables that need adjustment in your my.cnf or my.ini file:


# Buffer Pool - The most critical setting
innodb_buffer_pool_size = 256M  # Should be ~60-80% of available RAM for dedicated DB servers

# Per-connection buffers
key_buffer_size = 32M
query_cache_size = 0  # Disabled in MySQL 8.0+
tmp_table_size = 32M
max_heap_table_size = 32M

Use this formula to prevent over-allocation:


Max Memory Usage = 
  innodb_buffer_pool_size +
  key_buffer_size +
  (max_connections * (sort_buffer_size + read_buffer_size + 
   read_rnd_buffer_size + join_buffer_size + thread_stack))

For a server with 2GB RAM and 100 connections:


innodb_buffer_pool_size = 1.2G
key_buffer_size = 64M
max_connections = 100
sort_buffer_size = 2M
read_buffer_size = 1M
read_rnd_buffer_size = 1M
join_buffer_size = 1M
thread_stack = 256K

For containerized MySQL, use these runtime commands:


docker run --memory="2g" --memory-swap="2g" \
  -e MYSQL_INNODB_BUFFER_POOL_SIZE=1.2G \
  -e MYSQL_KEY_BUFFER_SIZE=64M \
  mysql:8.0

Verify your settings with these SQL commands:


SHOW VARIABLES LIKE '%buffer%size%';
SHOW VARIABLES LIKE '%pool%size%';
SHOW STATUS LIKE 'Memory%';

For MySQL 5.7+ and MariaDB 10.2+, enable detailed memory tracking:


UPDATE performance_schema.setup_instruments 
SET ENABLED = 'YES' 
WHERE NAME LIKE 'memory/%';

SELECT * FROM performance_schema.memory_summary_global_by_event_name
WHERE COUNT_ALLOC != 0
ORDER BY SUM_NUMBER_OF_BYTES_ALLOC DESC;