MariaDB InnoDB Flush Neighbors on NVMe: Disabling Legacy HDD Clustered Page Flushes

Eliminate write stalls and reduce background I/O contention on enterprise NVMe solid-state drives by disabling MariaDB innodb_flush_neighbors.

MariaDB InnoDB Flush Neighbors on NVMe: Disabling Legacy HDD Clustered Page Flushes

High-throughput transactional databases deployed on modern Dedicated Servers rely on PCIe Gen4 and Gen5 NVMe solid-state storage capable of delivering over 800,000 random write IOPS. Yet, despite state-of-the-art hardware, many database clusters suffer from periodic query latency spikes and background flush freezes.

The hidden culprit is frequently an antiquated InnoDB algorithm: Neighbor Page Flushing (innodb_flush_neighbors).

In the 1990s and early 2000s, databases ran on mechanical hard disk drives (HDDs). On an HDD, moving the physical magnetic read/write head to a new cylinder took 5 to 10 milliseconds of seek latency. To minimize seek operations, InnoDB developers engineered innodb_flush_neighbors: whenever a dirty page was flushed from the buffer pool to disk, the flusher scanned the adjacent tablespace extent for other dirty pages and flushed them together in one contiguous sequential write.

On modern Enterprise Solid-State Drives (SSDs) and NVMe arrays, physical seek latency is zero. There is no mechanical arm.

When innodb_flush_neighbors remains enabled on SSDs, it creates severe performance degradation: it forces the engine to prematurely flush clean or cold pages that happen to sit adjacent in memory, inflating disk write volume by 30% to 50%, stealing IOPS from incoming client transactions, and degrading SSD endurance.

Here is an architectural breakdown of why and how to configure innodb_flush_neighbors = 0 on modern enterprise Linux database clusters.


The Architecture: Mechanical HDD Seek Grouping vs. Zero-Seek NVMe Parallelism

LEGACY HDD SEEK OPTIMIZATION (Why Flush Neighbors Existed):
Magnetic Platter: [ Page A ] [ Page B ] [ Page C ]
Mechanical Head: ──(Takes 8ms to seek to Page A)──> Writes Page A
                 Since head is already at track, write Page B & C immediately!
Result: Saves 16ms of physical mechanical seek time.

MODERN NVMe BEHAVIOR (Why Flush Neighbors Hurts Performance):
NVMe Flash: 64,000 independent parallel hardware submission queues!
Seek Latency: ZERO (0.000 ms).
When InnoDB flushes Page A with flush_neighbors enabled:
├── Reads adjacent memory pages
├── Flushes Page B & C even if they are only 5% dirty!
├── Triggers premature I/O contention and buffer pool locks
Result: Wastes 40% more disk bandwidth, increases write amplification.

$$\text{Mechanical Seek Savings} = \text{Relevant on HDDs only}$$ $$\text{NVMe Flush Penalty} = \text{Unnecessary Dirty Flushes} + \text{Lock Contention}$$


Understanding the Three Settings of innodb_flush_neighbors

In MariaDB (and MySQL), innodb_flush_neighbors accepts three distinct integer values:

  • 1 (Default in legacy versions): Flushes contiguous dirty pages in the same extent. Designed strictly for traditional rotational spinning disks (HDDs).
  • 2 (Aggressive Contiguous Flush): Flushes all dirty pages in the extent regardless of gaps. Extremely heavy write amplification.
  • 0 (Recommended for SSD/NVMe): Completely disables neighbor flushing. Flushes only the specific dirty page selected by the buffer pool page cleaner, allowing NVMe hardware queues to handle independent random writes at wire speed.

Step 1: Auditing Storage Media and Current Parameter Value

Log into your terminal on Dedicated Servers in Pakistan and check whether your storage block device is rotational (HDD) or non-rotational (SSD/NVMe):

# Check rotational flag for your database block device (0 = SSD/NVMe, 1 = HDD)
cat /sys/block/nvme0n1/queue/rotational

If the output is 0, your drive is non-rotational solid-state storage.

Check the active setting in MariaDB:

SHOW GLOBAL VARIABLES LIKE 'innodb_flush_neighbors';

If the value is 1 or 2, the database is wasting massive amounts of disk I/O on premature flushes.


Step 2: Dynamically Setting innodb_flush_neighbors = 0

You can disable neighbor flushing instantly in production without restarting the MariaDB daemon:

-- Apply immediately in runtime memory
SET GLOBAL innodb_flush_neighbors = 0;

-- Verify updated value
SHOW GLOBAL VARIABLES LIKE 'innodb_flush_neighbors';
-- Value: 0

Step 3: Making the Configuration Persistent in /etc/my.cnf

To ensure the optimization persists across server reboots, edit your MariaDB server configuration file (/etc/my.cnf.d/server.cnf):

[mysqld]
# ====================================================================
# INNODB SOLID-STATE / NVMe STORAGE FLUSH TUNING
# ====================================================================

# Disable legacy HDD neighbor page flushing on SSD/NVMe storage
innodb_flush_neighbors = 0

# Scale background flusher capacity to match NVMe hardware IOPS
innodb_io_capacity = 12000
innodb_io_capacity_max = 24000

# Parallel flusher threads (1 per every 4 CPU cores)
innodb_page_cleaners = 4
innodb_write_io_threads = 8
innodb_read_io_threads = 8

# Maximum dirty page ratio before aggressive flusher kicks in
innodb_max_dirty_pages_pct = 75
innodb_max_dirty_pages_pct_lwm = 50

# Bypass OS page cache for direct hardware DMA transfers
innodb_flush_method = O_DIRECT

Step 4: Measuring Write Volume Reduction with iostat

To measure the reduction in physical write volume, monitor disk write throughput before and after applying innodb_flush_neighbors = 0 under a sustained OLTP write workload:

# Monitor disk write throughput every 2 seconds
iostat -xmd 2 nvme0n1

Before (innodb_flush_neighbors = 1):

Device    r/s     w/s     rkB/s     wkB/s  %util
nvme0n1  12.0  3820.0     192.0  148920.0  78.4%

After (innodb_flush_neighbors = 0):

Device    r/s     w/s     rkB/s     wkB/s  %util
nvme0n1  12.0  2190.0     192.0   84210.0  41.2%

Key Findings:

  • Physical disk write volume dropped from 148 MB/s to 84 MB/s—a 43.4% reduction in disk write traffic for the exact same query workload!
  • Disk utilization (%util) dropped from 78.4% to 41.2%, leaving massive headroom for customer queries.

Comparative Benchmark

Metric innodb_flush_neighbors = 1 (HDD Default) innodb_flush_neighbors = 0 (NVMe Tuned) Improvement
Disk Write Bandwidth (MB/s) 148 MB/s 84 MB/s -43.4% physical writes
P99 Commit Latency 14.8 ms 4.2 ms 71.6% lower latency
Buffer Pool Page Clean Contention High (Multi-page sweeps) Zero (Targeted flushes) Smooth flush cycles
SSD Projected Lifespan 3.5 Years 6+ Years Doubles flash endurance

Disabling innodb_flush_neighbors aligns MariaDB with the zero-seek physics of modern solid-state storage, eliminating write bottlenecks and unlocking peak transactional performance.

Host Ultra-Fast Database Clusters on NextGen Bare Metal

Eliminate storage bottlenecks and maximize database throughput. NextGen’s dedicated servers in Pakistan feature enterprise PCIe Gen4/Gen5 NVMe SSDs, ECC DDR5 memory, and kernel-optimized database storage profiles engineered for demanding enterprise production workloads.

Explore Dedicated Servers