diff --git a/YunXiaoTools/src/main/java/com/dsideal/YunXiaoTools/Service/MysqlRestoreService.java b/YunXiaoTools/src/main/java/com/dsideal/YunXiaoTools/Service/MysqlRestoreService.java index 7d52fd62..046373dd 100644 --- a/YunXiaoTools/src/main/java/com/dsideal/YunXiaoTools/Service/MysqlRestoreService.java +++ b/YunXiaoTools/src/main/java/com/dsideal/YunXiaoTools/Service/MysqlRestoreService.java @@ -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); }