暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

纳尼,MySQL 只剩个 ibd 文件也能救???

00后DBA实录 2024-10-25
46

前言


分享一个朋友写的非常非常强大的 mysql 恢复工具,救生产环境于水深火热之中。

项目地址:https://github.com/ddcw/ibd2sql

ibd2sql是一个使用纯python3
编写的离线解析MYSQL INNODB存储引擎的ibd文件
的工具. 无第三方依赖包. 使用GPL-3.0 license.


好工具应该被更多人知道,向大佬学习!!!


特点


  1. 方便: 提取表DDL

  2. 实用: 可替换库(--schema)/表(--table)名, 可在sql语句中输出完整的字段(--complete)

  3. 简单: 纯python3代码编写, 无依赖包.

  4. 支持众多数据类型: 支持所有mysql数据类型

  5. 支持复杂的表结构: 分区表, 注释, 主键, 外键, 约束, 自增, 普通索引, 前缀索引, 主键前缀索引, 唯一索引, 复合索引, 默认值, 符号, 虚拟字段, INSTANT, 无主键等情况的表

  6. 数据误删恢复: 可以输出被标记为deleted的数据

  7. 安全: 离线解析ibd文件, 仅可读权限即可

  8. 支持范围广: 支持mysql 5.6 or 5.7 or 8.0 or 8.4 or 9.0


