Products
GG网络技术分享 2026-04-15 20:42 3
对吧,你看。 日常运维中,难免遇到某些表不小心被drop的场景,而恰好又没有备份?咋办呢?当然是跑路啦。开个玩笑,跑路是下下策,咱们还是得硬着头皮想办法恢复。毕竟数据就是企业的命根子,丢了饭碗事小,丢了数据事大。今天咱们就来折腾一下 怎么用undrop-for-innodb和ibd2sql这两个工具,把MySQL 8.0里被误删的表给“捞”回来。说实话,这过程挺折磨人的,特别是当你面对一堆二进制文件的时候,那种绝望感,啧啧。
先来看看undrop-for-innodb的原理。这玩意儿其实挺暴力的,它不跟你讲什么虚的,直接去扫描磁盘。undrop-for-innodb 是一款很NB的数据恢复工具, 支持在没有备份的时候恢复被drop的表;网上教程也很多,但是都是针对5.6/5.7环境的, 我给跪了。 其实这款工具也是支持MySQL 8.0环境的。本文主要就是讲如何使用undrop-for-innodb和ibd2sql恢复mysql 8.0环境被drop的表。这可是个技术活,稍微不注意,可能就彻底找不回来了。

有一款名叫ibd2sql的工具可以解析ibd文件, 也是ibd文件,那不就可以解析了么!ibd2sql解析ibd文件的原理其实就是: 根据表结构一行行,一个个字段的读取ibd文件中的数据. 当然可以使用一些特殊选项来解析需要的数据. 听起来是不是很简单?但做起来全是坑。这工具就像个显微镜,能把ibd文件里的每一个字节都给你抠出来看。
准备使ibd2sql支持解析undrop-for-innodb碎片页的时候, 看了下undrop-for-innodb的原理, 发现其还不支持8.0环境, 故尝试使其与ibd2sql结合的效果, 还不错. 后续ibd2sql也会引进该功能。 差不多得了... 你看,工具也是在进化的,以前傻傻地解析文件系统,现在聪明多了。
太刺激了。 咱们得搞清楚数据是怎么存的。数据是放在索引页里面的, 索引页是有索引id的;但是对于溢出数据而言是放在溢出页的,而溢出页是不记录索引id的,那么应该怎么解析呢? 这就是个头疼的问题。undrop-for-innodb的做法是每个溢出页都放在pages-vda1/FIL_PAGE_TYPE_BLOB目录下面解析的时候需要哪个page就去读哪个page. 但如果存在相同的pageid的溢出页时会怎么样呢?这就很尴尬了可能会乱套。
FIL_PAGE_INDEX 目录的文件是根据indexid来的,FIL_PAGE_TYPE_BLOB目录下的文件是根据pageid来的。这个id字段就是tableid,故tableid=370。 最后说一句。 看起来比较啰嗦, 就是:解析ibdata1获取indexid,根据indexid扫描磁盘获取数据. 这就是核心逻辑,记住了这个,后面就不容易晕。
ibd2sql 版本的时候也是支持恢复drop的表的, 但原理是解析xfs文件系统,根据Inode记录的信息去对应的磁盘构建完整的ibd文件. 这种设计限制太大了如果inode被破坏了就无法恢复了. 所以ibd2sql 后续版本也会根据indexid扫描磁盘然后尽可能的恢复数据. 对于drop的表的恢复,和undrop-for-innodb的设计比起来ibd2sql还是太'老实'了不够创新,不够胆大。有时候,做技术就得胆大心细。
既然咱们聊到恢复工具了不如来看看市面上还有哪些奇奇怪怪的工具。虽然咱们今天主要讲undrop和ibd2sql, 我不敢苟同... 但多了解几个没坏处,万一哪天用上了呢?
| 工具名称 | 主要功能 | 适用场景 | 难易程度 | 推荐指数 |
|---|---|---|---|---|
| undrop-for-innodb | 扫描磁盘页, 恢复被drop的表 | 误删表,无备份 | 困难 | ★★★★★ |
| ibd2sql | 将ibd文件解析成SQL | 数据迁移,解析ibd | 中等 | ★★★★☆ |
| MySQL Binlog | 增量日志恢复 | 误操作,有开启binlog | 简单 | ★★★★★ |
| MyFlashback | 反向解析binlog | 误删除/更新数据 | 中等 | ★★★☆☆ |
| innodb_space | InnoDB空间分析 | 分析表碎片,空间占用 | 困难 | ★★★☆☆ |
C位出道。 光说不练假把式。咱们来模拟一下。本次使用8.0.43版本模拟. 数据库的安装就省略了 这个要是还要我教,那这文章你也别看了太基础了。咱们直接进入正题。
容我插一句... 咱们先建个表, 插点数据,然后删掉,制造事故现场。
select @@version;
create table t20250913_test_drop);
insert into t20250913_test_drop values,,;
drop table t20250913_test_drop;
看,表没了。是不是心里一紧?别慌,咱们开始恢复。
先说说得把工具弄下来。undrop-for-innodb的下载安装及编译. 这一步很繁琐, 特别是编译环境,缺个库都能让你折腾半天。
# 软件下载
wget
unzip
cd undrop-for-innodb-master
# 环境准备
yum install make gcc -y
# 编译
make
# 输出stream_parser,c_parser,innochecksum_changer 在当前目录
# 编译sys_parser
make sys_parser
# 输出 sys_parser
# 需要libmysqlclient
ln -s /soft/mysql_3306/mysqlbase/mysql/lib/.20 /usr/lib64/mysql/.20
ldconfig
然后是ibd2sql的下载。这个简单点,Python写的,只要有Python环境就行。
yum install python3 -y
wget
unzip
cd ibd2sql-
开倒车。 这是最关键的一步!咱们得找到tableid和indexid。在8.0里面 表/索引信息是放在数据字典里的,表结构信息还可以找开发提供,而indexid部分就无法使用undrop-for-innodb了. 咋办呢?
咱们得用ibd2sql去解析系统表。先根据表名获取tableid。
python3 /data/mysql_3306/mysqldata/ --sql --delete --complete --set table=tables | grep t20250913_test_drop
假设咱们找到了tableid是370。接 呵... 下来根据tableid获取主键的索引id。
python3 /data/mysql_3306/mysqldata/ --sql --delete --complete --set table=indexes | grep 370
table_id为370对应的数据有个 "id=159;root=4..." 中id=159的159就是indexid; root=4中的4是root pageno, 但都被drop了 就无法根据pageno来恢复了. 所以我们只需要indexid. 记住这个159,这就是咱们救命的稻草。
现在咱们有了indexid,就可以用stream_parser去扫描磁盘了。 挖野菜。 这就像在垃圾堆里找金子,得把整个磁盘翻一遍。
./stream_parser -f /dev/vda1 -t 50G -T 159
深得我心。 这个过程可能会很长,取决于你的磁盘大小和性能。喝杯咖啡,去散散步吧。stream_parser是扫描磁盘提取索引页的工具,支持使用-T指定要解析的索引。
扫描完之后会生成一堆目录,里面就是碎片页。为了方便展示,我们画个图:一堆文件夹,里面全是二进制文件,我们都...。
换个赛道。 现在数据页都提取出来了咱们得把它变成人能看懂的SQL。这里可以用undrop自带的c_parser,也可以用ibd2sql。
先试试c_parser:
./c_parser -6f pages-vda1/FIL_PAGE_INDEX/ -t t20250913_test_
或者用ibd2sql。得需要相同表结构的frm/ibd文件,且需要修改后缀.page为.ibd。目前ibd2sql不支持根据系统表来拼接DDL, 也是没谁了。 所以DDL部分我们还得找开发要. 我这里就直接给出DDL了。
-- t20250913_test
create table t20250913_test_drop);
然后我们就可以使用ibd2sql解析相关数据页的数据了,踩雷了。。
python3 /root/undrop-for-innodb-master/pages-vda1/FIL_PAGE_INDEX/ --sdi /data/mysql_3306/mysqldata/db2/t20250913_test_ --sql --set leafno=0 --set rootno=0 --force
这里解析出来数据是重复的, 是主要原因是undrop-for-innodb扫描的页就是重复的导致的. 这很正常, 挖野菜。 毕竟咱们是暴力扫描,扫到什么算什么。再说说自己去重一下就行了。
根据indexid, spaceid直接扫描磁盘,然后尽可能的还原为ibd文件,可能实现起来更简单点. 但如果目标文件很大的话, 无语了... 还原出来的ibd文件也可能很大了即使实际数据并不算多. 道阻且长。
思考1: 注意不一定能扫描出来的, 有可能被回收了全看运气,所以备份是很重要的. 这句话我说了八百遍了备份,我心态崩了。!
思考2: 这种恢复方式虽然能救命,但真的太折腾了。所以咱们平时操作数据库的时候, 试着... 手别抖,眼别花。最好有个审核流程,别想删就删。
换个思路。 再说说希望这篇乱七八糟的文章能帮到你。虽然写得烂,但技术是实打实的。如果真的遇到了这种情况, 别放弃,试一试undrop-for-innodb和ibd2sql,说不定奇迹就发生了。当然如果实在恢复不出来那...我也没办法了自求多福吧。
Demand feedback