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%'