From d2b37fd9ea15b35be7ff3fc00862a8bd8b6b54b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E6=B5=B7?= <10402852@qq.com> Date: Fri, 10 Jan 2025 15:00:36 +0800 Subject: [PATCH] 'commit' --- .../Service/DatabaseRestorer.java | 183 ------------------ .../Service/MysqlBackupService.java | 23 ++- .../Service/MysqlRestoreService.java | 107 +++++++++- .../src/main/resources/application.properties | 2 +- .../target/classes/application.properties | 2 +- 5 files changed, 110 insertions(+), 207 deletions(-) delete mode 100644 YunXiaoTools/src/main/java/com/dsideal/YunXiaoTools/Service/DatabaseRestorer.java diff --git a/YunXiaoTools/src/main/java/com/dsideal/YunXiaoTools/Service/DatabaseRestorer.java b/YunXiaoTools/src/main/java/com/dsideal/YunXiaoTools/Service/DatabaseRestorer.java deleted file mode 100644 index 43791e1a..00000000 --- a/YunXiaoTools/src/main/java/com/dsideal/YunXiaoTools/Service/DatabaseRestorer.java +++ /dev/null @@ -1,183 +0,0 @@ -package com.dsideal.YunXiaoTools.Service; - -import java.io.*; -import java.sql.*; -import java.util.ArrayList; -import java.util.List; - -public class DatabaseRestorer { - private final String jdbcUrl; - private final String username; - private final String password; - - public DatabaseRestorer(String jdbcUrl, String username, String password) { - this.jdbcUrl = jdbcUrl; - this.username = username; - this.password = password; - } - - /** - * 还原数据库 - */ - public void restore(String sqlFile) { - try { - // 读取SQL文件内容 - List sqlStatements = parseSqlFile(sqlFile); - System.out.println("SQL文件解析完成,共 " + sqlStatements.size() + " 条语句"); - - // 执行SQL语句 - try (Connection conn = DriverManager.getConnection(jdbcUrl, username, password)) { - conn.setAutoCommit(false); // 开启事务 - - try (Statement stmt = conn.createStatement()) { - int total = sqlStatements.size(); - int current = 0; - - for (String sql : sqlStatements) { - if (sql.trim().length() > 0) { - try { - stmt.execute(sql); - current++; - - // 显示进度 - if (current % 100 == 0 || current == total) { - System.out.printf("\r还原进度: %.2f%% (%d/%d)", - (current * 100.0 / total), current, total); - } - } catch (SQLException e) { - System.err.println("\n执行SQL出错: " + sql); - System.err.println("错误信息: " + e.getMessage()); - throw e; - } - } - } - - conn.commit(); // 提交事务 - System.out.println("\n数据库还原完成"); - - } catch (SQLException e) { - conn.rollback(); // 发生错误时回滚 - throw e; - } - } - - } catch (Exception e) { - throw new RuntimeException("还原数据库失败: " + e.getMessage(), e); - } - } - - /** - * 解析SQL文件 - */ - private List parseSqlFile(String sqlFile) throws IOException { - List sqlStatements = new ArrayList<>(); - StringBuilder statement = new StringBuilder(); - boolean inString = false; - - try (BufferedReader reader = new BufferedReader(new FileReader(sqlFile))) { - String line; - while ((line = reader.readLine()) != null) { - // 跳过注释行 - if (line.trim().startsWith("--") || line.trim().startsWith("/*")) { - continue; - } - - for (int i = 0; i < line.length(); i++) { - char c = line.charAt(i); - - // 处理字符串 - if (c == '\'') { - inString = !inString; - } - - statement.append(c); - - // 如果遇到分号且不在字符串中,说明一条语句结束 - if (c == ';' && !inString) { - sqlStatements.add(statement.toString()); - statement = new StringBuilder(); - } - } - - statement.append("\n"); - } - - // 处理最后一条可能没有分号的语句 - if (statement.length() > 0) { - sqlStatements.add(statement.toString()); - } - } - - return sqlStatements; - } - - /** - * 还原数据库(带进度回调) - */ - public void restore(String sqlFile, ProgressCallback callback) { - try { - callback.onStart("正在解析SQL文件..."); - List sqlStatements = parseSqlFile(sqlFile); - - callback.onProgress("开始执行SQL语句", 0); - try (Connection conn = DriverManager.getConnection(jdbcUrl, username, password)) { - conn.setAutoCommit(false); - - try (Statement stmt = conn.createStatement()) { - int total = sqlStatements.size(); - int current = 0; - long startTime = System.currentTimeMillis(); - - for (String sql : sqlStatements) { - if (sql.trim().length() > 0) { - try { - stmt.execute(sql); - current++; - - // 计算进度和速度 - if (current % 10 == 0 || current == total) { - int progress = (int) ((current * 100.0) / total); - long elapsed = System.currentTimeMillis() - startTime; - double speed = current * 1000.0 / elapsed; - - callback.onProgress( - String.format("已执行 %d/%d 条语句 (%.2f条/秒)", - current, total, speed), - progress - ); - } - } catch (SQLException e) { - callback.onError("执行SQL出错: " + sql, e); - throw e; - } - } - } - - conn.commit(); - callback.onComplete("数据库还原完成"); - - } catch (SQLException e) { - conn.rollback(); - throw e; - } - } - - } catch (Exception e) { - callback.onError("还原失败", e); - throw new RuntimeException("还原数据库失败: " + e.getMessage(), e); - } - } - - /** - * 进度回调接口 - */ - public interface ProgressCallback { - void onStart(String message); - - void onProgress(String message, int percent); - - void onError(String message, Exception e); - - void onComplete(String message); - } -} \ No newline at end of file diff --git a/YunXiaoTools/src/main/java/com/dsideal/YunXiaoTools/Service/MysqlBackupService.java b/YunXiaoTools/src/main/java/com/dsideal/YunXiaoTools/Service/MysqlBackupService.java index f91fe434..c81ce5d7 100644 --- a/YunXiaoTools/src/main/java/com/dsideal/YunXiaoTools/Service/MysqlBackupService.java +++ b/YunXiaoTools/src/main/java/com/dsideal/YunXiaoTools/Service/MysqlBackupService.java @@ -40,7 +40,6 @@ public class MysqlBackupService { // 获取mysqldump路径 String mysqldumpPath = CommonUtil.getMySQLDumpPath(); // 构建命令(不包含密码) - // MariaDB 兼容的备份命令 ProcessBuilder pb = new ProcessBuilder( mysqldumpPath, @@ -48,19 +47,19 @@ public class MysqlBackupService { "-P" + port, "-u" + user, "--skip-ssl", - "--no-tablespaces", - "--default-character-set=utf8", - "--single-transaction", // 保证数据一致性 - "--routines", // 包含存储过程 - "--triggers", // 包含触发器 - "--events", // 包含事件 - "--complete-insert", // 完整insert语句 "--add-drop-database", // 添加drop database语句 "--add-drop-table", // 添加drop table语句 - "--skip-lock-tables", // 跳过锁表 - "--compact", // 产生更紧凑的输出 - "--skip-extended-insert", // 分行显示insert语句 - database, + "--no-tablespaces", + "--default-character-set=utf8", + "--single-transaction", + "--routines", + "--triggers", + "--events", + "--complete-insert", + "--skip-lock-tables", + "--skip-extended-insert", + "--databases", // 确保这个参数在数据库名称之前 + database, // 数据库名称 "-r", backupPath ); 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 9982134b..0fb54731 100644 --- a/YunXiaoTools/src/main/java/com/dsideal/YunXiaoTools/Service/MysqlRestoreService.java +++ b/YunXiaoTools/src/main/java/com/dsideal/YunXiaoTools/Service/MysqlRestoreService.java @@ -5,35 +5,83 @@ import com.dsideal.YunXiaoTools.Utils.MultiThreadDownloader; import com.jfinal.kit.PropKit; import java.io.*; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.List; import java.util.zip.*; public class MysqlRestoreService { + private final String jdbcUrl; + private final String username; + private final String password; + + public MysqlRestoreService() { + jdbcUrl = PropKit.get("write.jdbcUrl"); + username = PropKit.get("write.user"); + password = PropKit.get("write.password"); + } /** * 执行完整的还原流程 * * @param obsKey OBS上的文件路径 */ - public void restore(String obsKey) { + public void restore(String jdbcUrl, String username, String password, String obsKey) { String tempDir = System.getProperty("java.io.tmpdir"); String sqlFile = null; String zipFile = tempDir + obsKey.split("/")[2]; try { // 1. 从OBS下载ZIP文件 downloadFromObs(obsKey, tempDir); - System.out.println("文件下载完成: " + zipFile); - // 2. 解压ZIP文件 sqlFile = unzipFile(zipFile); System.out.println("文件解压完成: " + sqlFile); - // 3. 还原数据库 - DatabaseRestorer dr=new DatabaseRestorer(PropKit.get("write.jdbcUrl"), PropKit.get("write.user"), PropKit.get("write.password")); - dr.restore(sqlFile); - System.out.println("数据库还原完成"); + try { + // 读取SQL文件内容 + List sqlStatements = parseSqlFile(sqlFile); + System.out.println("SQL文件解析完成,共 " + sqlStatements.size() + " 条语句"); + + // 执行SQL语句 + try (Connection conn = DriverManager.getConnection(jdbcUrl, username, password)) { + conn.setAutoCommit(false); // 开启事务 + try (Statement stmt = conn.createStatement()) { + int total = sqlStatements.size(); + int current = 0; + + for (String sql : sqlStatements) { + if (!sql.trim().isEmpty()) { + try { + stmt.execute(sql); + current++; + // 显示进度 + if (current % 100 == 0 || current == total) { + System.out.printf("\r还原进度: %.2f%% (%d/%d)", (current * 100.0 / total), current, total); + } + } catch (SQLException e) { + System.err.println("\n执行SQL出错: " + sql); + System.err.println("错误信息: " + e.getMessage()); + throw e; + } + } + } + conn.commit(); // 提交事务 + System.out.println("\n数据库还原完成"); + } catch (SQLException e) { + conn.rollback(); // 发生错误时回滚 + throw e; + } + } + } catch (Exception e) { + throw new RuntimeException("还原数据库失败: " + e.getMessage(), e); + } + System.out.println("数据库还原完成"); } catch (Exception e) { throw new RuntimeException("还原过程失败: " + e.getMessage(), e); } finally { @@ -100,12 +148,51 @@ public class MysqlRestoreService { } + /** + * 解析SQL文件 + */ + private List parseSqlFile(String sqlFile) throws IOException { + List sqlStatements = new ArrayList<>(); + StringBuilder statement = new StringBuilder(); + boolean inString = false; + + try (BufferedReader reader = new BufferedReader(new FileReader(sqlFile))) { + String line; + while ((line = reader.readLine()) != null) { + // 跳过注释行 + if (line.trim().startsWith("--") || line.trim().startsWith("/*")) { + continue; + } + for (int i = 0; i < line.length(); i++) { + char c = line.charAt(i); + // 处理字符串 + if (c == '\'') { + inString = !inString; + } + statement.append(c); + // 如果遇到分号且不在字符串中,说明一条语句结束 + if (c == ';' && !inString) { + sqlStatements.add(statement.toString()); + statement = new StringBuilder(); + } + } + statement.append("\n"); + } + // 处理最后一条可能没有分号的语句 + if (!statement.isEmpty()) { + sqlStatements.add(statement.toString()); + } + } + return sqlStatements; + } + public static void main(String[] args) { PropKit.use("application.properties"); //获取最后一次上传的数据库文件 String key = CommonUtil.getLastDataBaseZip(); - //开始还原数据库 - MysqlRestoreService mysqlRestoreUtil = new MysqlRestoreService(); - mysqlRestoreUtil.restore(key); + + //还原数据库 + MysqlRestoreService mr = new MysqlRestoreService(); + mr.restore(mr.jdbcUrl, mr.username, mr.password, key); } } \ No newline at end of file diff --git a/YunXiaoTools/src/main/resources/application.properties b/YunXiaoTools/src/main/resources/application.properties index c8b00b86..5358bbe1 100644 --- a/YunXiaoTools/src/main/resources/application.properties +++ b/YunXiaoTools/src/main/resources/application.properties @@ -9,7 +9,7 @@ read.jdbcUrl=jdbc:mysql://10.10.15.178:43306/ccyx_statistics?rewriteBatchedState # 写入侧数据库信息 write.user=root write.password=Password123@mysql -write.jdbcUrl=jdbc:mysql://10.10.14.203:3306/HuangHai_Test?rewriteBatchedStatements=true&useUnicode=true&zeroDateTimeBehavior=CONVERT_TO_NULL&useSSL=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&autoReconnect=true&failOverReadOnly=false +write.jdbcUrl=jdbc:mysql://10.10.14.203:3306/ds_db?rewriteBatchedStatements=true&useUnicode=true&zeroDateTimeBehavior=CONVERT_TO_NULL&useSSL=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&autoReconnect=true&failOverReadOnly=false # mysqldump执行文件位置 mysqldump_path=C:/Program Files/MariaDB 11.6/bin/mysqldump.exe diff --git a/YunXiaoTools/target/classes/application.properties b/YunXiaoTools/target/classes/application.properties index c8b00b86..5358bbe1 100644 --- a/YunXiaoTools/target/classes/application.properties +++ b/YunXiaoTools/target/classes/application.properties @@ -9,7 +9,7 @@ read.jdbcUrl=jdbc:mysql://10.10.15.178:43306/ccyx_statistics?rewriteBatchedState # 写入侧数据库信息 write.user=root write.password=Password123@mysql -write.jdbcUrl=jdbc:mysql://10.10.14.203:3306/HuangHai_Test?rewriteBatchedStatements=true&useUnicode=true&zeroDateTimeBehavior=CONVERT_TO_NULL&useSSL=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&autoReconnect=true&failOverReadOnly=false +write.jdbcUrl=jdbc:mysql://10.10.14.203:3306/ds_db?rewriteBatchedStatements=true&useUnicode=true&zeroDateTimeBehavior=CONVERT_TO_NULL&useSSL=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&autoReconnect=true&failOverReadOnly=false # mysqldump执行文件位置 mysqldump_path=C:/Program Files/MariaDB 11.6/bin/mysqldump.exe