【MySQL】Innodb 恢复工具介绍

      在和数据打交道的过程中,总会遇到误删除数据的情况,在没有备份和binlog的情况下,如何恢复呢?本文介绍一个工具Percona Data Recovery Tool for InnoDB 

使用 该工具的 注意事项:

1 The tools work only for InnoDB/XtraDB tables, and will not work with MyISAM tables. Percona does have a preliminary set of tools for MyISAM data recovery;  

2 The tools work on a saved copy of your data files, not on the running MySQL server.

3 There is no guarantee. Even with these tools, data is sometimes unrecoverable. For example, data that is overwritten cannot be recovered with these tools. There may be file system specific or physical means to recover overwritten data.

如果数据被覆盖,则使用该工具无法恢复。必须使用系统或者物理方法来恢复

4 Time is of the essence. The best chance for recovery comes when you act immediately to save a copy of your raw data files as soon as you discover the loss or corruption.

  当发生误删除数据时必须立即备份表文件以便确保数据被覆盖或者损坏。

5 There is manual work to do. Not everything is automatic.

6 Recovery depends on knowing your data. As part of the process you may have to choose between two versions of your data. The better you know your data, the better the chance you'll be able to recover it.

需要理解的是innodb-tools工具不是通过连接到在线的database进行数据恢复,而是通过离线拷贝数据的方式进行的。

注意:不要在MySQL运行的时候,直接拷贝InnoDB文件,这样是不安全的,会影响数据恢复过程。不过这点我做了测试,在数据库运行的时候是可以进行数据库恢复的。

    

一 安装

 进入解压后根目录下的mysql-source目录,运行配置命令,不运行make命令

 wget https://launchpad.net/percona-data-recovery-tool-for-innodb/trunk/release-0.5/+download/percona-data-recovery-tool-for-innodb-0.5.tar.gz

 cd percona-data-recovery-tool-for-innodb-0.5/mysql_source/

 ./configure

 cd ..

 make 

编译生成page_parser和constraints_parser工具 

注意create_defs.pl脚本需要依赖DBD,DBI,安装过程中可能会遇到错误。

二 模拟误删除数据

root@127.0.0.1 : test 22:12:22> delete from mac where id
Query OK, 4999 rows affected (0.62 sec)

root@127.0.0.1 : test 22:12:29> 

三  获取数据页

InnoDB页的默认大小是16K,innodb的page分为两大部分,一部分一级索引部分,另一部分为二级索引部分。page_parser工具通过读取数据文件,根据页头中的index ID,拷贝每个页到一个单独的文件中。

如果你的my.cnf配置了innodb_file_per_table=1,那么系统已经帮你实现上述过程。所有需要的页都在单独的.ibd文件,而且通常你不需要再切分它

如果.ibd文件中可能包含多个index,那么将页单独切分开还是有必要的。如果MySQL server没有配置innodb_file_per_table,那么数据会被保存在一个全局的表命名空间,这时候就需要按页对文件进行切分。 

[root@rac1 recovery-tool]# ./page_parser  -5 -f /opt/mysql/data/test/mac.ibd   

-5:代表 row format为Compact

-f:代表要解析的文件

输出信息:       

Opening file: /opt/mysql/data/test/mac.ibd:

2051            ID of device containing file

20283635                inode number

33200           protection

1               number of hard links

103             user ID of owner

106             group ID of owner

0               device ID (if special file)

11534336                total size, in bytes

4096            blocksize for filesystem I/O

22560           number of blocks allocated

1377958353      time of last access

1377958359      time of last modification

1377958359      time of last status change

11534336        Size to process in bytes

104857600       Disk cache size in bytes

[root@rac1 recovery-tool]# less pages-1377958391/FIL_PAGE_INDEX/0-205

0-2057/ 0-2058/ 0-2059/ 

以上三个为索引文件 0-2057/主键,0-2058/ 0-2059/ 二级索引。可以安装开启innodb_table_monitor获取。

四 获取表结构的定义

 

 ./create_defs.pl  --host 127.0.0.1 --user root --port 3306 --db test --table mac > include/table_defs.h  

[root@rac1 recovery-tool]# more include/table_defs.h

#ifndef table_defs_h

#define table_defs_h

// Table definitions

