When running high-transaction MySQL (InnoDB) workloads on Linux, you may eventually encounter performance degradation characterized by sudden spikes in CPU iowait, increased query latency, and unexplained connection pile-ups. While the usual suspects like insufficient RAM, unoptimized queries, or missing indexes are often to blame, a more insidious issue lurks at the filesystem layer: Ext4 journal flushing latency.
In this guide, we will dive deep into diagnosing high Disk I/O wait caused by the jbd2 (Journaling Block Device) process and explore advanced mitigation strategies for high-traffic environments.
The Symptoms: I/O Wait Spikes and jbd2 Overhead
The issue typically manifests during periods of heavy UPDATE or INSERT activity, especially when InnoDB is aggressively flushing its redo logs (innodb_flush_log_at_trx_commit = 1).
1. High %iowait in top or sar
Monitoring tools will show the CPU spending an excessive amount of time waiting for disk I/O:
$ sar -u 1 5
Linux 5.15.0-101-generic (db-node-01) 09/16/2026 _x86_64_ (16 CPU)
16:05:01 CPU %user %nice %system %iowait %steal %idle
16:05:02 all 4.50 0.00 2.10 45.20 0.00 48.20
16:05:03 all 5.10 0.00 2.50 52.80 0.00 39.60
2. The jbd2 Process Dominating Disk Operations
Using iotop, you might notice a kernel thread named jbd2/sda2-8 consuming a disproportionate amount of disk bandwidth and IOPS:
$ iotop -o -P
Total DISK READ: 0.00 B/s | Total DISK WRITE: 85.45 M/s
Current DISK READ: 0.00 B/s | Current DISK WRITE: 70.12 M/s
PID PRIO USER DISK READ DISK WRITE SWAPIN IO> COMMAND
381 be/3 root 0.00 B/s 45.20 M/s 0.00 % 85.20 % [jbd2/nvme0n1p2-8]
1405 be/4 mysql 0.00 B/s 40.25 M/s 0.00 % 12.10 % mysqld
The jbd2 thread is responsible for writing filesystem metadata to the Ext4 journal. When a high volume of small writes hits the filesystem, the journal can become a severe bottleneck, stalling application writes.
Deep-Dive Diagnostics
To confirm that the journal is the bottleneck, we can use perf and eBPF tools (like ext4slower from BCC) to inspect filesystem latencies.
Using ext4slower
The ext4slower script traces ext4 reads, writes, opens, and syncs slower than a specified threshold:
$ /usr/share/bcc/tools/ext4slower 10
Tracing ext4 operations slower than 10 ms
TIME COMM PID T BYTES OFF_KB LAT(ms) FILENAME
16:10:02 mysqld 1405 W 16384 125432 45.21 ib_logfile0
16:10:02 jbd2/nvme0n1p2 381 S 0 0 85.45 [ext4]
16:10:03 mysqld 1405 W 16384 125448 52.10 ib_logfile0
Here we see mysqld taking up to 52ms to write 16KB blocks to the InnoDB redo log, correlating directly with an 85ms synchronous operation (S) by jbd2.
Analyzing Block Device Latency
Check the underlying device queues with iostat -x 1:
Device r/s w/s rkB/s wkB/s rrqm/s wrqm/s %rrqm %wrqm r_await w_await aqu-sz rareq-sz wareq-sz svctm %util
nvme0n1 10.00 4500.00 120.00 85000.00 0.00 200.00 0.00 4.26 2.50 45.80 12.50 12.00 18.89 0.20 98.50
Notice the w_await (write await time) is extremely high at 45.80ms, and the %util is nearly saturated at 98.50%. If this is happening on a shared SAN or standard SSDs, the physical disks simply cannot keep up with the IOPS demand.
Mitigation and Resolution
1. Tuning Ext4 Mount Options
By default, Ext4 uses data=ordered, which forces all data to be written to the main filesystem before its metadata is committed to the journal. For a database system like MySQL (which maintains its own crash consistency via the InnoDB redo log and doublewrite buffer), this is redundant and causes double-writing.
You can modify the mount options in /etc/fstab to use data=writeback. This allows metadata to be written to the journal asynchronously with respect to data blocks.
# /etc/fstab
UUID=xxxx-xxxx /var/lib/mysql ext4 defaults,noatime,data=writeback,barrier=0 0 0
Note: barrier=0 disables write barriers. Only do this if your storage controller has a battery-backed cache (BBWC) or if you are using enterprise NVMe drives with power-loss protection (PLP).
2. Disabling the Ext4 Journal Completely
If you want to completely eliminate jbd2 overhead on a dedicated partition holding only MySQL data, you can disable the journal. Ext4 then acts more like Ext2 but retains the faster Ext4 allocation features (extents).
# Unmount the partition
umount /var/lib/mysql
# Remove the journal
tune2fs -O ^has_journal /dev/nvme0n1p2
# Run fsck to ensure consistency
e2fsck -f /dev/nvme0n1p2
# Remount
mount /var/lib/mysql
3. Hardware Upgrades: Migrating to Bare-Metal NVMe
Filesystem tuning can only go so far. If you are running on virtualized VPS environments with shared storage (Ceph/SAN), the network hop and noisy-neighbor IOPS contention will forever bound your database throughput.
To bypass shared I/O limitations and heavy disk bottlenecks completely, the permanent solution is migrating databases to bare-metal servers. By upgrading to Dedicated Servers equipped with local Enterprise NVMe drives in RAID 10, you can achieve sub-millisecond latencies and millions of IOPS. For businesses targeting the South Asian market, deploying on Dedicated Servers in Pakistan ensures not only unrestricted local NVMe performance but also ultra-low network latency for regional applications.
4. MySQL-Specific Adjustments
Reduce the frequency of filesystem syncs by tuning InnoDB:
innodb_flush_log_at_trx_commit = 2: Writes to the OS cache at each commit, but flushes to disk only once per second. This drastically reduces fsync() calls and I/O wait, at the risk of losing up to 1 second of transactions during a kernel panic or power loss.innodb_io_capacityandinnodb_io_capacity_max: Set these to match your SSD’s actual capabilities to prevent InnoDB from overwhelming the I/O queue.
Conclusion
High disk I/O wait and jbd2 latency are common scaling walls for MySQL on Ext4. By diagnosing with ext4slower and iostat, adjusting filesystem mount options, and ensuring your underlying hardware is capable (such as transitioning to dedicated NVMe bare-metal servers), you can restore optimal database performance and eliminate devastating I/O stalls.
