冷血灰大狼 發表於 2025-6-13 10:06:00

工具分享-从ibd文件中恢复数据的神器ibd2sql

<h1 id="工具分享-从ibd文件中恢复数据的神器ibd2sql">工具分享-从ibd文件中恢复数据的神器ibd2sql</h1>
<h2 id="1-ibd2sql-的使用场景">1. ibd2sql 的使用场景</h2>
<p>在单节点单表表空间损坏的情况下,一般我们想到的方法是从最近的备份中恢复表数据并从Binlog中合并数据。</p>
<p>假如备份和Binlog缺失,那就只能从ibd文件中紧急恢复数据,可以使用 ibd2sql 这个工具去恢复数据。</p>
<h2 id="2-ibd2sql-简介">2. ibd2sql 简介</h2>
<p>ibd2sql is tool of transform mysql ibd file to sql(data).</p>
<p>ibd2sql是一个使用纯<code>python3</code>编写的<strong>离线解析</strong> MySQL InnoDB 存储引擎的<code>ibd文件</code>的工具。无第三方依赖包,使用<strong>GPL-3.0</strong> license。</p>
<ul>
<li>项目地址:https://github.com/ddcw/ibd2sql</li>
</ul>
<h2 id="3-实测">3. 实测</h2>
<h3 id="31-环境信息">3.1 环境信息</h3>
<p>操作系统:ky10.x86_64</p>
<p>数据库版本:GreatSQL-8.0.32-27</p>
<h3 id="32数据库安装并初始化数据">3.2数据库安装并初始化数据</h3>
<p>GreatSQL安装参考:https://greatsql.cn/docs/8.0.32-27/3-quick-start/3-2-quick-start-with-tarball.html</p>
<pre><code class="language-SQL">--创建测试库
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, '[]');
</code></pre>
<h3 id="33ibd2sql下载使用">3.3ibd2sql下载使用</h3>
<pre><code class="language-SQL">-- 安装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
</code></pre>
<h4 id="331尝试对workflow_state表进行表结构恢复">3.3.1尝试对workflow_state表进行表结构恢复</h4>
<pre><code class="language-SQL">-- 恢复表结构,后面带的 --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 ;
</code></pre>
<h4 id="332尝试对workflow_state表进行表数据恢复">3.3.2尝试对workflow_state表进行表数据恢复</h4>
<pre><code class="language-SQL">-- 恢复表数据,后面带的 --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, '[]');
</code></pre>
<h4 id="333更多使用方法">3.3.3更多使用方法</h4>
<p>可以使用--help 查看完整的使用方法,在表空间损坏的情况下可以通过--force, -f 强制调用ibd文件拯救数据</p>
<pre><code class="language-SQL">--help详情
$ 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]
               

-- 解析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_NAMEreplace 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
</code></pre>
<h4 id="334修改lower_case_table_names">3.3.4修改lower_case_table_names</h4>
<p><code>lower_case_table_names</code> 是 MySQL 设置大小写是否敏感的一个参数。</p>
<pre><code class="language-SQL">lower_case_table_names = 0 表名存储为给定的大小和比较是区分大小写的
lower_case_table_names = 1 表名存储在磁盘是小写的,但是比较的时候是不区分大小写
lower_case_table_names = 2 表名存储为给定的大小写但是比较的时候是小写的
</code></pre>
<p>通常我们在数据库初始化的时候就已经确定这个参数,想要修改这个参数只能导出重新初始化再导入。</p>
<p>但是ibd2sql号称可以直接修改<code>lower_case_table_names</code>,请各位看官老爷往下看。</p>
<p><strong>lower_case_table_names 由0改成1,对象中已经有大小写混合,可以启动但是原本大小写混合对象读写会有问题</strong></p>
<pre><code class="language-go">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&gt; show tables;
+----------------+
| Tables_in_test |
+----------------+
| TMst         |
+----------------+
1 row in set (0.01 sec)

greatsql&gt; SELECT * FROM TMst;
ERROR 1146 (42S02): Table 'test.tmst' doesn't exist