table_def_t table_definitions[] = {

        {

                name: "mac",

                {

                        { /* int(10) unsigned */

                                name: "id",

                                type: FT_UINT,

                                fixed_length: 4,

                                has_limits: FALSE,

                                limits: {

                                        can_be_null: FALSE,

                                        uint_min_val: 0,

                                        uint_max_val: 4294967295ULL

                                },

                                can_be_null: FALSE

                        },

                        { /*  */

                                name: "DB_TRX_ID",

                                type: FT_INTERNAL,

                                fixed_length: 6,

                                can_be_null: FALSE

                        },

                        { /*  */

                                name: "DB_ROLL_PTR",

                                type: FT_INTERNAL,

                                fixed_length: 7,

                                can_be_null: FALSE

                        },

                        { /* varchar(50) */

                                name: "mac",

                                type: FT_CHAR,

                                min_length: 0,

                                max_length: 150,

                                has_limits: FALSE,

                                limits: {

                                        can_be_null: FALSE,

                                        char_min_len: 0,

                                        char_max_len: 150,

                                        char_ascii_only: TRUE

                                },

                                can_be_null: FALSE

                        },

                        { /* varchar(50) */

                                name: "name",

                                type: FT_CHAR,

                                min_length: 0,

                                max_length: 150,

                                has_limits: FALSE,

                                limits: {

                                        can_be_null: TRUE,

                                        char_min_len: 0,

                                        char_max_len: 150,

                                        char_ascii_only: TRUE

                                },

                                can_be_null: TRUE

                        },

                        { /* tinyint(4) */

                                name: "scope",

                                type: FT_INT,

                                fixed_length: 1,

                                has_limits: FALSE,

                                limits: {

                                        can_be_null: TRUE,

                                        int_min_val: -128,

                                        int_max_val: 127

                                },

                                can_be_null: TRUE

                        },

                        { /* datetime */

                                name: "gmt_create",

                                type: FT_DATETIME,

                                fixed_length: 8,

                                can_be_null: FALSE

                        },

                        { /* datetime */

                                name: "gmt_modify",

                                type: FT_DATETIME,

                                fixed_length: 8,

                                can_be_null: FALSE

                        },

                        { type: FT_NONE }

                }

        },

};

#endif

五 根据include/table_defs.h,重新编译constraints_parser工具:

[root@rac1 recovery-tool]# make

gcc -DHAVE_OFFSET64_T -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE=1 -D_LARGEFILE_SOURCE=1 -Wall -O3 -g -I include -I mysql-source/include -I mysql-source/innobase/include -c tables_dict.c -o lib/tables_dict.o

gcc -DHAVE_OFFSET64_T -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE=1 -D_LARGEFILE_SOURCE=1 -Wall -O3 -g -I include -I mysql-source/include -I mysql-source/innobase/include -c check_data.c -o lib/check_data.o

gcc -DHAVE_OFFSET64_T -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE=1 -D_LARGEFILE_SOURCE=1 -Wall -O3 -g -I include -I mysql-source/include -I mysql-source/innobase/include -o constraints_parser constraints_parser.c lib/tables_dict.o lib/print_data.o lib/check_data.o lib/libut.a lib/libmystrings.a

gcc -DHAVE_OFFSET64_T -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE=1 -D_LARGEFILE_SOURCE=1 -Wall -O3 -g -I include -I mysql-source/include -I mysql-source/innobase/include -static -lrt -o page_parser page_parser.c lib/tables_dict.o lib/libut.a 

恢复误删除的数据:

./constraints_parser -D -5 -f pages-1377958391/FIL_PAGE_INDEX/0-2057/ > /tmp/mac.rec

LOAD DATA INFILE '/root/recovery-tool/dumps/default/mac' REPLACE INTO TABLE `mac` FIELDS TERMINATED BY '\t' OPTIONALLY ENCLOSED BY '"' LINES STARTING BY 'mac\t' (id, mac, name, scope, gmt_create, gmt_modify);

执行 constraints_parser 命令会生成上午load data 的命令,在数据库中执行上述命令即可.

root@127.0.0.1 : test 22:20:54> select count(1) from mac;

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

| count(1) |

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

|     9973 |

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

1 row in set (0.00 sec)

root@127.0.0.1 : test 22:21:09> LOAD DATA INFILE '/tmp/mac.rec' REPLACE INTO TABLE `mac` FIELDS TERMINATED BY '\t' OPTIONALLY ENCLOSED BY '"' LINES STARTING BY 'mac\t' (id, mac, name, scope, gmt_create, gmt_modify);

Query OK, 4999 rows affected (0.22 sec)

Records: 4999  Deleted: 0  Skipped: 0  Warnings: 0

root@127.0.0.1 : test 22:21:13> select count(1) from mac;

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

| count(1) |

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

|    14972 |

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

1 row in set (0.00 sec)

root@127.0.0.1 : test 22:21:18> exit

总结

 1 整个恢复过程并不顺利,Percona 依赖于perl,在安装的时候遇到DBD安装不了的问题。

 2 可以恢复delete的数据,如果执行truncate table 是恢复失败的,drop的时候ibd文件丢同样没有文件来获取数据页而无法进行恢复。

  对于truncate的测试例子大家可以手动测试一下。

  

参考文章

http://www.mysqlperformanceblog.com/2012/02/20/how-to-recover-deleted-rows-from-an-innodb-tablespace/

http://www.percona.com/docs/wiki/innodb-data-recovery-tool:mysql-data-recovery:starthttp://www.orczhou.com/index.php/2013/07/how-to-recover-data-from-mysql-innodb-data-file-ibd-file/

阅读(12327) | 评论(1) | 转发(1) |

2

上一篇:【Python】转换mysql 结果集为词典类型

下一篇:【MySQL】online ddl 工具之pt-online-schema-change

时间: 2024-10-28 18:14:58

