Diagram illustrating InnoDB Cluster architecture optimized for low-bandwidth connectivity.

How to Run InnoDB Cluster in Low-Bandwidth Environments

,

InnoDB’s buffer pool is the core of MySQL performance. It is where data and indexes are cached, where most reads and writes touch memory first, and where a lot of subtle performance problems start.

This article walks through how the buffer pool works, how to size and configure it, and what to monitor. The focus is on practical, production-oriented guidance rather than internals for their own sake.

1. What the InnoDB buffer pool actually does

The buffer pool is a large memory area where InnoDB caches:

  • Data pages (table rows)
  • Index pages (B-tree nodes)
  • Undo pages and some internal structures

Every logical read goes through the buffer pool:

┌─────────────┐     ┌────────────────┐     ┌────────────┐
│ SQL query   │ ─▶ │ InnoDB engine  │ ─▶ │ Buffer pool │
└─────────────┘     └────────────────┘     └────────────┘
                                         ┌──────────────┐
                                         │ Data files   │
                                         └──────────────┘

If the page is in the buffer pool, it is a cache hit (fast). If not, InnoDB must read it from disk into the buffer pool (slow). Writes are also done in memory first and flushed later to disk.

2. Key configuration parameters

2.1 Core settings

These are the main knobs you should understand:

  • innodb_buffer_pool_size: total size of the buffer pool
  • innodb_buffer_pool_instances: number of buffer pool instances (sub-pools)
  • innodb_buffer_pool_chunk_size: allocation granularity for resizing

Check current values:

SHOW VARIABLES LIKE 'innodb_buffer_pool%';

2.2 Sizing guidelines

On a dedicated MySQL server (RHEL/Rocky Linux), a common starting point:

  • OLTP workload: 60-75% of RAM for innodb_buffer_pool_size
  • Mixed workloads or shared servers: 40-60%, depending on other services

Example for a 64 GB dedicated MySQL host:

[mysqld]
innodb_buffer_pool_size = 48G
innodb_buffer_pool_instances = 8

Best practices:

  • Leave enough RAM for OS page cache, MySQL connections, and utilities (often 20-25%).
  • Avoid swapping at all costs; it destroys MySQL performance.
  • On smaller systems (<4 GB), be conservative and monitor closely.

3. Instances, chunks, and concurrency

The buffer pool is divided into instances to reduce contention on internal locks. Each instance is an independent sub-pool with its own LRU list and hash table.

3.1 Choosing buffer pool instances

Rules of thumb:

  • Use multiple instances only if innodb_buffer_pool_size is large (e.g. ≥4 GB).
  • Target instance size around 1-8 GB each.
  • Do not set more instances than CPU cores.

Examples:

  • 8 GB buffer pool on 4 cores → 2-4 instances
  • 64 GB buffer pool on 16 cores → 8 instances

Changing instances requires restart on many versions, so choose sensibly early.

3.2 Chunk size and online resizing

innodb_buffer_pool_chunk_size defines how memory is allocated internally. You normally do not change it. What matters is that online resizing works in multiples of chunk size × instances.

Example: chunk size 128 MB, 8 instances → minimum increment is:

128 MB × 8 = 1024 MB (1 GB)

Resize online:

SET GLOBAL innodb_buffer_pool_size = 64 * 1024 * 1024 * 1024; -- 64G

Note: On busy systems, resizing a large buffer pool can temporarily increase IO and CPU. Schedule during quieter periods.

4. How pages move inside the buffer pool

InnoDB uses an approximate LRU (least recently used) algorithm with a “young” and “old” sublist to avoid cache pollution from full scans.

┌──────────────────────────────────────────────┐
│              InnoDB buffer pool             │
├──────────────────────────────┬──────────────┤
│          young list          │  old list    │
│  (recently & frequently used)│(newly loaded │
│                              │ or rarely    │
│                              │ used pages)  │
└──────────────────────────────┴──────────────┘

When a page is read from disk, it enters near the middle of the LRU (old list). If it is read again soon, it is promoted toward the young list. This reduces the impact of large sequential scans that would otherwise evict hot pages.

You can influence this behaviour with:

  • innodb_old_blocks_pct: percentage of the LRU used for the old list (default often 37)
  • innodb_old_blocks_time: milliseconds before a page in old list can be promoted

For workloads with heavy batch scans, increasing innodb_old_blocks_time (e.g. to 1000 ms) can protect hot pages from eviction.

