Your MySQL server absorbed 50,000 writes per second during the flash sale — then spent 45 minutes catching up on checkpointing afterward. InnoDB's redo log is the gatekeeper for write throughput, and most deployments leave it dramatically under-configured. Here's the complete tuning guide.
- MySQL 8.0.30+ uses a dynamic redo log with automatic sizing — the old
innodb_log_file_sizeis deprecated - Set
innodb_redo_log_capacityto 4–8x your peak writes-per-second throughput (in bytes) - Monitor
Innodb_redo_log_current_lsnvsInnodb_checkpoint_ageto catch redo log pressure - Undersized redo log forces frequent checkpoints, causing 30–50% write throughput reduction
How InnoDB's Redo Log Works
InnoDB writes all changes first to the redo log (write-ahead log) before modifying data pages in the buffer pool. This allows InnoDB to handle crash recovery and defer expensive random I/O to background checkpointing. The redo log is circular: when it fills up, InnoDB must flush dirty pages from the buffer pool to disk (a checkpoint) to make space.
MySQL 8.0.30+: Dynamic Redo Log
-- Check current redo log configuration
SHOW VARIABLES LIKE 'innodb_redo%';
-- innodb_redo_log_capacity: total redo log size (MySQL 8.0.30+)
-- Default: 104857600 (100MB) -- FAR TOO SMALL for production
-- Set via my.cnf:
-- innodb_redo_log_capacity = 4294967296 # 4GB
-- Check redo log pressure
SHOW STATUS LIKE 'Innodb_redo_log%';
SHOW STATUS LIKE 'Innodb_checkpoint%';Sizing the Redo Log
Measuring Current Redo Log Throughput
-- Measure redo log write rate over 60 seconds
SELECT variable_value INTO @lsn_start
FROM performance_schema.global_status
WHERE variable_name = 'Innodb_redo_log_current_lsn';
SELECT SLEEP(60);
SELECT variable_value INTO @lsn_end
FROM performance_schema.global_status
WHERE variable_name = 'Innodb_redo_log_current_lsn';
SELECT (@lsn_end - @lsn_start) / 60 AS redo_bytes_per_second,
(@lsn_end - @lsn_start) / 60 * 3600 AS redo_bytes_per_hour,
FORMAT((@lsn_end - @lsn_start) / 60 / 1024 / 1024, 2) AS redo_mb_per_second;
-- Rule of thumb: redo log capacity = 60-90 minutes of peak write throughput
-- If peak is 50 MB/s: capacity = 50 * 60 * 60 = 180GB (use 8-16GB in practice)Recommended Redo Log Sizing by Workload
| Write Throughput (peak) | Recommended innodb_redo_log_capacity |
|---|---|
| Under 10 MB/s | 1–2 GB |
| 10–50 MB/s | 4–8 GB |
| 50–200 MB/s | 8–32 GB |
| 200 MB/s+ | 32–64 GB |
Configuration for Production
# /etc/mysql/mysql.conf.d/innodb.cnf
[mysqld]
# Redo log (MySQL 8.0.30+)
innodb_redo_log_capacity = 8589934592 # 8GB
# Buffer pool (typically 70-80% of RAM)
innodb_buffer_pool_size = 48G
innodb_buffer_pool_instances = 8 # 1 per GB of buffer pool
# Checkpoint tuning
innodb_max_dirty_pages_pct = 75 # default 90; flush earlier
innodb_max_dirty_pages_pct_lwm = 65 # start flushing at 65%
innodb_io_capacity = 2000 # IOPS available for background I/O
innodb_io_capacity_max = 4000 # max IOPS during flush urgency
# Flush method (best for NVMe SSD)
innodb_flush_method = O_DIRECTMonitoring Redo Log Health
-- Checkpoint age as % of redo log capacity
-- Should stay below 75% during normal operations
SELECT
variable_value AS checkpoint_age_bytes,
ROUND(variable_value / @@innodb_redo_log_capacity * 100, 1) AS checkpoint_pct
FROM performance_schema.global_status
WHERE variable_name = 'Innodb_checkpoint_age';
-- If checkpoint_pct is consistently above 80%, increase redo log capacity
-- Track buffer pool hit rate
SELECT
innodb_buffer_pool_read_requests,
innodb_buffer_pool_reads,
ROUND((1 - innodb_buffer_pool_reads / NULLIF(innodb_buffer_pool_read_requests, 0)) * 100, 2)
AS hit_rate_pct
FROM (
SELECT
SUM(IF(variable_name = 'Innodb_buffer_pool_read_requests', variable_value, 0)) AS innodb_buffer_pool_read_requests,
SUM(IF(variable_name = 'Innodb_buffer_pool_reads', variable_value, 0)) AS innodb_buffer_pool_reads
FROM performance_schema.global_status
WHERE variable_name IN ('Innodb_buffer_pool_read_requests', 'Innodb_buffer_pool_reads')
) x;Changing innodb_redo_log_capacity on a running MySQL 8.0.30+ server takes effect immediately without restart. On older MySQL versions, changing innodb_log_file_size requires a clean server shutdown and can take significant time for large redo logs during recovery.
- The InnoDB redo log default (100MB) is dangerously undersized for production — size it to 60–90 minutes of peak write throughput.
- MySQL 8.0.30+ allows live redo log resizing via
innodb_redo_log_capacitywithout a server restart. - Monitor checkpoint age as a percentage of redo log capacity — sustained above 75% means your redo log is too small.
- Pair redo log tuning with
innodb_io_capacityandinnodb_max_dirty_pages_pctto control flush behavior under load.
Working with JusDB on MySQL Performance
JusDB tunes InnoDB configuration for MySQL deployments under heavy write loads — redo log sizing, buffer pool configuration, flush parameters, and storage I/O optimization. Our DBAs identify redo log pressure before it causes write stalls during peak traffic.
Explore JusDB MySQL Management → | Talk to a DBA
Related reading: