数据库|MySQL Drop Database之后的恢复测试

工具介绍 工具的名字叫做:undrop-for-innodb
代码地址: https://github.com/twindb/undrop-for-innodb
官方文档: https://recovery.twindb.com/
介绍工具的一篇ppthttp://www.slideshare.net/akuzminsky/undrop-for-innodb

当MySQL 执行 Drop Table或者 Drop Database 的时候,InnoDB并没有删除数据,数据的Page还在磁盘上。
如果innodb_file_per_table 被设置成了 OFF, 则数据库在ibdata1上,如果 innodb_file_per_table 被设置成了 ON, 则数据在 .ibd文件中,MySQL已经删除了这个文件。

安装恢复软件

  1. 首先安装软件所需要的包:makegcc flexbison git
[root@centos~]# yum install makegccflex bison git

  1. 下载代码
[root@centos~]# git clone https://github.com/twindb/undrop-for-innodb.git
Initializedempty Git repository in /root/undrop-for-innodb/.git/
remote:Counting objects: 221, done.
Receivingobjects: 100% (221/221), 1.10 MiB | 53 KiB/s, done.
remote: Total221 (delta 0), reused 0 (delta 0), pack-reused 221
Resolvingdeltas: 100% (53/53), done.
[root@centos~]# ls
anaconda-ks.cfgMySQL-5.6.27-1.el6.x86_64.rpm-bundle.tar MySQL-embedded-5.6.27-1.el6.x86_64.rpm MySQL-shared-compat-5.6.27-1.el6.x86_64.rpm
install.logMySQL-client-5.6.27-1.el6.x86_64.rpmMySQL-server-5.6.27-1.el6.x86_64.rpmMySQL-test-5.6.27-1.el6.x86_64.rpm
install.log.syslogMySQL-devel-5.6.27-1.el6.x86_64.rpmMySQL-shared-5.6.27-1.el6.x86_64.rpmundrop-for-innodb

3.编译代码
[root@centos~]# cd undrop-for-innodb/
[root@centosundrop-for-innodb]# ls
check_data.cdictionaryincludeLICENSEprint_data.c recover_dictionary.sh sql_parser.lstream_parser.ctables_dict.c
c_parser.cfetch_data.shinnochecksum.cMakefile README.mdsakilasql_parser.ysys_parser.ctest.sh
[root@centosundrop-for-innodb]# make
cc-D_FILE_OFFSET_BITS=64 -Wall -g -O3 -pipe -I./include -c stream_parser.c
cc-D_FILE_OFFSET_BITS=64 -Wall -g -O3 -pipe -I./include-pthread -lmstream_parser.o -o stream_parser
flexsql_parser.l
bison-o sql_parser.c sql_parser.y
sql_parser.y:conflicts: 6 shift/reduce
cc-D_FILE_OFFSET_BITS=64 -Wall -g -O3 -pipe -I./include -c sql_parser.c
lex.yy.c:3084:警告:‘yyunput’定义后未使用
lex.yy.c:3125:警告:‘input’定义后未使用
cc-D_FILE_OFFSET_BITS=64 -Wall -g -O3 -pipe -I./include -c c_parser.c
./include/ctype-latin1.c:359:警告:‘my_mb_wc_latin1’定义后未使用
./include/ctype-latin1.c:372:警告:‘my_wc_mb_latin1’定义后未使用
cc-D_FILE_OFFSET_BITS=64 -Wall -g -O3 -pipe -I./include -c tables_dict.c
cc-D_FILE_OFFSET_BITS=64 -Wall -g -O3 -pipe -I./include -c print_data.c
cc-D_FILE_OFFSET_BITS=64 -Wall -g -O3 -pipe -I./include -c check_data.c
cc-D_FILE_OFFSET_BITS=64 -Wall -g -O3 -pipe-I./includesql_parser.oc_parser.o tables_dict.o print_data.o check_data.o -o c_parser -pthread -lm
cc -D_FILE_OFFSET_BITS=64-Wall -g -O3 -pipe-I./include -oinnochecksum_changer innochecksum.c





测试恢复数据 测试环境 数据库的版本:MySQL-server-5.6.27
操作系统:Centos6.7 和 Windows 7

测试场景1:Drop Database (innodb_file_per_table=On) 创建数据库和测试表
我们先来看下创建好的数据库,有多少个文件。
[root@centos mysql]#ls
auto.cnfcentos.err centos.pidibdata1ib_logfile0 ib_logfile1mysqlmysql.sock performance_schema RPM_UPGRADE_HISTORY RPM_UPGRADE_MARKER-LASTtest

确认下我们的数据库的 innodb_file_per_table参数
mysql> show variables like '%per_table%';

+-----------------------+-------+

| Variable_name| Value |

+-----------------------+-------+

| innodb_file_per_table | ON|

+-----------------------+-------+

1 row in set (0.00 sec)

说明:OFF代表mysql是共享表空间,也就是所有库的数据都存放在一个ibdate1文件中
ON代表,每个表的存储空间都是独立的。

接下来创建爱数据库 test1 并创建测试表 test1
mysql>create database test1;
Query OK, 1row affected (0.00 sec)
mysql> usetest1;
Databasechanged
mysql>create table test1(id int);
Query OK, 0rows affected (0.14 sec)
mysql>insert into test1 values('1');
Query OK, 1row affected (0.54 sec)
mysql>insert into test1 select * from test1; -----反复运行多次,直到有足够的数据量
Query OK,131072 rows affected (2.28 sec)
Records:131072Duplicates: 0Warnings: 0
mysql>commit;
Query OK, 0rows affected (0.00 sec)

我们来看下数据文件多了哪些。
[root@centosmysql]# ls
auto.cnfcentos.err centos.pidibdata1ib_logfile0 ib_logfile1mysqlmysql.sock performance_schema RPM_UPGRADE_HISTORY RPM_UPGRADE_MARKER-LASTtesttest1
多了一个test1的目录。进入目录看下
[root@centosmysql]# cd test1
[root@centostest1]# ls
db.opttest1.frm test1.ibd
可以看到 test1.frm 和 test1.ibd 这2个文件。
ibd是MySQL数据文件、索引文件,无法直接读取。
frm是表结构文件,可以直接打开。
如果innodb_file_per_table 无论是ON还是OFF,都会有这2个文件,区别只是innodb_file_per_table为ON的时候,数据时放在 .idb中,如果为OFF则放在ibdata1中。

我们来看下数据文件的大小:
[root@centostest1]# du -sh *
4.0Kdb.opt
12Ktest1.frm
72Mtest1.ibd

[root@centosmysql]# du -sh *
4.0Kauto.cnf
4.0Kcentos.err
4.0Kcentos.pid
76Mibdata1
49Mib_logfile0
48Mib_logfile1
1.7Mmysql
0mysql.sock
636Kperformance_schema
4.0KRPM_UPGRADE_HISTORY
4.0KRPM_UPGRADE_MARKER-LAST
4.0Ktest
8.0Ktest2
发现 test1.ibd和ibdata1 都增长的很厉害,不知道为什么,这个之后再研究。

接下来删除数据库test1
drop databasetest1.

开始恢复数据

注意这里 -f 后面的参数是 裸盘 的地址,如果你不知道可以用 df -h 查看.
-t 是这个磁盘的大小。

[root@centos~]# df -h /var/lib/mysql
FilesystemSizeUsed Avail Use% Mounted on
/dev/mapper/vg_centos-lv_root
50G4.1G43G9% /

[root@centosundrop-for-innodb]#./stream_parser -f /dev/mapper/vg_centos-lv_root -t 50g
Opening file:/dev/mapper/vg_centos-lv_root
Fileinformation:

ID of devicecontaining file:5
inodenumber:6454
protection:60660 (block device)
number of hardlinks:1
user ID ofowner:0
group ID ofowner:6
device ID (ifspecial file):64768
blocksize forfilesystem I/O:4096
number ofblocks allocated:0
time of lastaccess:1449240755 Fri Dec4 22:52:35 2015
time of lastmodification:1449240755 FriDec4 22:52:35 2015
time of laststatus change:1449240755 FriDec4 22:52:35 2015
total size, inbytes:0 (0.000exp(+0))

Size to process:53687091200 (50.000 GiB)
Worker(0):1.03% done. 2015-12-05 00:04:40 ETA(in 00:14:38). Processing speed: 57.700MiB/sec
Worker(0):2.04% done. 2015-12-05 00:06:18 ETA(in 00:16:06). Processing speed: 51.902MiB/sec
Worker(0):3.06% done. 2015-12-05 00:01:27 ETA(in 00:11:08). Processing speed: 74.221MiB/sec
Worker(0):4.07% done. 2015-12-05 00:04:39 ETA(in 00:14:11). Processing speed: 57.672MiB/sec

Worker(0):98.51% done. 2015-12-04 23:54:19 ETA(in 00:00:05). Processing speed: 129.971MiB/sec
Worker(0):99.53% done. 2015-12-04 23:54:15 ETA(in 00:00:00). Processing speed: 520.000MiB/sec
All workersfinished in 263 sec


这里说明一下:
0000000000000001.page:恢复出来的 SYS_TABLES 表
0000000000000003.page:恢复出来的 SYS_INDEXES 表

创建存放恢复出来的文件的目录
[root@centosundrop-for-innodb]#mkdir -p dictionary dumps/default

[root@centosundrop-for-innodb]# ./c_parser -4Df./pages-vg_centos-lv_root/FIL_PAGE_INDEX/0000000000000001.page -t./dictionary/SYS_TABLES.sql-o./dumps/SYS_TABLES.dmp-l./dumps/SYS_TABLES.sql
恢复数据,因为我们是恢复删除掉的数据,所以一定要加参数D(注意是大写的D)。
然后查看生成出来的文件:
./dictionary/SYS_TABLES.sql是创建表 SYS_TABLES的脚本。
./dumps/SYS_TABLES.dmp是SYS_TABLES表里面的内容
./dumps/SYS_TABLES.sql是恢复数据到SYS_TABLES的SQL语句。

这里我们查看 ./dumps/SYS_TABLES.dmp,可以看到我们删除掉的数据

因为我们在test1数据库中只有1个test1表。所以这里只能看到一个 test1。
可以看到 table_id 是 20。

接下来我们看下索引的信息

可以看到,索引的ID 是22

这里有个重点的地方,我们首先要有表结构的SQL语句。(如果没有的话,可以参考我另外的一篇文章来恢复表的结构)。
创建 test1/test1.sql , 输入如下内容
Create table test1
(
Id int
)

开始恢复数据:
./c_parser -6f pages-ibdata1/FIL_PAGE_INDEX/0000000000000022.page-t test1/test1.sql -o dumps/test1.dmmp -l dumps/test1.sql

启动数据库,创建数据库test1
mysql> create database test1;
Query OK, 1 row affected (0.03 sec)

mysql> use test1;
Database changed

运行 test1/test1.sql 创建表 test1, 然后运行 dumps/test1.sql 恢复数据
mysql> source dumps/test1.sql
Query OK, 0 rows affected (0.00 sec)

Query OK, 45794 rows affected (0.90 sec)
Records: 45794 Deleted: 0Skipped: 0Warnings:

检查数据,可以看到数据已经正常恢复了。


测试场景2:Drop Database (innodb_file_per_table=OFF) 创建数据库和测试表

首先确认下 innodb_file_per_table的参数.
mysql> showvariables like 'inno%per%tab%';
+-----------------------+-------+
|Variable_name| Value |
+-----------------------+-------+
|innodb_file_per_table | ON|
+-----------------------+-------+
1 row in set(0.00 sec)

创建测试用的数据库表和数据
mysql>create database test6;
Query OK, 1row affected (0.00 sec)

mysql> usetest6
Databasechanged
mysql>create table a(id int);
Query OK, 0rows affected (0.08 sec)

mysql>create table b(id2 int);
Query OK, 0rows affected (0.06 sec)

mysql>insert into a values(1);
Query OK, 1row affected (0.07 sec)

mysql>insert into b values(1);
Query OK, 1row affected (0.04 sec)

mysql>commit;
Query OK, 0rows affected (0.00 sec)

查看下数据表的目录,可以看到只有 frm文件
[root@centostest6]# pwd
/var/lib/mysql/test6
[root@centostest6]# ls
a.frmb.frm db.opt

反复执行 Insert into aselect * from a; 直到有足够大的数据。
[root@centosmysql]# du -sh ibdata1
76Mibdata1
Ibdata1增长到了76M

删除数据库 test6
mysql> dropdatabase test6;
Query OK, 2rows affected (0.26 sec)

开始恢复数据
因为数据在ibdata1文件中,所以我们分析ibdata1文件
[root@centosundrop-for-innodb]# ./stream_parser -f /var/lib/mysql/ibdata1
Opening file:/var/lib/mysql/ibdata1
Fileinformation:

ID of devicecontaining file:64768
inodenumber:2621728
protection:100660 (regular file)
number of hardlinks:1
user ID ofowner:498
group ID ofowner:497
device ID (ifspecial file):0
blocksize forfilesystem I/O:4096
number ofblocks allocated:155648
time of lastaccess:1449385451 SunDec6 15:04:11 2015
time of lastmodification:1449385922 SunDec6 15:12:02 2015
time of laststatus change:1449385922 SunDec6 15:12:02 2015
total size, inbytes:79691776 (76.000 MiB)

Size toprocess:79691776(76.000 MiB)
All workersfinished in 0 sec

剩下的步骤和之前的一样,首先获取到 我们删除掉的test6的数据库里面的表,从结果里面可以看到是 a 和b 。ID 分别是 24 和 25。
[root@centosundrop-for-innodb]# ./c_parser -4Df./pages-ibdata1/FIL_PAGE_INDEX/0000000000000001.page-t ./dictionary/SYS_TABLES.sql-o ./dumps/SYS_TABLES.dmp-l ./dumps/SYS_TABLES.sql
[root@centosundrop-for-innodb]# cat ./dumps/SYS_TABLES.dmp
-- Page id: 8,Format: REDUNDANT, Records list: Invalid, Expected records: (0 10)
000000000F6A55000008010182SYS_TABLES"test6/a"2411064""0
000000000F6452000008060182SYS_TABLES"test6/b"2511064""0

获取表中的索引信息
[root@centosundrop-for-innodb]# ./c_parser -4Df./pages-ibdata1/FIL_PAGE_INDEX/0000000000000003.page-t ./dictionary/SYS_INDEXES.sql
-- Page id:11, Format: REDUNDANT, Records list: Invalid, Expected records: (0 12)
000000000F6A55000008010110SYS_INDEXES2426"GEN\_CLUST\_INDEX"0104294967295
000000000F6452000008060110SYS_INDEXES2527"GEN\_CLUST\_INDEX"0104294967295
-- Page id:11, Found records: 2, Lost records: YES, Leaf page: YES
-- Page id:11, Format: REDUNDANT, Records list: Invalid, Expected records: (0 12)
000000000F6A55000008010110SYS_INDEXES2426"GEN\_CLUST\_INDEX"0104294967295
000000000F6452000008060110SYS_INDEXES2527"GEN\_CLUST\_INDEX"0104294967295
SETFOREIGN_KEY_CHECKS=0;
LOAD DATALOCAL INFILE '/root/undrop-for-innodb/dumps/default/SYS_INDEXES' REPLACE INTOTABLE `SYS_INDEXES` FIELDS TERMINATED BY '\t' OPTIONALLY ENCLOSED BY '"'LINES STARTING BY 'SYS_INDEXES\t' (`TABLE_ID`, `ID`, `NAME`, `N_FIELDS`,`TYPE`, `SPACE`, `PAGE_NO`);
-- Page id:11, Found records: 2, Lost records: YES, Leaf page: YES
可以看到索引ID分别是 26 和 27

