Redo Log and Crash Recovery: How InnoDB Prevents Data Loss
AI generated
InnoDB
SQL
MySQL · InnoDB · Durability
Redo Log and Crash Recovery
how InnoDB prevents data loss

When a MySQL server crashes in the middle of a write, the redo log decides whether data is lost or whether the database automatically repairs itself on the next start. Understanding write-ahead logging, checkpoint mechanics and log sizing is therefore not an academic exercise but the foundation for resilient production databases. This article explains the full mechanism with real configuration examples.

19 min read innodb_log_file_size · checkpoint · LSN MySQL 8.0 · MariaDB 10.x

1. What the redo log does: write-ahead logging

The redo log is the core of InnoDB's crash safety and implements the principle of write-ahead logging. Before InnoDB actually writes a change into the affected data page in the buffer pool and later flushes that page to disk, the change is first persisted as a compact entry in the redo log. This entry does not describe the entire new state of the page, only the physical change itself, which makes writing to the redo log very fast, since it involves sequential, small writes instead of random access to scattered data pages.

The decisive advantage of this approach: as soon as a transaction commits, the actual data page does not need to be written to disk, only the corresponding redo log entry. InnoDB can write the data pages themselves later, batched and more efficiently, in the background. If the server crashes afterward, before the data page was actually persisted, InnoDB reconstructs the change from the redo log on the next start. This exact mechanism is what prevents committed transactions from being lost in a crash.

2. Structure: log buffer, log files and LSN

Before an entry is written to the redo log on disk, it first lands in the log buffer, a memory area controlled via innodb_log_buffer_size. The log buffer collects several changes and writes them to disk in batches, which reduces the number of expensive I/O operations. Every entry in the redo log receives a sequential log sequence number, or LSN, which serves as a unique timestamp for every physical change to the database and is used as a reference point during crash recovery.

Physically, the redo log consists of several files whose number and size are controlled via innodb_redo_log_capacity in current MySQL versions, or in older versions via the separate parameters innodb_log_file_size and innodb_log_files_in_group. These files are written to circularly: once the last file is full, InnoDB starts again at the beginning of the first file, provided the changes contained there have already been applied to the actual data pages via a checkpoint.


-- Inspect current redo log configuration
SHOW VARIABLES LIKE 'innodb_redo_log%';
SHOW VARIABLES LIKE 'innodb_log_buffer_size';

-- Current LSN position and checkpoint LSN
SHOW ENGINE INNODB STATUS\G
-- Look for the LOG section:
-- Log sequence number          123456789012
-- Log flushed up to            123456789012
-- Last checkpoint at           123456780000

3. Sizing innodb_log_file_size correctly

The size of the redo log directly affects two opposing factors: write performance and recovery time after a crash. A larger redo log lets InnoDB flush data pages less often, because more changes can accumulate in the log before a checkpoint is forced. This significantly improves write performance for write-heavy workloads, since fewer random I/O operations are needed to flush the data pages. The downside: a larger redo log potentially means more unsaved changes that have to be reapplied during crash recovery, which extends downtime after a crash.

For most production systems, a total redo log size between 1 and 4 GB is a solid starting point, and for very write-heavy systems with many large transactions, 8 GB or more can make sense too. An undersized configuration shows up as frequent warnings in the error log about too-short checkpoint intervals and as noticeable performance drops during write spikes, because InnoDB is forced to force flush operations instead of batching them.


# /etc/mysql/conf.d/innodb-redo-log.cnf
[mysqld]
# MySQL 8.0.30+: unified redo log capacity setting
innodb_redo_log_capacity = 4G

# Older MySQL versions: separate file size and count
# innodb_log_file_size = 1G
# innodb_log_files_in_group = 4

innodb_log_buffer_size = 64M
innodb_flush_log_at_trx_commit = 1

4. Checkpointing: fuzzy checkpoints and checkpoint age

A checkpoint marks the point up to which every change noted in the redo log has actually been applied to the persistent data pages. InnoDB uses fuzzy checkpointing instead of a full, blocking checkpoint: instead of flushing all changed pages at once, which would briefly freeze operations, InnoDB continuously flushes small batches of modified pages in the background and moves the checkpoint forward gradually.

The difference between the current LSN and the checkpoint LSN is called checkpoint age and is an important metric for the health of the system. As checkpoint age approaches the capacity limit of the redo log, InnoDB actively throttles new writes to give the checkpoint process time to catch up. For applications, this throttling shows up as a noticeable latency increase on write operations, and is often a symptom of an undersized redo log combined with a very write-heavy workload.


-- Monitor checkpoint age relative to redo log capacity
SHOW ENGINE INNODB STATUS\G
-- LOG section shows:
-- Log sequence number          145678900000
-- Log flushed up to            145678900000
-- Pages flushed up to          145670000000
-- Last checkpoint at           145660000000
-- Checkpoint age = Log sequence number - Last checkpoint at

-- History list length indicates unpurged undo, correlates with load
SELECT NAME, COUNT
FROM information_schema.INNODB_METRICS
WHERE NAME = 'trx_rseg_history_len';

5. innodb_flush_log_at_trx_commit in detail

The parameter innodb_flush_log_at_trx_commit controls how strictly InnoDB implements the durability guarantee of ACID and is one of the most important trade-offs between safety and performance in the entire redo log system. At value 1, the safe default, the redo log is written immediately on every commit and passed to disk with fsync. This guarantees that no committed transaction is lost in a crash, but costs a synchronous disk access on every single commit.

At value 2, the redo log is written on every commit, but only actually persisted with fsync once per second. A crash of the MySQL process itself is then uncritical, because the data sits in the operating system cache, but a crash of the entire server or a power outage can cost up to one second of committed transactions. At value 0, the redo log is only written once per second at all, which carries the highest risk but delivers the best performance. For production systems with real business data, value 1 is almost always the right choice; value 2 can be a sensible compromise for read replicas or non-critical reporting databases.


# /etc/mysql/conf.d/innodb-durability.cnf
[mysqld]
# 1 = safest, fsync on every commit (default, recommended for production)
# 2 = fsync once per second, tolerates mysqld crash but not OS/power loss
# 0 = fsync once per second, highest risk, highest throughput
innodb_flush_log_at_trx_commit = 1

# Benchmark comparison approach:
# SET GLOBAL innodb_flush_log_at_trx_commit = 2;
# Run sysbench write-heavy workload and compare commits/sec vs value 1

6. The crash recovery process step by step

When the MySQL server restarts after an uncontrolled crash, InnoDB first checks whether the last shutdown was clean. If not, the automatic crash recovery process begins. In the first step, InnoDB reads the redo log from the last checkpoint LSN onward and reapplies every change recorded in it to the data pages, regardless of whether the associated transaction was committed or not. This phase is called the redo phase and ensures that all physical changes already persisted in the log before the crash are restored.

In the second step, the undo phase, InnoDB identifies transactions that were not yet committed at the time of the crash and rolls them back using the undo logs. Only after both phases complete is the database back in a consistent state and ready to accept new connections. With a large redo log and high checkpoint age, this process can take several minutes, which is an important argument for not choosing the redo log arbitrarily large, but making a deliberate trade-off between write performance and recovery time.


# Observe crash recovery progress in the error log
tail -f /var/log/mysql/error.log
# Expected sequence during recovery:
# [Note] InnoDB: Starting crash recovery
# [Note] InnoDB: Restoring buffer pool pages from log
# [Note] InnoDB: Rolling back trx with id 12345, N rows to undo
# [Note] InnoDB: Rollback completed
# [Note] InnoDB: Crash recovery finished

7. Redo log vs. undo log vs. binlog

These three log types are frequently confused, but they serve fundamentally different purposes. The redo log is an InnoDB-internal structure that secures physical changes to data pages for crash recovery, is overwritten circularly, and is not directly visible to applications. The undo log stores the previous state of changed rows, is needed for rollbacks and for MVCC so other transactions get consistent reads of older row versions, and is purged once all relevant transactions have completed.

The binary log, or binlog, is a server-wide, logical record of every data-changing statement and primarily serves replication as well as point-in-time recovery from backups. Unlike the redo log, the binlog is not overwritten circularly but rotated and can be kept for extended periods for recovery purposes. A common mistake is assuming the redo log can replace the binlog or vice versa, when in fact both fulfill different, complementary purposes within the same durability strategy.

8. Monitoring and common problems

