DC娱乐网

马上EOL了,但MySQL 8.0还有个大Bug没修!建议直接上8.4 LTS

前言 如果你的 MySQL 8.0 从库开了 super_read_only,并且 innodb_undo_log_t
前言 如果你的 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=112717Bug #112262:https://bugs.mysql.com/bug.php?id=112262Bug #119628:https://bugs.mysql.com/bug.php?id=119628https://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