创建建表的文件test6/a.sql 和 test6/b.sql
开始恢复数据。
./c_parser -6fpages-ibdata1/FIL_PAGE_INDEX/0000000000000027.page -t test6/b.sql -odumps/b.dmmp -l dumps/b.sql

./c_parser -6fpages-ibdata1/FIL_PAGE_INDEX/0000000000000027.page -t test6/b.sql -odumps/b.dmmp -l dumps/b.sql

导入数据到数据库中

mysql>create database test6;
Query OK, 1row affected (0.00 sec)

mysql> usetest6;
Databasechanged
mysql>source test6/a.sql
Query OK, 0rows affected (0.07 sec)

mysql>source test6/b.sql
Query OK, 0rows affected (0.06 sec)

mysql>source dumps/a.sql
Query OK, 0rows affected (0.00 sec)

Query OK,1081922 rows affected (6.18 sec)
Records:1081922Deleted: 0Skipped: 0 Warnings: 0

mysql>source dumps/b.sql
Query OK, 0rows affected (0.00 sec)

Query OK, 2rows affected (0.07 sec)
Records:2Deleted: 0Skipped: 0 Warnings: 0

数据恢复成功



测试场景3: Drop Database (innodb_file_per_table=ON Windows平台) 我考虑到了另外一种情况,如果是windows平台下删除了数据库,是否有办法通过这个软件来读取呢,我们可以试一下
创建数据库和测试表
查看下innodb_file_per_table的值:
mysql> show variables like 'inno%per%tab%';
+-----------------------+-------+
| Variable_name|Value |
+-----------------------+-------+
| innodb_file_per_table | ON|
+-----------------------+-------+
1 row in set (0.00 sec)

创建测试用的数据库 test_recover和表a1。
mysql> use test_recover;
Database changed
mysql> create table a1(a1 int,a2 int);
Query OK, 0 rows affected (0.40 sec)

mysql> insert into a1 values(1,2)
-> ;
Query OK, 1 row affected (0.11 sec)

mysql> insert into a1 values(3,4)
-> ;
Query OK, 1 row affected (0.08 sec)

mysql> commit;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from a1;
+------+------+
| a1| a2|
+------+------+
|1 |2 |
|3 |4 |
+------+------+
2 rows in set (0.00 sec)

查看下我们的数据在哪个盘:
mysql> show variables like 'datadir';
+---------------+-----------------------------+
| Variable_name | Value|
+---------------+-----------------------------+
| datadir|D:\MyTool\xampp\mysql\data\ |
+---------------+-----------------------------+
1 row in set (0.00 sec)

删除数据库



开始恢复数据
首先安装 Samba。
yum install samba

因为我默认的administrator帐号没有密码,所以在windows上创建了一个用户 admin密码是 admin.
测试下帐号:
[root@centos~]# smbclient -L 10.0.0.4 -U admin
Enter admin'spassword:
Domain=[ACTION-PC]OS=[Windows 7 Ultimate 7601 Service Pack 1] Server=[Windows 7 Ultimate 6.1]

SharenameTypeComment
--------------------
ADMIN$Disk远程管理
C$Disk默认共享
D$Disk默认共享
E$Disk默认共享
F$Disk默认共享
IPC$IPC远程 IPC
sessionrequest to 10.0.0.4 failed (Called name not present)
sessionrequest to 10 failed (Called name not present)
sessionrequest to *SMBSERVER failed (Called name not present)
NetBIOS overTCP disabled -- no workgroup available

创建 /d 目录,然后 将D盘挂载到本地的 /d 目录下
[root@centos~]# mount -t cifs -o username=admin,password=admin//10.0.0.4/d$ /d/


