Skip to main content
Metrics type: Supporting MetricsCategory: InnoDB Buffer Pool

At a glance

The share of the InnoDB buffer pool that holds modified (“dirty”) pages not yet flushed to disk. Dirty pages are a normal, healthy part of how InnoDB batches writes: it modifies pages in memory and flushes them to storage in the background. The percentage matters because it is a pressure gauge. A steady, moderate level means flushing is keeping pace with the write workload; a high and rising level means the flusher is falling behind, which leads to checkpoint pressure, synchronous flush stalls, and bursty “async write storm” behaviour that spikes latency.

Calculation

The card divides the current dirty-page count by the current total-page count:
Context that makes the number readable:
  1. Dirty is not bad; runaway-dirty is bad. InnoDB intentionally keeps recently modified pages in memory so it can coalesce many small writes into fewer, larger, sequential disk writes. A write-heavy instance routinely sits at 20 to 60% dirty during peak with no ill effect. The danger is the trend, not the absolute: a level climbing toward innodb_max_dirty_pages_pct (default 90%) means the background flusher (innodb_io_capacity / innodb_io_capacity_max) cannot drain dirty pages as fast as the workload creates them.
  2. The 90% cliff. When dirty pages reach innodb_max_dirty_pages_pct, InnoDB stops being lazy and flushes aggressively and synchronously, which throttles incoming writes to let the flusher catch up. This shows up as a sudden latency spike on writes (“furious flushing” / async write storm). The 75% alert exists to catch the approach before the cliff.
  3. Checkpoint age is the deeper signal. The dirty-page percentage correlates with checkpoint age (how far the redo log has advanced past the oldest unflushed change). If the redo log is undersized relative to the write rate, checkpoint pressure forces flushing regardless of the dirty percentage. Pair with redo-log sizing when this card alerts persistently.

Worked example

A platform team runs a write-heavy MySQL 8.0 primary backing an order-ingestion pipeline. innodb_buffer_pool_size is 32 GB (roughly 2,000,000 pages at the default 16 KB page size). Snapshot taken on 22 May 26 at 20:15 BST during a flash-sale write burst.
The gauge reads 78.0%, above the 75% alert line, and Nerve Centre raises the alert flag. What it means and what to do:
  1. The flusher is behind. At 78% the pool is closing on the 90% synchronous-flush cliff. If the write burst continues, InnoDB will start throttling writes within minutes and write latency will spike. Query Latency p95 (ms) on write statements will already be drifting.
  2. First lever: raise flush throughput. If the storage can take more IOPS, raise innodb_io_capacity (and innodb_io_capacity_max) so the background flusher drains dirty pages faster. On fast NVMe / provisioned-IOPS volumes the default of 200 is far too conservative; values of several thousand are appropriate. Confirm the disk is not already saturated before raising this, otherwise it makes things worse.
  3. Second lever: redo-log headroom. If checkpoint age is the driver, increasing innodb_redo_log_capacity (MySQL 8.0.30+) gives InnoDB more room to defer flushing and smooth the burst. This trades a longer crash-recovery time for steadier write latency.
  4. Do not lower innodb_max_dirty_pages_pct as a reflex. Lowering it makes InnoDB flush sooner, which reduces the dirty percentage but increases total write IO and can hurt throughput. It is a tuning trade-off, not a fix.
Three takeaways:
  1. Read the trend, not the snapshot. 78% holding steady through a burst and then draining is healthy batching; 78% and still climbing is the warning.
  2. The percentage is a proxy for flush-vs-workload balance. When it alerts, the question is always “can the disk flush faster, or is the redo log too small?”
  3. Pair with hit rate and latency. Dirty pages is the write side; InnoDB Buffer Pool Hit Rate % is the read side. Together they describe the whole buffer pool.

Sibling cards merchants should reference together

Reconciling against the source

Where to look in MySQL’s own tooling:
SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_pages_%'; for pages_dirty and pages_total. Divide and multiply by 100 to match the card. SHOW ENGINE INNODB STATUS\G , the BUFFER POOL AND MEMORY section, which prints “Database pages”, “Modified db pages”, and pending-flush counts directly. SELECT @@innodb_max_dirty_pages_pct, @@innodb_io_capacity, @@innodb_io_capacity_max; to see the thresholds and flush settings driving the behaviour. On Amazon RDS / Aurora, Performance Insights buffer-pool counters; on Google Cloud SQL, the InnoDB buffer-pool metrics in Cloud Monitoring.
Why our number may legitimately differ from a hand reading: Cross-connector reconciliation:

Known limitations / FAQs

Is a high dirty-page percentage always a problem? No. A write-heavy instance routinely runs at 20 to 60% dirty during peak and that is healthy batching. The concern is a level that is high and still climbing toward innodb_max_dirty_pages_pct (default 90%), because at that cliff InnoDB switches to synchronous flushing and throttles writes. The 75% alert is an early-warning line, not a hard fault. What actually happens at the 90% cliff? When dirty pages reach innodb_max_dirty_pages_pct, InnoDB stops deferring writes and flushes aggressively and synchronously to bring the level down, throttling incoming writes in the process. The visible effect is a sudden write-latency spike, sometimes called “furious flushing” or an async write storm. The goal of watching this card is to act before you hit that point. Should I lower innodb_max_dirty_pages_pct to keep the percentage down? Usually not as a first move. Lowering it forces earlier, more frequent flushing, which reduces the dirty level but increases total write IO and can cut throughput. The better levers are raising innodb_io_capacity (if the disk has headroom) and increasing innodb_redo_log_capacity (to give more room to defer). Adjust the dirty-pages cap only after those, and with care. The percentage spiked during a backup and recovered. Why? Some backup methods (and large bulk-load or ALTER TABLE operations) generate heavy write activity that fills the pool with dirty pages faster than the flusher drains them. Once the operation finishes, the flusher catches up and the level recovers. If backups routinely push you near the cliff, run them against a replica or schedule them off-peak. Does dirty-page percentage affect crash recovery time? Indirectly, yes. The unflushed (dirty) changes are protected by the redo log, and crash recovery replays redo from the last checkpoint. A larger redo log and more deferred flushing mean faster steady-state writes but a longer recovery after an unclean shutdown. This is the core trade-off behind innodb_redo_log_capacity sizing. Why is this a point-in-time gauge and not a windowed delta like the hit rate? Dirty and total page counts are current-state gauges, not monotonically increasing counters, so the meaningful value is the instantaneous ratio. The hit rate is built from cumulative counters and therefore needs delta windowing; dirty-pages does not.

Tracked live in Vortex IQ Nerve Centre

InnoDB Dirty Pages % is one of hundreds of KPI pulses Vortex IQ tracks across MySQL and 70+ other ecommerce connectors. Nerve Centre runs the detection layer; Vortex Mind investigates the cause when something moves; Ask Viq lets you interrogate any number in plain English. Start for free or book a demo to see this metric running on your own data.