|
|
|
@ -7,6 +7,9 @@ import com.obs.services.ObsClient;
|
|
|
|
|
|
|
|
|
|
import java.io.*;
|
|
|
|
|
import java.util.UUID;
|
|
|
|
|
import java.util.concurrent.ExecutorService;
|
|
|
|
|
import java.util.concurrent.Executors;
|
|
|
|
|
import java.util.concurrent.Future;
|
|
|
|
|
import java.util.zip.*;
|
|
|
|
|
|
|
|
|
|
public class MysqlRestoreService {
|
|
|
|
@ -116,58 +119,80 @@ public class MysqlRestoreService {
|
|
|
|
|
return extractedFile;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 还原数据库
|
|
|
|
|
*/
|
|
|
|
|
private void restoreDatabase(String sqlFile) {
|
|
|
|
|
try {
|
|
|
|
|
// 获取mysql命令路径
|
|
|
|
|
String mysqlPath = CommonUtil.getMySQLPath();
|
|
|
|
|
|
|
|
|
|
// 构建还原命令
|
|
|
|
|
ProcessBuilder pb = new ProcessBuilder(
|
|
|
|
|
mysqlPath,
|
|
|
|
|
"-h" + dbHost,
|
|
|
|
|
"-P" + dbPort,
|
|
|
|
|
"-u" + dbUser,
|
|
|
|
|
//"--ssl-mode=DISABLED",
|
|
|
|
|
"--skip-ssl", // 替换为MariaDB兼容的参数
|
|
|
|
|
"--skip-ssl",
|
|
|
|
|
dbName
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// 设置环境变量传递密码
|
|
|
|
|
pb.environment().put("MYSQL_PWD", dbPassword);
|
|
|
|
|
|
|
|
|
|
// 执行还原命令
|
|
|
|
|
// 启动进程
|
|
|
|
|
Process process = pb.start();
|
|
|
|
|
// 使用多线程处理输入输出流,避免死锁
|
|
|
|
|
ExecutorService executor = Executors.newFixedThreadPool(2);
|
|
|
|
|
// 处理错误输出流
|
|
|
|
|
Future<?> errorFuture = executor.submit(() -> {
|
|
|
|
|
try (BufferedReader reader = new BufferedReader(
|
|
|
|
|
new InputStreamReader(process.getErrorStream()))) {
|
|
|
|
|
String line;
|
|
|
|
|
while ((line = reader.readLine()) != null) {
|
|
|
|
|
if (!line.contains("WARNING")) {
|
|
|
|
|
System.out.println("还原进度: " + line);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} catch (IOException e) {
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 将SQL文件内容写入mysql进程的输入流
|
|
|
|
|
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(sqlFile));
|
|
|
|
|
BufferedOutputStream bos = new BufferedOutputStream(process.getOutputStream())) {
|
|
|
|
|
// 处理输入流(SQL文件)
|
|
|
|
|
Future<?> inputFuture = executor.submit(() -> {
|
|
|
|
|
try (BufferedInputStream sqlInput = new BufferedInputStream(new FileInputStream(sqlFile));
|
|
|
|
|
BufferedOutputStream processOutput = new BufferedOutputStream(process.getOutputStream())) {
|
|
|
|
|
|
|
|
|
|
byte[] buffer = new byte[8192];
|
|
|
|
|
int len;
|
|
|
|
|
while ((len = bis.read(buffer)) > 0) {
|
|
|
|
|
bos.write(buffer, 0, len);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// 读取错误输出
|
|
|
|
|
StringBuilder errorOutput = new StringBuilder();
|
|
|
|
|
try (BufferedReader reader = new BufferedReader(
|
|
|
|
|
new InputStreamReader(process.getErrorStream()))) {
|
|
|
|
|
String line;
|
|
|
|
|
while ((line = reader.readLine()) != null) {
|
|
|
|
|
if (!line.contains("WARNING")) {
|
|
|
|
|
errorOutput.append(line).append("\n");
|
|
|
|
|
System.out.println("还原进度: " + line);
|
|
|
|
|
byte[] buffer = new byte[8192];
|
|
|
|
|
int len;
|
|
|
|
|
long total = 0;
|
|
|
|
|
long fileSize = new File(sqlFile).length();
|
|
|
|
|
|
|
|
|
|
while ((len = sqlInput.read(buffer)) != -1) {
|
|
|
|
|
processOutput.write(buffer, 0, len);
|
|
|
|
|
total += len;
|
|
|
|
|
|
|
|
|
|
// 显示进度
|
|
|
|
|
int progress = (int) ((total * 100) / fileSize);
|
|
|
|
|
System.out.printf("\r导入进度: %d%%", progress);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 重要:刷新并关闭输出流
|
|
|
|
|
processOutput.flush();
|
|
|
|
|
processOutput.close();
|
|
|
|
|
} catch (IOException e) {
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 等待输入输出处理完成
|
|
|
|
|
try {
|
|
|
|
|
inputFuture.get();
|
|
|
|
|
errorFuture.get();
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
throw new RuntimeException("处理输入输出流失败", e);
|
|
|
|
|
} finally {
|
|
|
|
|
executor.shutdown();
|
|
|
|
|
}
|
|
|
|
|
// 等待命令执行完成
|
|
|
|
|
|
|
|
|
|
// 等待进程完成
|
|
|
|
|
int exitCode = process.waitFor();
|
|
|
|
|
if (exitCode != 0) {
|
|
|
|
|
throw new RuntimeException("数据库还原失败:\n" + errorOutput);
|
|
|
|
|
throw new RuntimeException("数据库还原失败,退出码: " + exitCode);
|
|
|
|
|
}
|
|
|
|
|
System.out.println("\n数据库还原完成");
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
throw new RuntimeException("还原数据库失败: " + e.getMessage(), e);
|
|
|
|
|
}
|
|
|
|
|