main
黄海 6 months ago
parent 8df0f1baca
commit d2b37fd9ea

@ -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<String> 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<String> parseSqlFile(String sqlFile) throws IOException {
List<String> 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<String> 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);
}
}

@ -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
);

@ -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<String> 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<String> parseSqlFile(String sqlFile) throws IOException {
List<String> 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);
}
}

@ -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

@ -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

Loading…
Cancel
Save