MySQL 的 InnoDB 存储引擎依靠 redo log 保证已提交事务的持久性,依靠 undo log 支持回滚和多版本并发控制。安装阶段如果不调整这两个日志的默认配置,后续在高写入场景下容易出现频繁检查点、磁盘 I/O 飙升或回滚段争用等问题。与字符集、缓冲池等参数一样,redo log 和 undo log 的路径、大小、文件数量最好在初始化数据目录前规划清楚,这样能减少后期在线调整的复杂度。

一、先理解 redo log 与 undo log 的配置入口
redo log 是 InnoDB 的物理日志,记录的是数据页上的实际修改,采用循环写入方式。它的核心意义在于写入提交时不必每次同步刷数据页,只要 redo log 已经落盘,事务就可以认为提交成功,崩溃恢复时再根据 redo log 重做这些修改。undo log 则是逻辑日志,记录如何把某行数据恢复到之前的状态,用于事务回滚和 MVCC 读一致性快照。两者虽然都叫日志,但用途和配置方式并不相同。
在安装阶段,配置主要通过 MySQL 的配置文件完成。Linux 下通常是 /etc/my.cnf 或 /etc/mysql/mysql.conf.d/mysqld.cnf,Windows 下是 MySQL 安装目录中的 my.ini。所有相关参数都应放在 [mysqld] 段下面。如果是使用官方二进制包或压缩包手动部署,建议先写好配置文件,再执行 mysqld --initialize 初始化数据目录,这样 InnoDB 会按照配置创建 redo log 文件和 undo tablespace。
如果已经初始化完成才修改参数,redo log 大小的变更通常需要重启实例,而 undo tablespace 的数量调整则可能需要新建表空间并下线旧表空间,操作步骤会更繁琐。因此,安装阶段是配置这两个日志最合适的窗口期。
二、在安装阶段配置 redo log 的核心参数
redo log 的大小和文件数量直接影响写入性能与崩溃恢复时间。旧版本参数中,innodb_log_file_size 表示单个 redo 文件大小,innodb_log_files_in_group 表示文件组数量,两者相乘才是 redo log 总容量。默认总容量通常只有几十 MB 到一百多 MB,对于批量写入、大事务或高并发业务明显偏小。一般来说,可以按照业务在 15 到 30 分钟内产生的日志量来估算总大小,如果暂时无法估算,可以先配置 2GB 到 4GB 的总容量,再根据后续监控进行调整。
innodb_log_buffer_size 控制内存中的日志缓冲大小,默认 16MB,高并发写入时可以调大到 64MB 至 256MB,从而减少日志写盘次数。innodb_flush_log_at_trx_commit 控制提交时的刷盘策略,值为 1 时每次提交都写盘,持久性最好;值为 0 或 2 时性能更高,但可能丢失最近一部分事务日志。如果业务对数据可靠性要求高,建议保持为 1。
下面是一个 Linux 环境下的配置示例:
[mysqld] innodb_log_file_size=1G innodb_log_files_in_group=2 innodb_log_group_home_dir=/var/lib/mysql innodb_log_buffer_size=256M innodb_flush_log_at_trx_commit=1
MySQL 8.0.30 及以上版本推荐使用 innodb_redo_log_capacity 直接指定 redo log 总容量,不再需要手动用单文件大小乘以文件数量。例如配置为 2GB:
[mysqld] innodb_redo_log_capacity=2G innodb_log_group_home_dir=/var/lib/mysql innodb_log_buffer_size=256M innodb_flush_log_at_trx_commit=1
使用 innodb_redo_log_capacity 时,不要同时配置旧的 innodb_log_file_size 和 innodb_log_files_in_group,以免参数冲突。Windows 环境下路径写法类似,例如 innodb_log_group_home_dir=C:MySQLdata,注意反斜杠要原样保留,不要写成转义字符串。如果路径中包含空格,建议使用不含空格的目录,避免配置文件解析问题。
三、在安装阶段配置 undo log 的表空间与自动截断
MySQL 8.0 将 undo log 存储在独立的 undo tablespace 中,通过 innodb_undo_directory 指定存放目录,默认在数据目录下。innodb_undo_tablespaces 用于设置初始 undo tablespace 数量,默认是 2 个,允许的范围是 2 到 127。高并发事务量较大时,合理增加 undo tablespace 数量可以分散回滚段的竞争,减少锁等待。不过数量也不是越多越好,大多数业务设置 4 到 8 个已经足够。
undo log 的空间回收依赖自动截断机制。innodb_undo_log_truncate 默认开启,当某个 undo tablespace 超过 innodb_max_undo_log_size 设定的大小时,InnoDB 会将其标记为截断,并在合适的时机回收空闲空间。默认阈值是 1GB,对于批量更新或长事务较多的场景,可以适当调大到 2GB 或 4GB,同时增加 purge 线程数量,加快清理不再需要的历史版本数据。
[mysqld] innodb_undo_directory=/var/lib/mysql innodb_undo_tablespaces=4 innodb_max_undo_log_size=2G innodb_undo_log_truncate=ON innodb_purge_threads=4
Windows 下可以使用类似配置:
[mysqld] innodb_undo_directory=C:MySQLundo innodb_undo_tablespaces=4 innodb_max_undo_log_size=2G innodb_undo_log_truncate=ON innodb_purge_threads=4
需要注意的是,innodb_undo_directory 指定的目录必须存在,并且 MySQL 服务账户需要对该目录有读写权限。安装初始化前可以先手动创建目录。若数据目录已经初始化,再修改 undo tablespace 数量通常不会直接改变现有表空间,而需要新建表空间并逐步切换,因此安装阶段直接写入配置是最省事的做法。
四、配置后的验证与监控
MySQL 启动完成后,可以通过 SHOW VARIABLES 命令确认配置是否已经生效。执行下面的 SQL 可以查看 redo log 和 undo log 相关的运行参数:
SHOW VARIABLES LIKE 'innodb_log%'; SHOW VARIABLES LIKE 'innodb_redo_log_capacity'; SHOW VARIABLES LIKE 'innodb_undo%';
如果使用了 MySQL 8.0.30 以上版本的 redo 容量参数,SHOW VARIABLES LIKE 'innodb_log%' 仍然可以看到部分旧参数信息,但重点应关注 innodb_redo_log_capacity 的实际值。对于 undo log,除了查看变量,还可以查询 information_schema 中的表空间信息:
SELECT NAME, SPACE, FILE_NAME, ROW_FORMAT FROM information_schema.INNODB_TABLESPACES WHERE NAME LIKE 'undo%';
这条 SQL 可以确认 undo tablespace 的数量和文件位置。如果 FILE_NAME 位于配置的 innodb_undo_directory 目录下,并且表空间数量与 innodb_undo_tablespaces 设置一致,说明 undo 配置已经正确生效。
日常监控中可以执行 SHOW ENGINE INNODB STATUSG,查看 LOG 部分中的 Log sequence number、Log flushed up to 和 Pages flushed up to。如果 Log sequence number 与 Log flushed up to 的差值长期较大,说明日志刷盘跟不上写入速度,需要增大日志缓冲或优化磁盘。对于 undo log,可以关注 history list length,该值长期很大说明 purge 速度不足,需要增加 purge 线程或优化事务设计,避免大量旧版本数据堆积。
配置完成后最好做一次实际写入测试,连续插入十万行数据,观察插入耗时、磁盘利用率和错误日志中的 checkpoint 提示。如果 redo log 总容量过小,会出现频繁 checkpoint,写入性能会明显下降;如果 undo tablespace 数量过少,高并发事务下可能看到回滚段相关的锁等待。根据测试结果再微调参数,才能让 redo log 和 undo log 真正匹配业务负载。