DROP TABLE 恢复【一】
当DROP TABLE指令敲下的时候,你很爽,你有考虑过后果么?如果该表真的没用,你DROP到无所谓,如果还有用的,这时你肯定吓惨了吧,如果你有备份,那么恭喜你,逃过一劫,如果没有备份呢?这时就该绝望了?NO! 如果你的表是innodb表,那么还有希望挽救,如果是myisam表,那么真的没救了。前面文章介绍了 Recover InnoDB dictionary,这是恢复数据的前提。恢复innodb字典信息使用的是TwinDB recovery toolkit,我们恢复数据也是使用该工具。下面的案例是基于innodb_file_per_table=OFF的前提下,即使用共享表空间,所有的信息都保存在ibdata1中。使用独立表空间DROP TABLE后数据恢复将在后面的文章介绍。
错误的操作--删除表
用到的示例数据库还是sakila,关于下载地址前面的文章有地址。将模拟把sakila库中的actor表删除后进行恢复。
root@localhost : sakila 21:34:11> SELECT * FROM actor LIMIT 10;
+----------+------------+--------------+---------------------+
| actor_id | first_name | last_name | last_update |
+----------+------------+--------------+---------------------+
| 1 | PENELOPE | GUINESS | 2006-02-15 04:34:33 |
| 2 | NICK | WAHLBERG | 2006-02-15 04:34:33 |
| 3 | ED | CHASE | 2006-02-15 04:34:33 |
| 4 | JENNIFER | DAVIS | 2006-02-15 04:34:33 |
| 5 | JOHNNY | LOLLOBRIGIDA | 2006-02-15 04:34:33 |
| 6 | BETTE | NICHOLSON | 2006-02-15 04:34:33 |
| 7 | GRACE | MOSTEL | 2006-02-15 04:34:33 |
| 8 | MATTHEW | JOHANSSON | 2006-02-15 04:34:33 |
| 9 | JOE | SWANK | 2006-02-15 04:34:33 |
| 10 | CHRISTIAN | GABLE | 2006-02-15 04:34:33 |
+----------+------------+--------------+---------------------+
10 rows in set (0.01 sec) root@localhost : sakila 21:34:25>
root@localhost : sakila 21:34:25> CHECKSUM TABLE actor;
+--------------+------------+
| Table | Checksum |
+--------------+------------+
| sakila.actor | 2472295518 |
+--------------+------------+
1 row in set (0.07 sec) root@localhost : sakila 21:35:30> SET foreign_key_checks=OFF;
Query OK, 0 rows affected (0.00 sec) root@localhost : sakila 21:35:46> DROP TABLE actor;
Query OK, 0 rows affected (0.07 sec) root@localhost : sakila 21:35:57>
从ibdata1恢复数据
现在actor表已经删除,但表中的信息仍然存与ibdata1中。该数据保持不变,直到InnoDB的重用空闲的页。我们需要尽快停止mysqld进程。
对于恢复,我们将使用TwinDB恢复工具包。看看我前面的文章Recover InnoDB dictionary。
解析innodb表空间(ibdata1)
InnoDB将所有数据存储在B +树索引。 一个表有只有一个聚集索引,所有字段存储在这里。 如果表有辅助索引,由index_id标识每个索引。
如果我们要恢复一个表,我们必须找到属于特定index_id的所有页面。
stream_parser读取InnoDB表和排序按类型和每个index_id的InnoDB的页面。
[root@mysql-server- undrop-for-innodb]# ./stream_parser -f /data/mysql/user_3306/data/ibdata1
Opening file: /data/mysql/user_3306/data/ibdata1
File information: ID of device containing file:
inode number:
protection: (regular file)
number of hard links:
user ID of owner:
group ID of owner:
device ID (if special file):
blocksize for filesystem I/O:
number of blocks allocated:
time of last access: Sun Aug ::
time of last modification: Sun Aug ::
time of last status change: Sun Aug ::
total size, in bytes: (26.000 MiB) Size to process: (26.000 MiB)
All workers finished in sec
[root@mysql-server- undrop-for-innodb]#
使用stream_parser将把数据从page保存到pages-ibdata1
[root@mysql-server- FIL_PAGE_INDEX]# pwd
/root/undrop-for-innodb/pages-ibdata1/FIL_PAGE_INDEX
[root@mysql-server- FIL_PAGE_INDEX]# ll
total
-rw-r--r-- root root Aug : .page
-rw-r--r-- root root Aug : .page
-rw-r--r-- root root Aug : .page
-rw-r--r-- root root Aug : .page
-rw-r--r-- root root Aug : .page
。。。。。。。。。。。。。。。。。。。。。。。。。
-rw-r--r-- root root Aug : .page
-rw-r--r-- root root Aug : .page
-rw-r--r-- root root Aug : .page
-rw-r--r-- root root Aug : .page
-rw-r--r-- root root Aug : .page
-rw-r--r-- root root Aug : .page
-rw-r--r-- root root Aug : .page
现在InnoDB表空间的每个index_id被保存在一个单独的文件。我们可以用c_parser工具从page提取记录。但是,我们需要知道哪个index_id对应表Sakila/actor。这些信息,我们可以从字典中获取:SYS_TABLES和SYS_INDEXES。
SYS_TABLES始终存储在文件index_id为1的page,ibdata1/FIL_PAGE_INDEX/0000000000000001.page 这让我们找到Sakila/actor表的标识符。如果MySQL有足够的时间来刷新到磁盘的变化再加入D选项,意思是“寻找被删除的记录“,innodb字典信息永远是冗余格式,所以我们需要指定选项-4。
[root@mysql-server- undrop-for-innodb]# ./c_parser -4Df pages-ibdata1/FIL_PAGE_INDEX/.page -t dictionary/SYS_TABLES.sql | grep sakila/actor
45000002B902C8 SYS_TABLES "sakila/actor" ""
45000002B902C8 SYS_TABLES "sakila/actor" ""
SET FOREIGN_KEY_CHECKS=;
LOAD DATA LOCAL INFILE '/root/undrop-for-innodb/dumps/default/SYS_TABLES' REPLACE INTO TABLE `SYS_TABLES` FIELDS TERMINATED BY '\t' OPTIONALLY ENCLOSED BY '"' LINES STARTING BY 'SYS_TABLES\t' (`NAME`, `ID`, `N_COLS`, `TYPE`, `MIX_ID`, `MIX_LEN`, `CLUSTER_NAME`, `SPACE`);
[root@mysql-server- undrop-for-innodb]#
注意表名之后的数13。这是表标识符。这和前面的文章不谋而合,Recover InnoDB dictionary
接下来的事情,需要做的是找到actor表的的主键ID。为此,我们将从SYS_INDEXES文件0000000000000003.page获取记录(该表将包含有关index_id和表标识符信息)。 SYS_INDEXES的结构需要通过-t选项解析。
[root@mysql-server- undrop-for-innodb]# ./c_parser -4Df pages-ibdata1/FIL_PAGE_INDEX/.page -t dictionary/SYS_INDEXES.sql | grep
45000002B90145 SYS_INDEXES "PRIMARY"
45000002B901B7 SYS_INDEXES "idx\_actor\_last\_name"
45000002B90145 SYS_INDEXES "PRIMARY"
45000002B901B7 SYS_INDEXES "idx\_actor\_last\_name"
45000002B90145 SYS_INDEXES "PRIMARY"
45000002B901B7 SYS_INDEXES "idx\_actor\_last\_name"
SET FOREIGN_KEY_CHECKS=;
LOAD DATA LOCAL INFILE '/root/undrop-for-innodb/dumps/default/SYS_INDEXES' REPLACE INTO TABLE `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`);
[root@mysql-server- undrop-for-innodb]#
我们可以从输出看到,PRIMARY index_id标示符是15。因此,我们的数据将从0000000000000015.page寻找。
[root@mysql-server- undrop-for-innodb]# ./c_parser -6f pages-ibdata1/FIL_PAGE_INDEX/.page -t sakila/actor.sql | head -
-- Page id: , Format: COMPACT, Records list: Valid, Expected records: ( )
00000000032C AD000001750110 actor "PENELOPE" "GUINESS" "2006-02-15 04:34:33"
00000000032C AD00000175011A actor "NICK" "WAHLBERG" "2006-02-15 04:34:33"
00000000032C AD000001750124 actor "ED" "CHASE" "2006-02-15 04:34:33"
00000000032C AD00000175012E actor "JENNIFER" "DAVIS" "2006-02-15 04:34:33"
00000000032C AD000001750138 actor "JOHNNY" "LOLLOBRIGIDA" "2006-02-15 04:34:33"
00000000032C AD000001750142 actor "BETTE" "NICHOLSON" "2006-02-15 04:34:33"
00000000032C AD00000175014C actor "GRACE" "MOSTEL" "2006-02-15 04:34:33"
00000000032C AD000001750156 actor "MATTHEW" "JOHANSSON" "2006-02-15 04:34:33"
00000000032C AD000001750160 actor "JOE" "SWANK" "2006-02-15 04:34:33"
[root@mysql-server- undrop-for-innodb]#
看见上面的输出,是不是觉得希望来了?哈哈
上面的结果正是我们想要的,我们现在把数据存贮在文件中,然后倒入,创建dump/default目录存储数据。
[root@mysql-server- undrop-for-innodb]# mkdir -p dumps/default
[root@mysql-server- undrop-for-innodb]#
[root@mysql-server- undrop-for-innodb]# ./c_parser -6f pages-ibdata1/FIL_PAGE_INDEX/.page -t sakila/actor.sql > dumps/default/actor > dumps/default/actor_load.sql
[root@mysql-server- undrop-for-innodb]#
我们看看一个文件,其实是命令加载表而已
[root@mysql-server- undrop-for-innodb]# cat dumps/default/actor_load.sql
SET FOREIGN_KEY_CHECKS=;
LOAD DATA LOCAL INFILE '/root/undrop-for-innodb/dumps/default/actor' REPLACE INTO TABLE `actor` FIELDS TERMINATED BY '\t' OPTIONALLY ENCLOSED BY '"' LINES STARTING BY 'actor\t' (`actor_id`, `first_name`, `last_name`, `last_update`);
[root@mysql-server- undrop-for-innodb]#
将数据load回数据库中
现在将数据恢复到数据库中。但是,在导入数据以前,我们需要创建表actor(前提我们要有表结构备份,如果没有只有使用另外的工具找到表结构Percona Data Recovery Tool)看来还是需要两个工具结合使用啊。
root@localhost : sakila 23:03:50> source sakila/actor.sql
root@localhost : sakila 23:03:50> show create table actor\G
*************************** 1. row ***************************
Table: actor
Create Table: CREATE TABLE `actor` (
`actor_id` smallint(5) unsigned NOT NULL AUTO_INCREMENT,
`first_name` varchar(45) NOT NULL,
`last_name` varchar(45) NOT NULL,
`last_update` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`actor_id`),
KEY `idx_actor_last_name` (`last_name`)
) ENGINE=InnoDB AUTO_INCREMENT=201 DEFAULT CHARSET=utf8
1 row in set (0.00 sec) root@localhost : sakila 23:04:36>
现在我们导入数据,恢复actor表
[root@mysql-server-01 undrop-for-innodb]# mysql -uroot -p123456 -S /data/mysql/user_3306/mysql.sock --local-infile
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 18
Server version: 5.5.37-log MySQL Community Server (GPL) Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. root@localhost : (none) 23:17:16> use sakila
Database changed
root@localhost : sakila 23:17:19> source dumps/default/actor_load.sql;
Query OK, 0 rows affected (0.00 sec) Query OK, 600 rows affected (0.08 sec)
Records: 400 Deleted: 200 Skipped: 0 Warnings: 0 root@localhost : sakila 23:17:22>
检查恢复的数据
root@localhost : sakila 23:19:00> SELECT COUNT(*) FROM actor;
+----------+
| COUNT(*) |
+----------+
| 200 |
+----------+
1 row in set (0.00 sec) root@localhost : sakila 23:19:34> SELECT * FROM actor LIMIT 10;
+----------+------------+--------------+---------------------+
| actor_id | first_name | last_name | last_update |
+----------+------------+--------------+---------------------+
| 1 | PENELOPE | GUINESS | 2006-02-15 04:34:33 |
| 2 | NICK | WAHLBERG | 2006-02-15 04:34:33 |
| 3 | ED | CHASE | 2006-02-15 04:34:33 |
| 4 | JENNIFER | DAVIS | 2006-02-15 04:34:33 |
| 5 | JOHNNY | LOLLOBRIGIDA | 2006-02-15 04:34:33 |
| 6 | BETTE | NICHOLSON | 2006-02-15 04:34:33 |
| 7 | GRACE | MOSTEL | 2006-02-15 04:34:33 |
| 8 | MATTHEW | JOHANSSON | 2006-02-15 04:34:33 |
| 9 | JOE | SWANK | 2006-02-15 04:34:33 |
| 10 | CHRISTIAN | GABLE | 2006-02-15 04:34:33 |
+----------+------------+--------------+---------------------+
10 rows in set (0.00 sec) root@localhost : sakila 23:19:37> CHECKSUM TABLE actor;
+--------------+------------+
| Table | Checksum |
+--------------+------------+
| sakila.actor | 2472295518 |
+--------------+------------+
1 row in set (0.00 sec) root@localhost : sakila 23:19:40>
可以发现和drop table之前完全一致。到这里数据就恢复完成啦。希望小伙伴们永远不要使用到改工具。
参考资料
https://twindb.com/recover-innodb-table-after-drop-table-innodb/
DROP TABLE 恢复【一】的更多相关文章
- Hadoop之hive的drop table恢复
一.引言: 快下班的时候我开发同事问能不能将hive中drop掉的数据恢复过来,我记得是有开回收站的,当时我回答说可以恢复的. 二.恢复过程: 在之前我有对hadoop的回收站有过了解,就是将hdfs ...
- MySQL5.7下面,误操作导致的drop table db1.tb1; 的恢复方法:
MySQL5.7下面,误操作导致的drop table db1.tb1; 的恢复方法: 0.停业务数据写入.[iptables封禁] 1.从备份服务器上拉取最新的一个全备文件,恢复到一个临时的服务器上 ...
- hive drop和恢复partition external table
在hdfs目录:/user/xx/table/test_external 保存 test_external 表数据 先建表,使用列式存储格式 CREATE external TABLE `test_e ...
- DROP TABLE ** CASCADE CONSTRAINTS PURGE删除表的时候级联删除从表外键
1.关于 cascade constraints 假设A为主表(既含有某一主键的表),B为从表(即引用了A的主键作为外键). 则当删除A表时,如不特殊说明,则 drop table A 系统会出现错误 ...
- Oracle10g 回收站及彻底删除table : drop table xx purge
drop后的表被放在回收站(user_recyclebin)里,而不是直接删除掉.这样,回收站里的表信息就可以被恢复,或彻底清除. 1.通过查询回收站user_recyclebin获取被删除的表信息, ...
- oracle drop table and purge
一.drop表 执行drop table xx 语句 drop后的表被放在回收站(user_recyclebin)里,而不是直接删除掉.这样,回收站里的表信息就可以被恢复,或彻底清除. 通过查询回收站 ...
- Oracle Drop表并未直接删除 drop table xx purge
drop表 执行drop table xx 语句 drop后的表被放在回收站(user_recyclebin)里,而不是直接删除掉.这样,回收站里的表信息就可以被恢复,或彻底清除. 通 ...
- Drop Table对MySQL的性能影响分析
[问题描述] 最近碰到有台MySQL实例出现了MySQL服务短暂hang死,表现为瞬间的并发线程上升,连接数暴增. 排查Error Log文件中有page_cleaner超时的信息,引起我们的关注: ...
- Oracle Drop Table
DROP TABLE 使用DROP TABLE语句将表或对象表移动到回收站或从数据库中完全删除表及其所有数据. 注:除非指定purge子句,否则drop table语句不会将表占用的空间释放回表空间供 ...
随机推荐
- stm32常识
cmsis全称Cortex Microcontroller Software Interface Standard,就是Cortex微处理器软件接口标准 stm32每组gpio有7组端口,分别是2个3 ...
- Codeforces Round #264 (Div. 2) D. Gargari and Permutations 多序列LIS+dp好题
http://codeforces.com/contest/463/problem/D 求k个序列的最长公共子序列. k<=5 肯定 不能直接LCS 网上题解全是图论解法...我就来个dp的解法 ...
- js-实现双色球功能
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8&qu ...
- Django:全文检索功能可参考博客
https://blog.csdn.net/AC_hell/article/details/52875927 https://www.zmrenwu.com/courses/django-blog-t ...
- ZKWeb网页框架1.6正式发布
1.6.0更新的内容有 Dapper改进 更换Dapper.Contrib到Dommel 支持自定义列名的设置 支持忽略未映射的成员 支持插入Guid类型到MySQL数据库 支持JSON序列化类型 遇 ...
- 【ElasticSearch】:QueryDSL
Search API URI Search Response Body Search Query DSL Response Body Search使用Query DSL语句,相对URI Search功 ...
- 修改ssh远程默认端口
修改ssh远程默认端口 Linuxssh端口修改 1. 修改ssh配置文件 [root@distzabbix ~]# vim /etc/ssh/sshd_config 找到第17行附近#Port 22 ...
- Network - Tips
001 - 查询whois 可通过在线工具进行查询: https://www.whois365.com http://whois.aliyun.com http://whois.chinaz.com ...
- JS脚本实现CSDN免登陆免关闭广告插件自动展开“阅读更多”内容
最近在CSDN查资料,总是弹出以下弹窗,然后就自动跳转到登录页面,蛋疼! 于是重新捣腾了一下,修改了原来的脚本,最新的脚本代码如下: 温馨提示:在打开CSDN页面后立刻执行以下脚本即可免登陆免关闭广告 ...
- Liferay-Activiti 功能介绍 (新版Liferay7基本特性)
一句话简介 Liferay是世界领先的开源企业门户(也可作为综合门户),是最强大(没有之一)的JAVA开源门户,在Gartner和Forrester和评价非常高,近几年已经超越了微软门户Sharepo ...