问题现象

使用 XtraBackup 对 MySQL 进行热备份时,出现如下报错,备份任务中断:

[ERROR] [MY-011825] [Xtrabackup] unable to open /innodb_redo/ib_redo368 err 1504
[ERROR] [MY-011825] [Xtrabackup] read_logfile() failed

根本原因

XtraBackup 的工作机制

XtraBackup 热备的核心流程如下:

  1. 记录备份开始时的 LSN(Log Sequence Number)
  2. 拷贝 InnoDB 数据文件(此过程数据仍在变化)
  3. 后台持续监听并复制 redo log,确保能捕获备份期间所有数据变化
  4. 备份完成后,通过 --prepare 阶段对拷贝的数据做 crash recovery,使其达到一致性状态

第 3 步是问题的关键:XtraBackup 需要不间断地读取 redo log 文件。

MySQL 8.0.30 的 redo log 变更

MySQL 8.0.30 对 InnoDB redo log 做了重大架构调整:

对比项8.0.30 之前8.0.30 及之后
存储位置datadir 根目录#innodb_redo/ 子目录
文件名ib_logfile0ib_logfile1#ib_redo<N>(活跃)、#ib_redo<N>_tmp(备用)
管理方式固定 2 个文件,循环写入多文件动态创建与回收
容量配置innodb_log_file_size × 2innodb_redo_log_capacity

新机制下,MySQL 会动态回收已经不再需要的 redo log 文件。在没有任何保护的情况下,XtraBackup 后台线程正在读取某个 #ib_redo<N> 文件时,MySQL 可能已将其回收,导致 XtraBackup 打开文件失败,从而报出 unable to open ... read_logfile() failed


解决方案:--register-redo-log-consumer

参数说明

该参数在 Percona XtraBackup 8.0.30-23 版本引入,默认关闭。

1
2
3
4
5
6
xtrabackup \
  --user=root \
  --password=your_password \
  --backup \
  --register-redo-log-consumer \
  --target-dir=/backup/full

工作原理

启用该参数后,XtraBackup 在备份开始时向 MySQL Server 注册自己为 redo log consumer

注册生效后,MySQL 的 redo log 回收策略发生变化:

  • MySQL 不会回收 XtraBackup(consumer)尚未读取的 redo log 文件
  • XtraBackup 读取 redo log 后,手动向 MySQL 推进 LSN,通知 MySQL 哪些日志已安全消费
  • MySQL 根据 consumer 上报的消费进度,决定何时可以回收对应的 redo log 文件

这样就从根本上消除了 XtraBackup 读取 redo log 与 MySQL 回收 redo log 之间的竞争条件。

注意事项

写入阻塞: XtraBackup 向 MySQL 推进 LSN 时,MySQL Server 会短暂阻塞写入操作。在业务高峰期使用时需关注此影响。

潜在死锁风险: MySQL 官方 Bug #112608 记录了一个极端场景:当 redo log 容量接近上限,且同时发生如 CREATE USER 等 DDL 操作时,可能出现循环等待导致备份挂起。建议备份前确认 redo log 有充足剩余空间。


版本要求

组件最低版本要求
Percona XtraBackup8.0.30-23
MySQL8.0.30+(低版本无此问题,无需该参数)

XtraBackup 的大版本号必须与 MySQL 保持一致(均为 8.0.x),否则可能引发其他兼容性错误。


完整备份流程参考

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# 1. 全量备份
xtrabackup \
  --user=root \
  --password=your_password \
  --backup \
  --register-redo-log-consumer \
  --target-dir=/backup/full

# 2. prepare(恢复前必做,使数据达到一致性状态)
xtrabackup --prepare --target-dir=/backup/full

# 3. 恢复(停止 MySQL 后执行)
xtrabackup --copy-back --target-dir=/backup/full
chown -R mysql:mysql /var/lib/mysql

小结

read_logfile() failed 报错的根本原因是 MySQL 8.0.30 引入的 redo log 动态回收机制与 XtraBackup 后台读取线程之间的竞争。加上 --register-redo-log-consumer 参数,XtraBackup 以 consumer 身份向 MySQL 注册,使 MySQL 在 XtraBackup 完成消费前保留 redo log 文件,从而彻底解决此问题。该参数自 XtraBackup 8.0.30-23 起可用,在 MySQL 8.0.30+ 环境下强烈建议开启。