安装 python 3


     wget https://www.python.org/ftp/python/3.7.0/Python-3.7.0.tar.xz
    tar -xvJf Python-3.7.0.tar.xz
    cd Python-3.7.0/
    ./configure prefix=/usr/local/python3
    ./configure --enable-optimizations
    make && make install
    ln -fs usr/local/python3/bin/python3 usr/bin/python3
     ln -fs /usr/local/python3/bin/pip3 /usr/bin/pip3


    安装 ibd2sql


       wget https://github.com/ddcw/ibd2sql/archive/refs/heads/main.zip
      unzip main.zip
      cd ibd2sql-main


      只剩个 ibd 文件怎么抢救数据


      测试数据

        create table testidb2sql(
        id int primary key,
        info varchar(255),
        text blob,
        key(info)
        );
        insert into testidb2sql values(1,'aa','wadwaderoiohooawde12222222');
        insert into testidb2sql values(2,'aa','1212112121211rrrrrr');

        root@localhost [ddl] 18:42:16 > show create table testidb2sql;
        +-------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
        | Table | Create Table |
        +-------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
        | testidb2sql | CREATE TABLE `testidb2sql` (
        `id` int NOT NULL,
        `info` varchar(255) DEFAULT NULL,
        `text` blob,
        PRIMARY KEY (`id`),
        KEY `info` (`info`)
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci |
        +-------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
        1 row in set (0.00 sec)

        root@localhost [ddl] 19:06:02 > select * from testidb2sql;
        +----+------+--------------------------------------------------------+
        | id | info | text |
        +----+------+--------------------------------------------------------+
        | 1 | aa | 0x77616477616465726F696F686F6F617764653132323232323232 |
        | 2 | aa | 0x31323132313132313231323131727272727272 |
        +----+------+--------------------------------------------------------+
        2 rows in set (0.00 sec)


        先拷贝一个 ibd 文件的备份

          cp /data/mysql_8_3306/ddl/testidb2sql.ibd /data/mysql_8_3306/ddl/testidb2sql.ibd_bak

          破坏数据库

             root@localhost [ddl] 18:47:37 > drop table testidb2sql;
            Query OK, 0 rows affected (0.02 sec)


            只剩个 ibd ,拿到表结构

              [root@localhost ibd2sql]# python3 main.py data/mysql_8_3306/ddl/testidb2sql.ibd_bak --ddl
              CREATE TABLE IF NOT EXISTS `ddl`.`testidb2sql`(
              `id` int NOT NULL,
              `info` varchar(255) NULL,
              `text` blob NULL,
              PRIMARY KEY (`id` ),
              KEY `info` (`info` )
              ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ;

              对比一下,是不是没有问题。


              恢复方式 1 导入表空间


              先登录数据库使用表结构,把表恢复出来,将表结构先写入数据字典。

                 CREATE TABLE IF NOT EXISTS `ddl`.`testidb2sql`(
                `id` int NOT NULL,
                `info` varchar(255) NULL,
                `text` blob NULL,
                PRIMARY KEY (`id` ),
                KEY `info` (`info` )
                ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ;

                看一下数据目录,可以看到已经生成了 ibd testidb2sql.ibd,表创建流程参考前面 ONLINE DDL 关于 ddllog 的解析。

                   [root@localhost ddl]# ll
                  总用量 864
                  -rw-r-----. 1 mysql mysql 131072 10月 21 22:42 al_ddl.ibd
                  -rw-r-----. 1 mysql mysql 131072 10月 21 18:30 ddl.ibd
                  -rw-r-----. 1 mysql mysql 114688 10月 22 00:03 int_test.ibd
                  -rw-r-----. 1 mysql mysql 114688 10月 20 12:09 onlineddl.ibd
                  -rw-r-----. 1 mysql mysql 131072 10月 23 15:21 tddl.ibd
                  -rw-r-----. 1 mysql mysql 131072 10月 25 18:54 testidb2sql.ibd
                  -rw-r-----. 1 root root 131072 10月 25 18:47 testidb2sql.ibd_bak

                  然后卸载表空间

                     alter table `ddl`.`testidb2sql` discard tablespace;

                    ddl log只有 2行

                       2024-10-25T18:58:57.406440+08:00 73 [Note] [MY-012485] [InnoDB] DDL log post ddl : begin for thread id : 73
                      2024-10-25T18:58:57.406595+08:00 73 [Note] [MY-012486] [InnoDB] DDL log post ddl : end for thread id : 73

                      可以看到 ibd 文件没了

                         [root@localhost ddl]# ll
                        总用量 736
                        -rw-r-----. 1 mysql mysql 131072 10月 21 22:42 al_ddl.ibd
                        -rw-r-----. 1 mysql mysql 131072 10月 21 18:30 ddl.ibd
                        -rw-r-----. 1 mysql mysql 114688 10月 22 00:03 int_test.ibd
                        -rw-r-----. 1 mysql mysql 114688 10月 20 12:09 onlineddl.ibd
                        -rw-r-----. 1 mysql mysql 131072 10月 23 15:21 tddl.ibd
                        -rw-r-----. 1 root root 131072 10月 25 18:47 testidb2sql.ibd_bak

                        我们改个名导入一下。

                           [root@localhost ddl]# mv testidb2sql.ibd_bak testidb2sql.ibd

                          啊嘞,报错了,找不到表空间。

                             root@localhost [(none)] 18:58:57 > alter table `ddl`.`testidb2sql` import tablespace;
                            ERROR 1812 (HY000): Tablespace is missing for table `ddl`.`testidb2sql`.

                            大家知道为什么吗?

                            可以看到这里:

                               -rw-r-----. 1 root  root  131072 10月 25 18:47 testidb2sql.ibd_bak

                              所以大家记得务必改一下权限哦。

                                 [root@localhost ddl]# chown mysql.mysql testidb2sql.ibd
                                [root@localhost ddl]# ll
                                总用量 736
                                -rw-r-----. 1 mysql mysql 131072 10月 21 22:42 al_ddl.ibd
                                -rw-r-----. 1 mysql mysql 131072 10月 21 18:30 ddl.ibd
                                -rw-r-----. 1 mysql mysql 114688 10月 22 00:03 int_test.ibd
                                -rw-r-----. 1 mysql mysql 114688 10月 20 12:09 onlineddl.ibd
                                -rw-r-----. 1 mysql mysql 131072 10月 23 15:21 tddl.ibd
                                -rw-r-----. 1 mysql mysql 131072 10月 25 18:47 testidb2sql.ibd

                                再次导入

                                   root@localhost [(none)] 19:03:03 > select * from `ddl`.`testidb2sql`;
                                  +----+------+--------------------------------------------------------+
                                  | id | info | text |
                                  +----+------+--------------------------------------------------------+
                                  | 1 | aa | 0x77616477616465726F696F686F6F617764653132323232323232 |
                                  | 2 | aa | 0x31323132313132313231323131727272727272 |
                                  +----+------+--------------------------------------------------------+
                                  2 rows in set (0.00 sec)

                                  可以看到没有问题吧!!

                                  厉害吧!!


                                  恢复方式二 sql 导入


                                  直接创建表结构,然后导入就可以了,适合小表。

                                     [root@localhost ibd2sql]# python3 main.py data/mysql_8_3306/ddl/testidb2sql.ibd_bak --sql 
                                    INSERT INTO `ddl`.`testidb2sql` VALUES (1, 'aa', 'wadwaderoiohooawde12222222');
                                    INSERT INTO `ddl`.`testidb2sql` VALUES (2, 'aa', '1212112121211rrrrrr');


                                    解析误删数据


                                    这个的原理是,拿到标记为删除位的数据,触发回收机制就没救了,所以只能碰碰运气。


                                    我们给刚才的数据删掉 1 条,不要用 delete from testidb2sql 删全部啦,触发回收就没了。

                                       root@localhost [ddl] 19:06:02 > select * from testidb2sql;
                                      +----+------+--------------------------------------------------------+
                                      | id | info | text |
                                      +----+------+--------------------------------------------------------+
                                      | 1 | aa | 0x77616477616465726F696F686F6F617764653132323232323232 |
                                      | 2 | aa | 0x31323132313132313231323131727272727272 |
                                      +----+------+--------------------------------------------------------+
                                      2 rows in set (0.00 sec)

                                      root@localhost [ddl] 19:34:40 > delete from testidb2sql where id=1;
                                      Query OK, 1 row affected (0.01 sec)

                                      然后解析一下

                                         python3 main.py /data/mysql_8_3306/ddl/testidb2sql.ibd --sql --delete

                                        可以看到解析出来啦。

                                           [root@localhost ibd2sql]# python3 main.py /data/mysql_8_3306/ddl/testidb2sql.ibd --sql --delete
                                          INSERT INTO `ddl`.`testidb2sql` VALUES (1, 'aa', 'wadwaderoiohooawde12222222');

                                          膜拜大佬。




                                          文章转载自00后DBA实录,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                                          评论