Recommended Free Tools
iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more
Antihost offers Linux VPS plans with full root access, unlimited traffic on a 1 Gbps port and a 14-day free trial.
MySQL stops being killed only when its peak memory fits inside the limit that actually applies to it. First determine whether the kill came from host-wide Linux OOM, a container or cgroup limit, or systemd-oomd. Then budget the InnoDB buffer pool, global allocations, per-connection buffers, temporary tables and other services together. Lower max_connections and oversized per-thread buffers when necessary; changing OOM scores or adding swap can reduce risk but cannot compensate for an oversized budget.
Identify which out-of-memory mechanism killed mysqld
“Out of memory” is not one condition. The kernel can exhaust RAM on the whole host, a cgroup can hit its own memory.max, or systemd-oomd can terminate a service after sustained memory pressure. The fix depends on the scope. Host RAM does not override a container limit, and protecting mysqld from one killer does not prevent another policy from acting.
Quick wins for a faster PC:
Scan for outdated or missing drivers - takes under a minuteDriver Scan →Clear out junk files and repair common Windows errorsFree Scan →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Kernel OOM on the host
The kernel OOM killer runs when an allocation cannot be satisfied in the memory context that triggered it. That context may be the entire machine or a constrained memory controller. Kernel messages normally name the killed process, its PID, and memory statistics. A kill in this category often affects several services competing for the same RAM.
A cgroup or container limit
Docker, Kubernetes, LXC and systemd scopes can impose a hard memory ceiling below physical RAM. When the group reaches that ceiling, the kernel can kill a process inside the group while the host still shows free memory. Inspect the group’s effective limit and current usage rather than relying on free output from the host.
#1 Best Overall
systemd-oomd before a kernel OOM
systemd-oomd is a userspace service. It monitors cgroups-v2 and pressure stall information (PSI), then can kill eligible units when configured swap or memory-pressure policies are met. A service terminated by oomd may have no classic “Out of memory: Kill process” line from the kernel. Check the oomd journal and unit properties before changing MySQL settings.
Confirm the event and capture evidence
Collect evidence immediately after a kill, before restarting or clearing logs. Record the time, killed PID, unit or container name, peak connections, RAM, swap and the applicable cgroup path.
Free tools Windows power users keep installed
One-click scans. No signup required.
- Search kernel messages:
journalctl -k -b. On systems that provide it, also rundmesg -T. Look for “Out of memory,” “Killed process,” “oom-kill,” or a memory-cgroup failure. - Read the MySQL error log around the same timestamp. A sudden disappearance, followed by normal startup messages on the next launch, is consistent with an external kill; an InnoDB error or assertion indicates a different failure.
- Inspect service status and recent unit logs with
systemctl status mysql(the unit may be namedmysqld) andjournalctl -u mysql --since "-2 hours". - Check current capacity with
free -h,swapon --show, andcat /proc/meminfo. Capture both available memory and swap usage; “free” RAM alone is not a peak measurement. - For a systemd service, inspect limits and drop-ins:
systemctl show mysql -p MemoryMax -p MemoryHigh -p ManagedOOMSwap -p ManagedOOMMemoryPressure -p ControlGroupandsystemctl cat mysql. - Check whether oomd is active:
systemctl status systemd-oomd, then searchjournalctl -u systemd-oomdfor the unit or cgroup. - In a container, read the container’s cgroup files (commonly
/sys/fs/cgroup/memory.max,memory.current,memory.events, or their cgroup-v1 equivalents). A value ofmaxmeans no explicit limit in that file; it does not guarantee unlimited host memory.
The key result is a named scope: host, cgroup/container, or systemd-oomd policy. Do not tune a buffer pool until that scope is known.
Build a realistic MySQL memory budget
innodb_buffer_pool_size is the largest familiar allocation, but it is not MySQL’s total memory. Global caches, per-thread work areas, thread stacks, temporary tables, Performance Schema, replication, client libraries and the operating-system page cache all compete for the same limit.
| Component | How it grows | What to inspect |
|---|---|---|
| InnoDB buffer pool | Global; normally the largest fixed allocation | innodb_buffer_pool_size |
| Connection and thread memory | Can multiply by active sessions; some allocations occur per connection or per operation | max_connections, thread cache and stack settings |
| Sort, join and read buffers | Per-thread or per-operation; large values become expensive under concurrency | sort_buffer_size, join_buffer_size, read_buffer_size, read_rnd_buffer_size |
| Temporary tables | Each concurrent workload can create in-memory temporary tables, then spill or fail when limits are reached | tmp_table_size, max_heap_table_size |
| Binary-log and other caches | Per-session or global, depending on variable | Binary-log cache settings and global cache variables |
| Instrumentation and replication | Additional global or workload-dependent memory | Performance Schema, relay logs, replication configuration |
| Non-MySQL processes | Competes inside the same host or cgroup | Web servers, agents, backups, JVMs and filesystem cache |
MySQL’s documented starting range for the InnoDB buffer pool is typically 50%–75% of system memory. That is a starting range for a dedicated host, not a promise that 75% is safe in a container or on a busy shared server. Subtract the memory required by the OS, every co-resident service and a safety reserve first.
For initial planning, MySQL gives this illustrative lower-bound estimate:
PC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteinnodb_buffer_pool_size + key_buffer_size + max_connections*(sort_buffer_size + read_buffer_size + binlog_cache_size) + max_connections*2MB
The expression is not a peak guarantee. Add room for join and random-read buffers, temporary-table growth, thread stacks, Performance Schema, replication, allocator overhead, filesystem cache and short bursts. Oracle-provided MySQL binaries commonly use a 256 KB thread stack; a 2 MB stack is also common, so verify the actual build and setting rather than assuming one number.
Measure peaks, not idle RSS
Idle mysqld RSS can look safe while a reporting job opens many sessions and allocates sort or temporary buffers simultaneously. Track process RSS and cgroup memory.current during the busiest period. Compare the highest observed connection count with max_connections; sizing for a theoretical maximum that applications never reach wastes memory, while sizing for today’s idle count misses bursts.
Step-by-step: make the budget fit
1. Reserve memory for the scope outside MySQL
Start with the effective limit, not the machine’s installed RAM. Reserve explicit headroom for the kernel, filesystem cache, monitoring, backups and every other service. On a 16 GiB container capped at 8 GiB, the budget starts at 8 GiB, not 16 GiB. Keep a reserve for bursts and reclaim latency; a configuration that equals the limit will eventually hit it.
2. Set a conservative buffer pool
Lower innodb_buffer_pool_size until the remaining budget covers measured non-buffer usage and peak concurrency. MySQL supports dynamic buffer-pool resizing in current versions, so a change can often be made without a restart:
SET GLOBAL innodb_buffer_pool_size = 4294967296;
The value is in bytes; use a value appropriate to the measured limit. Confirm the change with:
Rank #3
SHOW GLOBAL VARIABLES LIKE 'innodb_buffer_pool_size';
Resizing can temporarily consume resources and may affect cache hit rate. If the desired value cannot be changed dynamically on your version or packaging, schedule the required restart and verify the persistent configuration afterward.
3. Cap concurrency at a measured requirement
max_connections multiplies memory that is cheap at one session and dangerous at hundreds. Find the high-water mark:
Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Repair Windows errors before they cause bigger problems3Fix the driver behind crashes, sound loss and screen glitchesSHOW GLOBAL STATUS LIKE 'Threads_connected';
SHOW GLOBAL STATUS LIKE 'Max_used_connections';
SHOW GLOBAL VARIABLES LIKE 'max_connections';
Set a limit above the measured legitimate peak, with a small operational margin, rather than an arbitrary four-digit value. Apply it persistently in the server configuration and use a connection pool to queue excess application work. A lower limit can expose application errors or queueing, so test clients for proper retry and back-pressure behavior.
4. Reduce oversized per-thread buffers
Inspect and lower unusually large values for sort_buffer_size, join_buffer_size, read_buffer_size, read_rnd_buffer_size, binary-log cache variables and thread-stack settings. These buffers are not reserved once for the server; concurrent operations can allocate them repeatedly. Change one class of variable at a time, then observe query latency, disk-based temporary tables and peak RSS. A smaller buffer may increase sorting, joining or temporary-table spills, trading memory for I/O.
5. Control in-memory temporary tables
tmp_table_size and max_heap_table_size limit internal in-memory temporary tables. Large limits can multiply across concurrent queries. Set them to a value justified by workload measurements, and monitor whether lowering them causes excessive disk temporary tables or unacceptable latency. Do not assume that raising these limits is a free performance improvement.
6. Recalculate and observe
Re-run the planning formula with the new values, then observe peak cgroup usage, mysqld RSS, connection count, swap activity and query latency over a representative busy period. Keep a reserve below the hard limit. If memory still climbs, identify which category grew instead of repeatedly shrinking the buffer pool.
Rank #4
Container and systemd limits: fixes outside MySQL
When a cgroup limit is too low
If the workload genuinely needs more memory, raise the container or service limit and account for the infrastructure cost. Otherwise, reduce MySQL’s budget to fit the existing ceiling. Raising a host’s RAM without raising memory.max changes nothing for a capped container. Check both the parent and descendant cgroups; a nested limit can remain lower than the value you changed.
When systemd applies a hard or soft limit
MemoryMax is a hard ceiling; MemoryHigh applies reclaim and throttling pressure before that ceiling. Drop-ins can override the vendor unit, so inspect all effective properties with systemctl show and the files shown by systemctl cat. After editing a drop-in, run:
systemctl daemon-reload
systemctl restart mysql
Restarting the service is required for the unit-limit change to take effect, and it will interrupt connections. Coordinate it with application failover or maintenance procedures.
When systemd-oomd is selecting the unit
Check ManagedOOMSwap= and ManagedOOMMemoryPressure= on the unit and relevant slice. Review oomd journal entries for the exact cgroup and threshold. You can change policy or eligibility, but disabling protection without fixing the memory budget simply moves the eventual failure to the kernel or another service. Validate any policy change during a controlled pressure test.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Swap: useful cushion, not a cure
Some swap gives the kernel room to move cold pages and can delay an immediate kill. Verify that swap exists with swapon --show, then monitor paging latency and application response time. Heavy swapping can make MySQL unusably slow, and systemd-oomd policies may deliberately act when swap is exhausted or pressure remains high. Adding swap does not reduce MySQL’s allocation; it only changes how pressure is handled. Never count swap as a substitute for a RAM budget that fits the workload.
OOM-score tuning and victim selection
Linux uses oom_score_adj to adjust a process’s badness score. A lower score can make mysqld less likely to be selected, but it does not free memory or lower MySQL’s demand. The kernel may then kill a web server, backup process or monitoring agent that is more important to recovery. Treat score changes as a last-resort failure-priority decision after capacity and cgroup settings are correct.
Best Value
Inspect the current value with cat /proc/$(pidof mysqld)/oom_score_adj. If you deliberately change it, make the setting persistent through the service manager, document which process is allowed to die instead, and test that the value survives a restart. Do not use it to conceal a recurring budget error.
Compare remediation choices before applying them
| Option | Peak-memory effect | Performance or operational trade-off | Restart? | Reversibility and blast radius |
|---|---|---|---|---|
| Reduce buffer pool | Direct, predictable global reduction | Potentially more disk reads and lower cache hit rate | Often no; dynamic resizing is documented | Usually reversible; mainly affects MySQL |
Lower max_connections |
Caps connection-driven growth | Applications may queue or receive “too many connections” | Depends on how the persistent setting is applied | Reversible; requires client testing |
| Reduce per-thread buffers | Reduces concurrent-work spikes | More temporary files, I/O or query latency | Variable-specific; verify documentation | Reversible; query classes may differ |
| Raise cgroup or unit limit | Increases available headroom | Uses more host or cloud capacity and may endanger neighbors | Usually requires unit/container update and restart | Reversible, but affects infrastructure and other tenants |
| Add swap | Delays hard failure during bursts | Swap latency; may trigger oomd policy | Usually no service restart | Reversible; affects the whole scope |
Lower oom_score_adj |
None | Moves the likely victim to another process | Service-manager dependent | Reversible, but blast radius is unpredictable |
Troubleshooting branches
The buffer pool was lowered but mysqld is still killed
- Check whether the kill is actually from systemd-oomd or a cgroup limit.
- Compare peak, not idle, connection count with
max_connections. - Inspect per-thread buffers and temporary-table limits; these can dominate during bursts.
- Account for Performance Schema, replication, binary logging, thread stacks and non-MySQL processes.
- Read
memory.eventsfor cgroup OOM counters and correlate timestamps with kernel and unit logs.
The host has free RAM, but the container reports OOM
The container’s memory controller is the applicable scope. Read its effective memory.max and current usage, then either raise that limit or fit the MySQL budget inside it. Host-level free output cannot override a lower cgroup ceiling.
Connections fail after lowering max_connections
Confirm the application uses pooling, bounded retries and a queue. Set the limit above the measured legitimate peak, deploy clients that release idle sessions, and watch Threads_connected and connection errors. Increasing the limit again without reducing per-session memory restores the original risk.
Performance collapses after memory reductions
Check disk temporary-table rates, sort and join latency, buffer-pool hit behavior, swap-in activity and storage latency. Restore only the setting that caused the regression, and fund that increase by reducing another memory consumer or raising the cgroup limit. Avoid restoring every previous value at once.
Operational checklist
- Identify kernel OOM, cgroup OOM or systemd-oomd in logs.
- Record the effective memory limit, peak usage, swap and killed PID.
- Measure
Max_used_connectionsduring the busiest period. - Calculate a budget including global, per-thread, temporary-table and non-MySQL memory.
- Leave an explicit reserve below
MemoryMaxormemory.max. - Reduce the buffer pool, connection cap or oversized buffers in measured steps.
- Use a pool to queue excess application concurrency.
- Verify swap behavior and oomd thresholds after every policy change.
- Persist settings, document restart requirements and monitor peak RSS and cgroup usage.
Conclusion
A durable fix is a memory budget that fits the real scope and the real peak. Diagnose the killer first, reserve memory outside MySQL, then tune the buffer pool, concurrency and per-thread allocations together. Cgroup limits, swap and OOM scores determine how failure appears, but only reducing demand or providing adequate capacity prevents the next kill.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