[root@centos~]# df -h
FilesystemSizeUsed Avail Use% Mounted on
/dev/mapper/vg_centos-lv_root
50G4.2G43G9% /
tmpfs499M0 499M0% /dev/shm
/dev/sda1477M36M 416M8% /boot
/dev/mapper/vg_centos-lv_home
47G52M45G1% /home
//10.0.0.4/d$101G89G12G89% /d

尝试去恢复数据:
[root@centosundrop-for-innodb]#./stream_parser -f//10.0.0.4/d$ -t 101g
Opening file://10.0.0.4/d$
Fileinformation:

Errno = 2,Error = No such file or directory
All workersfinished in 0 sec
换个参数:
[root@centosundrop-for-innodb]#./stream_parser -f/d/ -t 101g
Opening file:/d
Fileinformation:

ID of devicecontaining file:28
inodenumber:1407374883553285
protection:40755 (directory)
number of hardlinks:1
user ID ofowner:0
group ID ofowner:0
device ID (ifspecial file):0
blocksize forfilesystem I/O:16384
number ofblocks allocated:80
time of lastaccess:1449495079 MonDec7 21:31:19 2015
time of lastmodification:1449495079 MonDec7 21:31:19 2015
time of laststatus change:1449495079 MonDec7 21:31:19 2015
total size, inbytes:40960 (40.000 kiB)

Size toprocess:108447924224(101.000 GiB)
Worker(0):Failed to read from disk: Is a directory
All workersfinished in 0 sec

最终都失败了。看来没有办法读取windows下的分区来恢复数据,不知道如果把物理磁盘挂载到Linux下会不会有效果。

测试场景4:Drop Database (innodb_file_per_table=OFF Windows平台) 分区是无法读取了,但是文件或许可以,让我们再次测试下。
创建数据库和测试表
查看下innodb_file_per_table的值:
mysql> showvariables like 'inno%per%tab%';
+-----------------------+-------+
|Variable_name| Value |
+-----------------------+-------+
| innodb_file_per_table| OFF|
+-----------------------+-------+
1 row in set(0.00 sec)

创建测试用的数据库 test_recover2和表 a2。
mysql>create database test_recover2;
Query OK, 1row affected (0.00 sec)

mysql> use test_recover2;
Databasechanged
mysql>create table a2(a1 int,a2 int);
Query OK, 0rows affected (0.40 sec)

mysql>insert into a2 values(1,2)
-> ;
Query OK, 1row affected (0.06 sec)

mysql>insert into a2 values(3,4)
-> ;
Query OK, 1row affected (0.04 sec)

mysql>insert into a2 values(5,6);
Query OK, 1row affected (0.06 sec)

mysql>commit;
Query OK, 0rows affected (0.00 sec)

mysql>select * from a2;
+------+------+
| a1| a2|
+------+------+
|1 |2 |
|3 |4 |
|5 |6 |
+------+------+
3 rows in set(0.00 sec)

查看下我们的数据在哪个盘:
mysql> showvariables like 'datadir';
+---------------+-----------------------------+
|Variable_name | Value|
+---------------+-----------------------------+
| datadir| D:\MyTool\xampp\mysql\data\|
+---------------+-----------------------------+
1 row in set(0.00 sec)

删除数据库


开始恢复数据
将 D:\MyTool\xampp\mysql\data目录下的 ibdata1 文件上传到Linux服务器的/tmp目录下
开始恢复数据
[root@centosundrop-for-innodb]#./stream_parser -f/tmp/ibdata1
Opening file:/tmp/ibdata1
Fileinformation:

ID of devicecontaining file:64768
inodenumber:2753060
protection:100644 (regular file)
number of hardlinks:1
user ID ofowner:0
group ID ofowner:0
device ID (ifspecial file):0
blocksize forfilesystem I/O:4096
number ofblocks allocated:155648
time of lastaccess:1436277889 TueJul7 22:04:49 2015
time of lastmodification:1449498101 MonDec7 22:21:41 2015
time of laststatus change:1449498181 MonDec7 22:23:01 2015
total size, inbytes:79691776 (76.000 MiB)

