innodb_buffer_pool_size. Sometimes that is the fix. Often it is not, and the extra memory just pushes the VPS closer to swapping without making any query faster. Before touching the config, it is worth confirming that the buffer pool really is too small for the data your site uses.
What the buffer pool does and what too small looks like
Innodb_buffer_pool_read_requests counts logical reads, meaning every time InnoDB asked for a page. Innodb_buffer_pool_reads counts the requests that could not be served from the pool and had to go to disk. The ratio between the two is your miss rate, and it is the core of this whole check.
Reading the counters without fooling yourself
SQL
SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_read%';
SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_wait_free';
SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_pages%';
SHOW GLOBAL STATUS LIKE 'Uptime';
SHOW GLOBAL VARIABLES LIKE 'innodb_buffer_pool_size';mysqladmin can print the difference between snapshots for you:
BASH
# Print counter deltas every 60 seconds. The first block shows absolute totals, so skip it. Ctrl+C to stop.
mysqladmin -r -i 60 extended-status | grep -E 'Innodb_buffer_pool_(reads|read_requests|wait_free) '-u and -p, or rely on a client config file that already holds credentials. Run it during a period when the site is actually slow, not at 4 AM when nobody is visiting.
Now look at the deltas. As an illustrative example, if one minute shows 1,000,000 read requests and 100 disk reads, the pool is serving nearly everything from memory. If the same minute shows 1,000,000 requests and 50,000 disk reads, about 5% of page lookups are going to disk, and that is worth investigating. A common rule of thumb is that a warmed-up server with steady traffic typically sits well under 1%, but the acceptable level depends on your workload and how fast the storage is.
The absolute number matters too, not just the ratio. With the default 16 KB page size, 50,000 page reads per minute is roughly 800 MB of reads per minute. On fast NVMe that may be tolerable; on slower or shared storage it will hurt. If you want background on how storage latency changes this, see NVMe SSD vs SATA in Web Hosting.
Innodb_buffer_pool_wait_free is the other counter to watch. It increases when InnoDB needs a free page and has to wait for one to be flushed. On a healthy server it usually stays at or near zero. If it climbs during normal traffic, the pool is under real pressure.
Comparing the pool with your data size
SQL
SELECT ROUND(SUM(data_length + index_length) / 1024 / 1024) AS innodb_data_mb
FROM information_schema.TABLES
WHERE engine = 'InnoDB';innodb_buffer_pool_size, which is reported in bytes. Then look at Innodb_buffer_pool_pages_free from the earlier output.
If the pool is larger than your total InnoDB data and there are still plenty of free pages, size is not your problem. Everything fits, and any disk reads are coming from somewhere else or from a pool that is still warming up.
If free pages are near zero, the miss rate is sustained, and your data is clearly larger than the pool, you are looking at a genuine fit problem. Even then, remember the working set point. A 20 GB database where only a few GB is hot may run fine on a modest pool, so the miss rate is a better guide than the raw size comparison.
Red herrings that look like a small buffer pool
Innodb_buffer_pool_read_requests enormously, and if the table does not fit, it drags cold pages through the pool and pushes hot ones out. A bigger pool can hide this for a while, but the real fix is the query or the index. The slow query log and EXPLAIN will show it.
Temporary tables written to disk create disk I/O that has nothing to do with the buffer pool. Compare Created_tmp_disk_tables with Created_tmp_tables in SHOW GLOBAL STATUS. If a large share of temporary tables land on disk, that I/O will look like a database read problem on your graphs.
Swap is the trap that works in the opposite direction. If the pool is already too large for the VPS, the kernel starts swapping MySQL memory out, and the disk activity you see is swap traffic. Check free -m and the si and so columns in vmstat 5. If swap is active, increasing the pool makes things worse. The article on why 80% of RAM is not safe on a VPS that also runs the web stack covers that budgeting.
Other processes can also be the reader. Backup jobs, mysqldump, malware scans, and log processing all read heavily from disk. Tools like iotop or pidstat -d, if installed, show which process is actually doing the I/O. If it is not mysqld or mariadbd, the buffer pool is not involved.
Confirming the root cause and checking the fix
Innodb_buffer_pool_wait_free is rising or disk reads are clearly coming from the database process, the hot data is larger than the pool, and the server is not swapping.
If that is the case, increase the pool in a moderate step that leaves room for PHP-FPM, the web server, and per-connection MySQL buffers. Recent MySQL and MariaDB versions can resize the pool online with SET GLOBAL innodb_buffer_pool_size, but that change is lost at restart unless you also set it in the config file. Where that file lives depends on the distro and control panel.
After the change, confirm the value is actually in effect with SHOW GLOBAL VARIABLES LIKE 'innodb_buffer_pool_size', since editing a config file alone does not prove the server loaded it. Then let the pool warm up and run the same mysqladmin sampling during a similar traffic period. You are looking for fewer disk reads per minute, a lower miss rate, and no new swap activity. If the miss rate dropped but the site is still slow, the buffer pool was only part of the story, and the next place to look is the queries themselves.
The short version: do not resize on a hunch or on a single snapshot of lifetime counters. Sample the deltas after warm-up, check free pages and data size, rule out full scans, disk temp tables, swap, and other I/O, and only then add memory. Then measure again, because the second measurement is what tells you the change actually worked.