mysql innodb 从 ibd 文件恢复表数据
最近内部的 mysql 数据库发生了一件奇怪的事,其中有一个表 users625 突然出现问题,
所有对它的操作都报错误 数据表不存在。
mysql> select count(*) from users625;
ERROR 1146 (42S02): Table 'km8.users625' doesn't exist
show tables 它还显示在列表里,在 mysql 数据目录中也可以找到对应的表文件,也没有
进行过删除操作,突然出现这样的错误非常奇怪。
内部运行环境:
| 名称 | 值 |
|---|---|
| OS | Debian Squeeze x64 |
| mysql 版本 | 5.1 |
| mysql 引擎 | innodb |
发生了什么
突然出现这种情况,第一反应必定是想办法将表中的用户数据找回,但是目前发生问题的情况与原因都不明晰,
不能轻举妄动。
查看 mysql 日志,在操作出错的时候,日志这样显示:
mysqld: 180926 11:10:53 InnoDB: cannot calculate statistics for table km8/users625
mysqld: InnoDB: because the .ibd file is missing. For help, please refer to
mysqld: InnoDB: http://dev.mysql.com/doc/refman/5.1/en/innodb-troubleshooting.html
mysqld: 180926 11:10:53 [ERROR] MySQL is trying to open a table handle but the .ibd file for
mysqld: table km8/users625 does not exist.
mysqld: Have you deleted the .ibd file from the database directory under
mysqld: the MySQL datadir, or have you used DISCARD TABLESPACE?
mysqld: See http://dev.mysql.com/doc/refman/5.1/en/innodb-troubleshooting.html
mysqld: how you can resolve the problem.
其中提到3个可追溯的点:
- ibd file
- DISCARD TABLESPACE
- http://dev.mysql.com/doc/refman/5.1/en/innodb-troubleshooting.html
了解这3点提到的内容,应该对判断情况有很好的帮助。
ibd file
日志中提问,是否丢失了 ibd 文件?先到 mysql 数据目录下查找,
.
├── ibdata1
├── .......
├── .......
└── km8
├── ............
├── ............
├── users625.frm
├── users625.ibd
├── ............
└── ............
users625 的 ibd 文件是存在的,与之一起的还有文件 users625.frm 。
根据官方文档对 frm 文件的描述,frm 文件是用来保存 table 表结构(即 table 的定义)的,无论使用什么存储引擎。
与之相对的,ibd 文件是用来存储表数据(即行数据)的,通常情况下,所有数据都会存储在系统的 ibd 文件,
但是当开启选项 innodb_file_per_table 的时候,每个表的数据会使用单独的 ibd 文件来存储。
当前的 mysql 就开启了这个选项,
[mysqld]
innodb_file_per_table=1
目前 frm 与 ibd 文件都存在,从中恢复数据便存在一些希望。
DISCARD TABLESPACE
日志中提到的 DISCARD TABLESPACE 其实是在猜测导致 ibd 文件丢失的原因,因为它会删除相应 table 的 ibd 文件(所谓 tablespace)。
> ALTER TABLE km8.users625 DISCARD TABLESPACE;
底层的 users625.ibd 文件就会被删除,丢失所有表数据。
根据目前情况来看, ibd 文件还存在,所以它不是导致错误的原因。
trouble shooting doc
日志中提到的参考链接,其中列举了多种情况,和当前问题相关的是一个子链接,
按照它提供的方法,尝试进行数据恢复。
数据恢复
官方文档提到的恢复数据的方法,思路很清晰:
- 启用相同版本的 mysql 实例(启用选项 innodb_file_per_table)
- 建立同样结构的数据表
- 替换 ibd 文件(保持文件权限一致)
- 导入 ibd 文件中的数据
- 使用 mysqldump,导出数据
- 将导出的数据导入原数据库
我按照这种方式尝试恢复数据,并不是那么顺利:
如何获得 table 表结构?
在第2步,需要建立同样结构的数据表,目前只有 frm 和 ibd 文件,怎么样得到 create table 命令?
根据底层数据存储的理解,table 表结构存储在 frm 文件中,而目前已经有相应的方法从中提取出 create table 命令,
这样就可以用于在新的 mysql 实例中建立 table 。
tablespace id 不对应?
在第4步,尝试导入数据的时候,
> ALTER TABLE km8.users625 IMPORT TABLESPACE;
ERROR 1030 (HY000): Got error -1 from storage engine
总是出现失败,同时在 mysql 新实例的日志中发现这样的错误:
mysqld: InnoDB: Error: tablespace id in file './km8/users625.ibd' is 18446744073709551615, but in the InnoDB
mysqld: InnoDB: data dictinary it is 1.
原来在内部,ibd 文件本身有一个 id,必须和 mysql innodb 内部的 table 元数据相对应,才可以进行导入。
根据错误信息搜索到一篇文章,其中提到两种办法:
- 重复建表,因为 mysql 内部的 tablespace id 是累计递增的,预先建立 (18446744073709551615 - 1)张表,再建立
users625 表,就可以对应 id,并进行导入。 - 修改 ibd 文件,因为 tablespace id 存储于 ibd 文件,找到它并将其修改为 1,使之与内部的 id 对应,就可以进行导入。
考虑第 1 种方法,要预先建立上亿张空表?!这根本不可能。
于是尝试第 2 种方法,研究 ibd 的文件格式,修改对应 id。
用二进制编辑器打开 users625.ibd 文件,

