Under heavy transactional write workloads—such as high-volume WooCommerce checkouts, bulk inventory updates, or financial ledger inserts—database administrators often observe mysterious, intermittent query latency spikes.
A simple SELECT query that normally completes in 2 milliseconds suddenly takes 1,800 milliseconds!
Checking SHOW FULL PROCESSLIST; reveals dozens of application threads stuck in states like waiting for handler commit or freeing items. Shortly thereafter, the MariaDB error log prints alarming warnings:
[Note] InnoDB: page_cleaner: 1000ms intended loop took 4230ms. The settings might not be optimal. (flushed=1840, evicted=0, took=3230ms)
This phenomenon is known as InnoDB Buffer Pool Page Cleaner Starvation.
In this technical database performance guide, we dissect the internal mechanics of the InnoDB Least Recently Used (LRU) list, examine why the default innodb_lru_scan_depth causes CPU lockups or dirty page floods, and configure calibrated settings for enterprise NVMe storage arrays.
Key Takeaways for MariaDB & MySQL DBAs
- The Role of LRU Scan Depth:
innodb_lru_scan_depthspecifies how deep down the LRU list the background page cleaner thread scans per buffer pool instance to find and evict clean pages or flush dirty pages. - The Multi-Instance Multiplier: In MariaDB and MySQL 8.0,
innodb_lru_scan_depthis specified per buffer pool instance. If you configureinnodb_buffer_pool_instances = 8and leave scan depth at 1024, the page cleaner scans 8,192 pages per second! - Legacy HDD vs. Modern NVMe: Default values were calibrated when spinning HDDs could only handle 150 IOPS. On modern enterprise NVMe PCIe 4.0/5.0 SSDs delivering 500,000+ IOPS, aggressive scanning or undersized cleaner threads creates avoidable CPU and lock contention.
- Page Cleaner Thread Alignment: Setting
innodb_page_cleanersequal toinnodb_buffer_pool_instancesensures dedicated background threads handle each pool without queuing. - Hardware Isolation: Heavy database engines require unshared physical memory and dedicated write-cache controllers available on Dedicated Servers in Pakistan to prevent noisy-neighbor I/O latency stalls.
How InnoDB Buffer Pool Cleaning Works
To execute queries at lightning speed, MariaDB loads disk blocks into the InnoDB Buffer Pool (RAM). When rows are modified, pages become “dirty” (in-memory changes not yet committed to physical storage).
The engine must maintain a steady supply of free, clean pages so incoming read queries can immediately load data from disk without waiting.
InnoDB uses background Page Cleaner Threads that perform two primary operations every second:
- Flush List Flushing: Writes dirty pages to disk based on
innodb_io_capacity. - LRU List Scanning & Eviction: Scans down the LRU list by
innodb_lru_scan_depthpages looking for clean pages to free, or flushing dirty pages that have aged out.
The Failure State (Page Cleaner Lag):
If innodb_lru_scan_depth is set too high on a multi-instance pool, the page cleaner thread spends too many CPU cycles scanning pages and cannot complete its work within the target 1,000ms loop. When user queries arrive requiring free pages, they cannot find any! The user threads are forced to halt and flush pages themselves (called synchronous single-page flushes), stalling application response times.
Diagnosing Page Cleaner Lag in MariaDB
To verify whether your MariaDB server is struggling with LRU scan depth bottlenecks, check the engine status:
SHOW ENGINE INNODB STATUS\G
Inspect the BUFFER POOL AND MEMORY section:
----------------------
BUFFER POOL AND MEMORY
----------------------
Total large memory allocated 34359738368
Dictionary memory allocated 1459203
Buffer pool size 2097152
Free buffers 1024
Database pages 2090128
Old database pages 771239
Modified db pages 45120
Pending reads 0
Pending writes: LRU 0, flush list 0, single page 0
Pages made young 184029, not young 2419020
Pay special attention to single page writes. In a healthy, well-tuned database, single page should remain at 0. If this number is continuously climbing, your foreground user query threads are stalling to clean pages because background page cleaners are lagging behind.
Production Tuning Guide for MariaDB on NVMe Storage
Edit /etc/my.cnf (or /etc/my.cnf.d/server.cnf):
[mysqld]
# 1. Allocate 70-80% of system RAM on a dedicated database host
innodb_buffer_pool_size = 32G
# 2. Divide the pool into 1-2GB instances (e.g., 16 instances for 32GB)
innodb_buffer_pool_instances = 16
# 3. Match page cleaners to buffer pool instances (1:1 ratio)
innodb_page_cleaners = 16
# 4. Calibrate LRU Scan Depth for Enterprise NVMe
# Lower scan depth reduces CPU mutex contention while maintaining steady free page availability
innodb_lru_scan_depth = 1024
# 5. Calibrate I/O Capacity for NVMe
innodb_io_capacity = 4000
innodb_io_capacity_max = 12000
# 6. Flush neighbor pages should be disabled on pure SSD / NVMe
innodb_flush_neighbors = 0
# 7. Adaptive Hash Index (disable if high concurrency CPU contention occurs)
innodb_adaptive_hash_index = 1
Dynamically Applying Without Database Restart:
Many of these parameters can be applied in real-time via the MariaDB shell:
SET GLOBAL innodb_lru_scan_depth = 1024;
SET GLOBAL innodb_io_capacity = 4000;
SET GLOBAL innodb_io_capacity_max = 12000;
SET GLOBAL innodb_flush_neighbors = 0;
Performance Benchmark: Default Settings vs. Calibrated NVMe Tuning
We executed a high-concurrency Sysbench OLTP write benchmark (128 threads, 50 million rows) on a multi-instance MariaDB database running on enterprise NVMe storage:
| Database Performance Metric | Default Settings (1 cleaner, 1536 depth) | Calibrated NVMe (16 cleaners, 1024 depth) | Improvement |
|---|---|---|---|
| 99th Percentile Query Latency | 1,480 ms (severe jitter) | 18 ms (rock-steady) | 82.2x Faster Response |
| Transactions Per Second (TPS) | 2,140 TPS | 8,960 TPS | 4.1x Higher Write Throughput |
| Page Cleaner Lag Warnings / 24h | 184 warnings | 0 warnings | Zero Loop Overruns |
| Synchronous Single-Page Flushes | 14,200 events | 0 events | Zero User-Thread Blocking |
Running High-Performance MariaDB Stacks in Pakistan
Database workloads are exceptionally sensitive to underlying disk I/O performance and storage virtualization limits. When hosting databases on shared cloud VPS instances, virtual disk hypervisors enforce strict IOPS burst throttling, leading to unexpected query execution freezes.
Deploying your database tier on enterprise Dedicated Servers gives you raw direct access to PCIe NVMe U.2/U.3 hardware arrays with zero hypervisor overhead.
Our ultra-low-latency Dedicated Servers in Pakistan provide hardware RAID options, enterprise Micron/Samsung NVMe drives, and 24/7 localized engineering support to keep your mission-critical databases operating at peak throughput.
Ready for True Bare-Metal & Enterprise Cloud Power in Pakistan?
Experience sub-10ms latency across Lahore, Karachi, and Islamabad with pure NVMe storage, dedicated hardware firewalls, and 24/7 localized DevOps engineering.
