暂无图片
暂无图片
1
暂无图片
暂无图片
2
暂无图片

[MYSQL] 数据恢复, 无备份, 只剩一个 ibd 文件 怎么恢复数据?

原创 大大刺猬 2024-04-12
1670

背景

环境: mysql 8.0

不小心删除了mysql数据目录, 但还剩个.ibd文件在. 没得备份, 没得binlog , 要恢复这个ibd文件里面的数据.

啊. 这… 先打一顿没有做备份的dba

分析

我们通常是使用备份+binlog来恢复数据, 但这次只有个孤零零的ibd文件.

我们知道mysql 8.0 的ibd文件也包含元数据信息(你问我怎么知道的?). 所以我们先恢复表结构, 再恢复数据.

恢复表结构

如果开发有相关的DDL更好. 没得的话. 我们就自己解析.

mysql 8.0的ibd文件存在sdi page 记录元数据信息的, 压缩的json格式. 我们可以使用官方自带的 ibd2sdi 解析出来这个json信息.

ibd2sdi /data/mysql_3314/mysqldata/ibd2sql/ddcw_alltype_table.ibd
复制

image.png
但还要自己去拼接DDL, 太麻烦了.

所以我们使用其它工具来提取DDL, 这里就使用 ibd2sql 来提取(为啥使用这个呢? 因为是我写的 -_- 用起来顺手)

python3 main.py /tmp/ddcw_alltype_table.ibd --ddl
复制

image.png

现在DDL已经提取出来了. 我们先创建个测试环境, 创建相同的库, 再使用上面的DDL去恢复相关的表结构

CREATE TABLE IF NOT EXISTS `ibd2sql`.`ddcw_alltype_table`( `id` int NOT NULL AUTO_INCREMENT, `int_col` int NULL, `tinyint_col` tinyint NULL DEFAULT '1', `smallint_col` smallint NULL, `mediumint_col` mediumint NULL, `bigint_col` bigint NULL, `float_col` float NULL, `double_col` double NULL, `decimal_col` decimal(10,2) NULL, `date_col` date NULL, `datetime_col` datetime NULL, `timestamp_col` timestamp NULL, `time_col` time NULL, `year_col` year NULL, `char_col` char(100) NULL, `varchar_col` varchar(200) NULL DEFAULT 'aa', `binary_col` binary(10) NULL, `varbinary_col` varbinary(20) NULL, `bit_col` bit(4) NULL, `enum_col` enum('A','B','C') NULL, `set_col` set('X','Y','Z') NULL, `josn_type` json NULL, `newcol` varchar(200) NULL DEFAULT 'aa', `newcol2` varchar(200) NULL DEFAULT 'aa', `newcoldasdas2` varchar(300) NULL DEFAULT 'bbaa', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ;
复制

image.png

恢复数据

恢复了表结构后, 就该恢复数据了.

方法1(推荐)

mysql可以使用discard table来删除表空间, 然后使用import tablespace 来导入表空间. 我们就使用这种方式来恢复数据.

官网介绍: https://dev.mysql.com/doc/refman/8.0/en/innodb-table-import.html

-- 移除表空间 alter table ddcw_alltype_table discard tablespace; -- 拷贝要恢复的表空间 system cp -ra /tmp/ddcw_alltype_table.ibd /data/mysql_3314/mysqldata/ibd2sql -- 导入要恢复的表空间 alter table ddcw_alltype_table import tablespace; -- 验证数据 select count(*) from ddcw_alltype_table;
复制

image.png

这种方法非常简单方便, 推荐使用.

但有可能会失败(人生不总是一帆风顺).

ERROR 1815 (HY000): Internal error: Cannot reset LSNs in table `dbname`.`tablename` : Data structure corruption
复制

方法2

如果无法导入表空间的话, 我们还可以解析这个ibd文件得到相关的数据. 这种工具市面上较少 我这里还是使用 ibd2sql (夹带私货-_-)

目前不支持溢出页(默认置为NULL). 也不建议在mysql里面存储大数据.

数据类型基本上都支持, 不支持空间坐标字段(为啥? 因为要太复杂了, 一时半会解析不了…)

python3 main.py /tmp/ddcw_alltype_table.ibd --sql > /tmp/ddcw_alltype_table.sql
复制

image.png

然后我们就可以把解析出来的sql导入数据库了. 当然也可以解析的时候直接通过管道写入数据库

mysql -h127.0.0.1 -P3314 -p123456 < /tmp/ddcw_alltype_table.sql
复制

image.png

总结

虽然只剩一个ibd文件也能恢复数据, 但还是要备份. 毕竟这些工具不一定能用. (多数都有备份, 这些工具使用例子就少, 支持范围就小)

如果ibd2sql工具使用有啥问题, 请到github提相关issue, 附上ibd2sql版本和mysql版本, 最好能附上debug日志.

下载地址: https://github.com/ddcw/ibd2sql/archive/refs/tags/v1.1.tar.gz

单表恢复方案参考:

  1. pxb+binlog (binlog提取单表 看之前的文章)
  2. mysqldump+binlog
  3. 从库拷贝ibd文件
  4. innodb_force_recovery + mysqldump
  5. ibd2sql

附mysql数据类型
(懒得整理, 直接拿ibd2sql里面的代码来看吧, 将就)

innodb_read_data object: read_varchar read_char read_varbinary read_binary read_bit read_tinyint read_smallint read_mediumint read_int read_bigint read_float read_double read_decimal #最离谱... read_date read_datetime read_time read_timestamp read_year read_enum read_set # json (可能存在溢出页) read_json # 大字段 (可能存在溢出页) read_tinyblob read_mediumblob read_blob read_longblob read_tinytext read_mediumtext read_text read_longtext # 空间坐标(也NM离谱) read_geometry #几何 (通用) read_point #点 read_linestring #线 read_polygon #多边形 read_multipoint read_multilinestring read_multipolygon read_geometrycollection #几何集合
复制
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论

库海无涯
暂无图片
11月前
评论
暂无图片 0
学习了,期待这个工具更完善。
11月前
暂无图片 点赞
1
大大刺猬
暂无图片
11月前
回复
暂无图片 0
感谢支持. 后面会逐步完善的.
11月前
暂无图片 点赞
回复