【使用java代码调用mysqldump备份mysql指定数据库,指定表备份到指定目录】

使用java代码备份mysql指定数据库,指定表备份到指定目录

java项目环境

SpringBoot+MybatisPlus
MySql 5.6+

备份需求

在java中使用mysqldump命令对指定的表进行备份,并生成sql文件输出到指定目录

具体代码逻辑




import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;

/**
 * @author 
 * 执行mysql数据备份
 */
@Service
public class MysqlDumpExec {

    private static final Logger logger = LoggerFactory.getLogger(MysqlDumpExec.class);


    /**
     * 备份文件输出路径
     */
    @Value("${mysql.data.backup.filePath:}")
    private String filePath;

    /**
     * mysqldump的可执行文件路径(一般在mysql安装目录的bin目录下)
     */
    @Value("${mysql.data.backup.mysqlDumpPath:/usr/local/mysql/bin/}")
    private String mysqlDumpPath;

    /**
     * 要备份的数据库表名 空格隔开
     */
    @Value("${mysql.data.backup.tables:test_t1 test_t2}")
    private String tables;

 @Value("${spring.datasource.url:}")
    private String dataUrl;

    @Value("${spring.datasource.username:}")
    private String dataUserName;

    @Value("${spring.datasource.password:}")
    private String dataPwd;


    public String backUpSystemLogs()  {
        String backPath = "";
        try {
          
            String fileName = "backUpSystemLog_" + new SimpleDateFormat("yyyyMMdd_hhmmss").format(System.currentTimeMillis()) + "_sql.sql";
            backPath = filePath + "/" + fileName;
            //开始拼接命令
            StringBuilder command = appendCmd(backPath);
            // 调用外部执行exe文件的javaAPI
            logger.info("执行mysql指令:" + command);
            String os = System.getProperty("os.name");
            Process process = null;
            if(os.toLowerCase().startsWith("win")){
                process = Runtime.getRuntime().exec(command.toString());
            } else {
                process = Runtime.getRuntime().exec(new String[]{"/bin/sh", "-c", command.toString()});
            }

            // 0 表示线程正常终止。
            if (process.waitFor() != 0) {
                logger.error("===========备份失败================");
         
            } else {
                logger.info("===========备份成功================");
           
                process.destroy();
            }

        } catch (UnsupportedEncodingException e) {       
            logger.error("backUpSystemLogs UnsupportedEncodingException", e);
            throw new ServiceException(SystemLogErrorCode.BACKUP_INVALID_PARAMETER);
        } catch (IOException e) {
            logger.error("backUpSystemLogs IOException", e);
            throw new ServiceException(SystemLogErrorCode.BACKUP_INVALID_PARAMETER);
        } catch (InterruptedException e) {      
            logger.error("backUpSystemLogs InterruptedException", e);
            throw new ServiceException(SystemLogErrorCode.BACKUP_INVALID_PARAMETER);
        } 
        if (logger.isDebugEnabled()) {
            logger.debug("Execute MysqlDumpExec::backUpSystemLogs() end.");
        }
        return backPath;
    }

    /**
     * 拼接执行命令
     *
     * @return
     */
    private StringBuilder appendCmd(String backPath) {
        StringBuilder command = new StringBuilder();
        String mysqlIp = "";
        String mysqlPort = "";
        String mysqlData = "";

        if (StringUtils.isNotBlank(dataUrl)) {
           //从配置中解析出数据库ip+名+端口
            String[] split = dataUrl.split("\\?")[0].split("/");
            mysqlData = split[split.length - 1];
            //192.144.210.30:33306
            String allIp = split[split.length - 2];
            String[] ips = allIp.split(":");
            mysqlIp = ips[0];
            mysqlPort = ips[1];
        }

        // 拼接命令行的命令
        //windows: D:\MySQL Server 5.7\bin\mysqldump  --opt -h127.0.0.1 --user=root -P33306 --password=123#! --databases test --tables test_user --result-file=D:\logsql\sql.sql --default-character-set=utf8
        //linux: /usr/local/mysql/bin/mysqldump  --opt -h111.144.210.30 --user=root --password='23!@#' -P33306 --databases test --tables test_t1 test_t2 --result-file=/syslog/backUpSystemLog_20211118_030951_sql.sql
        //如果加了-t 是只导出数据不导出表结构
        command.append(mysqlDumpPath+"mysqldump");
        command.append("  --opt -h");
        command.append(mysqlIp);
        command.append(" --user=");
        command.append(dataUserName);
        // 区分系统
        String os = System.getProperty("os.name");
        if(os.toLowerCase().startsWith("win")){
            command.append(" --password=");
            command.append(dataPwd);
        } else {
            //linux需要引号密码,否则会执行失败
            command.append(" --password=");
            command.append("'"+dataPwd+"'");
        }
        //端口用大写的P指向
        command.append(" -P");
        // 导出范围
        if (StringUtils.isEmpty(tables)) {
        //全部表
            command.append(" --all-databases");
        } else {
        //指定表
            command.append(mysqlPort + " --databases " + mysqlData + " --tables ");
            command.append(tables);
        }
        command.append(" --result-file=");
        command.append(backPath);
        return command;
    }

}

遇到的问题

一、windows命令的密码用引号包含–password='123#@!'就执行失败,报错如下

mysqldump: Got error: 1045: Access denied for user 'root'@'124.65.8.8' (using password: YES) when trying to connect
mysqldump: Got error: 1045: Access denied for user ‘root’@‘124.65.8.8’ (using password: YES) when trying to connect

解决方案:把密码的双引号去掉
!!!(但是去掉双引号后在linux执行命令又会报错)
在这里插入图片描述
最终解决方案:
windows的时候–password不加引号
linux的时候–password加引号

二、linux的命令行单独在命令行执行没问题,但是放在代码里面就执行失败
类似这个命令
【/usr/local/mysql/bin/mysqldump --opt -h111.144.210.30 --user=root --password=‘23!@#’ -P33306 --databases test --tables test_t1 test_t2 --result-file=/syslog/backUpSystemLog_20211118_030951_sql.sql】

原因:可能是Runtime.getRuntime().exec(string);解析命令的时候,因为命令有特殊字符或者空格之类的,导致命令解析异常

解决方案:更改exec执行参数(针对linux !!!windows不能这样写)
process = Runtime.getRuntime().exec(new String[]{"/bin/sh", “-c”, command.toString()});

windows下:(本人没测试,不知道是否好用)
Runtime.getRuntime().exec(new String[]{ “cmd”, “/c”, cmds});

三、使用如下命令在linux不好用,但是windows好用
【/usr/local/mysql/bin/mysqldump -h111.144.210.30 -uroot -p’23!@#’ -P33306 test test_t1 > /log/test.sql】
原因: 目前本人没找到原因,请大佬指点
解决方案:直接换成以上代码中的命令

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值