greatsql&gt; INSERT INTO test.TMst (creator) VALUES ('user3');
ERROR 1146 (42S02): Table 'test.tmst' doesn't exist


greatsql&gt; DROP database test;
greatsql&gt; 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).
</code></pre>
<p><strong>lower_case_table_names 由1改成0,对象读写正常</strong></p>
<pre><code class="language-go">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为1
$ 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 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&gt; CREATE TABLE IF NOT EXISTS `test1`.`TMst`(
    -&gt;   `id` int NOT NULL AUTO_INCREMENT,
    -&gt;   `creator` varchar(64) NULL,
    -&gt;   `updated_by` varchar(64) NULL,
    -&gt;   `end_at` datetime(6) NULL,
    -&gt;   PRIMARY KEY(`id` )
    -&gt; ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ;
Query OK, 0 rows affected (0.01 sec)

greatsql&gt; INSERT INTO test1.TMst (creator) VALUES ('user2');
Query OK, 1 row affected (0.02 sec)

greatsql&gt; INSERT INTO test1.TMst (creator) VALUES ('user1');
Query OK, 1 row affected (0.01 sec)

greatsql&gt; SELECT * FROM `test1`.`TMst`;
+----+---------+------------+--------+
| id | creator | updated_by | end_at |
+----+---------+------------+--------+
|1 | user2   | NULL       | NULL   |
|2 | user1   | NULL       | NULL   |
+----+---------+------------+--------+
2 rows in set (0.00 sec)

greatsql&gt; SELECT * FROM `test1`.`tmst`;
+----+---------+------------+--------+
| id | creator | updated_by | end_at |
+----+---------+------------+--------+
|1 | user2   | NULL       | NULL   |
|2 | user1   | NULL       | NULL   |
+----+---------+------------+--------+
2 rows in set (0.01 sec)
</code></pre>
<h3 id="结论">结论</h3>
<ol>
<li>
<p>修改lower_case_table_names</p>
</li>
<li>
<p>由0改成1,对象中已经有大小写混合,可以启动但是原本大小写混合对象读写会有问题。</p>
</li>
<li>
<p>由1改成0,对象读写正常,操作名字大小混合的对象也正常。</p>
</li>
</ol>
<h2 id="参考文章">参考文章</h2>
<ol>
<li>GreatSQL 二进制安装:https://greatsql.cn/docs/8.0.32-27/3-quick-start/3-2-quick-start-with-tarball.html</li>
<li>ibd2sql项目README_zh.md https://github.com/ddcw/ibd2sql/blob/main/README_zh.md</li>
</ol>
<hr>
<p>Enjoy GreatSQL 😃</p>
<h2 id="关于-greatsql">关于 GreatSQL</h2>
<p>GreatSQL是适用于金融级应用的国内自主开源数据库,具备高性能、高可靠、高易用性、高安全等多个核心特性,可以作为MySQL或Percona Server的可选替换,用于线上生产环境,且完全免费并兼容MySQL或Percona Server。</p>
<p>相关链接:   GreatSQL社区        Gitee        GitHub        Bilibili</p>
<h2 id="greatsql社区">GreatSQL社区:</h2>
<blockquote>
<p>社区博客有奖征稿详情:https://greatsql.cn/thread-100-1-1.html</p>
</blockquote>
<p><img src="https://img2024.cnblogs.com/other/2630741/202506/2630741-20250613100628461-1110992950.png"></p>
<h2 id="技术交流群">技术交流群:</h2>
<blockquote>
<p>微信:扫码添加<code>GreatSQL社区助手</code>微信好友,发送验证信息<code>加群</code>。</p>
</blockquote>
<p><img src="https://img2024.cnblogs.com/other/2630741/202506/2630741-20250613100628762-519585386.png"></p><br><br>
来源:https://www.cnblogs.com/greatsql/p/18926542
頁: [1]
查看完整版本: 工具分享-从ibd文件中恢复数据的神器ibd2sql