当前位置: 首页 > news >正文

mysql数据库备份

在这里插入图片描述

文章目录

  • 一、背景
  • 二、代码
    • DatabaseManageControl
    • DatabaseManageUserControl
    • ConfigValue
    • DataServiceConfigValue
    • application.properties
    • application-cvt.properties
    • application-xpt.properties
    • CommonUtil
    • QueryBackupDatabaseParams
    • FileUtils
    • ClientService
    • ClientServiceI
    • DataBaseServImpl
    • SystemDao
    • SystemDaoImpl
  • 三、说明
  • 四、错误场景
    • 错误场景1:java执行cmd命令方式有3种
    • 错误场景2:java.io.IOException: Cannot run program "cd /d C:\Program Files (x86)\xnms-install\cvt-windows-service\..\mysql\bin\": CreateProcess error=2, 系统找不到指定的文件。
    • 错误场景3:备份命令是否带空格
    • 错误场景4:'C:\Program' 不是内部或外部命令,也不是可运行的程序或批处理文件。
    • 错误场景5:mysqldump: Got error: 1049: Unknown database 'files' when selecting the database
  • 五、总结

一、背景

项目针对Mysql某个数据库进行压缩,这里的压缩指代“逻辑压缩”,备份结果是个xx.sql文件。

MySQL备份的执行流程(以逻辑备份和物理备份为例)
备份主要分为两大类:逻辑备份 和 物理备份。它们的执行流程有所不同。

逻辑备份

逻辑备份就像是给数据库“拍照”,保存的是数据库的逻辑结构(CREATE DATABASE, CREATE TABLE语句)和数据(INSERT语句)。最常见的工具是 mysqldump。

执行流程(以 mysqldump 为例):

  1. 连接数据库:使用授权的账号密码连接到MySQL实例。

  2. 刷新日志与锁表(关键步骤):

    • 备份工具会请求数据库刷新日志,并开启一个一致性快照。

    • 对于支持事务的存储引擎(如InnoDB),mysqldump 默认使用 --single-transaction 参数。它通过启动一个事务,利用MVCC(多版本并发控制)来获取一个一致性的数据快照。在这个过程中,不需要锁表,数据库可以正常读写。

    • 对于非事务引擎(如MyISAM),为了保持数据一致性,它需要对所有表加读锁。在加锁期间,其他会话的写操作(INSERT, UPDATE, DELETE)会被阻塞,直到锁释放。这会影响业务,因此建议避免在生产环境使用非事务引擎。

  3. 逐表读取数据:根据上一步获得的一致性视图,逐个读取表的结构和数据。

  4. 生成SQL文件:将读取到的信息转换成SQL语句,写入到备份文件中。

  5. 释放资源:备份完成,释放事务或锁。

  6. 记录Binlog位置(如果指定了 --master-data 参数):在备份文件中记录下备份结束时二进制日志的位置,这对于后续搭建从库或做基于时间点的恢复至关重要。

优点:备份文件是SQL,可读性强,可以在不同版本的MySQL之间迁移,恢复粒度可以到表级别。
缺点:备份和恢复速度较慢(因为要执行SQL语句),对服务器性能有一定影响。

物理备份

物理备份就像是直接“复印”数据库的物理文件(数据文件、日志文件等)。最常见的工具是 Percona XtraBackup(适用于InnoDB/XtraDB引擎)。