5. Monitoring the buffer pool

5.1 Basic status metrics

Start with global status:

SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool%';

Key metrics:

  • Innodb_buffer_pool_read_requests: logical reads (from buffer pool)
  • Innodb_buffer_pool_reads: physical reads (from disk)
  • Innodb_buffer_pool_pages_total, _data, _free: page counts

Calculate buffer pool read hit ratio over an interval:

hit_ratio = 1 - (Innodb_buffer_pool_reads / Innodb_buffer_pool_read_requests)

Collect values at two points in time and compute differences. A high ratio (e.g. >99%) is good, but context matters: small systems or workloads with very large working sets may see lower ratios.

5.2 Detailed instrumentation

For deeper analysis, enable the Performance Schema and InnoDB metrics (if available in your version):

SHOW ENGINE INNODB STATUS\G

Look for sections like:

  • Buffer pool and memory
  • Page hash
  • LRU list

Watch for:

  • High read IO compared to logical reads → buffer pool too small or poorly used.
  • Frequent page flushing and checkpointing → may indicate write pressure or mis-tuned flushing.

6. Step-by-step: tuning the buffer pool

6.1 Step 1: Collect baseline metrics

  1. Record SHOW GLOBAL STATUS and SHOW VARIABLES.
  2. Capture SHOW ENGINE INNODB STATUS\G.
  3. Measure OS-level metrics: CPU, RAM, swap, IO latency (e.g. iostat -x 1 on Rocky Linux).

6.2 Step 2: Check memory and swap usage

On RHEL/Rocky Linux:

free -h
vmstat 5

If you see swap in use and high swap-in/out activity, reduce buffer pool size immediately and investigate other memory consumers. Swapping MySQL is worse than a smaller buffer pool.

6.3 Step 3: Evaluate hit ratio and IO

Over a representative period (e.g. 5-15 minutes under normal load):

  • Compute hit ratio from buffer pool metrics.
  • Check disk utilisation and latency with iostat -x.

Typical observations and actions:

  • High disk reads, low hit ratio, free RAM available → increase buffer pool size.
  • High disk writes but reads acceptable → look at flush settings and log file sizes, not just buffer pool.
  • CPU saturated, IO moderate → adding buffer pool may not help; look at queries and indexes.

6.4 Step 4: Adjust size cautiously

When increasing innodb_buffer_pool_size online:

  • Increase in modest steps (e.g. 10-20% at a time).
  • Observe IO and response times during and after the change.
  • Ensure you stay safely below RAM capacity to avoid swapping.

Example (for a running instance):

-- WARNING: Changing buffer pool size affects memory usage immediately.
-- Ensure you have enough free RAM before running this in production.
SET GLOBAL innodb_buffer_pool_size = 56 * 1024 * 1024 * 1024; -- 56G

6.5 Step 5: Review instance count

If you see contention in InnoDB mutexes (via SHOW ENGINE INNODB STATUS or Performance Schema), and you have a large buffer pool with many cores, consider increasing innodb_buffer_pool_instances at the next maintenance window. Avoid extremes; too many small instances can hurt rather than help.

7. Common anti-patterns and pitfalls

  • Huge buffer pool on small RAM: Setting 90%+ of RAM for InnoDB leaves no headroom for connections or OS cache. This often leads to swapping and worse performance.
  • Ignoring non-InnoDB memory: MyISAM, query cache (if enabled), sort buffers, and application processes all need RAM.
  • Frequent huge resizes: Treat buffer pool size as a stable capacity parameter, not a knob to turn every day.
  • Assuming “bigger is always better”: After your working set fits in memory, further increases bring diminishing returns. Focus on schema and query design instead.

8. Operational best practices

  • Document buffer pool settings and rationale per environment (dev, staging, prod).
  • Use configuration management (Ansible, etc.) to keep settings consistent across nodes.
  • Monitor buffer pool metrics continuously and alert on anomalies (e.g. sudden drop in hit ratio, unexpected increase in physical reads).
  • Re-evaluate buffer pool size during major workload or data volume changes (e.g. new feature rollout, data growth).
  • Test configuration changes on a staging system with realistic data and workload.

This article offers general technical guidance. Validate all configurations in a safe environment before applying them to production.

Smart reads for curious minds

We don’t spam! Read more in our privacy policy

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *