问题现象
使用 XtraBackup 对 MySQL 进行热备份时,出现如下报错,备份任务中断:
[ERROR] [MY-011825] [Xtrabackup] unable to open /innodb_redo/ib_redo368 err 1504
[ERROR] [MY-011825] [Xtrabackup] read_logfile() failed
根本原因
XtraBackup 的工作机制
XtraBackup 热备的核心流程如下:
- 记录备份开始时的 LSN(Log Sequence Number)
- 拷贝 InnoDB 数据文件(此过程数据仍在变化)
- 后台持续监听并复制 redo log,确保能捕获备份期间所有数据变化
- 备份完成后,通过
--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_logfile0、ib_logfile1 | #ib_redo<N>(活跃)、#ib_redo<N>_tmp(备用) |
| 管理方式 | 固定 2 个文件,循环写入 | 多文件动态创建与回收 |
| 容量配置 | innodb_log_file_size × 2 | innodb_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 版本引入,默认关闭。
| |
工作原理
启用该参数后,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 XtraBackup | 8.0.30-23 |
| MySQL | 8.0.30+(低版本无此问题,无需该参数) |
XtraBackup 的大版本号必须与 MySQL 保持一致(均为 8.0.x),否则可能引发其他兼容性错误。
完整备份流程参考
| |
小结
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+ 环境下强烈建议开启。