执行流程(以 XtraBackup 为例):

  1. 开始备份:启动备份进程。

  2. 拷贝数据文件

    • 并行地拷贝InnoDB的表空间文件(.ibd)和共享表空间文件(ibdata1)。

    • 此阶段数据库可以正常读写。

  3. 记录LSN并锁表

    • 在拷贝完所有InnoDB文件后,XtraBackup会记录下此时的LSN(日志序列号)。

    • 然后,它对非InnoDB表(如MyISAM)施加一个短暂的全局读锁(通常只有几秒钟)。

  4. ``拷贝其他文件`:在短暂的锁表期间,快速拷贝非InnoDB表的结构文件(.frm、.MYD等)、二进制日志位置信息等。

  5. 释放锁并结束备份:释放全局读锁,备份完成。

  6. 准备备份

    • 由于备份过程中数据库仍在运行,拷贝的数据文件可能处于不一致的状态(例如,有部分数据在内存中还未写入文件)。

    • 因此,需要一个 --prepare 步骤。这个步骤会应用备份过程中产生的重做日志(Redo Log),使备份数据文件达到一个逻辑上一致的状态,就像数据库在备份完成那个时间点被安全关闭了一样。

优点:备份和恢复速度非常快(文件拷贝),对服务器性能影响小。
缺点:备份文件大,不具可读性,通常不能跨版本或跨平台恢复。

关于“数据库压缩”

压缩通常在备份流程的最后一步进行,与备份类型无关。

  • 逻辑备份压缩:可以直接将 mysqldump 的输出通过管道传递给压缩工具。
bash
mysqldump -u root -p mydatabase | gzip > backup.sql.gz
  • 物理备份压缩:XtraBackup 自带压缩功能(–compress),也可以在备份完成后,使用操作系统命令对备份目录进行压缩。

在这里插入图片描述

二、代码

DatabaseManageControl

@Operation(summary = "数据库备份")
@GetMapping(value = "/backupDatabase")
public ResponseModel backupDatabase() {return databaseManageUserControl.backupDatabase();
}

DatabaseManageUserControl

@Autowired
private ConfigValue configValue;@Autowired
private DataServiceConfigValue dataServiceConfigValue;private static final SimpleDateFormat YMDHMS = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");public ResponseModel<String> backupDatabase() {try {QueryBackupDatabaseParams params = new QueryBackupDatabaseParams();String dSDataSource = configValue.obtainConfigValue("xnms.data.service.DSDataSource");String dSPort = configValue.obtainConfigValue("xnms.data.service.DSPort");String jdbcUrl = configValue.obtainConfigValue("spring.datasource.url");String[] jdbcUrlParse = FileUtils.parseJdbcUrl(jdbcUrl);if (jdbcUrlParse != null && jdbcUrlParse.length > 0) {params.setDataSource(jdbcUrlParse[0]);params.setdSPort(jdbcUrlParse[1]);if (!dSDataSource.equals(jdbcUrlParse[0])) {configValue.updateConfig("xnms.data.service.DSDataSource", jdbcUrlParse[0]);dataServiceConfigValue.writeConfig("xnms.data.service.DSDataSource", jdbcUrlParse[0]);}if (!dSPort.equals(jdbcUrlParse[1])) {configValue.updateConfig("xnms.data.service.DSPort", jdbcUrlParse[1]);dataServiceConfigValue.writeConfig("xnms.data.service.DSPort", jdbcUrlParse[1]);}}String userName = configValue.obtainConfigValue("spring.datasource.username");String password = configValue.obtainConfigValue("spring.datasource.password");String databaseName = configValue.obtainConfigValue("xnms.data.service.DSDatabaseName");String applicationPath = CommonUtil.getApplicationPath();File installDir = new File(applicationPath).getParentFile();String basePath = installDir.getAbsolutePath();String databaseBackupPath = basePath + configValue.obtainConfigValue("xnms.data.service.DBBackupPath");logger.info("databaseBackupPath:{}", databaseBackupPath);params.setUserName(userName);params.setPassword(password);params.setDatabaseName(databaseName);params.setDatabaseBackupPath(databaseBackupPath);params.setInstallBackupPath(basePath);File targetFile = new File(databaseBackupPath);if (!targetFile.exists()) {targetFile.mkdirs();}SingleResponse<Boolean> booleanSingleResponse = clientService.backupDatabase(params);Boolean isSuccess = booleanSingleResponse.getData();if (!isSuccess) {return ResponseModel.ofError(languageFind.findKey("BackupFailed"));}String dateFormat = YMDHMS.format(new Date());configValue.updateConfig("xnms.client.BackupDateTime", dateFormat);dataServiceConfigValue.writeConfig("xnms.client.BackupDateTime", dateFormat);Account account = (Account) SecurityUtils.getSubject().getPrincipal();clientService.clientLog(account.getUserName(), ClientLogType.LogDataBaseManager, ClientSubLogType.LogDataBaseManager_BackUpDB, "DatabaseBackupSuccess", account.getIp());} catch (Exception e) {logger.error("backupDatabase:{}", e.getMessage());}return ResponseModel.ofSuccess(languageFind.findKey("BackupSuccess"));
}

ConfigValue

@Autowired
private Environment env;@Autowired
private ApplicationContext applicationContext;@Autowired
private ApplicationContext applicationContext;public String obtainConfigValue(String key) {String configValue = "";try {configValue = env.getProperty(key);} catch (Exception ex) {logger.error("[XNMSProxyService] ObtainConfigValue :" + ex.getMessage(), ex);}return configValue;
}public String updateConfig(String key, String value) {// 获取 ConfigurableEnvironmentConfigurableEnvironment environment = (ConfigurableEnvironment) applicationContext.getEnvironment();// 更新动态配置的 MapdynamicConfigMap.put(key, value);// 使用自定义的 PropertySource 来存储动态配置PropertySource<?> propertySource = new org.springframework.core.env.MapPropertySource("dynamicConfig",dynamicConfigMap);environment.getPropertySources().remove("dynamicConfig");environment.getPropertySources().addFirst(propertySource);return "ok";
}

DataServiceConfigValue

@Autowired
private Environment env;@Autowired
private ApplicationContext applicationContext;public void writeConfig(String key, String value) {String workMode = env.getProperty("xnms.service.center.WorkMode");// 获取配置文件路径Resource resource = applicationContext.getResource("classpath:application.properties");if (Objects.equals(workMode, "0")) {resource = applicationContext.getResource("classpath:application-cvt.properties");}if (Objects.equals(workMode, "1")) {resource = applicationContext.getResource("classpath:application-xpt.properties");}// 用于存储文件原始内容List<String> lines = new ArrayList<>();try (InputStream inputStream = resource.getInputStream();BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {String line;while ((line = reader.readLine()) != null) {lines.add(line);  // 保存每行内容}} catch (IOException e) {logger.error("ConfigService, writeConfig method, failed to read file:", e);return;}// 修改配置内容boolean keyFound = false;for (int i = 0; i < lines.size(); i++) {String line = lines.get(i).trim();// 跳过空行和注释行if (line.isEmpty() || line.startsWith("#")) {continue;}// 检查是否匹配到目标keyif (line.startsWith(key + "=")) {lines.set(i, key + "=" + value);  // 修改指定键值对keyFound = true;break;}}if (keyFound) {try {// 获取文件的物理路径File file = resource.getFile();// 使用 FileWriter 覆盖原文件try (BufferedWriter writer = new BufferedWriter(new FileWriter(file))) {for (String line : lines) {writer.write(line);writer.newLine();  // 保证每行后面换行}writer.flush();}} catch (IOException e) {logger.error("ConfigService, writeConfig method, failed to write file:", e);}} else {logger.warn("没有找到指定的key: {}", key);}
}

application.properties


application-cvt.properties

xnms.service.center.WorkMode=0
xnms.client.BackupDateTime=
xnms.data.service.DBBackupPath=\\xnms-app\\mysqlBackup\\
xnms.data.service.DSDatabaseName=cvt_db
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://IP:13306/cvt_db
spring.datasource.username=root
spring.datasource.password=123456
xnms.client.BackupDateTime=
xnms.data.service.DSDataSource=localhost
xnms.data.service.DSPort=13306
xnms.data.service.DSDatabaseName=cvt_db

application-xpt.properties

xnms.service.center.WorkMode=1
xnms.client.BackupDateTime=
xnms.data.service.DBBackupPath=\\xnms-app\\mysqlBackup\\
xnms.data.service.DSDatabaseName=xpt_db
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://IP:13306/xpt_db
spring.datasource.username=root
spring.datasource.password=123456
xnms.client.BackupDateTime=
xnms.data.service.DSDataSource=localhost
xnms.data.service.DSPort=13306
xnms.data.service.DSDatabaseName=xpt_db

CommonUtil

/*** 获取应用路径** @return 应用路径*/
public static String getApplicationPath() {String baseFolder = "";try {baseFolder = new File("").getAbsolutePath(); // 获取当前工作目录} catch (Exception ex) {logger.error("<getApplicationPath> " + ex.getMessage(), ex);}return baseFolder;
}

QueryBackupDatabaseParams

package com.xnms.data.contract.database.db;import org.apache.commons.lang3.builder.ReflectionToStringBuilder;public class QueryBackupDatabaseParams {String dataSource;String dSPort;String userName;String password;String databaseName;String databaseBackupPath;String installBackupPath;public String getInstallBackupPath() {return installBackupPath;}public void setInstallBackupPath(String installBackupPath) {this.installBackupPath = installBackupPath;}public QueryBackupDatabaseParams() {}public String getDataSource() {return dataSource;}public void setDataSource(String dataSource) {this.dataSource = dataSource;}public String getUserName() {return userName;}public void setUserName(String userName) {this.userName = userName;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public String getDatabaseName() {return databaseName;}public void setDatabaseName(String databaseName) {this.databaseName = databaseName;}public String getDatabaseBackupPath() {return databaseBackupPath;}public void setDatabaseBackupPath(String databaseBackupPath) {this.databaseBackupPath = databaseBackupPath;}public String getdSPort() {return dSPort;}public void setdSPort(String dSPort) {this.dSPort = dSPort;}@Overridepublic String toString() {return ReflectionToStringBuilder.toString(this);}
}

FileUtils

public static String[] parseJdbcUrl(String jdbcUrl) {// 正则表达式匹配:jdbc:mysql://主机:端口/Pattern pattern = Pattern.compile("jdbc:mysql://([^:/]+):(\\d+)/");Matcher matcher = pattern.matcher(jdbcUrl);if (matcher.find()) {String host = matcher.group(1);String port = matcher.group(2);return new String[]{host, port};}return null;
}

ClientService

SingleResponse<Boolean> backupDatabase(QueryBackupDatabaseParams params);

ClientServiceI

@Override
public SingleResponse<Boolean> backupDatabase(QueryBackupDatabaseParams params) {SingleResponse<Boolean> singleResponse = new SingleResponse<>();try {singleResponse.setData(dataBase.backupDatabase(params));singleResponse.setSuccess(true);} catch (Exception ex) {logger.error("[DataBaseI] BackupDatabase error: " + ex.getMessage(), ex);singleResponse.setSuccess(false);singleResponse.setMsg(ex.getMessage());}return singleResponse;
}

DataBaseServImpl

public boolean backupDatabase(QueryBackupDatabaseParams params) {try {systemDao.backupDatabase(params); // 调用备份方法return true; // 备份成功} catch (Exception ex) {// 记录错误信息logger.error("[DataBaseServImpl] BackupDatabase: " + ex.getMessage() +(ex.getCause() != null ? "\n" + ex.getCause().getMessage() : ""), ex);return false; // 备份失败}
}

SystemDao

void backupDatabase(QueryBackupDatabaseParams params);

SystemDaoImpl

@Override
public void backupDatabase(QueryBackupDatabaseParams params) {try {List<String> cmds = new ArrayList<>();String fullPath = params.getInstallBackupPath() + "\\mysql\\bin\\mysqldump.exe";String dataSource = params.getDataSource();String dSPort = params.getdSPort();String userName = params.getUserName();String password = params.getPassword();String databaseName = params.getDatabaseName();String databaseBackupPath = params.getDatabaseBackupPath();String backupPath = databaseBackupPath + databaseName + "-" + dateFormat.format(new Date()) + ".sql";cmds.add("cmd");cmds.add("/c");cmds.add(fullPath);cmds.add("-h");cmds.add(dataSource);cmds.add("-P");cmds.add(dSPort);cmds.add("-u");cmds.add(userName);cmds.add("-p" + password);cmds.add("--databases");cmds.add(databaseName);runCmds(cmds, backupPath);} catch (Exception ex) {logger.error("<ServiceImpl backupDatabase> Error: {}", ex.getMessage(), ex);}
}private void runCmds(List<String> cmds, String backupPath) {try {ProcessBuilder processBuilder = new ProcessBuilder(cmds);processBuilder.redirectOutput(new File(backupPath));processBuilder.redirectErrorStream(true);Process process = processBuilder.start();int exitCode = process.waitFor();logger.info("Exit code: {}", exitCode);if (exitCode == 0) {logger.info("Backup successful: {}", backupPath);} else {logger.error("Backup failed with exit code: {}", exitCode);}} catch (Exception e) {logger.error("Error while running commands: {}", e.getMessage(), e);}
}

三、说明

说明点1:上面看着比较多,实际大多都是无用的层级调,configValue和dataServiceConfigValue用于读取配置文件内容。

说明点2:该备份为逻辑备份,而非物理备份。

四、错误场景

错误场景1:java执行cmd命令方式有3种

第1种:Method 1: Using cmd /c with full command string (Recommended)

private void executeCommandWithSpaces() {try {String fullCommand = "\"C:\\Program Files (x86)\\xnms-install\\mysql\\bin\\mysqldump.exe\" -h localhost -P 13306 -u root -p123456 --databases cvt_db > \"C:\\Program Files (x86)\\xnms-install\\xnms-app\\mysqlBackup\\backup.sql\"";ProcessBuilder processBuilder = new ProcessBuilder("cmd", "/c", fullCommand);Process process = processBuilder.start();// Read output streamBufferedReader outputReader = new BufferedReader(new InputStreamReader(process.getInputStream()));String outputLine;while ((outputLine = outputReader.readLine()) != null) {System.out.println("Output: " + outputLine);}// Read error streamBufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));String errorLine;while ((errorLine = errorReader.readLine()) != null) {System.err.println("Error: " + errorLine);}int exitCode = process.waitFor();System.out.println("Exit code: " + exitCode);} catch (Exception e) {e.printStackTrace();}
}

第2种:Method 2: Using ProcessBuilder with individual arguments

private void executeCommandWithSpaces() {try {ProcessBuilder processBuilder = new ProcessBuilder("cmd", "/c","\"C:\\Program Files (x86)\\xnms-install\\mysql\\bin\\mysqldump.exe\"","-h", "localhost","-P", "13306", "-u", "root","-p123456","--databases", "cvt_db",">","\"C:\\Program Files (x86)\\xnms-install\\xnms-app\\mysqlBackup\\backup.sql\"");Process process = processBuilder.start();// Handle streamsBufferedReader outputReader = new BufferedReader(new InputStreamReader(process.getInputStream()));BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));String line;while ((line = outputReader.readLine()) != null) {System.out.println("Output: " + line);}while ((line = errorReader.readLine()) != null) {System.err.println("Error: " + line);}int exitCode = process.waitFor();System.out.println("Exit code: " + exitCode);} catch (Exception e) {e.printStackTrace();}
}

第3种:Method 3: Using Runtime.exec() with array

private void executeCommandWithSpaces() {try {String[] command = {"cmd", "/c","\"C:\\Program Files (x86)\\xnms-install\\mysql\\bin\\mysqldump.exe\" -h localhost -P 13306 -u root -p123456 --databases cvt_db > \"C:\\Program Files (x86)\\xnms-install\\xnms-app\\mysqlBackup\\backup.sql\""};Process process = Runtime.getRuntime().exec(command);// Handle streamsBufferedReader outputReader = new BufferedReader(new InputStreamReader(process.getInputStream()));BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));String line;while ((line = outputReader.readLine()) != null) {System.out.println("Output: " + line);}while ((line = errorReader.readLine()) != null) {System.err.println("Error: " + line);}int exitCode = process.waitFor();System.out.println("Exit code: " + exitCode);} catch (Exception e) {e.printStackTrace();}
}

错误场景2:java.io.IOException: Cannot run program “cd /d C:\Program Files (x86)\xnms-install\cvt-windows-service…\mysql\bin”: CreateProcess error=2, 系统找不到指定的文件。

2025-10-09 10:20:42.545 [http-nio-61000-exec-5] ERROR com.xnms.data.service.dao.mysql.impl.SystemDaoImpl - Error while running commands: Cannot run program "cd /d C:\Program Files (x86)\xnms-install\cvt-windows-service\..\mysql\bin\": CreateProcess error=2, 系统找不到指定的文件。
java.io.IOException: Cannot run program "cd /d C:\Program Files (x86)\xnms-install\cvt-windows-service\..\mysql\bin\": CreateProcess error=2, 系统找不到指定的文件。at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1143)at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1073)at com.xnms.data.service.dao.mysql.impl.SystemDaoImpl.runCmds(SystemDaoImpl.java:94)at com.xnms.data.service.dao.mysql.impl.SystemDaoImpl.backupDatabase(SystemDaoImpl.java:137)at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: java.io.IOException: CreateProcess error=2, 系统找不到指定的文件。at java.base/java.lang.ProcessImpl.create(Native Method)at java.base/java.lang.ProcessImpl.<init>(ProcessImpl.java:494)at java.base/java.lang.ProcessImpl.start(ProcessImpl.java:159)at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1110)... 100 common frames omitted

我的错误代码如下

private void runCmds(List<String> cmds) {try {ProcessBuilder processBuilder = new ProcessBuilder();processBuilder.command(cmds);Process process = processBuilder.start();// 输出命令的结果BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));String line;while ((line = reader.readLine()) != null) {logger.info("SystemDaoImpl类,runCmds方法:cmds = [{}]",line);}int exitCode = process.waitFor();if (exitCode != 0) {logger.error("Command execution failed with exit code: {}", exitCode);}} catch (Exception e) {logger.error("Error while running commands: {}", e.getMessage(), e);}}@Overridepublic void backupDatabase(QueryBackupDatabaseParams params) {try {List<String> cmds = new ArrayList<>();String applicationPath = CommonUtil.getApplicationPath();cmds.add("cd /d " + applicationPath);String dataSource = params.getDataSource();String dSPort = params.getdSPort();String userName = params.getUserName();String password = params.getPassword();String databaseName = params.getDatabaseName();String databaseBackupPath = params.getDatabaseBackupPath();String suffix = databaseName + " > " + databaseBackupPath + databaseName + "-" + dateFormat.format(new Date()) + ".sql";// 构建命令if (password == null || password.isEmpty()) {String cmd = String.format("MYSQLDUMP.exe -h %s -u %s --databases %s", dataSource, userName, suffix);logger.info("backupDatabase-cmd1:{}", cmd);cmds.add(cmd);} else {String cmd = String.format("MYSQLDUMP.exe -h %s -P %s -u %s -p%s --databases %s", dataSource, dSPort, userName, password, suffix);logger.info("backupDatabase-cmd2:{}", cmd);cmds.add(cmd);}runCmds(cmds);} catch (Exception ex) {logger.error("<ServiceImpl backupDatabase> Error: {}", ex.getMessage(), ex);}}

这个错误是因为在 Java 程序中直接执行 cd 命令导致的。cd 是 Windows 命令提示符的内部命令,不是独立的可执行程序。

问题分析

当 Java 的 Runtime.exec() 或 ProcessBuilder 尝试执行 cd 命令时,它会在系统 PATH 中查找名为 cd.exe 的可执行文件,但找不到,因为 cd 是 cmd 的内部命令。

解决方案

方法1:直接执行目标程序(推荐)

// 不要执行 cd 命令,直接执行 mysqldump 的完整路径
String command = "C:\\Program Files (x86)\\xnms-install\\mysql\\bin\\mysqldump.exe -h localhost -P 13306 -u root -p123456 --databases cvt_db";

方法2:使用 cmd /c 执行命令

// 让 cmd 解释器来执行命令
String command = "cmd /c \"C:\\Program Files (x86)\\xnms-install\\mysql\\bin\\mysqldump.exe -h localhost -P 13306 -u root -p123456 --databases cvt_db\"";

方法3:设置工作目录

// 使用 ProcessBuilder 设置工作目录
ProcessBuilder pb = new ProcessBuilder("mysqldump.exe", "-h", "localhost", "-P", "13306", "-u", "root", "-p123456", "--databases", "cvt_db"
);
pb.directory(new File("C:\\Program Files (x86)\\xnms-install\\mysql\\bin"));
Process process = pb.start();

错误场景3:备份命令是否带空格

假设命令不带空格,直接执行该命令没问题,可以生成sql文件

E:\WorkSpace2\mysql\bin\mysqldump.exe -h 10.110.24.62 -P 13306 -u root -p123456 --databases cvt_db>E:\WorkSpace2\xnms-app\mysqlBackup\cvt_db-20251009162355.sql

如果命令带空格或者(),比如mysqldump.exe存在的路径是

E:\Work Space (x2)\mysql\bin\mysqldump.exe

那么执行这个命令是错误的,会报错如下

'E:\Work' 不是内部或外部命令,也不是可运行的程序或批处理文件。

分析:为什么会这样?
答案:如果带空格在cmd进行解析时候,它不会把它当成命令执行,此实你就需要带双引号包裹,这时候你会想到的方案,或者网上找到的方案是加双引号,这个时候你的java生成的命令可能会长成这样

\"E:\WorkSpace2\mysql\bin\mysqldump.exe\" -h 10.110.24.62 -P 13306 -u root -p123456 --databases cvt_db>\"E:\WorkSpace2\xnms-app\mysqlBackup\cvt_db-20251009162355.sql\"

此实验证你会发现,这个命令放到cmd窗口执行是完全可以执行成功的,但是走如果你采用错误场景1的方法1会发现执行还是无法生成sql文件,所以解决方案应该是采用方案2的写法,不能使用方案1的写法。

错误场景4:‘C:\Program’ 不是内部或外部命令,也不是可运行的程序或批处理文件。

C:\Users\Administrator>C:\Program Files (x86)\xnms-install\mysql\bin\mysqldump.exe -h localhost -P 13306 -u root -p123456 --databases cvt_db>C:\Program Files (x86)\xnms-install\xnms-app\mysqlBackup\cvt_db-20251009151450.sql
'C:\Program' 不是内部或外部命令,也不是可运行的程序
或批处理文件。

原因:由于有空格没用双引号括起来,这个跟错误场景3差不多。

错误场景5:mysqldump: Got error: 1049: Unknown database ‘files’ when selecting the database

C:\Program Files (x86)\xnms-install\mysql\bin>mysqldump.exe -h localhost -P 13306 -u root -p123456 --databases cvt_db > C:\Program Files (x86)\xnms-install\cvt-windows-service\..\xnms-app\mysqlBackup\test.sqlcvt_db-20251009101122.sql
mysqldump: [Warning] Using a password on the command line interface can be insecure.
mysqldump: Got error: 1049: Unknown database 'files' when selecting the database

问题分析

原因1:因为命令中的重定向符号 > 后面的路径包含了空格,但没有用引号括起来,导致系统将路径解析错误。

系统将你的命令解析为:

  • mysqldump.exe … --databases cvt_db - 这是正确的
  • > - 重定向符号
  • C:\Program - 被当作第一个参数
  • Files - 被当作第二个参数(系统误认为这是数据库名)

所以 mysqldump 试图连接名为 “files” 的数据库,但该数据库不存在。

原因2:路径中的 … 问题:Java 的 ProcessBuilder 或 Runtime.exec() 不能直接解析 … 相对路径

解决方案

方法1:使用引号括起文件路径

mysqldump.exe -h localhost -P 13306 -u root -p123456 --databases cvt_db>"C:\Program Files (x86)\xnms-install\cvt-windows-service\..\xnms-app\mysqlBackup\test.sqlcvt_db-20251009101122.sql"

方法2:简化路径(推荐)

mysqldump.exe -h localhost -P 13306 -u root -p123456 --databases cvt_db>"C:\xnms-install\xnms-app\mysqlBackup\test.sqlcvt_db-20251009101122.sql"

方法3:先切换到目标目录再执行

cd "C:\Program Files (x86)\xnms-install\cvt-windows-service\..\xnms-app\mysqlBackup"
mysqldump.exe -h localhost -P 13306 -u root -p123456 --databases cvt_db>test.sqlcvt_db-20251009101122.sql

五、总结

错误场景原因有以下几种:

  • 命令路径带空格,方案1写法不带空格不用加双引号,如果有空格请加双引号,所以采用方案2写法。
  • 命令带…\这种返回上一级的有问题。
  • 命令不要带cd \d的写法,Java编写解析有问题。
  • 命令必须带-p123456,如果不带该参数,控制台会等待输入命令,但是程序执行期间如何输入命令?所以已经要带上不然无效果。
http://www.dtcms.com/a/460863.html

相关文章:

  • 22.shell编程实战(一)
  • PyTorch、ONNX Runtime、Hugging Face、NVIDIA Triton 和 LangChain 五个概念的关系详解
  • 【云原生】Neo4j 图数据库从搭建到项目使用深度详解
  • 关于网站开发的技术博客女装网站模板
  • Kubernetes(K8s)全场景命令宝典:从新手入门到故障排查全覆盖
  • 基于protobuf实现网络版本通讯录(protobuf 0基础可看)
  • 开源3d数字人学习笔记2025
  • 四大名著智能可视化推演平台
  • 成像系统(十四-2:《手机影像系统揭秘(二):ISP后端处理 - 画质增强与风格化》):从LED冬奥会、奥运会及春晚等大屏,到手机小屏,快来挖一挖里面都有什么
  • jsp ajax网站开发典型实例佟年给韩商言做的网站
  • 【算法】二分查找(二)查找边界二分
  • 【QT】采用fcitx5框架Ubuntu支持中文输入,QT不支持,解决?
  • 在Robosuite中如何使用Xbox游戏手柄操控mujoco仿真中的机械臂?
  • 数据民主化实践:ChatBI赋能全民数据分析
  • 零基础学AI大模型之LangChain链
  • 拱墅区网站建设网页培训机构
  • 潮州网站建设公司青岛市公共资源交易网
  • 告别重复数据烦恼!MySQL ON DUPLICATE KEY UPDATE 优雅解决存在更新/不存在插入难题
  • 开源项目安全性
  • 找网站建设都需要注意哪些云优化 网站建设
  • dockerfile构建案例
  • UiPath2025笔记第七节:B端Ai操控C端Rpa机器人
  • C++ 经典数组算法题解析与实现教程
  • 详解SOA架构,微服务架构,中台架构以及他们之间的区别和联系
  • 【C++学习笔记】伪随机数生成
  • Unity笔记(十二)——角色控制器、导航寻路系统
  • 关于嵌入式硬件需要了解的基础知识
  • 个人电脑做服务器网站目录型搜索引擎有哪些
  • 从赌场到AI:期望值如何用C++改变世界?
  • H3C网络设备 实验三: 搭建两个局域网,使两个局域网相互通信(路由器,自动分配ip,DHCP协议)