【MySQL】Innodb 恢复工具介绍的相关文章

MySQL/InnoDB和Group Commit(2)

今天发现Percona Release的Percona-Server-5-5-18-23-0已经完成了Group Commit工作,而且是用最优雅的方式(移植了MariaDB的实现,而不是workaround),心里难掩激动. 这篇文章接前篇继续介绍一下问题的背景:什么是Group Commit,现在的官方版本Group Commit做到了什么程度? 1. 什么是Group Commit MySQL/InnoDB在做事务的时候使用的日志先行(Write-ahead logging)的方式保证事务

MySQL InnoDB 共享表空间和独立表空间

MySQL  InnoDB 共享表空间和独立表空间 官网:https://dev.mysql.com/doc/refman/5.6/en/innodb-multiple-tablespaces.html 前言:学习mysql的时候总是习惯性的和oracle数据库进行比较.在学习mysql InnoDB的存储结构的时候也免不了跟oracle进行比较.Oracle的数据存储有表空间.段.区.块.数据文件:mysql InnoDB的存储管理也类似,但是mysql增加了一个共享表空间和独立表空间的概念:

MySQL默认数据库介绍

MySQL默认数据库介绍 大家在学习MySQL时,安装后都会发现里边已经自带了几个默认的数据库,我装的MySQL5.5里边自带六个数据库 网上查了一些资料对这几个数据库的功能做一下学习. 1.information_schema 这个库中有很多的表 information_schema数据库表说明: SCHEMATA表:提供了当前mysql实例中所有数据库的信息.是show databases的结果取之此表. TABLES表:提供了关于数据库中的表的信息(包括视图).详细表述了某个表属于哪个sc

Mysql 优化详细介绍

Mysql 优化详细介绍 MySQL 提供了很多参数进行服务器的设置, MySQL 在安装的时候提供几个默认的参数文件供选择,分别是: my-small.cnf . my-medium.cnf . my-large.cnf . my-huge.cnf . my-innodb-heavy-4G.cnf ,从文件名我们可以看出该配置文件适合的应用规模.通常情况下,我们可以选择使用接近自己的系统规模的配置文件,但是系统默认的参数在不同的生产环境可能不能完全满足实际的应用需求,我们可以再按照实际情况对部

反驳"MySQL InnoDB (不行)的性能问题",千万级别记录来测试说明

在 JavaEye 上看到一篇对 MySQL FUD(Fear, uncertainty and doubt) 的文章 用MySQL InnoDB Benchmark 性能测试来说明 http://www.javaeye.com/topic/34676 文中提到:"InnoDB 的磁盘性能很令人担心,MySQL 缺乏良好的 tablespace 真是天大的缺陷! --网上有用户反映存在同样的插入性能问题,百万行记录插入之后,插入速度下降到了 1/30,从开始的 1600行/秒衰退到 50行/秒-

巧用MySQL InnoDB引擎锁机制解决死锁问题

最近,在项目开发过程中,碰到了数据库死锁问题,在解决问题的过程中,笔者对MySQL InnoDB引擎锁机制的理解逐步加深. 案例如下: 在使用Show innodb status检查引擎状态时,发现了死锁问题: *** (1) TRANSACTION: TRANSACTION 0 677833455, ACTIVE 0 sec, process no 11393, OS thread id 278546 starting index read mysql tables in use 1, loc

MySQL Semisynchronous Replication介绍

  这篇文章主要介绍了MySQL Semisynchronous Replication介绍,本文讲解了Semisynchronous Replication 定义.,需要的朋友可以参考下 前言 MySQL 5.5版本之前默认的复制是异步(Asynchronous )模式的, MySQL 5.5 以plugins的方式提供了Semisynchronous Replication 模式.在介绍 semi sync 之前,我们先了解:半同步 Asynchronous 和 同步 Synchronous

MySQL Innodb数据库性能实践——热点数据性能

对于大部分的应用来说,都存在热点数据的访问,即:某些数据在一定时间内的访问频率要远远高于其它数据. 常见的热点数据有"最新的新闻"."最热门的新闻"."下载量最大"的电影等. 为了了解MySQL Innodb对热点数据的支持情况,我进行了基准测试,测试环境如下: [硬件配置] 硬件 配置 CPU Intel(R) Xeon(R) CPU E5620 主频2.40GHz, 物理CPU 2个,逻辑CPU 16个 内存 24G(6块 * 4G  DDR

RDS for MySQL InnoDB 行锁等待和锁等待超时的处理

RDS for MySQL InnoDB 行锁等待和锁等待超时的处理   1. InnoDB 引擎表行锁等待和等待超时发生的场景 2.InnoDB 引擎行锁等待情况的处理 2.1 InnoDB 行锁等待超时参数 innodb_lock_wait_timeout 2.2 大量行锁等待和行锁等待超时的处理 1. InnoDB 引擎表行锁等待和等待超时发生的场景 当一个 RDS for MySQL 连接会话等待另外一个会话持有的互斥行锁时,会发生 InnoDB 引擎表行锁等待情况. 通常情况下,持有该