最近遇到一个MySQL开发库,被告知误删除了InnoDB主表空间文件:ibdata1和重做日志ib_logfile*的情况。
MySQL使InnoDB文件始终保持打开状态。以下恢复技术基于此场景,这种情况下可以尝试对数据库抢救恢复。
实际上,文件已经被删除一段时间。但是,只要mysqld在运行状态中,即使文件被删除,这些文件在物理上也会保持打开状态,它们仍旧存在于文件系统中,mysqld的进程可以打开这些文件对其进行读写。
因此,从用户的角度来看,删除后没有任何变化。但重启后InnoDB将会检测到既没有系统表空间文件也没有日志文件,因此它将创建空的文件。InnoDB字典也就为空了,InnoDB将无法使用一堆当前的ibd文件。但还是存在一种可能性,只要MySQL没有重启,就有可能快速恢复数据库。
模拟如下过程,删除数据目录下的ibdata和redo日志iblog file,让sysbench模拟数据库读写活动的场景。
Terminal 1:
Terminal 2:
[root@localhost data]# rm ../redologs/ib_logfile*
rm: remove regular file `../redologs/ib_logfile0'? y
rm: remove regular file `../redologs/ib_logfile1'? y
rm: remove regular file `../redologs/ib_logfile2'? y
[root@localhost data]# rm ibdata1
rm: remove regular file `ibdata1'? y
现在文件已经消失,但MySQL仍在运行。它们在/data/mysql/下面已经被删除了,但可以在/proc文件系统中访问:
[root@localhost data]# ls -la /proc/26248/fd/ | grep -e ibdata -e ib_
lrwx------ 1 root root 64 Mar 20 09:27 10 -> /data/mysql/redologs/ib_logfile1 (deleted)
lrwx------ 1 root root 64 Mar 20 09:27 11 -> /data/mysql/redologs/ib_logfile2 (deleted)
lrwx------ 1 root root 64 Mar 20 09:27 5 -> /data/mysql/redologs/ib_logfile0 (deleted)
lrwx------ 1 root root 64 Mar 20 09:27 9 -> /data/mysql/data/ibdata1 (deleted)
其中26248是mysqld进程的PID
但是,我们不能将它们复制回来,当前MySQL还在运行,如果在任何给定的时间点,buffer pool中都有已修改的dirty page。这些页面还没有写到磁盘上,如果没有永久写入更改,它们将丢失。这可能导致ibdata文件损坏和数据丢失。
为保证数据的完整性和一致性,必须确保数据库所有修改都已经全部落盘。为此,需要停止任何的写操作和事务,并等待InnoDB刷新所有dirty 。因此,我们可以停止应用程序or 锁表等操作。
操作如下:
(root@localhost:)[(none)]> flush tables with read lock;
Query OK, 0 rows affected (0.01 sec)
通过innodb引擎的状态观察到
因此设置如下参数操作如下:
(root@localhost:)[(none)]> set global innodb_max_dirty_pages_pct=0;
Query OK, 0 rows affected, 2 warnings (0.00 sec)
继续观察innodb的状态
检查点状态
事务状态
复制proc文件系统删除的文件到相应目录
[root@localhost data]# cp /proc/26248/fd/9 /data/mysql/data/ibdata1
[root@localhost data]# cp /proc/26248/fd/5 /data/mysql/redologs/ib_logfile0
[root@localhost data]# cp /proc/26248/fd/10 /data/mysql/redologs/ib_logfile1
[root@localhost data]# cp /proc/26248/fd/11 /data/mysql/redologs/ib_logfile2
[root@localhost data]# ls -l /data/mysql/redologs/
total 786444
-rw-r----- 1 root root 268435456 Mar 20 09:52 ib_logfile0
-rw-r----- 1 root root 268435456 Mar 20 09:52 ib_logfile1
-rw-r----- 1 root root 268435456 Mar 20 09:52 ib_logfile2
修改文件的属性
[root@localhost data]# chown -R mysql:mysql /data/mysql/redologs/*
[root@localhost data]# chown -R mysql:mysql /data/mysql/data/ibdata1
[root@localhost data]#
[root@localhost data]#
[root@localhost data]# /etc/init.d/mysqld restart
Shutting down MySQL.. [ OK ]
Starting MySQL.... [ OK ]
验证数据库的数据:
至此,完成恢复。
Tips:1、出现问题,要保留现场,不要随意重启MySQL。
2、MySQL数据库的核心文件也有监控的必要。
--the end