18:26:08 UTC - mysqld got signal 6. This could be because you hit a bug. It is also possible that this
binary or one of the libraries it was linked against is corrupt, improperly built or misconfigured.
This error can also be cuased by malfunctioning hardware.
不敢相信自己的眼睛,居然有错误 log 在二进制文件里?!ibd 的文件格式可没有这么说明过。
随便找一个邻居表正常的 ibd 文件作对比,

看来是出现了 bug ,崩溃的环境直接将数据文件给毁了,这也解释了为什么 tablespace id 会那么大,因为 log
覆盖了原本的 id 字段,使 mysql 解读出了一个好笑的数字。
暂时放弃
这种情况下,还没有办法将数据恢复回来,只能暂时将表删除,新建空表,保证上层应用程序可以运行。
将 ibd 文件备份下来,看后续还没有其它的办法将其恢复。
检测所有 table 状态
当前只发现一个出现问题的 table ,可能同时也有其它的 table 出现问题。对此需要做一个全面的检测,
检测有没有其它的表受到牵连。
$ mysqlcheck --all-databases
写在最后
数据库的备份是非常重要的!直接导入备份数据,是解决问题最保险最便捷的办法。
如果没有备份,遇到 bug 丢失数据,只能怪时运不济。
同时数据库也最好选择稳定的版本,降低出现 bug 的概率。
mysql innodb 从 ibd 文件恢复表数据的更多相关文章
- MySQL 利用frm文件和ibd文件恢复表结构和表数据
文章目录 frm文件和ibd文件简介 frm文件恢复表结构 ibd文件恢复表数据 通过脚本利用ibd文件恢复数据 通过shell脚本导出mysql所有库的所有表的表结构 frm文件和ibd文件简介 在 ...
- MySQL innodb引擎下根据.frm和.ibd文件恢复表结构和数据
记录通过.frm和.ibd文件恢复数据到本地 .frm文件:保存了每个表的元数据,包括表结构的定义等: .ibd文件:InnoDB引擎开启了独立表空间(my.ini中配置innodb_file_per ...
- mysql5.7根据.frm和.ibd文件恢复表结构和数据
一.恢复表结构 1.环境:Windows .mysql5.7:首先创建一个数据库,可以通过navicat来创建: 2.使用当前创建的数据库:use ww; 3.随意创建一张表,但是这张表的名字 ...
- mysql数据恢复:.frm和.ibd,恢复表结构和数据
mysql数据恢复:.frm和.ibd,恢复表结构和数据 一.恢复表结构 二.恢复表数据 相关内容原文地址: CSDN:她说巷尾的樱花开了:mysql根据.frm和.ibd文件恢复表结构和数据 博客园 ...
- 通过.frm表结构和.ibd文件恢复数据
整个恢复过程其实可以总结为下面几步: (1):恢复表结构 (2):复制出来创建表的sql语句 (3):恢复表数据(在恢复表数据的时候,首先需要解除当前创建的表与默认生成的.ibd文件间的关系,接着将要 ...
- mysql通过frm+ibd文件还原data
此方法只适合innodb_file_per_table = 1 当误删除ibdata 该怎么办? 如下步骤即可恢复: 1.准备工作 1)准备一台纯洁的mysql环境[从启动到现在没有 ...
- mysql 之 frm+ibd文件还原data
此方法只适合innodb_file_per_table = 1 当误删除ibdata 该怎么办? 如下步骤即可恢复: 1.准备工作 1)准备一台纯洁的mysql环境[从启动到现在 ...
- Oracle恢复表数据
Oracle恢复数据 在oracle 10g以及之后的版本,提供了回收站的机制,为了防止误操作将表数据清空而有回收机制. 换句话说,我们删除的表不会立马消失,而是进入回收站.下面我们可以查看回收站 查 ...
- mysql: 关于MySQL InnoDB锁行还是锁表?
baidu zone - 关于MYSQL Innodb 锁行还是锁表,深入讲解
随机推荐
- Loj #2256. 「SNOI2017」英雄联盟
题目 我就是个丝薄 如果要用\(dp_i\)表示凑出\(i\)的最小花费显然不可能的 之后大力猜想能凑出来的状态不会很多,我的暴力也告诉我不是很多,好像也确实不多的样子,大概\(4e4\)左右 但是我 ...
- 解决django配合nginx部署后admin样式丢失
解决django配合nginx部署后admin样式丢失 1. 在项目的settings.py文件里添加以下内容: STATIC_URL = '/static/' STATICFILES_DIRS = ...
- linux centos 7.5下 源码编译安装 lua环境
lua 5.3.5 下载安装时发现缺少库 readline 需要添加依赖 yum search readline 看有哪些包 安装带有 devel 字样的 安装无 devel 的非开发包,通常不会自动 ...
- ngRouter和ui-router区别
在单页面应用中要把各个分散的视图给组织起来是通过路由机制来实现的.本文主要对 AngularJS 原生的 ngRoute 路由模块和第三方路由模块 ui.router 的用法进行简单介绍,并做一个对比 ...
- springmvc IDEA
回顾Java平台上Web开发历程来看,从Servlet出现开始,到JSP繁盛一时,然后是Servlet+JSP时代,最后演化为现在Web开发框架盛行的时代.一般接触到一个新的Web框架,都会想问这个框 ...
- pytest 框架自动化Selenium 之yield 使用
环境 python 3.7 由于3.0-3.5以下部分pytest可能有部分兼容问题安装建议2.7-2.9,3.5-最新 pip install pytest专属 pytest框架包 pip inst ...
- P1169 [ZJOI2007]棋盘制作
题目描述 国际象棋是世界上最古老的博弈游戏之一,和中国的围棋.象棋以及日本的将棋同享盛名.据说国际象棋起源于易经的思想,棋盘是一个8*8大小的黑白相间的方阵,对应八八六十四卦,黑白对应阴阳. 而我们的 ...
- 带编译器的codeblocks下载地址
曾下载过一个没有编译器的codeblocks,弄了很久才发现自己下载的版本没有编译器,所以将带编译器的codeblocks放在腾讯微盘中,方便自己也方便他人,这样就不用去官网下载了,官网有时候真的是有 ...
- oracle中的条件语句
oracle中case when then及decode用法 一.case … when … then 语法: – 写法一: case(条件) when 值1 then 返回值1 when 值 ...
- Go语言相对于C++的优点
Go语言是Google公司在2009年开源的一门高级编程语言,它为解决大型系统开发过程中的实际问题而设计,支持并发.规范统一.简单优雅,被很多Go语言传道者誉为“互联网时代的C语言”.而C++语言诞生 ...