Recover InnoDB dictionary
为什么我们需要恢复innodb的字典信息?当我们drop 一个表时,发现误操作,这时又没有备份,那么想恢复数据是非常困难的。所以我们想恢复被删除的表时,首先就需要恢复表结构,目前已经有了undrop-for-innodb这个工具,相比之前的工具percona-data-recovery-tool-for-innodb有了更大的进步,这两个工具都是同一个作者开发的。这个工具我以前也写了相关的博客--Percona Data Recovery Tool 单表恢复,现在undrop-for-innodb这个工具更加完美,少了很多限制。但是对于drop table以后表结构的恢复还是需要使用percona-data-recovery-tool-for-innodb。没有看见undrop-for-innodb可以恢复表结构,这也是比较遗憾的地方吧。
1.TwinDB恢复工具包编译安装
安装工具包依赖的软件
yum install gcc bison flex bzr -y
2.下载软件包并编译安装
[root@mysql-server- ~]# bzr branch lp:undrop-for-innodb
You have not informed bzr of your Launchpad ID, and you must do this to
write to Launchpad or access private data. See "bzr help launchpad-login".
Branched revision(s).
[root@mysql-server- ~]#
[root@mysql-server- ~]# cd undrop-for-innodb/
[root@mysql-server- undrop-for-innodb]# make
cc -g -O3 -I./include -c stream_parser.c
cc -g -O3 -I./include -pthread -lm stream_parser.o -o stream_parser
flex sql_parser.l
bison -o sql_parser.c sql_parser.y
sql_parser.y: conflicts: shift/reduce
cc -g -O3 -I./include -c sql_parser.c
cc -g -O3 -I./include -c c_parser.c
cc -g -O3 -I./include -c tables_dict.c
cc -g -O3 -I./include -c print_data.c
cc -g -O3 -I./include -c check_data.c
cc -g -O3 -I./include sql_parser.o c_parser.o tables_dict.o print_data.o check_data.o -o c_parser -pthread -lm
cc -g -O3 -I./include -o innochecksum_changer innochecksum.c
[root@mysql-server- undrop-for-innodb]#
如果没有抛出错误,证明就ok了,会生成编译好的工具c_parser。
一. 解析 ibdata1
InnoDB的字典信息存储在ibdata1。因此,我们需要使用stream_parser工具对它进行解析并获得存储在字典中的记录页。该工具在make以后就自动生成了。
[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这个工具发现在ibdata1中,找到了存储页面类型(FIL_PAGE_INDEX或FIL_PAGE_TYPE_BLOB)由index_id的整理InnoDB的页面。
[root@mysql-server- pages-ibdata1]# pwd
/root/undrop-for-innodb/pages-ibdata1
[root@mysql-server- pages-ibdata1]# ll
total
drwxr-xr-x root root Aug : FIL_PAGE_INDEX
drwxr-xr-x root root Aug : FIL_PAGE_TYPE_BLOB
[root@mysql-server- pages-ibdata1]#
SYS_TABLES
SYS_TABLES本身是一个表,该表用于规范innodb各种表定义和保存innodb中各种表的基本信息,结合SYS_COLUMNS,SYS_INDEXES和SYS_FOREIGN系统表定义了特定某个表的所有信息。
[root@mysql-server- undrop-for-innodb]# ll pages-ibdata1/FIL_PAGE_INDEX/.page
-rw-r--r-- root root Aug : pages-ibdata1/FIL_PAGE_INDEX/.page
SYS_INDEXES
SYS_INDEXES用于保存innodb中每个表定义的每个索引对象。
[root@mysql-server- undrop-for-innodb]# ll pages-ibdata1/FIL_PAGE_INDEX/.page
-rw-r--r-- root root Aug : pages-ibdata1/FIL_PAGE_INDEX/.page
SYS_COLUMNS
SYS_COLUMNS用于保存innodb引擎每个表定义的列,与SYS_TABLES相似。
[root@mysql-server- undrop-for-innodb]# ll pages-ibdata1/FIL_PAGE_INDEX/.page
-rw-r--r-- root root Aug : pages-ibdata1/FIL_PAGE_INDEX/.page
SYS_FIELDS
SYS_FIELDS用于保存innodb中每个索引的每个列对象。
[root@mysql-server- undrop-for-innodb]# ll pages-ibdata1/FIL_PAGE_INDEX/.page
-rw-r--r-- root root Aug : pages-ibdata1/FIL_PAGE_INDEX/.page
从SYS_TABLES和SYS_INDEXES导出记录
获取记录了需要使用c_parser工具。但首先我们要创建转存的数据目录
[root@mysql-server- undrop-for-innodb]# mkdir -p dumps/default
[root@mysql-server- undrop-for-innodb]#
InnoDB的字典总是在冗余格式,因此选择-4是必需的:
[root@mysql-server- undrop-for-innodb]# ./c_parser -4f pages-ibdata1/FIL_PAGE_INDEX/.page -t dictionary/SYS_TABLES.sql > dumps/default/SYS_TABLES > dumps/default/SYS_TABLES.sql
[root@mysql-server- undrop-for-innodb]#
现在找到我们关心的数据库,我之前有导入MySQL官方的示例数据库,sakila
[root@mysql-server- undrop-for-innodb]# grep sakila dumps/default/SYS_TABLES
SYS_TABLES "sakila/actor" ""
SYS_TABLES "sakila/address" ""
SYS_TABLES "sakila/category" ""
960000013A0110 SYS_TABLES "sakila/city" ""
970000013D0110 SYS_TABLES "sakila/country" ""
SYS_TABLES "sakila/customer" ""
9A000001460110 SYS_TABLES "sakila/film" ""
00000000031B 9C0000014C0110 SYS_TABLES "sakila/film\_actor" ""
00000000031D 9E000001500110 SYS_TABLES "sakila/film\_category" ""
00000000031F A0000001540110 SYS_TABLES "sakila/inventory" ""
A2000001590110 SYS_TABLES "sakila/language" ""
A30000015B0110 SYS_TABLES "sakila/payment" ""
A6000001620110 SYS_TABLES "sakila/rental" ""
A90000016A0110 SYS_TABLES "sakila/staff" ""
00000000032A AB0000016F0110 SYS_TABLES "sakila/store" ""
[root@mysql-server- undrop-for-innodb]#
可见该库下的所有表都看见了(用过sakila示例库的同学都知道^_^)。
dumps/default/SYS_TABLES使使用LOAD DATA INFILE命令生成的。具体的命令c_parsers打印到标准错误输出。把改SQL保存在了dumps/default/SYS_TABLES.sql
[root@mysql-server- undrop-for-innodb]# cat dumps/default/SYS_TABLES.sql
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`);
用同样的方法导出SYS_INDEXES:
[root@mysql-server- undrop-for-innodb]# ./c_parser -4f pages-ibdata1/FIL_PAGE_INDEX/.page -t dictionary/SYS_INDEXES.sql > dumps/default/SYS_INDEXES > dumps/default/SYS_INDEXES.sql
[root@mysql-server- undrop-for-innodb]#
查看一下结果,确保没有异常。
[root@mysql-server- undrop-for-innodb]# head - dumps/default/SYS_INDEXES
-- Page id: , Format: REDUNDANT, Records list: Valid, Expected records: ( )
810000012D0177 SYS_INDEXES "ID\_IND"
810000012D01A5 SYS_INDEXES "FOR\_IND"
810000012D01D3 SYS_INDEXES "REF\_IND"
810000012D026D SYS_INDEXES "ID\_IND"
[root@mysql-server- undrop-for-innodb]# head - dumps/default/SYS_INDEXES.sql
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]#
现在我们可以使用字典了,如果表在数据库中,那么会更加方便。
加载字典表到MySQL
通过grep可以从SYS_TABLES和SYS_INDEXES的主要用途是得到为了表名index_id。如果SYS_TABLES和SYS_INDEXES在MySQL中,那么操作将变得更简单。
root@localhost : (none) 18:10:31> create database yayun;
Query OK, 1 row affected (0.00 sec) root@localhost : (none) 18:10:42>
上面创建的库主要用来导入两张表而已。
[root@mysql-server- undrop-for-innodb]# mysql -uroot -p123456 -S /data/mysql/user_3306/mysql.sock yayun < dictionary/SYS_TABLES.sql
[root@mysql-server- undrop-for-innodb]# mysql -uroot -p123456 -S /data/mysql/user_3306/mysql.sock yayun < dictionary/SYS_INDEXES.sql
[root@mysql-server- undrop-for-innodb]#
继续导入数据
[root@mysql-server- undrop-for-innodb]# mysql -uroot -p123456 -S /data/mysql/user_3306/mysql.sock yayun < dumps/default/SYS_TABLES.sql
[root@mysql-server- undrop-for-innodb]# mysql -uroot -p123456 -S /data/mysql/user_3306/mysql.sock yayun < dumps/default/SYS_INDEXES.sql
[root@mysql-server- undrop-for-innodb]#
现在我们的InnoDB字典信息已经存在在MySQL中,我们可以像普通的表进行查询
root@localhost : (none) 20:56:44> use yayun
Database changed
root@localhost : yayun 20:56:48> SELECT * FROM SYS_TABLES WHERE NAME = 'sakila/actor';
+--------------+----+--------+------+--------+---------+--------------+-------+
| NAME | ID | N_COLS | TYPE | MIX_ID | MIX_LEN | CLUSTER_NAME | SPACE |
+--------------+----+--------+------+--------+---------+--------------+-------+
| sakila/actor | 13 | 4 | 1 | 0 | 0 | | 0 |
+--------------+----+--------+------+--------+---------+--------------+-------+
1 row in set (0.08 sec) root@localhost : yayun 20:56:51> SELECT * FROM SYS_INDEXES WHERE TABLE_ID = 13;
+----------+----+---------------------+----------+------+-------+---------+
| TABLE_ID | ID | NAME | N_FIELDS | TYPE | SPACE | PAGE_NO |
+----------+----+---------------------+----------+------+-------+---------+
| 13 | 15 | PRIMARY | 1 | 3 | 0 | 307 |
| 13 | 16 | idx_actor_last_name | 1 | 0 | 0 | 308 |
+----------+----+---------------------+----------+------+-------+---------+
2 rows in set (0.05 sec) root@localhost : yayun 20:58:14>
通过上述的查询,我们可以看到sakila.actor表有两个索引,PRIMARY和idx_actor_last_name,分别对应15,16,。如果我们不小心误操作,drop table actor,那么恢复数据就需要知道相应的id。后续文章将介绍drop table后如何恢复数据。
参考资料
https://twindb.com/how-to-recover-innodb-dictionary/
https://twindb.com/innodb-dictionary/
Recover InnoDB dictionary的更多相关文章
- DROP TABLE 恢复【一】
当DROP TABLE指令敲下的时候,你很爽,你有考虑过后果么?如果该表真的没用,你DROP到无所谓,如果还有用的,这时你肯定吓惨了吧,如果你有备份,那么恭喜你,逃过一劫,如果没有备份呢?这时就该绝望 ...
- MySQL Flashback 工具介绍
MySQL Flashback 工具介绍 DML Flashback 独立工具,通过伪装成slave拉取binlog来进行处理 MyFlash 「大众点点评」 binlog2sql 「大众点评(上海) ...
- ORCLE INNODB 博客与 innodb_lru_scan_depth
https://blogs.oracle.com/mysqlinnodb/ http://mysqllover.com/?p=485 •MySQL. MySQL 5.6.10 http://www.m ...
- 记一次揪心的MySQL数据恢复过程
https://blog.csdn.net/poxiaonie/article/details/78304699 === 先说下背景,公司其中一个项目所有服务都部署在客户的机房内,机房较小,没有UPS ...
- ha_innobase::open
http://mysql.taobao.org/monthly/2015/08/07/ /******************************************************* ...
- Innodb 表修复(转)
摘要: 突然收到MySQL报警,从库的数据库挂了,一直在不停的重启,打开错误日志,发现有张表坏了.innodb表损坏不能通过repair table 等修复myisam的命令操作.现在记录下 ...
- Recovering InnoDB table from an .ibd file.
Recovering an InnoDB table from only an .ibd file. Sometime you may need to recover a table when all ...
- MySQL 5.6 Reference Manual-14.6 InnoDB Table Management
14.6 InnoDB Table Management 14.6.1 Creating InnoDB Tables 14.6.2 Moving or Copying InnoDB Tables to ...
- MySQL 5.6 Reference Manual-14.5 InnoDB Tablespace Management
14.5 InnoDB Tablespace Management 14.5.1 Resizing the InnoDB System Tablespace 14.5.2 Changing the ...
随机推荐
- python 简单的server请求
1.代码 #!/usr/bin/env python3 # -*- coding: utf-8 -*- # __author henry # __date 2018/11/4 from wsgiref ...
- springboot+shiro+redis(单机redis版)整合教程-续(添加动态角色权限控制)
相关教程: 1. springboot+shiro整合教程 2. springboot+shiro+redis(单机redis版)整合教程 3. springboot+shiro+redis(集群re ...
- Scala学习笔记——简化代码、柯里化、继承、特质
1.简化代码 package com.scala.first import java.io.File import javax.management.Query /** * Created by co ...
- IOS多线程处理
http://www.jianshu.com/p/0b0d9b1f1f19 首页专题下载手机应用 显示模式登录 注册登录 添加关注 作者 伯恩的遗产2015.07.29 00:37* 写了35 ...
- vue 项目安装sass的依赖包
安装sass的依赖包 npm install --save-dev sass-loader //sass-loader依赖于node-sass npm install --save-dev node- ...
- ubuntu16.04下安装opencv3.4.1及其扩展模块
1.源文件下载 opencv-3.4.1.tar.gz(https://github.com/opencv/opencv/releases) opencv_contrib-3.4.1.tar.gz(h ...
- 依赖: nginx-common (= 1.14.0-0ubuntu1) 但是它将不会被安装
.apt --fix-broken install .sudo apt-get remove nginx nginx-common # 卸载删除除了配置文件以外的所有文件. .sudo apt-get ...
- Ubuntu 安装 .bundle 文件
ubuntu安装VMware-Workstation-Full-15.0.2-10952284.x86_64.bundle 一.*.bundle 文件比较特殊,只有在给它了执行权限后才能执行安装操作. ...
- LightOJ 1224 - DNA Prefix - [字典树上DFS]
题目链接:https://cn.vjudge.net/problem/LightOJ-1224 Given a set of $n$ DNA samples, where each sample is ...
- [No000014F]计算机编程语言家族史
https://www.levenez.com/lang/