longpan 发表于 2018-10-1 08:14:53

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已经删除了这个文件。
安装恢复软件

[*]  首先安装软件所需要的包:makegcc flexbison git
  # yum install makegccflex bison git

[*]  下载代码
  # 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.
  # ls
  anaconda-ks.cfg    MySQL-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.log      MySQL-client-5.6.27-1.el6.x86_64.rpm   MySQL-server-5.6.27-1.el6.x86_64.rpm   MySQL-test-5.6.27-1.el6.x86_64.rpm
  install.log.syslogMySQL-devel-5.6.27-1.el6.x86_64.rpm      MySQL-shared-5.6.27-1.el6.x86_64.rpm   undrop-for-innodb
  3.编译代码
  # cd undrop-for-innodb/
  # ls
  check_data.cdictionary    include         LICENSE   print_data.c recover_dictionary.sh sql_parser.lstream_parser.ctables_dict.c
  c_parser.c    fetch_data.shinnochecksum.cMakefile README.md   sakila               sql_parser.ysys_parser.c   test.sh
  # 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)
创建数据库和测试表
  我们先来看下创建好的数据库,有多少个文件。
  #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)
  我们来看下数据文件多了哪些。
  # ls
  auto.cnfcentos.err centos.pidibdata1ib_logfile0 ib_logfile1mysqlmysql.sock performance_schema RPM_UPGRADE_HISTORY RPM_UPGRADE_MARKER-LASTtesttest1
  多了一个test1的目录。进入目录看下
  # cd test1
  # 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中。
  我们来看下数据文件的大小:
  # du -sh *
  4.0K    db.opt
  12K   test1.frm
  72M   test1.ibd
  # du -sh *
  4.0K    auto.cnf
  4.0K    centos.err
  4.0K    centos.pid
  76M   ibdata1
  49M   ib_logfile0
  48M   ib_logfile1
  1.7M    mysql
  0       mysql.sock
  636K    performance_schema
  4.0K    RPM_UPGRADE_HISTORY
  4.0K    RPM_UPGRADE_MARKER-LAST
  4.0K    test
  8.0K    test2
  发现 test1.ibd和ibdata1 都增长的很厉害,不知道为什么,这个之后再研究。
  接下来删除数据库test1
  drop databasetest1.
开始恢复数据
  注意这里 -f 后面的参数是 裸盘 的地址,如果你不知道可以用 df -h 查看.
  -t 是这个磁盘的大小。
  # df -h /var/lib/mysql

  Filesystem         >  /dev/mapper/vg_centos-lv_root
  50G4.1G43G   9% /
  #./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>
  group>
  device>  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 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
http://blog.51cto.com/e/u261/themes/default/images/spacer.gif
  这里说明一下:
  0000000000000001.page:恢复出来的 SYS_TABLES 表
  0000000000000003.page:恢复出来的 SYS_INDEXES 表
  创建存放恢复出来的文件的目录
  #mkdir -p dictionary dumps/default
  # ./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,可以看到我们删除掉的数据
http://blog.51cto.com/e/u261/themes/default/images/spacer.gif
  因为我们在test1数据库中只有1个test1表。所以这里只能看到一个 test1。
  可以看到 table_id 是 20。
  接下来我们看下索引的信息
http://blog.51cto.com/e/u261/themes/default/images/spacer.gif
  可以看到,索引的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文件
  # pwd
  /var/lib/mysql/test6
  # ls
  a.frmb.frm db.opt
  反复执行 Insert into aselect * from a; 直到有足够大的数据。
  # du -sh ibdata1
  76M   ibdata1
  Ibdata1增长到了76M
  删除数据库 test6
  mysql> dropdatabase test6;
  Query OK, 2rows affected (0.26 sec)
开始恢复数据
  因为数据在ibdata1文件中,所以我们分析ibdata1文件
  # ./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>
  group>
  device>  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 toprocess:                  79691776(76.000 MiB)
  All workersfinished in 0 sec
  剩下的步骤和之前的一样,首先获取到 我们删除掉的test6的数据库里面的表,从结果里面可以看到是 a 和b 。ID 分别是 24 和 25。
  # ./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
  # cat ./dumps/SYS_TABLES.dmp

  -- Page>  000000000F6A    55000008010182SYS_TABLES      "test6/a"       24   1       1       0      64      ""      0
  000000000F64    52000008060182SYS_TABLES      "test6/b"       25   1       1       0      64      ""      0
  获取表中的索引信息
  # ./c_parser -4Df./pages-ibdata1/FIL_PAGE_INDEX/0000000000000003.page-t ./dictionary/SYS_INDEXES.sql

  -- Page>  000000000F6A    55000008010110SYS_INDEXES   24   26      "GEN\_CLUST\_INDEX"   0      1       0       4294967295
  000000000F64    52000008060110SYS_INDEXES   25   27      "GEN\_CLUST\_INDEX"   0      1       0       4294967295

  -- Page>
  -- Page>  000000000F6A    55000008010110SYS_INDEXES   24   26      "GEN\_CLUST\_INDEX"   0      1       0       4294967295
  000000000F64    52000008060110SYS_INDEXES   25   27      "GEN\_CLUST\_INDEX"   0      1       0       4294967295
  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分别是 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)
  删除数据库
http://blog.51cto.com/e/u261/themes/default/images/spacer.gif
开始恢复数据
  首先安装 Samba。
  yum install samba
  因为我默认的administrator帐号没有密码,所以在windows上创建了一个用户 admin密码是 admin.
  测试下帐号:
  # smbclient -L 10.0.0.4 -U admin
  Enter admin'spassword:
  Domain=OS= Server=
  Sharename       Type   Comment
  ---------       ----   -------
  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 目录下
  # mount -t cifs -o username=admin,password=admin   //10.0.0.4/d$ /d/
  # df -h

  Filesystem         >  /dev/mapper/vg_centos-lv_root
  50G4.2G43G   9% /
  tmpfs               499M   0 499M   0% /dev/shm
  /dev/sda1             477M   36M 416M   8% /boot
  /dev/mapper/vg_centos-lv_home
  47G   52M45G   1% /home
  //10.0.0.4/d$         101G89G   12G89% /d
  尝试去恢复数据:
  #./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
  换个参数:
  #./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>
  group>
  device>  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 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)
  删除数据库
http://blog.51cto.com/e/u261/themes/default/images/spacer.gif
开始恢复数据
  将 D:\MyTool\xampp\mysql\data目录下的 ibdata1 文件上传到Linux服务器的/tmp目录下
  开始恢复数据
  #./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>
  group>
  device>  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 toprocess:                  79691776(76.000 MiB)
  All workersfinished in 0 sec
  然后解析文件,获取表的信息:
  # ./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
  # cat ./dumps/SYS_TABLES.dmp | grep recover
  000000055C05    05000002181423SYS_TABLES      "test\_recover/a1"      1289   2       1       0      80      ""      1275
  000000055C19    14000002042D29SYS_TABLES      "test\_recover2/a2"   1290   2       1       0      64      ""      0
  000000055C05    05000002181423SYS_TABLES      "test\_recover/a1"      1289   2       1       0      80      ""      1275
  000000055C19    14000002042D29SYS_TABLES      "test\_recover2/a2"   1290   2       1       0      64      ""      0
  这里我们发现了上一次测试场景里面的 test_recover.a1表的信息。我们这里可以一起尝试恢复下
  test_recover.a11289
  test_recover2.a21290
  分别获取这2个表的索引信息:
  # ./c_parser -4Df ./pages-ibdata1/FIL_PAGE_INDEX/0000000000000003.page-t ./dictionary/SYS_INDEXES.sql | grep 1289
  00000000CCD1    58000001FA2FC1SYS_INDEXES   841    1289    "PRIMARY"       1      3       827   3
  SETFOREIGN_KEY_CHECKS=0;
  # ./c_parser -4Df./pages-ibdata1/FIL_PAGE_INDEX/0000000000000003.page-t ./dictionary/SYS_INDEXES.sql | grep 1290
  000000055C19    14000002042C82SYS_INDEXES   1290    1575    "GEN\_CLUST\_INDEX"   0      1       0       4294967295
  00000000CCD8    5C0000025C1EBBSYS_INDEXES   842    1290    "PRIMARY"       2      3       828   3
  000000055C19    14000002042C82SYS_INDEXES   1290   1575    "GEN\_CLUST\_INDEX"   0      1       0       4294967295
  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
  开始恢复数据。
  # ./c_parser -6fpages-ibdata1/FIL_PAGE_INDEX/0000000000001575.page -t test_recover2/a2.sql -odumps/a2.dmmp -l dumps/a2.sql
  # cat dumps/a2.dmmp

  -- Page>  000000003500    000000055C11    8E000001410110a2   1       2
  000000003501    000000055C12    8F000002750110a2   3       4
  000000003502    000000055C17    92000002760110a2   5       6

  -- Page>
  -- Page>  000000003500    000000055C11    8E000001410110a2   1       2
  000000003501    000000055C12    8F000002750110a2   3       4
  000000003502    000000055C17    92000002760110a2   5       6

  -- Page>  #
  可以看到数据可以恢复。
  剩下的步骤就都一样了,创建表,然后加载数据。
恢复数据总结
  Linux 平台:都可以恢复。
  Windows平台: 如果 innodb_file_per_table=OFF,则可以恢复,否则无法恢复。
  恢复步骤:

[*]  用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 的目录。所有恢复出来的数据都在这个目录下。

[*]  用c_parser 来解析恢复出来的文件
[*]  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。

[*]  page 文件中是恢复出来的 SYS_INDEXS的内容。
  ./c_parser -4Df./pages-ibdata1/FIL_PAGE_INDEX/0000000000000003.page-t ./dictionary/SYS_INDEXES.sql
  查看结果,筛选出所需要恢复表所对应的索引ID

[*]  恢复数据
  找到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
  # ./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>  -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
  # ./stream_parser -f /dev/mapper/vg_centos-lv_root -t 50g
  Could notcreate directory pages-vg_centos-lv_root
  mkdir(): File exists
  如果看到这个错误,是因为已经存在 pages-vg_centos-lv_root这个目录了,只要删除这个目录就可以了。
Failed to parse tablestructure
  # ./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
  这个错误是因为最后少了一个分号


页: [1]
查看完整版本: MySQL Drop Database之后的恢复测试