MySQL报错MY-012799,ER_IB_MSG_974问题诊断和远程修复方案分享
- 问答
- 2026-01-06 09:27:47
- 10
最近在处理一个客户的线上数据库问题时,遇到了一个比较棘手的错误:MySQL的错误日志中反复出现“MY-012799”和“ER_IB_MSG_974”的报错信息,这个错误直接导致了数据库实例无法正常启动,业务完全中断,经过一番排查和修复,最终解决了问题,现在把整个诊断思路和远程修复的过程分享出来,希望能给遇到类似情况的朋友一些参考。
我们来看一下错误日志里具体说了什么。(来源:客户提供的MySQL错误日志文件)
当时日志中核心的报错信息是这样的:
[ERROR] [MY-012799] [InnoDB] A tablespacesbtestsbtest1with page size 16384 is being written to a data file which has a different page size of 32768.
紧接着是:
[ERROR] [MY-012799] [InnoDB] Page size mismatch for tablespacesbtestsbtest1(16384 vs 32768).
以及一个更明确的错误代码:
[ERROR] [MY-011665] [InnoDB] Operating system error number 2 in a file operation.
[ERROR] [MY-012670] [InnoDB] Cannot open datafile for read-only: './sbtest/sbtest1.ibd' OS error: 71
[ERROR] [MY-012930] [InnoDB] Cannot open datafile: './sbtest/sbtest1.ibd'
[ERROR] [MY-012930] [InnoDB] Cannot open datafile: './sbtest/sbtest1.ibd'
[ERROR] [MY-012671] [InnoDB] Could not open a file for read-only: './sbtest/sbtest1.ibd' OS error: 71
[ERROR] [MY-012956] [InnoDB] The file './sbtest/sbtest1.ibd' cannot be opened.
[ERROR] [MY-012645] [InnoDB] The system tablespace file './ibdata1' has the wrong size. Please check that you a
[ERROR] [MY-012645] [InnoDB] The system tablespace file './ibdata1' has the wrong size. Please check that you a
[ERROR] [MY-012930] [InnoDB] Cannot open datafile: './sbtest/sbtest1.ibd'
[ERROR] [MY-012930] [INNODB] Cannot open datafile: './sbtest/sbtest1.ibd'
[ERROR] [MY-012930] [INNODB] Cannot open datafile: './sbtest/sbtest1.ibd'
[ERROR] [MY-011026] [INNODB] Unable to lock ./sbtest/sbtest1.ibd error: 71
[ERROR] [MY-011026] [INNODB] Unable to lock ./sbtest/sbtest1.ibd error: 71
[ERROR] [MY-011026] [INNODB] Unable to lock ./sbtest/sbtest1.ibd error: 71
[ERROR] [MY-012974] [INNODB] Trying to access page number 4294967295 in space 4294967295, space name sbtest/sbtest1, which is outside the tablespace bounds.
最关键的就是最后一行,也就是标题中提到的 ER_IB_MSG_974,它明确指出了问题:InnoDB存储引擎试图访问一个远远超出表空间文件实际大小的页面号,而前面的错误则指出了核心矛盾:sbtest1 这个表的表空间文件(.ibd文件)的页面大小不匹配,MySQL认为它应该是16384字节(16KB),但实际文件的页面大小却是32768字节(32KB)。
为什么会发生这种页面大小不匹配的情况呢?(来源:基于MySQL官方文档和社区案例的经验判断)
根据我们的经验,这种情况极少是MySQL自身运行中突然产生的,几乎可以肯定是由于外部操作导致的,我们立刻询问了客户近期是否对数据库或服务器进行过任何操作,客户回忆说,在问题发生前,因为磁盘空间不足,他们尝试过使用 cp 命令来备份和移动过一些数据文件,听到这里,问题的根源就基本浮出水面了。
我们判断,极有可能是在使用操作系统命令(如 cp)复制巨大的 .ibd 文件(可能几十GB甚至更大)过程中,出现了意外中断,比如网络闪断、磁盘IO问题,或者操作员手动终止了命令,这导致复制出来的 .ibd 文件是一个不完整的“残次品”,其文件大小可能看起来正常(比如有几十GB),但内部结构已经损坏,文件头部的元数据(包括页面大小信息)可能丢失或被破坏,导致InnoDB引擎无法正确识别。
接下来是远程修复的步骤。(来源:本次实际处理过程)

由于是远程支持,我们无法接触物理服务器,所有操作都需要通过指令指导客户完成,我们的首要目标是让数据库尽快恢复服务。
-
确认备份: 第一步永远是确认是否有可用的备份,万幸的是,客户有定期的全量备份和二进制日志(binlog)备份,这给了我们修复的底气,如果没有备份,情况会复杂得多。
-
停止MySQL服务: 确保MySQL服务已经完全停止,避免任何可能的写入加重损坏。
-
隔离问题文件: 我们指导客户将出问题的表空间文件
sbtest1.ibd移动到另一个安全的备份目录,而不是直接删除,命令类似于:mv /var/lib/mysql/sbtest/sbtest1.ibd /tmp/sbtest1.ibd.bak,这样做的目的是“移除”这个坏文件,让MySQL在启动时不再因为它而卡住。
-
尝试启动MySQL: 移走坏文件后,我们尝试启动MySQL服务,如果只有这一个表损坏,MySQL服务通常能够成功启动,启动后,我们连接到数据库,发现
sbtest.sbtest1这个表还存在元数据定义(在information_schema中能看到),但尝试查询时会报错说表不存在,这是因为对应的 .ibd 文件已经被我们移走了。 -
从备份中恢复特定表: 接下来就是恢复数据,我们使用客户的备份工具(这里是Percona XtraBackup的热备文件)来单独恢复
sbtest1这个表,这个过程大致是:- 从备份文件中导出
sbtest1表的表结构(.frm文件,如果是MySQL 8.0则方式不同)和表空间文件。 - 在已经启动的MySQL实例上,先丢弃(DROP)掉损坏的表的空壳。
- 重新创建这个表的结构。
- 执行
ALTER TABLE sbtest1 DISCARD TABLESPACE;丢弃新创建的空表空间。 - 将备份中健康的
sbtest1.ibd文件复制回sbtest数据库目录下。 - 执行
ALTER TABLE sbtest1 IMPORT TABLESPACE;导入表空间。
- 从备份文件中导出
-
验证数据: 导入完成后,我们让客户随机查询几条数据,并检查表的大致行数,确认数据恢复成功。
-
应用增量日志(如果必要): 由于从全量备份恢复到问题发生之间可能还有数据写入,我们利用备份的二进制日志,通过
mysqlbinlog工具导出自全量备份点之后的所有变更,并应用到数据库中,从而实现数据的零丢失。 -
根本原因分析与建议: 问题解决后,我们向客户强调了操作规范:严禁在数据库运行时使用操作系统命令直接复制或移动正在被MySQL使用的数据文件,正确的备份应该使用
mysqldump、mysqlpump或专业的热备份工具(如XtraBackup),如果确实需要移动文件,必须先彻底关闭MySQL服务。
MY-012799和ER_IB_MSG_974这个错误组合,在我们这个案例中,根本原因是由于不当的外部文件操作导致了表空间文件损坏,修复的关键在于“隔离问题文件,从备份恢复”,整个过程再次证明了定期备份并验证其有效性的重要性,希望这个真实的排查和修复经历能对大家有所帮助。
本文由召安青于2026-01-06发表在笙亿网络策划,如有疑问,请联系我们。
本文链接:https://www.haoid.cn/wenda/75488.html
