马上EOL了,但MySQL 8.0还有个大Bug没修!建议直接上8.4 LTS(我马上就到了用英语怎么说) 99xcs.com

前言

如果你的 MySQL 8.0 从库开了 super_read_only,并且 innodb_undo_log_truncate 还是默认的 ON,请立刻检查 Undo 截断状态。

1 月 5 日,MySQL 领域资深大佬 Jean-François Gagné 发了一篇博客,开篇几乎是直接开炮:

“MySQL 8.0 中一个有数据损坏风险的 Undo Log 截断 Bug,竟然只修 8.4 不修 8.0?”

字里行间透着不满和担忧。

我顺着他的线索翻了一遍 Bug 列表,发现事情确实有点严重。

一、问题出在哪?

场景

MySQL 8.0 从库常见配置:

super_read_only=ON + innodb_undo_log_truncate=ON

(前者是从库规范配置,后者是默认值)

触发条件

当自动 undo truncate 被触发时,在 super_read_only 模式下,截断过程可能开始但无法正确结束。

本质原因(一句话讲明白)

这不是“业务写入”导致的,而是系统线程的元数据收尾被只读挡住了。从库开了 super_read_only 后,InnoDB 做自动 undo truncate 时需要更新数据字典(DD)/undo 表空间元数据来完成“收尾”(包括清理 undo_*_trunc.log 这类标记文件)。

但这些 DD 写入在 super_read_only 模式下也会被拦住,于是就出现“截断开始了,但结束不了”,留下 trunc.log,并引发后续一连串连环问题。

(也正因此,根本修复思路其实很直白:对 undo truncate 这类系统线程的 DD 更新路径放行,不要让它被 super_read_only 卡住。)

二、一连串的 Bug 链

这是同一个问题,但引发了一串连环坑:

Bug #112717(2023 年报告)

truncate 过程卡住,残留 undo_*_trunc.log 文件;INFORMATION_SCHEMA 中 FILE_SIZE 可能显示为 0。

汇报点:重启时可能触发 undo 表空间重建,元数据错乱,影响 Clone 备份。

Bug #112262(同年另一个报告)

同场景下,undo truncate 更新数据字典(DD)失败,报错“缺少 tablespace/innodb_undo_002”等,同样残留 trunc.log。

汇报点:元数据不一致,导致 Percona XtraBackup 等工具备份失败。

Bug #119628(Jean-François 今年报告)

这才是最吓人的一环:

truncate 失败残留日志 → 下次启动触发 undo 重建;

如果此时实例曾经崩溃,且有未提交事务,重启后这些事务可能未被回滚,未提交的数据可能被保留下来。

汇报点:数据损坏,而且可能是静默的——没有明显报错,但数据可能已经错了。

三、官方的态度?

这个问题影响数据安全,按理说应该非常敏感。

但截至今天发布的 8.0.45,这条链路相关 Bug 在官方 Bug 系统里仍未显示已解决(尤其是 #119628 仍是 Open / Critical)

另外,按官方计划,MySQL 8.0 将在 2026 年 4 月 进入 EOL(最后一个 8.0 小版本号为 8.0.46,以官方最终发布为准)。

从 #112262 的官方备注看,修复进入 8.4.0/9.0.0;但是否会 backport 到 8.0,目前看不到明确迹象。

值得一提的是,Percona Server 在 8.0.39 的 release notes 里明确修了同类问题(PS-9322)。

Jean-François 在博客里也直接质问:“这么重要的数据损坏 Bug,你们就只在 8.4 修,不管 8.0 用户了?”

我们该怎么办?

1、立即检查

如果你的 8.0 从库配置了 super_read_only:

  • 检查数据目录是否残留 undo_*_trunc.log 文件
  • 同时监控 INFORMATION_SCHEMA.INNODB_TABLESPACES 中 undo 表空间状态(例如 FILE_SIZE、状态字段是否异常)

2、短期规避

建议在从库上设置 innodb_undo_log_truncate=OFF,先避免自动截断继续触发风险。

注意:这可能导致 undo 表空间逐步变大,需要配合容量监控/巡检;后续需要在维护窗口“手工收缩/处理”,常见思路两种(二选一):

  • 方案 A(维护窗口临时放开只读让它自动截断一次):

临时将 super_read_only=OFF,并将 innodb_undo_log_truncate=ON(必要时配合阈值参数),让 undo truncate 在“可写 DD”的条件下正常跑完并收尾。

  • 方案 B(手动引导某个 undo 表空间进入可截断状态):

对目标 undo 表空间执行 ALTER UNDO TABLESPACE innodb_undo_002 SET INACTIVE,让它退出分配;待该表空间变空后由系统完成截断/收缩(适合有明确目标表空间时使用)。

3、处理中间态(很关键)

巡检发现残留 undo_*_trunc.log 时,可以安排一次计划内维护:

设置 innodb_fast_shutdown=0,做一次“慢关机”后再启动

前提是:你已经触发了 trunc.log 遗留,但还没有重启过

如果已经在 trunc.log 遗留的情况下重启过(日志出现过 “Reconstructing undo tablespace …” 这类重建行为),就别把它当“小毛病”:

至少要做一致性校验/抽样对账

在高风险场景(曾 crash + 有未提交事务)更稳妥的做法是:重建从库(重搭副本)

4、根本解决

升级到 MySQL 8.4。

这不是软广,而是严肃建议:8.4 作为 LTS,更符合“生产保平安”的定位;并且这条链路的修复点已经进入 8.4 分支。既然 8.0 即将 EOL,早升级早安心。

总结

这是一个典型的“元数据操作在 read-only 模式下踩坑”的问题,但因为涉及 undo 这种核心恢复机制,最终可能上升到静默数据损坏的风险。

你可以把高风险触发条件理解为:

存在 trunc.log + 异常重启/崩溃 + 有未提交事务(风险显著上升)

在 8.0 生命周期进入倒计时、且 8.0 分支是否回补修复不明朗的背景下,升级到 8.4 不仅是追新,更是数据安全的要求。

>>>>

参考资料

  • Bug #112717:https://bugs.mysql.com/bug.php?id=112717
  • Bug #112262:https://bugs.mysql.com/bug.php?id=112262
  • Bug #119628:https://bugs.mysql.com/bug.php?id=119628
  • https://jfg-mysql.blogspot.com/2026/01/undo-log-truncation-bug-in-80-leads-to-data-corruption.html.html

作者丨芬达

来源丨公众号:芬达的学习笔记(ID:database_learning)

dbaplus社群欢迎广大技术人员投稿,投稿邮箱:editor@dbaplus.cn