前言:
天有不测风云人有旦夕祸福,DBA做为数据守护的第一责任人,数据丢失,在生产环境中不可避免,尤其遇到NB的开发,写了个看似NB的SQL,SQL最后还忘记写where条件,一件事的发生,就是种种不可能在一起发生的巧合组成了,有时就这么巧就发生了,你说怎么办?
今天给大家分享一个NB的开发写的一个python脚本,它就可以解决上面NB开发写的NB SQL的问题!!!
这个软件的名字叫ibd2sql (https://github.com/ddcw/ibd2sql/archive/refs/heads/main.zip)
ibd2sql 是使用python3 编写的 提取mysql 8.0 innodb存储引擎在磁盘上的 ibd 文件信息为SQL语句的工具.
不需要连接数据库, 只需要对目录ibd文件有可读权限即可. 无第三方依赖包, 纯python3代码. 使用GPL-3.0 license.
别的原理啥的,我们先不谈,现在的情况是,只有一个表的物理文件,比如test.ibd文件,要怎么通过ibd2sql来恢复里面的数据呢,且听我慢慢讲来哈!!
ibd2sql的功能特点:
方便: 提取表DDL
实用: 可替换库(--schema)/表(--table)名, 可在sql语句中输出完整的字段(--complete)
简单: 纯python3代码编写, 无依赖包. 还可以使用**--debug**查看解析过程
选择性强: 可以根据条件过滤符合要求的数据 --where , --limit
支持众多数据类型: 支持所有mysql数据类型 (比如 int, decimal, date, varchar, char, json, binary, enum, set, blob/text, longblob,空间坐标等).
支持复杂的表结构: 分区表, 注释, 主键, 外键, 约束, 自增, 普通索引, 前缀索引, 主键前缀索引, 唯一索引, 复合索引, 默认值, 符号, 虚拟字段, INSTANT, 无主键等情况的表
数据误删恢复: 可以输出被标记为deleted的数据
安全: 离线解析ibd文件, 仅可读权限即可
支持范围广: 支持mysql 5.7 or 8.x
ibd2sql安装配置:
首先需要安装python3:
wget https://github.com/ddcw/ibd2sql/archive/refs/heads/main.zip
unzip main.zip
ibd2sql-main/
python3 main.py -h
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
由于是python脚本,就不需要三板斧哈,直接使用,注意要python 3.x以上的版本 python2.x是不行的哈
数据恢复案例:这边只测试了8.0版本的数据恢复,5.7的好像不行,大家可以按作者的方法试一下,在5.7版本下,我没有验证成功
以下操作都是在MySQL8.0版本下哈
在数据库中创建表和插入数据:
use test;
CREATE TABLE `test` (
`id` int DEFAULT NULL,
`name` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT 'name'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
插入测试数据:
mysql> insert into test.test ( id,name) values(1,'skinfo'),(2,'skinfo'),(3,'skinfo');
Query OK, 3 rows affected (0.02 sec)
Records: 3 Duplicates: 0 Warnings: 0
查看插入的数据:
mysql> select * from test.test;
+------+--------+
| id | name |
+------+--------+
| 1 | skinfo |
| 2 | skinfo |
| 3 | skinfo |
+------+--------+
3 rows in set (0.00 sec)
这时再删除1条数据:
mysql> delete from test.test where id=3;
Query OK, 1 row affected (0.02 sec)
mysql> select * from test.test;
+------+--------+
| id | name |
+------+--------+
| 1 | skinfo |
| 2 | skinfo |
+------+--------+
2 rows in set (0.00 sec)
假设这个时间数据库宕机了,实例也无法启动了,要如何恢复test.test中的数据呢,这个时间就是ibd2sql发挥作用的时间了,哈哈。。
1.找到test.test表的物理文件,如果是rpm包安装的,在/var/lib/mysql/test这个目录下,有个叫test.ibd的文件
2.把这个文件复制到其它目录,没错,是直接复制到其它目录,数据库实例也不需要启动哈
[root@mysql8035 test]# cd /var/lib/mysql/test
[root@mysql8035 test]# pwd
/var/lib/mysql/test
[root@mysql8035 test]# ls
test.ibd
[root@mysql8035 test]# cp test.ibd /root/
[root@mysql8035 ~]# pwd
/root
[root@mysql8035 ~]# ls
test.ibd
3.运行以下的命令:
到ibd2sql目录下:
[root@mysql8035 ibd2sql-main]# pwd
/root/ibd2sql-main
[root@mysql8035 ibd2sql-main]# ls
getsql.py ibd2sql LICENSE main.py README.md README_OLD.md
[root@mysql8035 ibd2sql-main]#
运行以下命令:
查看test表的创建语句:
[root@node234 ibd2sql-main]# python3 ./main.py ./test.ibd --ddl
CREATE TABLE IF NOT EXISTS `test`.`test`(
`id` int NULL,
`name` varchar(20) NOT NULL COMMENT 'name'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ;
查看test表中已存在的数据:
[root@node234 ibd2sql-main]# python3 ./main.py ./test.ibd --sql
INSERT INTO `test`.`test` VALUES (1, 'skinfo');
INSERT INTO `test`.`test` VALUES (2, 'skinfo');
查看test表中已删除的数据:(注意:如果表已analyze了,这个就解析不出来哈)
[root@node234 ibd2sql-main]# python3 ./main.py ./test.ibd --sql --delete
INSERT INTO `test`.`test` VALUES (3, 'skinfo');
有上面一些数据,接入来就是导入数据库就可以了
通过ibd2sql解析出来的SQL语句跟上面操作的一样哈,数据还原回来了哈,大家可以按上面的步骤自己动手实践一下哈。。。
总结:
ibd2sql主要用于以下数据恢复场景:
没有备份,数据误删,文件有部分损坏等情况下可以尝试分析ibd数据文件,来恢复数据哈
2024-05-12
MySQL8.0数据灾难恢复之只有ibd物理文件怎么恢复数据?
评论
发表评论
姓 名: