案例 MySQL 8.4.13:丢弃表空间再导入旧镜像后,点查为什么读到旧数据

2026-11-05 21:07:05

MySQL 8.4.13:丢弃表空间再导入旧镜像后,点查为什么读到旧数据

适用版本:MySQL 8.4.13(2026-10-20)及之后。8.4.13 修复了两个与 Adaptive Hash Index(AHI)和表空间导入相关的缺陷,它们会影响「导出表 → 修改表 → DISCARD TABLESPACE → 导入旧镜像」这类操作后的读一致性与崩溃恢复。

现象一:点查返回被丢弃代的行或值

操作序列是:导出一张表,之后表被修改,其表空间被 DISCARD,再导入一份更早的导出镜像。此时点查(point lookup)可能返回被丢弃的那一代(generation)表空间中的行或值,而不是当前导入镜像里的内容。

原因是 AHI 中残留了指向旧表空间的条目。点查命中 AHI 时直接返回,绕过了 B-tree 上的实际页。8.4.13 起,陈旧的 AHI 条目被当作 miss 处理,查询回退到正常的 B-tree 遍历,返回值以实际页为准。

Bug #39661793

现象二:IMPORT TABLESPACE 失败后,eviction 阶段断言崩溃

ALTER TABLE ... IMPORT TABLESPACE 失败后,被丢弃表空间的残留页可能在后续页面淘汰(eviction)时触发断言:

[ERROR] [MY-013183] [InnoDB] Assertion failure: btr0sea.cc:1082:block->page.id.space() == index->space

失败导入的清理逻辑现在会保留移除陈旧 AHI 条目所需的 index space identifier,使清理阶段能定位并删除这些条目。

Bug #39661792

排查步骤

1. 确认版本与 AHI 开关

SELECT VERSION();
SHOW GLOBAL VARIABLES LIKE 'innodb_adaptive_hash_index';

MySQL 8.4.0 起 innodb_adaptive_hash_index 默认是 OFF(8.0 中默认 ON)。若实例上显式打开了它,先确认是否属于本次现象的影响范围;关闭后观察点查返回值是否恢复正常。

2. 用 EXPLAIN 确认访问路径

EXPLAIN SELECT ... WHERE pk = ?;

EXPLAIN 只能反映优化器选择的访问路径与索引使用情况,AHI 对优化器不可见,因此看不到 AHI 命中。它的作用是排除「查询本身走了错误的索引或覆盖索引」这一层原因,把问题定位到存储层。

3. 重建表或索引

重建会生成新的索引结构,使旧的 AHI 条目失效:

ALTER TABLE t FORCE;
-- 或
OPTIMIZE TABLE t;
-- 或对相关索引 DROP 后重新 ADD

重建后再执行原来的点查,对比返回值。

4. 导入前做一致性检查

  • .cfg 元数据文件必须与 .ibd 匹配,两者来自同一次 FLUSH TABLES ... FOR EXPORT 导出。
  • 导出完成后不要再修改该表;修改过的表不要与旧镜像混用。
  • IMPORT TABLESPACE 执行期间表处于锁定状态,不能并发写入。
  • 导入失败后不要直接复用同一份镜像重试,先确认残留状态已被清理,并升级到包含上述修复的版本。

同版本的其他 InnoDB 修复

  • InnoDB redo-log consumer UDF 传入 null 输入的问题(Bug #39632565)。
  • 可传输表空间导入时索引页校验的问题(Bug #39295605)。
  • InnoDB 全文检索 Boolean Mode 表达式的解析器嵌套问题(Bug #39234789)。
  • 并发 COPY ALTER 操作的问题(Bug #39134921)。
  • 重命名被自引用 InnoDB 外键使用的列的问题(Bug #39091341)。
  • 页重组产生尺寸不匹配时,InnoDB 可能继续使用重组后的页却不记录对应 redo;随后的插入加崩溃可导致恢复失败或页损坏。该不匹配现在按致命错误处理,不再让不一致的 redo 状态继续(Bug #116574、Bug #37258813)。

版本号接口变化

8.4.13 起 MySQL Server 支持四段式版本标识 MAJOR.MINOR.PATCH.UPDATE,可通过 VERSION_WITH_UPDATE()、只读全局变量 version_with_update 和 mysqld --version-with-update 获取。VERSION() 等既有接口保持三段式兼容语义。

复制全文 生成海报 MySQL InnoDB 数据库 故障排查 表空间

推荐文章

程序员茄子在线接单