数据恢复关键:ibd文件数据提取工具深度剖析
1. ibd2sql的应用场景
当单节点下单个表的表空间出现损坏情况时,常规的做法通常是从最近的备份中恢复表数据,并且从Binlog中合并数据。
要是备份和Binlog都缺失的话,那就只能从ibd文件里紧急恢复数据,这时候可以使用ibd2sql这个工具来进行恢复。
2. ibd2sql概述
ibd2sql是一款用于将MySQL InnoDB存储引擎的ibd文件转换为SQL(数据)的工具。
ibd2sql是用纯python3编写的离线解析ibd文件的工具,没有第三方依赖包,采用GPL-3.0许可证。
3. 实测
3.1 环境情况
操作系统:ky10.x86_64
数据库版本:GreatSQL-8.0.32-27
3.2数据库的安装与数据初始化
GreatSQL的安装参考:https://greatsql.cn/docs/8.0.32-27/3-quick-start/3-2-quick-start-with-tarball.html
--创建测试数据库
CREATE DATABASE test;
--创建测试表
CREATE TABLE `test`.`workflow_state` (
`id` int NOT NULL AUTO_INCREMENT,
`creator` varchar(64) DEFAULT NULL,
`create_at` datetime(6) NOT NULL,
`update_at` datetime(6) NOT NULL,
`updated_by` varchar(64) DEFAULT NULL,
`end_at` datetime(6) DEFAULT NULL,
`is_deleted` tinyint(1) NOT NULL,
`name` varchar(64) NOT NULL,
`desc` varchar(64) DEFAULT NULL,
`type` varchar(32) NOT NULL,
`processors_type` varchar(32) NOT NULL,
`processors` varchar(255) DEFAULT NULL,
`distribute_type` varchar(32) NOT NULL,
`notify_rule` varchar(32) NOT NULL,
`notify_freq` int NOT NULL,
`fields` longtext,
`extras` varchar(1000) DEFAULT NULL,
`is_draft` tinyint(1) NOT NULL,
`is_builtin` tinyint(1) NOT NULL,
`workflow_id` int NOT NULL,
`is_terminable` tinyint(1) NOT NULL,
`followers` varchar(255) DEFAULT NULL,
`followers_type` varchar(32) NOT NULL,
`api_instance_id` int DEFAULT NULL,
`assignors` longtext DEFAULT (_utf8mb3''),
PRIMARY KEY (`id`),
KEY `workflow_state_workflow_id_ef53cea4_fk_workflow_workflow_id` (`workflow_id`),
KEY `workflow_state_is_deleted_37d5c517` (`is_deleted`)
) ENGINE=InnoDB;
--插入初始数据
INSERT INTO `test`.`workflow_state` VALUES (1, 'admin', '2025-4-28 10:0:0.0', '2025-4-28 10:0:0.0', NULL, NULL, 0, '审批节点1', '基础审批流程', 'approval', 'user', 'user123', 'round_robin', 'immediate', 1, '{"field1": "value1"}', '{"priority": "high"}', 0, 1, 1, 1, 'user456,user789', 'specific', 1001, '["assignor1"]');
INSERT INTO `test`.`workflow_state` VALUES (10, 'system', '2025-4-28 10:45:0.0', '2025-4-28 10:45:0.0', NULL, NULL, 0, '子流程', '调用子工作流', 'subflow', 'system', NULL, 'direct', 'immediate', 1, '{"subflow_id": 100}', '{"parameters": "{}"}', 0, 1, 10, 1, NULL, 'none', 1006, '[]');
3.3ibd2sql的下载与使用
-- 安装python3
yum -y install python3
-- 下载ibd2sql,若无法通过wget下载,可直接复制网址到浏览器进行下载
wget https://github.com/ddcw/ibd2sql/archive/refs/heads/main.zip
-- 解压
unzip ibd2sql-main.zip
-- 进入ibd2sql目录
cd ibd2sql-main
3.3.1尝试恢复workflow_state表的表结构
-- 恢复表结构,后面添加--ddl参数用于生成表结构
$ python3.7 main.py /greatsql/dbdata/data3306/data/test/workflow_state.ibd --sql --ddl
CREATE TABLE IF NOT EXISTS `test`.`workflow_state`(
`id` int NOT NULL AUTO_INCREMENT,
`creator` varchar(64) NULL,
`create_at` datetime(6) NOT NULL,
`update_at` datetime(6) NOT NULL,
`updated_by` varchar(64) NULL,
`end_at` datetime(6) NULL,
`is_deleted` tinyint(1) NOT NULL,
`name` varchar(64) NOT NULL,
`desc` varchar(64) NULL,
`type` varchar(32) NOT NULL,
`processors_type` varchar(32) NOT NULL,
`processors` varchar(255) NULL,
`distribute_type` varchar(32) NOT NULL,
`notify_rule` varchar(32) NOT NULL,
`notify_freq` int NOT NULL,
`fields` longtext NULL,
`extras` varchar(1000) NULL,
`is_draft` tinyint(1) NOT NULL,
`is_builtin` tinyint(1) NOT NULL,
`workflow_id` int NOT NULL,
`is_terminable` tinyint(1) NOT NULL,
`followers` varchar(255) NULL,
`followers_type` varchar(32) NOT NULL,
`api_instance_id` int NULL,
`assignors` longtext NULL DEFAULT (_utf8mb3''),
PRIMARY KEY (`id` ),
KEY `workflow_state_workflow_id_ef53cea4_fk_workflow_workflow_id` (`workflow_id` ),
KEY `workflow_state_is_deleted_37d5c517` (`is_deleted` )
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ;
3.3.2尝试恢复workflow_state表的数据
-- 恢复表数据,后面添加--sql参数将数据转换为sql,也可使用--complete-insert合并insert语句
$ python3.7 main.py /greatsql/dbdata/data3306/data/test/workflow_state.ibd --sql
INSERT INTO `test`.`workflow_state` VALUES (1, 'admin', '2025-4-28 10:0:0.0', '2025-4-28 10:0:0.0', NULL, NULL, 0, '审批节点1', '基础审批流程', 'approval', 'user', 'user123', 'round_robin', 'immediate', 1, '{"field1": "value1"}', '{"priority": "high"}', 0, 1, 1, 1, 'user456,user789', 'specific', 1001, '["assignor1"]');
INSERT INTO `test`.`workflow_state` VALUES (10, 'system', '2025-4-28 10:45:0.0', '2025-4-28 10:45:0.0', NULL, NULL, 0, '子流程', '调用子工作流', 'subflow', 'system', NULL, 'direct', 'immediate', 1, '{"subflow_id": 100}', '{"parameters": "{}"}', 0, 1, 10, 1, NULL, 'none', 1006, '[]');
3.3.3更多使用方法
可以使用–help命令查看完整的使用方法,在表空间损坏时可通过–force, -f参数强制调用ibd文件来拯救数据
--查看帮助详情
$ python3.7 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]
[--keyring-file KEYRING_FILE]
[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
--keyring-file KEYRING_FILE, -k KEYRING_FILE
keyring filename
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
3.3.4修改lower_case_table_names
lower_case_table_names
是MySQL中用于设置表名大小写是否敏感的一个参数。
lower_case_table_names = 0 表名以给定的大小写存储且比较时区分大小写
lower_case_table_names = 1 表名在磁盘上存储为小写,但比较时不区分大小写
lower_case_table_names = 2 表名以给定的大小写存储,但比较时为小写
通常在数据库初始化时就已确定该参数,若要修改只能导出后重新初始化再导入。不过ibd2sql号称能直接修改lower_case_table_names
,各位接着往下看。
lower_case_table_names由0改为1,若对象中已有大小写混合情况,可启动但原本大小写混合的对象读写会出问题
CREATE TABLE IF NOT EXISTS `test`.`TMst`(
`id` int NOT NULL AUTO_INCREMENT,
`creator` varchar(64) NULL,
`updated_by` varchar(64) NULL,
`end_at` datetime(6) NULL,
PRIMARY KEY (`id` )
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ;
INSERT INTO test.TMst (creator) VALUES ('user2');
INSERT INTO test.TMst (creator) VALUES ('user1');
--查看原来的lower_case_table_names是1还是0
$ python3 modify_lower_case_table_names.py /greatsql/dbdata/data3306/data/mysql.ibd
lower_case_table_names: 0
--停止数据库
$ systemctl stop greatsql
--修改lower_case_table_names为1
$ python3 modify_lower_case_table_names.py /greatsql/dbdata/data3306/data/mysql.ibd ./mysql.ibd 1
set lower_case_table_names=1 into new file(./mysql.ibd) finish.
--对比文件权限属主
$ ls -la ./mysql.ibd
-rw-r--r-- 1 root root 26214400 Apr 29 10:58 ./mysql.ibd
$ ls -la /greatsql/dbdata/data3306/data/mysql.ibd
-rw-r----- 1 greatsql greatsql 26214400 Apr 29 10:56 /greatsql/dbdata/data3306/data/mysql.ibd
--修改文件属主
$ chmod 640 ./mysql.ibd
$ chown greatsql:greatsql ./mysql.ibd
-- 覆盖原来的mysql.ibd文件
$ mv ./mysql.ibd /greatsql/dbdata/data3306/data
mv: overwrite '/greatsql/dbdata/data3306/data/mysql.ibd'? y
--修改配置文件中的lower_case_table_names=1
$ vi /greatsql/conf/greatsql3306.cnf
--启动数据库
$ systemctl start greatsql
--查询表,插入数据报错
greatsql> show tables;
+----------------+
| Tables_in_test |
+----------------+
| TMst |
+----------------+
1 row in set (0.01 sec)
greatsql> SELECT * FROM TMst;
ERROR 1146 (42S02): Table 'test.tmst' doesn't exist
greatsql> INSERT INTO test.TMst (creator) VALUES ('user3');
ERROR 1146 (42S02): Table 'test.tmst' doesn't exist
greatsql> DROP database test;
greatsql> CREATE database test;
ERROR 3678 (HY000): Schema directory './test' already exists. This must be resolved manually (e.g. by moving the schema directory to another location).
lower_case_table_names由1改为0,对象读写正常
create database test1;
CREATE TABLE IF NOT EXISTS `test1`.`tmst`(
`id` int NOT NULL AUTO_INCREMENT,
`creator` varchar(64) NULL,
`updated_by` varchar(64) NULL,
`end_at` datetime(6) NULL,
PRIMARY KEY (`id` )
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ;
INSERT INTO test1.tmst (creator) VALUES ('user2');
INSERT INTO test1.tmst (creator) VALUES ('user1');
--查看原来的lower_case_table_names是1还是0
$ python3 modify_lower_case_table_names.py /greatsql/dbdata/data3306/data/mysql.ibd
lower_case_table_names: 1
--停止数据库
$ systemctl stop greatsql
--修改lower_case_table_names为0
$ python3 modify_lower_case_table_names.py /greatsql/dbdata/data3306/data/mysql.ibd ./mysql.ibd 0
set lower_case_table_names=0 into new file(./mysql.ibd) finish.
--对比文件权限属主
$ ls -la ./mysql.ibd
-rw-r--r-- 1 root root 26214400 Apr
© 版权声明
文章版权归作者所有,未经允许请勿转载。
相关文章
暂无评论...