当 MySQL InnoDB 引擎的 Redo Log 拯救了你的启动

发布: (2025年12月7日 GMT+8 11:07)
6 min read
原文: Dev.to

Source: Dev.to

灯塔守护者的类比

把 InnoDB 的 redo log 想象成灯塔守护者的日志。

在现代 GPS 之前,灯塔守护者会仔细记录日志:

  • “3:15 PM — 船只向北通过。”
  • “4:22 PM — 为雾天点亮灯塔。”
  • “5:03 PM — 风向转向西。”

如果出现任何问题,调查人员可以通过阅读日志来重建事发经过。

InnoDB 的工作方式相同。在进行任何更改之前,它会先写入 redo log:

“我即将更新表 users 中的第 47 行。以下是我要更改的内容。”

这项 预写日志(WAL) 是你在崩溃、断电以及宇宙射线翻转 RAM 位时的安全网。

**注意:**灯塔守护者可能会成为瓶颈。

几乎让我们崩溃的事务模式

我们的应用处理金融交易——速度极快。峰值时我们每秒处理约 5,000 次写入

一个典型的事务如下:

-- Running thousands of times per second
START TRANSACTION;

UPDATE accounts 
SET balance = balance - 100 
WHERE user_id = ?;

INSERT INTO transaction_log 
(user_id, amount, timestamp) 
VALUES (?, 100, NOW());

UPDATE user_metadata 
SET last_transaction = NOW() 
WHERE user_id = ?;

COMMIT;

看起来很 innocuous(无害),对吧?错。 这种模式在悄悄地扼杀我们的 redo log 系统。

Redo Log:技术深度剖析(不聊枯燥部分)

可视化 InnoDB 内部的运行情况:

┌─────────────────────────────────────────────────────┐
│  Transaction Flow                                    │
├─────────────────────────────────────────────────────┤
│  1. Client: "UPDATE accounts..."                     │
│          │                                          │
│          ▼                                          │
│  2. InnoDB: Write to REDO LOG (on disk)              │
│          [Sequential write - fast! ⚡]              │
│          │                                          │
│          ▼                                          │
│  3. InnoDB: Update buffer pool (in RAM)              │
│          [Random access - still fast! 💨]          │
│          │                                          │
│          ▼                                          │
│  4. Client: "COMMIT"                                 │
│          │                                          │
│          ▼                                          │
│  5. InnoDB: Flush redo to disk (fsync)               │
│          [This is where we wait... 🐌]             │
└─────────────────────────────────────────────────────┘

**关键洞察:**Redo 写入是顺序的(快),但 fsync 极其慢,尤其在高负载下。每秒 5,000 笔事务,每笔都需要磁盘刷新,这相当于让存储每秒执行 5,000 次同步操作——连 SSD 都受不了。

调查:改变一切的四个变量

1. innodb_flush_log_at_trx_commit

-- Safest, slowest
SET GLOBAL innodb_flush_log_at_trx_commit = 1;

-- OS cache, faster
SET GLOBAL innodb_flush_log_at_trx_commit = 2;

-- Unsafe, fastest
SET GLOBAL innodb_flush_log_at_trx_commit = 0;
设置持久性性能使用场景
1完全 ACID最慢金融数据
2操作系统缓存Web 应用
0有风险最快分析

我们改为 2,提升了 10 倍吞吐量

2. innodb_log_file_size

Redo log 是一个循环缓冲区:

[Checkpoint] ---> ███████ write position ---> (wrap)

如果写指针追上检查点 → 停滞

SHOW VARIABLES LIKE 'innodb_log_file_size';

我们把它从 48 MB 增大到 2 GB × 2 个文件 = 4 GB
经验法则: 大小足以容纳 ≈ 1 小时的峰值写入

3. innodb_flush_method

SET GLOBAL innodb_flush_method = 'O_DIRECT';

防止双重缓存,使我们的 I/O 等待降低了 30 %

4. 批量提交

之前:

5000 commits/sec → 5000 fsync calls

批量后:

100 commits/sec → 100 fsync calls

**结果:**磁盘操作减少了 50 倍。

只读事务的秘密武器

START TRANSACTION READ ONLY;

SELECT SUM(balance)
FROM accounts
WHERE region = 'US-WEST';

COMMIT;

随后 InnoDB:

  • 跳过 redo 日志记录
  • 跳过锁定
  • 跳过创建事务 ID

结果:对报表查询 ≈ 4 倍更快

监控 Redo Log

SELECT 
  'Redo Log Usage' AS metric,
  ROUND(
    (SELECT VARIABLE_VALUE 
     FROM performance_schema.global_status 
     WHERE VARIABLE_NAME = 'Innodb_os_log_written') / 1024 / 1024,
    2
  ) AS value
UNION ALL
SELECT 
  'Log Waits',
  (SELECT VARIABLE_VALUE 
   FROM performance_schema.global_status 
   WHERE VARIABLE_NAME = 'Innodb_log_waits')
UNION ALL
SELECT 
  'Checkpoint Age',
  ROUND(
    (SELECT VARIABLE_VALUE 
     FROM performance_schema.global_status 
     WHERE VARIABLE_NAME = 'Innodb_checkpoint_age') / 1024 / 1024,
    2
  );

如果 Innodb_log_waits > 0 → 说明你的 redo log 太小。

生产环境优化手册

  1. 优化前先进行剖析

    SET GLOBAL slow_query_log = 1;
    SET GLOBAL long_query_time = 0.1;
    SET GLOBAL log_slow_extra = 1;
  2. 为 Redo Log 设定合适大小
    使用每日指标,将日志文件大小设为 ≈ 2 倍峰值小时

  3. 通过基准测试验证持久性设置
    对比 innodb_flush_log_at_trx_commit 为 1、2、0 时的表现。

  4. 使用只读事务 进行报表和分析。

经验教训

  • Redo log 既是 你的安全网,也是 瓶颈
  • 每一种持久性保证都伴随性能代价。
  • 日志文件大小至关重要。
  • 只读事务被严重低估。
  • 批量写入是大规模场景下最有效的优化之一。

进一步阅读

  • MySQL InnoDB 文档:Redo Log
  • Percona:《调优 InnoDB Redo 日志》
  • 《High Performance MySQL》(O’Reilly)

Tags: #mysql #database #performance #devops

Back to Blog

相关文章

阅读更多 »