记录一次删了开发环境数据库文件恢复的过程!(大部分恢复)

是的,我一不小心把开发环境下数据库的data删除了

show variables like '%datadir%';

对的,就是上面这个路径下的全删了,恐怖。。。。。 当时脑子一片空白,想想还好是开发环境,后面赶快找运维恢复。。

 

删了这些文件之后,mysql进程还在(这是最好的结果),服务已经挂了。

 

在看完运维噼里啪啦一顿操作数据库终于恢复好了(有惊无险。。),赶紧抓着这个机会向大佬学习了一波,后来我自己又试着恢复了日志文件,下面就用恢复日志来举例,恢复数据库文件也是一样的过程(但是复杂多了,考虑的东西也多多了)。

 

注意:这种恢复方法只能恢复那些被进程调用并存在于内存中的文件,如服务的日志文件,数据库的数据等,对于日志和数据库的恢复来说非常有用

 

恢复过程:

1、首先先查到我们删除的文件会被哪个关联的进程调用(这个是恢复前提,没有这个就不能恢复),我们可以看到这时运行着redis服务,端口是6380, 这时开着aof 每秒追加的模式。如果对redis持久化不熟悉的可以查 redis学习日记(二):redis 小工具及持久化

 

在这里我们可以看着这个名为  appendonly-6380.log 日志文件,这个就是和redis进程有关的文件,下面我们将删除这个文件再恢复。

 

 

2、好的,现在这个文件被删除,首先我们使用 lsof 命令查看这个文件与哪个进程有关, 通过这个文件的路径grep 查询即可,我们可以发现这个进程号就是redis服务的进程号。

 

3、在确定这个进程号之后,我们进入linux   /proc/pid/fd 路径下,这里我们pid是15120, 所以我们进入  cd  /proc/15120/fd ,打印里面的内容看看。 我们可以看到这个文件后面被标了 (deleted) 标记。

4、 打印这个文件发现内容和原来一样,所以我们重定向生成原来的文件即可 。 

root@czx:/proc/15120/fd# cat 5 > /data/soft/redis-5.0.0/data/appendonly-6380.aof

5、 这样我们就把一个日志文件重新恢复了。数据库文件也是一样,加载的数据库数据都会被mysql进程可视,这时最后一道可以找到这个文件的入口,如果这个进程没了就也找不到了。

 

总结:

1、通过 lsof  结合grep 找到和删除文件相关的pid。

root@czx:/data/soft/redis-5.0.0/data# lsof | grep /data/soft/redis-5.0.0/data/appendonly-6380.aof

2、拿着这个pid 进入 /proc/pid/fd  文件夹,找到被删除的文件,在文件后面会有 deleted 标记。

root@czx:/proc/15120/fd# pwd
/proc/15120/fd

3、通过重定向或者复制这个文件到原来的路径就可以了。

root@czx:/proc/15120/fd# cat 5 > /data/soft/redis-5.0.0/data/appendonly-6380.aof

 

看了恢复的过程,我又去了解了下为什么linux下可以这么做。

恢复的原理:

1、首先 linux 操作系统下文件实际上是一个指向inode的链接, inode链接包含了文件的所有属性, 比如权限和所有者, 数据块地址(文件存储在磁盘的这些数据块中). 当你删除(rm)一个文件, 实际删除了指向inode的链接, 并没有删除inode的内容. 进程可能还在使用. 只有当inode的所有链接完全移去, 这些数据才算真正删除,这也是之前为什么一直强调要有指向这个文件的进程就是这个道理,当我们rm删除一个文件时,我们就只剩下进程这个指向这个文件的链接了,也就是说这时如果我们把这个进程kill掉,那这个文件就用这个方法恢复不了了。

2、既然这时实际文件没有被删除,那它就还存在于磁盘中,准确说应该是内存中,那它存在哪里呢?

答案就是在这个 /proc 文件夹下,这个proc文件夹下存放了各种以进程号命名的文件(如上面的 15120 文件夹)和 如 stat 这些 linux 内核相关的文件(stat文件就写着当前cpu的一些信息)。而 /proc/15120/fd 下就是存放这个进程放在内存中的一些文件,我们可以看到这里就有删除的文件。

3、有了这个即将删除的文件我们就能随意操作了。
 

 

回到主题:

我们用上述方式恢复了部分数据库文件,对的,只能恢复部分,悲剧。。。。只能接着又去请教了运维

 

那为什么只能恢复部分呢?

按照上述讲的内容,只有进程正在使用的文件会被加载到内存中来,即使全部文件正在使用好了,可能也会被计算机本身的内存所限制而只存放部分文件,更何况有些数据根本没人使用。

 

还有一个问题,有些数据库文件被恢复了但是仍然不能访问或者没数据的情况

这时就牵扯到mysql数据库的存储方式了。

1、首先数据库有个存放数据的路径 ,叫【datadir】 。在配置文件中如  datadir = /var/lib/mysql 就指定存放位置,这下面就存放MySQL 数据库文件,包括 MySQL 所建数据库文件和 MySQL 所用存储引擎创建的数据库文件

我们知道现在主流的数据库存储的两个引擎是 MyISAM 和InnoDB。那在这两个引擎模式下它又是以怎么样的方式存放的呢?

我这里画了一个图方便理解。

我们可以看到无论是什么引擎,【.frm文件】都是存在的,我们可以理解为这个是定义一张表的表结构的文件,每个表对应一个同名frm文件。

而对于MyISAM存储引擎来说,它的表索引和表数据是单独分开的,所以一张表对应一个 【MYD表数据文件】 和 一个 【MYI表索引文件】。

对于InnoDB存储引擎来说,它的表索引和表数据是存放在一起的,所以一张表对应一个 【MYD表数据文件】 和 一个 【MYI表索引文件】,默认使用一个表一个 【IDB文件】。

2、所以要恢复数据库的一张表,如果是 InnoDB 存储引擎,除了 IDB文件外还要有 FRM文件,这里的 FRM 文件和 IDB 文件必须是一一对应,如果FRM对应的表结构和 IDB 存储的数据格式不一致 恢复也不能成功,反正就是这两个的文件缺失或者格式不对都不能正常使用,一定得是同时存在并且格式一致。

 

最后

说下恢复结果 ,昨天下午不小心删了数据,晚上按照之前的方法大致恢复了一部分,基本的数据都恢复了,以为没事了。

结果第二天反应说有些表不能使用(100多张表),后来发现少了frm文件,然后从测试库复制了缺失的文件到开发,还剩30多张不能使用(不能使用的原因大概就是frm文件和数据文件不对应)。。。黔驴技穷。。。把这30多张表删了,直接把测试环境的表结构和数据都导入到了开发环境。。

 

虽然最后大部分恢复了,但还是有点小难受,吃一堑长一智,使用  rm 命令前一定要千万小心,小心再小心。。。

 

最后的最后。。。大佬们如果有什么恢复数据的好方法,一定虚心求教!写的有什么不对的,下方评论留言我也好学习学习

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章