Introduction Many MySQL setups begin life with a familiar incantation:
InnoDB Buffer Pool Tuning: From Rule-of-Thumb to Real Signals appeared first on MariaDB.org
Many MySQL setups begin life with a familiar incantation:
innodb_buffer_pool_size = 70% of RAM…and then nothing changes.
That’s not tuning. That’s a starting guess.
Real tuning starts when the workload pushes back.

The InnoDB buffer pool is where database performance is quietly decided. It determines whether your workload hums along in memory or drags itself across disk. If you’re not actively observing and tuning it, you’re leaving performance on the table.
This guide walks through how to monitor, understand, and tune the buffer pool using real signals instead of guesswork.
The buffer pool isn’t just “memory for MySQL.” It’s a living system under constant pressure:
Think of it as your database’s working memory. If your working set fits, queries glide. If it doesn’t, pages are constantly evicted and reloaded, introducing latency that rarely announces itself clearly.
+---------------------------+
| Buffer Pool |
|---------------------------|
Reads ---> | Cached Pages |
| |
Writes ---> | Dirty Pages (pending IO) |
| |
Eviction -> | LRU / Free List |
+---------------------------+
|
v
Disk (slow)Three forces are always competing:
Your job is to keep this system balanced.
SHOW ENGINE INNODB STATUS\GUseful for human inspection. Look for:
Great for debugging. Not ideal for automation.
SELECT
pool_id,
free_buffers,
database_pages,
modified_database_pages
FROM information_schema.INNODB_BUFFER_POOL_STATS;Key fields:
free_buffers → Available pages (breathing room)database_pages → Pages holding datamodified_database_pages → Dirty pages waiting to flushGreat for automation.
Yes, it’s widely used. No, it’s not enough.
A high hit ratio does not mean your system is healthy. It does not capture:
You can have a 99% hit ratio and still be IO-bound.
Use it as a sanity check, not a decision-maker.
SELECT SUM(free_buffers) AS free_buffers
FROM information_schema.INNODB_BUFFER_POOL_STATS;Interpretation:
SELECT
(SUM(modified_database_pages) / SUM(database_pages)) * 100.0 AS dirty_pct
FROM information_schema.INNODB_BUFFER_POOL_STATS;Interpretation (context matters):
SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_reads';
-- Take two samples 60s apart and compareTrack the rate of change (reads/sec), not the absolute value.
Interpretation:
SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_read_ahead%';
SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_pages_evicted';
SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_reads';Interpretation:
Focus on rates of change over time, not absolute values.
Thrashing is when the buffer pool constantly evicts and reloads pages.
Classic SymptomsTime --->
Memory: [FULL][FULL][FULL][FULL]
Reads: ↑ ↑↑ ↑↑↑ ↑↑↑↑
Latency: - ^ ^^ ^^^
Evictions: ↑ ↑↑ ↑↑↑ ↑↑↑↑If you see this pattern, your working set does not fit in memory.
Instead of blindly assigning 70% of RAM:
Avoid starving the OS or filesystem cache.
innodb_max_dirty_pages_pct = 75
innodb_io_capacity = 1000
innodb_io_capacity_max = 2000What they control:
innodb_io_capacity → Expected steady-state IO throughputinnodb_io_capacity_max → Burst flushing capacityinnodb_max_dirty_pages_pct → Threshold for aggressive flushing⚠️ These values should reflect real hardware capability.
A practical, battle-tested guideline:
Use 1 instance per ~1GB of buffer pool, up to a reasonable limit.
Buffer Pool Instances: Reducing Contention
The buffer pool can be split into multiple instances, each managing its own internal structures. This helps reduce contention under high concurrency.
Without this, all threads compete for the same buffer pool internals. With multiple instances, that load is distributed.
Buffer pool instances only help when contention exists. You’ll see benefits if your system has:
If your workload is primarily IO-bound, this setting will have little impact.
General guidance:
Each instance needs enough memory to function efficiently.
Avoid going below ~1GB per instance.
If instances are too small:
Example
innodb_buffer_pool_size = 32G
innodb_buffer_pool_instances = 8This gives ~4GB per instance, which is well-balanced.
Buffer pool resizing is online in modern MySQL versions, but:
innodb_buffer_pool_chunk_sizeCause: Working set barely fits
Fix: Increase buffer pool size gradually
If increasing the buffer pool size does not reduce disk reads, the problem is not memory.
Cause: Flushing cannot keep up
Fix:
innodb_io_capacityCause: Checkpoint pressure
Fix:
SELECT
(SUM(database_pages) * 16) / 1024 AS mb_used
FROM information_schema.INNODB_BUFFER_POOL_STATS;Assumes default 16KB page size (innodb_page_size).
Dirty Page PercentageSELECT
(modified_database_pages / database_pages) * 100 AS dirty_pct
FROM information_schema.INNODB_BUFFER_POOL_STATS;SELECT SUM(free_buffers) AS free_buffers
FROM information_schema.INNODB_BUFFER_POOL_STATS;If you remember nothing else:
The InnoDB buffer pool doesn’t fail loudly. It degrades quietly until your disk becomes the bottleneck.
By the time you notice, you’re debugging latency instead of preventing it.
Monitor the right signals, and you’ll see problems forming before users do.
That’s the difference between reacting to performance… and controlling it. ∎
| # | Наименование новости | Тональность | Информативность | Дата публикации |
|---|---|---|---|---|
| 1 | MariaDB has broken the concept of dynamically configurable buffer pools! | 0 | 10.18 | 09-02-2026 |
| 2 | InnoDB Redo Log Sizing: Stop Guessing, Start Measuring | 0 | 5.82 | 02-05-2026 |
| 3 | InnoDB Page Flushing Diagram | 0 | 5.76 | 18-06-2022 |
| 4 | ANALYZE FORMAT=JSON now shows InnoDB buffer pool reads | 0 | 6.9 | 26-09-2023 |
| 5 | Efficient MySQL Performance In 10 Sentences | 0 | 9.92 | 09-11-2024 |
| 6 | MySQL LRU Flushing and I/O Capacity | 0 | 7.54 | 02-09-2021 |
| 7 | Hardening MySQL: Practical Security Strategies for DBAs | 0 | 5.76 | 02-03-2026 |
| 8 | How Not to Use MySQL | 0 | 5.77 | 16-09-2022 |
| 9 | InnoDB Tablespace Duplicate Check Threads (and EBS Volumes for MySQL Startup with Many Tables) | 0 | 7.41 | 03-12-2024 |
| 10 | Tune your MariaDB IO workload using this simple step | 0 | 6.97 | 14-07-2021 |