Size toprocess:79691776(76.000 MiB)
All workersfinished in 0 sec

然后解析文件,获取表的信息:
[root@centosundrop-for-innodb]# ./c_parser -4Df./pages-ibdata1/FIL_PAGE_INDEX/0000000000000001.page-t ./dictionary/SYS_TABLES.sql-o ./dumps/SYS_TABLES.dmp-l ./dumps/SYS_TABLES.sql

[root@centosundrop-for-innodb]# cat ./dumps/SYS_TABLES.dmp | grep recover
000000055C0505000002181423SYS_TABLES"test\_recover/a1"128921080""1275
000000055C1914000002042D29SYS_TABLES"test\_recover2/a2"129021064""0
000000055C0505000002181423SYS_TABLES"test\_recover/a1"128921080""1275
000000055C1914000002042D29SYS_TABLES"test\_recover2/a2"129021064""0
这里我们发现了上一次测试场景里面的 test_recover.a1表的信息。我们这里可以一起尝试恢复下
test_recover.a11289
test_recover2.a21290

分别获取这2个表的索引信息:
[root@centosundrop-for-innodb]# ./c_parser -4Df ./pages-ibdata1/FIL_PAGE_INDEX/0000000000000003.page-t ./dictionary/SYS_INDEXES.sql | grep 1289
00000000CCD158000001FA2FC1SYS_INDEXES8411289"PRIMARY"138273
SETFOREIGN_KEY_CHECKS=0;

[root@centosundrop-for-innodb]# ./c_parser -4Df./pages-ibdata1/FIL_PAGE_INDEX/0000000000000003.page-t ./dictionary/SYS_INDEXES.sql | grep 1290
000000055C1914000002042C82SYS_INDEXES12901575"GEN\_CLUST\_INDEX"0104294967295
00000000CCD85C0000025C1EBBSYS_INDEXES8421290"PRIMARY"238283
000000055C1914000002042C82SYS_INDEXES12901575"GEN\_CLUST\_INDEX"0104294967295
SETFOREIGN_KEY_CHECKS=0;
LOAD DATALOCAL INFILE '/root/undrop-for-innodb/dumps/default/SYS_INDEXES' REPLACE INTOTABLE `SYS_INDEXES` FIELDS TERMINATED BY '\t' OPTIONALLY ENCLOSED BY '"'LINES STARTING BY 'SYS_INDEXES\t' (`TABLE_ID`, `ID`, `NAME`, `N_FIELDS`,`TYPE`, `SPACE`, `PAGE_NO`);

可以看到,只有1290找到了索引的ID是 1575 。test_recover.a1确实无法恢复了。

创建建表的文件test_recover2/a2.sql
开始恢复数据。
[root@centosundrop-for-innodb]# ./c_parser -6fpages-ibdata1/FIL_PAGE_INDEX/0000000000001575.page -t test_recover2/a2.sql -odumps/a2.dmmp -l dumps/a2.sql
[root@centosundrop-for-innodb]# cat dumps/a2.dmmp
-- Page id:336, Format: COMPACT, Records list: Valid, Expected records: (3 3)
000000003500000000055C118E000001410110a212
000000003501000000055C128F000002750110a234
000000003502000000055C1792000002760110a256
-- Page id:336, Found records: 3, Lost records: NO, Leaf page: YES
-- Page id:336, Format: COMPACT, Records list: Valid, Expected records: (3 3)
000000003500000000055C118E000001410110a212
000000003501000000055C128F000002750110a234
000000003502000000055C1792000002760110a256
-- Page id:336, Found records: 3, Lost records: NO, Leaf page: YES
[root@centosundrop-for-innodb]#

可以看到数据可以恢复。
剩下的步骤就都一样了,创建表,然后加载数据。

恢复数据总结 Linux 平台:都可以恢复。
Windows平台: 如果 innodb_file_per_table=OFF,则可以恢复,否则无法恢复。

恢复步骤:
  1. 用stream_parser 工具恢复数据。
