There is no universally “best” my.cnf for a 1GB or 2GB Ubuntu server. The safe approach is to budget memory for Ubuntu and every co-resident service first, then allocate a conservative InnoDB buffer pool and cap connection-driven memory. A practical starting profile is a 256M buffer pool, 25 maximum connections, small per-thread buffers, 16M temporary-table limits, and a 512 table cache—but each value must be recalculated from the host’s actual workload.
Why low-RAM MySQL tuning is a budgeting problem
MySQL memory has two broad parts: allocations that exist largely once per server and allocations that can multiply with concurrent sessions. The InnoDB buffer pool is the largest global allocation on most InnoDB workloads. Sort, read, join, temporary-table, binary-log, and thread-stack memory can grow as more connections execute simultaneously. Ubuntu itself, SSH, a web server, PHP workers, monitoring agents, and the filesystem cache also need headroom.
As an Amazon Associate I earn from qualifying purchases.
Oracle’s MySQL documentation says its default configuration is designed to let a server start on a virtual machine with approximately 512MB of RAM. That is a bootability target, not a recommendation for a busy shared VPS. The same documentation commonly cites 50–75% of system memory for innodb_buffer_pool_size, but that range assumes a database server with enough room for the operating system and other allocations. On a 1GB or 2GB Ubuntu machine running application services, treating 75% as automatically safe can trigger swapping or an out-of-memory kill.
Free tools Windows power users keep installed
One-click scans. No signup required.
Think of physical RAM as a fixed envelope. A larger cache may reduce disk reads, but if it leaves no room for a PHP worker spike, a replication thread, a backup process, or the kernel, the server becomes slower and less reliable. The useful setting is the largest one that preserves headroom during the worst normal workload, not the largest number that fits while the machine is idle.
#1 Best Overall
Measure the host before changing my.cnf
Record a baseline during normal traffic and during the busiest period you can reproduce. Without this baseline, a larger cache can appear beneficial while the host is silently swapping.
- Capture total and available RAM, resident memory (RSS) for
mysqld, and current swap usage. - Record swap-in and swap-out activity, not just whether a swap partition exists.
- Check current and peak MySQL connection counts.
- Measure representative query latency and error rates.
- Inspect internal temporary-table counters to see how often queries spill to disk.
- Check file-descriptor limits before increasing table caches.
- List every service sharing the host and estimate its peak memory, including web and PHP worker pools.
On a small VPS, the application’s connection pool is often more important than the nominal max_connections value. A ceiling of 200 connections does not make sense when the application can create only 10 concurrent workers, and it creates a much larger worst-case memory envelope.
Use the same observation window after every change. A five-minute idle sample is not enough: capture a deployment, a busy web period, scheduled jobs, and any backup or reporting task that normally runs. Compare both averages and peaks. A setting that looks fine at midday can still fail when all application workers reconnect after a restart.
Calculate a defensible memory envelope
Use the buffer pool as the first line in the budget, then reserve memory for Ubuntu, co-resident services, and MySQL’s remaining global structures. Finally, account for memory that can be multiplied by active sessions.
MySQL’s documented estimate includes:
innodb_buffer_pool_size
+ key_buffer_size
+ max_connections * (sort_buffer_size + read_buffer_size + binlog_cache_size)
+ max_connections * 2MB
The manual cautions that this formula must be adapted to the MySQL version and configuration. It is a planning aid, not a guarantee: execution plans, temporary tables, thread stacks, plugins, prepared statements, Performance Schema, and the operating system add variability. The final max_connections * 2MB term is a broad allowance, not a promise that each connection consumes exactly 2MB in every release.
Keep separate lines in your worksheet for global allocations, per-connection allowances, Ubuntu and service memory, and a safety reserve. Do not count swap as available application RAM. Swap can prevent an immediate crash, but sustained swap-in and swap-out usually means latency has already become unacceptable.
For a shared 1GB host, start with a deliberately modest pool and leave room for Ubuntu and application workers. On a 2GB host, you can usually give MySQL more room, but only after measuring the non-MySQL footprint and peak concurrency. Increase one allocation at a time and watch resident memory and swap.
A conservative starting profile
The following profile is an example for a small shared Ubuntu server. The numbers are not universal defaults; recalculate them for your RAM, services, MySQL release, and observed concurrency.
[mysqld]
# Recalculate after measuring Ubuntu, web/PHP workers, and other services.
innodb_buffer_pool_size = 256M
# Align this with the application's real peak concurrency.
max_connections = 25
# Keep per-thread working buffers modest on a small host.
sort_buffer_size = 256K
read_buffer_size = 128K
read_rnd_buffer_size = 256K
join_buffer_size = 256K
# Keep internal temporary tables from consuming unbounded RAM.
tmp_table_size = 16M
max_heap_table_size = 16M
# Raise gradually only when file-descriptor headroom exists.
table_open_cache = 512
A 256M pool is an example starting point, not a recommendation that every 1GB or 2GB server should use exactly 256M. If the host is dedicated to MySQL, has a small working set, or has substantial application memory, the appropriate value may be lower or higher. The only reliable way to choose is to observe the resulting memory and latency under representative load.
The sample deliberately omits settings that are not justified by the available facts. For example, there is no universal low-RAM value for every cache, log, or thread option. Add a variable only when you can explain its memory cost, its expected benefit, and how you will measure whether it helped.
Settings that matter most
innodb_buffer_pool_size
The buffer pool caches InnoDB data and indexes and is normally the most valuable large allocation. Size it only after reserving memory for Ubuntu, other services, and MySQL’s connection-dependent buffers. A larger pool can reduce disk reads when the hot working set fits, but it cannot compensate for a host that is paging.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
MySQL 8.0 documentation lists a default of 134217728 bytes (128MB) and a documented minimum of 5242880 bytes (5MB). The pool can be resized dynamically, but make changes gradually and test them under realistic traffic. If swap activity rises or the kernel kills mysqld, reduce the pool before increasing anything else.
Compare the hot working set, not merely the total database size, with the pool. A database larger than RAM can still perform well when frequently used indexes and rows fit; a small database can perform poorly if queries scan it repeatedly. Buffer-pool hit behavior and storage latency should be considered alongside RSS and swap rather than treated as a reason to consume every free megabyte.
max_connections
This is a memory-safety limit, not a performance setting. Several buffers and thread stacks are multiplied by concurrent sessions, so a high ceiling creates a large worst-case commitment even when most connections are idle. Set it above the application’s measured peak with a small operational margin, rather than copying a value from a high-RAM template.
Check both configured and observed values:
SHOW VARIABLES LIKE 'max_connections';
SHOW STATUS LIKE 'Threads_connected';
SHOW STATUS LIKE 'Threads_running';
SHOW STATUS LIKE 'Max_used_connections';
Threads_connected shows the current occupancy, while Threads_running indicates sessions actively executing. Max_used_connections reveals the highest simultaneous use since the server started or counters were reset. Look at all three: a high connected count with few running threads may reflect idle pool connections, while a high running count can signal genuine concurrency or a query backlog.
If Max_used_connections remains far below the ceiling, lowering max_connections usually releases more risk than enlarging a cache. If the application genuinely needs more simultaneous sessions, use a connection pool and verify that the host can absorb the resulting per-session memory. A rejected connection is visible and recoverable; an OOM kill can take down the database and application together.
Per-thread buffers
sort_buffer_size, read_buffer_size, read_rnd_buffer_size, and join_buffer_size are tempting knobs when one query is slow. Raising them globally, however, multiplies the worst-case memory requirement by active connections. Keep them modest globally and optimize the offending query, indexes, or schema instead. Session-level increases for a controlled reporting connection are safer than making every client pay the cost.
These buffers are working space, not permanent cache. A larger value does not force every query to become faster, and it cannot repair a missing index or an inefficient join plan. When a particular report needs extra sort or join memory, isolate that workload, measure its concurrency, and return to the smaller global value for ordinary web traffic.
tmp_table_size and max_heap_table_size
These limits constrain in-memory internal temporary tables. Keep them equal on a small host so one limit does not undermine the other. The 16M values in the sample profile are workload-dependent starting points, not a published universal low-RAM standard.
After changing them, inspect temporary-table counters:
SHOW GLOBAL STATUS LIKE 'Created_tmp%';
More disk-based temporary tables can increase latency, but that trade-off may be preferable to exhausting RAM. If spills are frequent, identify the queries causing them and improve indexes or execution plans before simply raising both limits. A temporary table that spills because it contains a large sort or grouping operation may be better addressed by reducing rows early, selecting fewer columns, or adding an appropriate index.
table_open_cache
A larger table cache can reduce table-open churn, but it also consumes descriptors. Ubuntu guidance recommends increasing it gradually. Raise it only when status counters indicate repeated table opens and the service’s file-descriptor limit has clear headroom. If MySQL reports “Too many open files,” roll the value back and review the systemd/service limit before trying again.
Do not confuse table-open churn with query execution time. If the cache is already sufficient, increasing it spends descriptor and bookkeeping capacity without improving latency. Check the configured service limit, current descriptor use, and the status counters before each step; the operating-system ceiling can bind before physical RAM does.
Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Clear out junk files and repair common Windows errors3Fix the driver behind crashes, sound loss and screen glitchesinnodb_buffer_pool_instances
Multiple buffer-pool instances are associated with pools of at least 1GB and with scalability on larger systems. For a small pool, leave the default or use one instance unless measurements show contention that a change actually resolves. Splitting a small pool into many instances adds complexity without creating memory.
Changing the instance count is not a substitute for sizing the total pool. Evaluate it only after the pool is large enough for the feature to be relevant and after contention has been observed under load. On a small VPS, simpler configuration is usually easier to validate and recover.
innodb_dedicated_server
Do not enable this automatically on a shared VPS. MySQL documents it for an instance on a dedicated server that can use the machine’s available resources. When Ubuntu, a web server, workers, or other tenants share the host, explicit low-RAM settings make the budget visible and controllable.
Even on a nominally dedicated machine, verify that backup agents, monitoring, security tools, and scheduled jobs are included in the budget before delegating sizing decisions to an automatic mode. Shared-resource assumptions are the reason a setting that is sensible in a database-only environment can be dangerous on a small application server.
The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Choosing settings for 1GB versus 2GB hosts
| Decision factor | 1GB shared Ubuntu host | 2GB shared Ubuntu host |
|---|---|---|
| Buffer-pool strategy | Start conservatively and reserve substantial room for the OS and application. Increase only after swap and RSS remain stable. | Measure the larger non-MySQL footprint first; increase the pool in steps while retaining headroom for peak workers. |
| Connections | Keep the ceiling close to measured application concurrency; avoid idle connection overprovisioning. | Allow more concurrency only when the application needs it and per-session memory remains affordable. |
| Per-thread buffers | Keep the sample small values unless a specific session-level workload proves otherwise. | Do not enlarge globally merely because total RAM doubled; concurrency can still exhaust memory. |
| Temporary tables | Prefer controlled disk spills to an OOM event; fix spill-heavy queries. | Test whether additional memory improves latency without causing swap, then adjust cautiously. |
| Table cache | Stay below the descriptor ceiling and increase only when open churn is measured. | Apply the same descriptor check; extra RAM does not remove file-limit constraints. |
These are decision patterns, not fixed recipes. Dataset size, read/write mix, query shape, connection pooling, and co-resident services determine the correct values. A 2GB host running many PHP workers may have less memory available for MySQL than a 1GB database-only machine, so capacity labels alone cannot select a safe profile.
Apply changes safely
- Save the current Ubuntu MySQL configuration and record the baseline metrics listed earlier.
- Change one logical group at a time: first the buffer pool, then connection/per-thread limits, then temporary-table limits or table cache.
- Place settings in the active
[mysqld]section of the server configuration used by your Ubuntu package. Confirm the server reads that file rather than an unused template. - Restart only when the particular variable requires it; variables that support dynamic changes can be adjusted online according to the MySQL version’s documentation.
- Run representative application traffic or a controlled load test. Watch RSS, available memory, swap-in/out, connection counts, query latency, errors, and temporary-table counters.
- Keep the change only if latency or throughput improves without eroding safety headroom. Otherwise restore the previous value and continue with a smaller adjustment.
Ubuntu package layouts and systemd limits vary by release, so verify the active configuration path and service definition on the actual machine. A syntactically correct option in an unused template has no effect, while a typo or unsupported variable can prevent startup. Keep a tested rollback copy and validate the service after each restart.
Never combine a larger buffer pool, a higher connection ceiling, and larger per-thread buffers in one unmeasured edit. If the result is an OOM kill, you cannot tell which change caused it, and recovery becomes harder.
Rank #4
Troubleshoot the symptoms you actually see
MySQL is killed by the kernel
- Reduce
innodb_buffer_pool_sizefirst. - Lower
max_connectionsto the application’s real peak. - Keep sort, read, join, and temporary-table limits modest.
- Check memory consumed by web workers and other services before giving MySQL more RAM.
Review what else was running at the time: deployment hooks, backup utilities, log processing, and PHP worker expansion can consume the headroom that looked available during testing. Restore a known-safe profile, confirm the service starts, and then change one item at a time.
Recommended Free Tools
The server is swapping after increasing connections
Undo the connection increase and inspect Max_used_connections. A higher ceiling can multiply thread and working-buffer memory even when only a fraction of sessions execute queries. Fix connection pooling or request concurrency rather than masking the pressure with a still larger swap area.
Queries became slower after lowering temporary-table limits
Confirm whether disk temporary tables increased, then identify the statements responsible. Improve indexes, reduce unnecessary sorting/grouping, or tune those sessions specifically. Raising global limits is justified only when measured memory headroom remains ample.
Table-open errors appear after raising the cache
Lower table_open_cache and inspect the service’s file-descriptor limit. Increase the cache in smaller steps only after descriptor headroom and table-open churn are both demonstrated.
More buffer pool does not improve latency
If the hot working set is already cached, additional pool space may deliver no benefit. Stop increasing it when gains flatten; investigate query plans, indexes, storage latency, and application behavior instead.
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 minuteConnections are refused even though the server has free RAM
Free RAM alone does not prove that a larger connection ceiling is safe. Check whether the configured limit is being reached, whether the application is leaking idle sessions, and whether each connection’s buffers leave enough worst-case headroom. Correct the pool behavior and query duration before raising the ceiling.
When configuration tuning is no longer enough
Ubuntu’s tuning guidance notes that, after configuration changes reach diminishing returns, the durable options are improving the application, using a more powerful machine, or scaling the database environment. A low-RAM server that continuously swaps is already beyond the safe operating envelope; no single my.cnf value can turn insufficient physical memory into reliable capacity.
Scaling may mean moving MySQL to a database-only host, selecting a larger VPS, reducing co-resident worker counts, or changing the application’s query and caching strategy. Treat the measured bottleneck as the decision point: if memory pressure dominates, add capacity or reduce concurrency; if storage or query plans dominate, changing RAM settings will not solve the underlying problem.
If a larger VPS is the practical next step, Antihost Linux VPS plans provide 2–64 GB RAM, NVMe storage, and full root access in the USA East, Netherlands, and Ukraine. The self-managed setup lets you apply the same measured memory budget as you scale.
Quick wins for a faster PC:
Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Repair Windows errors before they cause bigger problemsFix Now →Frequently Asked Questions
What is a good MySQL buffer pool size for a 1GB Ubuntu server?
Start conservatively, such as the 256M example, only after reserving memory for Ubuntu, web/PHP workers, and other services. The often-cited 50–75% range is a reference for a database host with sufficient headroom, not an automatic rule for a shared 1GB VPS.
Best Value
What is a good buffer pool size for a 2GB Ubuntu server?
Measure the non-MySQL footprint and peak concurrency first, then increase the pool in steps while watching RSS, swap, latency, and throughput. There is no fixed 2GB value that is safe for every workload.
Why did MySQL start swapping after I increased max_connections?
Connection-related buffers and thread stacks can multiply with concurrent sessions. Inspect Threads_connected, Threads_running, and Max_used_connections, then return the ceiling to the application’s real peak plus a small margin.
Should tmp_table_size and max_heap_table_size be the same?
Keeping them equal makes the in-memory temporary-table budget predictable. The 16M sample is only a starting point; check Created_tmp% counters and fix spill-heavy queries before raising both limits.
Should I enable innodb_dedicated_server on a VPS?
Not when Ubuntu, a web server, workers, or other services share the machine. The option is intended for an instance that can use the dedicated server’s available resources; explicit limits are safer on a shared VPS.
How high should table_open_cache be?
Start below the service’s file-descriptor ceiling and increase gradually only when table-open churn is measured. If you see “Too many open files,” lower the cache and review the systemd limit.
Do multiple innodb_buffer_pool_instances help a small server?
Usually not. The MySQL reference associates multiple instances with pools of at least 1GB and larger-scale scalability. For a small pool, leave the default or use one instance unless measurements show a specific contention problem.
Can I fix one slow query by increasing sort_buffer_size globally?
That can multiply memory use across active sessions. Keep global per-thread buffers modest, improve the query or indexes, or apply a larger value only to a controlled reporting session.
What should I monitor after editing my.cnf?
Track mysqld RSS, available memory, swap-in/out, current and peak connections, query latency and errors, temporary-table counters, and file-descriptor headroom. Compare the same metrics during representative busy traffic.
When should I stop tuning and upgrade the server?
Stop when larger caches no longer improve latency or when the host swaps, suffers OOM kills, or lacks safe headroom. Improving the application, moving MySQL to a larger or dedicated machine, or scaling the database environment is then more durable.
The Bottom Line
For a low-RAM Ubuntu server, start with a memory budget rather than a copied template: reserve room for Ubuntu and application services, use a conservative InnoDB buffer pool, align max_connections with real concurrency, keep per-thread and temporary-table limits modest, and raise table caches only within descriptor limits. Measure RSS, swap, connections, temporary-table spills, and latency after every change. If gains flatten or the host keeps swapping, improve the workload or add capacity instead of pushing my.cnf harder.
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.
Quick wins for a faster PC:
Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Clear out junk files and repair common Windows errorsFree Scan →Scan for outdated or missing drivers - takes under a minuteDriver Scan →




