mysql8只有ibd文件的情况下恢复数据

mysql8只有ibd文件的情况下恢复数据

1. 本地安装数据库或在cmd中执行 ibd2sdi 命令

ps:ibd2sdi是mysql8及以上自带工具

2.新建数据库

3.执行java代码生成创建表的sql语句

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.file.FileWriter;
import cn.hutool.json.*;
import java.io.IOException;
import java.util.List;
/**
* 根据ibd文件生成对应的json文件
**/
    public static void getJson(){
        String command = "ibd2sdi --dump-file C:\\Users\\zs\\Desktop\\db\\DATA_NAME.json C:\\Users\\zs\\Desktop\\test\\DATA_NAME.ibd";
        Runtime runtime = Runtime.getRuntime();
        List<String> strings = FileUtil.listFileNames("C:\\Users\\zs\\Desktop\\test");
        strings.forEach(s -> {
            String new_command = command.replace("DATA_NAME", s.replace(".ibd", ""));
            System.out.println(new_command);
            try {
                Process process = runtime.exec(new_command);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        });
    }
 /**
 * 根据json文件生成对应的sql语句
 **/
 public static void getSql(){
        String baseDir = "C:\\Users\\zs\\Desktop\\db";
        List<String> strings = FileUtil.listFileNames(baseDir);
        StringBuilder sqlSql = new StringBuilder();
        StringBuilder alSql = new StringBuilder();
        strings.forEach(s->{
            String s1 = FileUtil.readString(baseDir + "\\" + s, "utf-8");
            JSONArray objects = JSONUtil.parseArray(s1);
            JSONObject data = (JSONObject) objects.get(1);
            // 提取表名和字段信息
            String tableName = data.getJSONObject("object").getJSONObject("dd_object").getStr("name");
            JSONArray columns = data.getJSONObject("object").getJSONObject("dd_object").getJSONArray("columns");
            // 构建创建表的 SQL 查询语句
            StringBuffer sql = new StringBuffer("CREATE TABLE ");
            sql.append(tableName).append(" (");
            columns.forEach(c->{
                JSONObject columnObj = (JSONObject) c;
                String columnName = columnObj.getStr("name");
                // 如果字段名不是 DB_TRX_ID 和 DB_ROLL_PTR,则构建该字段的 SQL
                if (!"DB_TRX_ID".equals(columnName)&&
                            !"DB_ROLL_PTR".equals(columnName)&&
                            !"!hidden!_dropped_v1_p7_bId".equals(columnName)&&
                            !"DB_ROW_ID".equals(columnName)) {
                    String default_value = columnObj.getStr("default_value_utf8");
                    String columnType = columnObj.getStr("column_type_utf8");
                    String isNullable = columnObj.getBool("is_nullable") ? "NULL" : "NOT NULL";
                    String default_ = columnObj.getBool("default_value_utf8_null") ? "" : "DEFAULT "+default_value;
                    Boolean isAutoIncrement = columnObj.getBool("is_auto_increment");

                    // 构建列的注释,如果注释为空,不包含 COMMENT 部分
                    String comment = columnObj.getStr("comment");
                    // 构建列的 SQL
                    sql.append(columnName).append(" ")
                            .append(columnType).append(" ");
                    if (isAutoIncrement){
                        sql.append(" auto_increment ");
                    }
                    sql.append(default_).append(" ")
                            .append(isNullable).append(" ")
                            .append("COMMENT '").append(comment).append("'");
                    if (isAutoIncrement){
                        sql.append(" primary key ");
                    }
                    sql.append(",");
                }
            });

            String substring = sql.substring(0, sql.length() - 1);
            sqlSql.append(substring).append(" ) ENGINE=InnoDB ; \n alter table ") .append(tableName).append(" discard tablespace;\n");
            alSql.append("alter table ").append(tableName).append(" import tablespace; \n");
        });
        FileWriter fileWriter = new FileWriter(baseDir + "\\sql\\test.sql");
        fileWriter.write(sqlSql.toString());
        FileWriter al = new FileWriter(baseDir + "\\sql\\al.sql");
        al.write(alSql.toString());
    }

4.在2新建的数据库中执行3中等到的test.sql文件

ps:test.sql文件包含两部分,建表语句+将InnoDB表的表空间移除

5.将你原有的ibd文件拷贝到2新建数据库对应的文件夹中

6.执行3中al.sql文件

ps:al.sql文件用来重新加载表空间

7.刷新当前数据库,数据已恢复

写在最后,我恢复的是InnoDB引擎的数据,其他请查阅资料
-- 查询数据存储位置
show global variables like '%datadir%'
### 使用 MySQL IBD 文件进行表空间或数据恢复的最佳实践 #### 方法概述 当需要通过 `.ibd` 文件恢复 MySQL 表的空间或数据时,可以按照以下方法操作。此过程涉及多个步骤,包括创建数据库架构、丢弃和重新导入表空间以及调整文件权限。 --- #### 步骤说明 1. **创建目标数据库 Schema** 需要先确保目标数据库已经存在并具有相同的结构。如果没有现成的建表语句,则可以通过解析 `ibdata` 或其他方式获取 DDL 信息[^2]。 ```sql CREATE DATABASE IF NOT EXISTS target_database; USE target_database; ``` 2. **重建表结构** 如果原始表定义仍然可用,则可以直接执行相应的建表语句;否则可能需要手动重构这些表的定义或者尝试从元数据中提取它们的信息[^3]。 3. **丢弃现有表空间** 对于每一个待恢复的表,在其上运行如下 SQL 命令来释放当前关联的存储引擎实例: ```sql ALTER TABLE table_name DISCARD TABLESPACE; ``` 4. **复制原生 .ibd 文件至适当位置** 将备份中的实际物理磁盘映像拷贝回默认路径下的相应子目录里去替换掉旧版本的那个副本,并确认所属关系正确无误以便后续加载动作能够顺利开展下去: ```bash cp /path/to/backup/table_name.ibd /var/lib/mysql/target_database/ chown mysql:mysql /var/lib/mysql/target_database/table_name.ibd ``` 5. **重载外部链接资源** 完成了前面几步之后就可以再次调用下面这条指令让系统重新认识这个已经被更改过的对象了——即把之前分离出去的部分接回来形成完整的整体视图供查询使用等功能正常运作起来啦! ```sql ALTER TABLE table_name IMPORT TABLESPACE; ``` 上述流程完成后应该就能看到预期效果咯~不过需要注意的是整个过程中涉及到的操作都比较敏感所以一定要小心谨慎行事哦😊 --- ### 注意事项 - 确认源环境和服务端配置参数一致比如字符集编码等细节方面的东西不然可能会引起兼容性问题导致失败告警提示出来呢❌; - 备份前最好关闭自动提交模式以免中途被打断造成不必要的麻烦😅; - 不同操作系统之间可能存在细微差异所以在移植跨平台项目的时候记得查阅官方文档了解更多相关内容吧📚。 ```python # 示例 Python 脚本用于自动化部分任务 (可选) import os import subprocess def restore_ibd(database, table, backup_path): # Step 1: Create database and use it create_db_cmd = f"CREATE DATABASE IF NOT EXISTS {database};" execute_sql(create_db_cmd) # Step 2: Discard tablespace discard_cmd = f"ALTER TABLE `{table}` DISCARD TABLESPACE;" execute_sql(discard_cmd) # Step 3: Copy .ibd file to correct location ibd_file = f"{backup_path}/{table}.ibd" dest_dir = f"/var/lib/mysql/{database}/" copy_command = ["cp", ibd_file, dest_dir] change_owner_command = ["chown", "mysql:mysql", f"{dest_dir}{table}.ibd"] run_shell(copy_command) run_shell(change_owner_command) # Step 4: Import tablespace back into the system import_cmd = f"ALTER TABLE `{table}` IMPORT TABLESPACE;" execute_sql(import_cmd) def execute_sql(query): """Executes given SQL query.""" command = ['mysql', '-uroot', '-e', query] result = subprocess.run(command, capture_output=True, text=True) if result.returncode != 0: raise Exception(f"Error executing SQL: {result.stderr}") def run_shell(cmd_list): """Runs shell commands provided as a list of strings.""" process = subprocess.Popen(cmd_list, stdout=subprocess.PIPE, stderr=subprocess.PIPE) output, error = process.communicate() if process.returncode != 0: raise Exception(f"Shell Command Failed with Error:\n{error.decode('utf-8')}") ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值