The most important monitoring signal for the redo log is the already mentioned checkpoint age relative to configured capacity. A second relevant signal is the number of redo log writes per second, visible via the status variable Innodb_os_log_written, which can indicate a changed workload or a problem with long-running transactions blocking checkpoint progress when it suddenly increases.

A classic real-world problem is a single, very long-running transaction, for example a forgotten manual BEGIN without COMMIT in an administrative session. As long as this transaction stays open, InnoDB cannot purge the associated undo information, which indirectly also limits the usable headroom in the redo log and grows the history list length. A regular look at information_schema.INNODB_TRX reliably reveals such forgotten transactions.


-- Find long-running transactions that block checkpoint progress
SELECT
    trx_id,
    trx_started,
    TIMESTAMPDIFF(SECOND, trx_started, NOW()) AS seconds_running,
    trx_query
FROM information_schema.INNODB_TRX
ORDER BY trx_started ASC
LIMIT 5;

9. Flush strategies compared

The choice of innodb_flush_log_at_trx_commit is a deliberate decision between data safety and throughput. The following table compares the three options.

Value Behavior Risk on crash Recommendation
1 fsync on every commit No data loss Production systems, default
2 Write on commit, fsync 1x/second Up to 1s on OS crash Read replicas, reporting
0 Write and fsync 1x/second Up to 1s on any crash Non-critical test systems only

For business-critical databases with order or payment data, value 1 is non-negotiable. Only for systems where a data loss of a few seconds is acceptable to the business, for example pure read replicas for reporting, does value 2 come into question as a trade-off for higher throughput.

Mironsoft

Database resilience and recovery planning

Is your redo log ready for the worst case?

We review redo log sizing, checkpoint behavior and durability settings, and simulate crash recovery scenarios so a crash doesn't turn into a downtime disaster.

Recovery test

Controlled crash recovery simulation and timing

Log sizing

innodb_redo_log_capacity tailored to your workload

Durability audit

Set flush_log_at_trx_commit according to data criticality

10. Summary

The redo log is the mechanism that puts InnoDB in a position to automatically restore a consistent state after a crash, without manual repair or data loss on committed transactions. Write-ahead logging ensures changes are persisted before the actual data page is written, and fuzzy checkpointing keeps operations running even under load, without blocking full flushes.

The correct sizing of innodb_redo_log_capacity or innodb_log_file_size is a deliberate trade-off between write performance and recovery time. Combined with the right choice of innodb_flush_log_at_trx_commit, the balance between data safety and throughput can be tuned deliberately to the actual criticality of the data, instead of leaving it to chance.

Redo log and crash recovery, the essentials at a glance

Write-ahead logging

Changes are persisted to the redo log first, before the data page itself is written.

Sizing

1 to 4 GB for most systems, larger for write-heavy workloads with many large transactions.

Durability

innodb_flush_log_at_trx_commit=1 for production, guarantees no loss of committed transactions.

Crash recovery

Runs automatically on startup: redo phase followed by undo phase, no manual intervention.

11. FAQ: Redo Log and Crash Recovery

1What is the redo log?
An InnoDB-internal structure that persists physical changes via write-ahead logging before the data page itself is written.
2How large should it be?
1 to 4 GB for most systems, larger for very write-heavy workloads with many large transactions.
3What is checkpoint age?
Difference between current LSN and checkpoint LSN. Near the capacity limit InnoDB throttles new writes.
4What does value 1 mean?
Redo log written immediately with fsync on every commit. Guarantees no loss of committed transactions.
5How long does recovery take?
From seconds to several minutes, depending on checkpoint age and redo log size at time of crash.
6Redo log vs. undo log?
Redo log secures crash recovery. Undo log stores previous row states for rollbacks and MVCC.
7Does binlog replace redo log?
No. Binlog serves replication and point-in-time recovery, redo log serves InnoDB-internal crash recovery. Both complement each other.
8What is fuzzy checkpointing?
Continuous flushing of small batches in the background instead of a blocking full flush of all changed pages.
9When does value 2 make sense?
For read replicas or non-critical reporting systems, where losing up to one second on OS crash is acceptable.
10Redo log too small?
More frequent forced checkpoints and throttled writes, visible as a latency increase during write spikes.