如何恢复MySQL误删除数据文件

在生产环境上,误删除ibdata1、ib_logfile0和ib_logfile1。如果mysql进程还在运行,此时select读取数据还是insert、update更新数据都正常。

这时可以通过命令查看mysql的进程

# ps -ef | grep mysqld|awk '{print $1,$2}'|grep mysql
# mysql 4070

查看mysql误删除文件在proc的位置

ll /proc/4070fd|grep -e ibdata -e ib_

可以看到,被删除的3个文件ibdata1、ib_logfile0和ib_logfile1在内存中已经标记为deleted了,可见文件确实是被删除了。

那么为什么MySQL还能正常使用呢?其实,mysqld在运行状态下,会保持ibdata1、ib_logfile0、ib_logfile1这些文件为打开状态,即使把它们删除了,它们仍旧存在于内存文件系统中,所以,mysqld仍然可以对其进行读写。只要mysqld进程不结束(MySQL服务不重启),就可以通过proc文件系统找到这几个被删除的文件。

现在数据库还一直对外提供服务,也就是有数据会持续写入,而在InnoDB存储引擎的buffer pool中,有许多dirty page(脏数据,就是内存中的数据已经被修改,但是没有写到磁盘中)还没提交,如果直接把文件复制回去,肯定会丢失数据,甚至还有可能导致ibdata1文件损坏。在复制数据文件之前,必须保证所有buffer pool中的数据修改都保存到了硬盘上,因此,首先需要停止目前的写入、更新和删除等操作,然后刷新内存数据到磁盘,最后才能复制文件。如何操作呢?可执行下面几个SQL:

FLUSH TABLES WITH READ LOCK;
SHOW engine innodb STATUS\G;
show variables like '%innodb_max_dirty_pages_pct%';
SET global innodb_max_dirty_pages_pct=0;
这样设置后,脏页会迅速减少,磁盘写操作会迅速完成。等待所有脏数据刷新到磁盘后,就可以进行文件复制了。
cp /proc/4070/fd/10  /data1/mysql/ib_logfile1
cp /proc/4070/fd/4   /data1/mysql/ibdata1
cp /proc/4070/fd/9   /data1/myql/ib_logfile0

修改文件权限为MySQL,操作如下:

chown mysql:mysql /data1/mysql/ib*

所有操作完成后,还需要重启数据库服务:

/etc/init.d/mysqld restart

关注公众号“大模型全栈程序员”回复“小程序”获取1000个小程序打包源码。更多免费资源在http://www.gitweixin.com/?p=2627

发表评论

邮箱地址不会被公开。 必填项已用*标注