MySQL 数据恢复:使用 ibd2sql 工具从 IBD 文件中恢复数据的完整指南
编辑ibd2sql 是一款强大的 MySQL 数据恢复工具,能够从
.ibd
文件中提取数据并生成.sql
文件,帮助用户在数据丢失和数据库损坏时有效恢复数据。尽管在某些方面有局限性,但其简单易用的特点使得它成为处理 MySQL 数据库问题时的得力助手。通过本文的介绍,希望你能更好地理解和应用 ibd2sql,为你的数据库管理工作提供支持。ibd2sql是一个使用纯
python3
编写的离线解析MYSQL INNODB存储引擎的ibd文件
的工具. 无第三方依赖包. 使用GPL-3.0 license.
特点
方便: 提取表DDL
实用: 可替换库(--schema)/表(--table)名, 可在sql语句中输出完整的字段(--complete)
简单: 纯python3代码编写, 无依赖包.
支持众多数据类型: 支持所有mysql数据类型
支持复杂的表结构: 分区表, 注释, 主键, 外键, 约束, 自增, 普通索引, 前缀索引, 主键前缀索引, 唯一索引, 复合索引, 默认值, 符号, 虚拟字段, INSTANT, 无主键等情况的表
数据误删恢复: 可以输出被标记为deleted的数据
安全: 离线解析ibd文件, 仅可读权限即可
支持范围广: 支持mysql 5.6 or 5.7 or 8.0 or 8.4 or 9.0
下载
wget https://github.com/ddcw/ibd2sql/archive/refs/heads/main.zip
unzip main.zip
cd ibd2sql-main
要求和支持范围
要求: python3
支持范围: mysql5.x 8.x 9.x
简单使用
本工具使用纯python3
编写, 无依赖包, 所以建议直接使用源码.
Linux
python3 main.py /data/mysql_3314/mysqldata/ibd2sql/ddcw_alltype_table.ibd --sql --ddl
Windows
注意python名字和路径
python main.py F:\t20240627\test\ddcw_char_ascii.ibd --sql --ddl
若要将结果保存到文件, 可使用重定向(python3 main.py xxx.ibd --sql > xxxx.sql
)
参数说明
SHELL>python3 main.py --help
usage: main.py [--help] [--version] [--ddl] [--sql] [--delete]
[--complete-insert] [--force] [--set] [--multi-value]
[--replace] [--table TABLE_NAME] [--schema SCHEMA_NAME]
[--sdi-table SDI_TABLE] [--where-trx WHERE_TRX]
[--where-rollptr WHERE_ROLLPTR] [--limit LIMIT] [--debug]
[--debug-file DEBUG_FILE] [--page-min PAGE_MIN]
[--page-max PAGE_MAX] [--page-start PAGE_START]
[--page-count PAGE_COUNT] [--page-skip PAGE_SKIP] [--mysql5]
[FILENAME]
解析mysql 5.7/8.0的ibd文件 https://github.com/ddcw/ibd2sql
positional arguments:
FILENAME ibd filename
optional arguments:
--help, -h show help
--version, -v, -V show version
--ddl, -d print ddl
--sql print data by sql
--delete print data only for flag of deleted
--complete-insert use complete insert statements for sql
--force, -f force pasrser file when Error Page
--set set/enum to fill in actual data instead of strings
--multi-value single sql if data belong to one page
--replace "REPLACE INTO" replace to "INSERT INTO" (default)
--table TABLE_NAME replace table name except ddl
--schema SCHEMA_NAME replace table name except ddl
--sdi-table SDI_TABLE
read SDI PAGE from this file(ibd)(partition table)
--where-trx WHERE_TRX
default (0,281474976710656)
--where-rollptr WHERE_ROLLPTR
default (0,72057594037927936)
--limit LIMIT limit rows
--debug, -D will DEBUG (it's too big)
--debug-file DEBUG_FILE
default sys.stdout if DEBUG
--page-min PAGE_MIN if PAGE NO less than it, will break
--page-max PAGE_MAX if PAGE NO great than it, will break
--page-start PAGE_START
INDEX PAGE START NO
--page-count PAGE_COUNT
page count NO
--page-skip PAGE_SKIP
skip some pages when start parse index page
--mysql5 for mysql5.7 flag
Example:
ibd2sql /data/db1/xxx.ibd --ddl --sql
ibd2sql /data/db1/xxx.ibd --delete --sql
ibd2sql /data/db1/xxx#p#p1.ibd --sdi-table /data/db1/xxx#p#p0.ibd --sql
ibd2sql /mysql57/db1/xxx.ibd --sdi-table /mysql80/db1/xxx.ibd --sql --mysql5
FILENAME 目标文件, 即要解析的ibd文件
--help
仅打印帮助信息,不做任何操作
--version
仅展示版本信息, 不做任何操作
--ddl
打印目标文件的DDL信息.
--sql
打印目标文件的数据, 并拼接为SQL语句
--delete
打印目标文件被标记为deleted的数据, 需要和--sql
联合使用.
--complete-insert
打印的SQL语句更完整, 即增加字段信息(某些数据库需要字段信息)
--force
对于某些可能报错的场景可以使用此选项跳过. 目前无实际使用场景.
--set
本来是对set/enum的值取int还是实际值, 现默认启用. 故此参数无效
--multi-value
对于生成的INSERT语句, 按照每页作为一个SQL语句. 即insert into table values(),(),();
--replace
使用replace语句代替insert语句. 和--multi-value
冲突
--table
使用指定的表名替代元数据信息中的表名.
--schema
使用指定的库名替代元数据中的库名.
--sdi-table
指定元数据表文件. 对于5.x和分区表这种元数据信息不在指定的目标文件中, 则需要单独指定元数据文件.
--where-trx
指定事务范围. 默认(0,281474976710656)
--where-rollptr
指定回滚指针范围. 默认(0,72057594037927936)
--limit
仅打印N行数据. 同DML中的limit.
--debug
使用DEBUG功能, 会生成大量的解析日志信息.
--debug-file
当启用debug功能时, 可使用此选项指定debug日志文件. 默认stdout
--page-min
如果正在解析的页号小于这个值, 则跳过该页.
--page-max
如果正在解析的页号大于这个值, 则跳过.
--page-start
指定第一个数据页(叶子节点). 方便跳过坏块.
--page-count
解析的页数量. 通常和--page-start
联合使用.
--page-skip
跳过的页数量.
--mysql5
如果是mysql 5.6/5.7 除了指定--sdi-table
选项外, 还应指定这个选项, 方便ibd2sql失败为mysql5的数据文件.
使用例子
为了方便展示, 如下使用xxx.ibd文件来代替实际的ibd文件, 实际解析的时候需要 相对
/绝对
路径.
未特别说明的场景, 均是指mysql 8.x环境.
解析出表结构(DDL)
python3 main.py xxx.ibd --ddl
解析出数据(DML)
python3 main.py xxx.ibd --sql
解析表数据(DDL+DML)
python3 main.py xxx.ibd --ddl --sql
解析被误删的数据
python3 main.py xxx.ibd --sql --delete
分区表解析
分区表需要指定元数据信息
python3 main.py /data/mysql_3314/mysqldata/ibd2sql/ddcw_partition_range#p#p1.ibd --sql --sdi-table /data/mysql_3314/mysqldata/ibd2sql/ddcw_partition_range#p#p0.ibd
5.6 & 5.7
如果是mysql5.6或者5.7, 则需要先使用mysqlfrm
提取元数据信息并写入到mysql8.0的环境中, 以供ibd2sql获取元数据信息.
# 提取出DDL
mysqlfrm /data/mysql_3308/mysqldata/db1/ddcw_alltype_table.frm --diagnostic
# 然后导入到8.0环境(以获取SDI信息.)
....
# 就可以使用本工具解析了
python3 main.py --sdi-table /data/mysql_3314/mysqldata/ibd2sql/ddcw_alltype_table.ibd /data/mysql_3308/mysqldata/db1/ddcw_alltype_table.ibd --sql --mysql5
注: mysqlfrm 存在 timestamp等数据类型的精度丢失问题. 需要人工确认. 如果可以直接从数据库里面获取元数据信息
更好.
ibd文件损坏的场景
如果ibd文件数据页损坏, 则可以跳过该页, 或者暴力解析.
对于想并发解析的, 也可以使用本方法.
如果是ibd文件的元数据信息损坏, 则要先恢复元数据信息. 然后使用--sdi-table
选项指定正确的元数据信息文件.
我这里没有做重定向, 是直接打印在屏幕上的(方便演示)
filename="/tmp/ddcw_alltype_table.ibd" # 要解析的ibd文件名
python3 main.py ${filename} --ddl # 获取表结构信息
filesize=`stat -c %s ${filename}`
maxpagecount=$[ ${filesize} / 16384 ]
current_page=1
while [ ${current_page} -le ${maxpagecount} ];do
echo "-- ${filename} PAGE NO: ${current_page}";
current_page=$[ ${current_page} + 1 ]
python3 main.py ${filename} --sql --page-start ${current_page} --page-count 1 2>/dev/null ;
done
如使用过程中遇到问题可以到issues 中查看有没有类似的问题以及解决方案,也欢迎在本文章中评论进行交流和学习!
完整测试结果
版本更新日志
Github
- 2
- 0
-
分享