如果 innodb_file_per_table=OFF, 所有数据在 ibdata1中,用下面的命令:
./stream_parser-f /var/lib/mysql/ibdata1
如果innodb_file_per_table=ON, 所有数据在数据目录下,用下面的命令:
./stream_parser -f /dev/mapper/vg_centos-lv_root -t 50g
需要用df查看到的逻辑卷的地址,并用-t 指定逻辑卷的大小。

运行完毕后,会在当前目录下生成一个pages-xxxxx 的目录。所有恢复出来的数据都在这个目录下。

  1. 用c_parser 来解析恢复出来的文件
  2. 0000000000000001.page 文件中是恢复出来的SYS_TABLES 的内容。
./c_parser -4Df ./pages-vg_centos-lv_root/FIL_PAGE_INDEX/0000000000000001.page -t ./dictionary/SYS_TABLES.sql-o ./dumps/SYS_TABLES.dmp-l ./dumps/SYS_TABLES.sql
查看SYS_TABLES.dmp ,找到需要恢复的表的ID。
  1. page 文件中是恢复出来的 SYS_INDEXS的内容。
./c_parser -4Df./pages-ibdata1/FIL_PAGE_INDEX/0000000000000003.page-t ./dictionary/SYS_INDEXES.sql
查看结果,筛选出所需要恢复表所对应的索引ID

  1. 恢复数据
找到000000[索引ID].page 文件,解析,前提是我们必须要有该表的建表语句
./c_parser -6f pages-ibdata1/FIL_PAGE_INDEX/0000000000000027.page -ttest6/b.sql -o dumps/b.dump -l dumps/b.sql
恢复出来的数据在.dump 文件中,运行 test6/b.sql 创建表(如果没有建表语句的话,可以通过其他方式获取,在别的文章里面会提到),然后运行dumps/b.sql 加载数据。


命令手册 C_Parser [root@centos undrop-for-innodb]# ./c_parser -h
Error: Usage: ./c_parser -4|-5|-6 [-dDV] -f -t table.sql [-T N:M] [-b ]
Where
-f -- InnoDB page or directory with pages(all pages shouldhave same index_id)
-t -- 将创建表的语句输出到table.sql 文件中
-o -- Save dump in this file. Otherwise print to stdout
-l -- Save SQL statements in this file. Otherwise print to stderr
-h-- Print this help
-d-- Process only those pages which potentiallycould have deleted records (default = NO)
-D-- 只恢复删除的数据(默认是No) (default = NO)
-U-- 只恢复没有删除的数据(默认是Yes) (default = YES)
-V-- Verbose mode (lots of debug information)
-4-- innodb_datafile is in REDUNDANT format
-5-- innodb_datafile is in COMPACT format
-6-- innodb_datafile is in MySQL 5.6 format
-T-- retrieves only pages with index id = NM (N- high word, M - low word of id)
-b -- Directory where external pages can be found. Usually it ispages-XXX/FIL_PAGE_TYPE_BLOB/
-i -- Read external pages at their offsets from .
-p prefix -- Use prefix for a directoryname in LOAD DATA INFILE command


遇到的错误 Could not create directory [root@centosundrop-for-innodb]# ./stream_parser -f /dev/mapper/vg_centos-lv_root -t 50g
Could notcreate directory pages-vg_centos-lv_root
【数据库|MySQL Drop Database之后的恢复测试】mkdir(): File exists
如果看到这个错误,是因为已经存在 pages-vg_centos-lv_root这个目录了,只要删除这个目录就可以了。

Failed to parse tablestructure [root@centos undrop-for-innodb]# ./c_parser -6fpages-ibdata1/FIL_PAGE_INDEX/0000000000000026.page -t test6/a.sql -odumps/a.dmmp -l dumps/a.sql
Line 2: syntax error at ''
1: create tablea(id int)

2:
Failed to parse table structure

这个错误是因为最后少了一个分号


转载于:https://blog.51cto.com/action825/1726615

    推荐阅读