Mysql和达梦数据库备份与恢复

2023-05-16

Mysql和达梦数据库备份与恢复

  • 备份与恢复
    • Mysql备份与恢复
      • Mysql备份要先开启binlog日志:
      • 备份与恢复命令
        • 全量备份:
        • 全量恢复:须在bin目录下完成 cd /usr/local/mysql/bin windows下不用加./
        • 增量备份:
        • 增量还原:
    • 达梦数据库备份与恢复
      • 达梦数据库备份与恢复命令
        • windows备份恢复命令
        • Linux备份恢复命令
      • 备份与恢复压缩文件
    • Java 代码实现
          • MySQLBackupRestoreUtils Mysql备份与恢复工具类
          • DamengBackupRestoreUtils 达梦数据库备份与恢复工具类
          • UploadFileBackupRestoreUtils 文件资源备份恢复工具类

备份与恢复

本文介绍了Mysql数据库和达梦数据库全量、增量、自定义备份与恢复。以及文件资源以压缩包的形式实现备份与恢复。
使用java定时任务实现备份与恢复操作。

Mysql备份与恢复

Mysql备份要先开启binlog日志:

windows:
    在mysql安装目录下的my.ini文件中添加以下配置:
    # dir\[filename]  dir为日志存放目录 mysql-bin为新建文件夹  filename为日志文件名 形式为filename.number number的形式为000001、000002等 会自动递增
    log-bin=D:\\mysql-8.0.28-winx64\\Data\\mysql-bin\\mylog
    binlog_format=Mixed
    #需要备份的数据库名,如果备份多个数据库,重复设置这个选项即可
    binlog-do-db=testbackup
    #不需要备份的数据库名,如果备份多个数据库,重复设置这个选项即可
    #binlog-ignore-db=
    skip_ssl
liunx:
    在my.cnf中添加以下配置:
    #开启log——bin日志
    log-bin=/usr/local/mysql/mylog
    binlog_format=Mixed
    #需要备份的数据库名,如果备份多个数据库,重复设置这个选项即可
    binlog-do-db=testbackup
    #不需要备份的数据库名,如果备份多个数据库,重复设置这个选项即可
    #binlog-ignore-db=
    skip_ssl
然后重启数据库使配置生效

备份与恢复命令

全量备份:

mysqldump  -hIP -u用户名 -p密码 -P端口号 数据库名 --ssl-mode=DISABLED --result-file=/disk/backup/full/add/def_linux/linux_mysql8/MYSQL_20230228112504.sql(备份文件地址及文件名) --default-character-set=utf8

全量恢复:须在bin目录下完成 cd /usr/local/mysql/bin windows下不用加./

./mysql -hIP -u用户名 -p密码 -P端口号 -A -D 数据库名 -e "SOURCE /disk/backup/full/add/def_linux/linux_mysql8/MYSQL_20230228112504.sql"

增量备份:

首先全量备份一次,然后利用binlog日志,定时刷新日志生成新的日志文件,备份与恢复均依赖于binlog日志实现

mysqldump  -hIP -u用户名 -p密码 -P端口号 数据库名 --ssl-mode=DISABLED --result-file=/disk/backup/full/add/def_linux/linux_mysql8/MYSQL_ADDBACKUP_FULL.sql --default-character-set=utf8

每次增量备份即为刷新日志生成新的日志文件

./mysqladmin  -hIP -u用户名 -p密码 -P端口号 flush-logs

增量还原:

首先全量恢复一次

./mysql -hIP -u用户名 -p密码 -P端口号 -A -D 数据库名 -e "SOURCE /disk/backup/full/add/def_linux/linux_mysql8/MYSQL_ADDBACKUP_FULL.sql"

然后按日志生成顺序挨个恢复,可指定要恢复到的时间

./mysqlbinlog --no-defaults /usr/local/mysql/mylog.000004 |mysql -hIP -u用户名 -p密码 -P端口号

达梦数据库备份与恢复

命令行连接远程达梦数据库并进入dlsql命令行:
disql 模式名/密码@IP:端口号

达梦数据库备份与恢复有多种方式,本文采用逻辑备份,无需停掉达梦数据库服务。
逻辑备份:
导出:dexp / 导入:dimp
逻辑导出和逻辑导入数据库对象分为四种级别:数据库级、用户级、模式级和表级。四种级别独立互斥,不能同时存在。四种级别所提供的功能:
数据库级(FULL):导出或导入整个数据库中的全部对象。
用户级(OWNER):导出或导入一个或多个用户所拥有的全部对象。模式级(SCHEMAS):导出或导入一个或多个模式下的全部对象。
表级(TABLE):导出或导入一个或多个指定的表或表分区。

达梦数据库备份与恢复命令

首先介绍几个配置命令:

TABLE_EXISTS_ACTION=[SKIP | APPEND | TRUNCATE | REPLACE]   用于要导入的表已经存在时的处理方式。默认为直接报错
SKIP:跳过此表
APPEND:直接向现有表中导入数据。
TRUNCATE:先删除现有表中的数据,再向表中导入数据。
REPLACE:先删除现有表,再导数据。

TABLES选项支持模糊匹配
FUZZY_MATCH:用于指定 TABLES 选项是否支持模糊匹配,取值Y/N
FUZZY_MATCH=N:表示TABLES 选项不支持模糊匹配,指定的表名与数据库中的表名必须精确匹配;
FUZZY_MATCH=Y:TABLES选项支持模糊匹配,指定的表名与数据库中的表名采用LIKE模糊查询匹配;

示例

        2.1.1、导出XMLTEST模式中,表名包含YG的所有表

        [dmdba@localhost bin]$ ./dexp SYSDBA/SYSDBA@LOCALHOST:5237 DIRECTORY=/home/dmdba file=dexp_tab_fz.dmp log=dexp_tab_fz.log tables=XMLTEST.%YG% fuzzy_match=Y

        2.1.2、导出XMLTEST模式中,表名以T字母开头的所有表

        [dmdba@localhost bin]$ ./dexp SYSDBA/SYSDBA@LOCALHOST:5237 DIRECTORY=/home/dmdba file=dexp_tab_fz1.dmp log=dexp_tab_fz1.log tables=XMLTEST.T% fuzzy_match=Y

        2.1.3、导出XMLTEST模式中,表名最后两个字母为BU的所有表

        [dmdba@localhost bin]$ ./dexp SYSDBA/SYSDBA@LOCALHOST:5237 DIRECTORY=/home/dmdba file=dexp_tab_fz2.dmp log=dexp_tab_fz2.log tables=XMLTEST.%BU fuzzy_match=Y

        2.2 导出表数据时,只导出符合条件的数据

        QUERY选项:用于指定过滤条件来对表数据进行导出。

        QUERY="<where_condition>" ,QUERY选项的值为where条件(SQL语句中的where条件),比如QUERY="WHERE DEPT=20"

        示例:

        [dmdba@localhost bin]$ ./dexp SYSDBA/SYSDBA@LOCALHOST:5236 DIRECTORY=/home/dmdba file=dexp_tab_q1.dmp log=dexp_tab_q1.log tables=XMLTEST.T_EMP,XMLTEST.T1 query="where deptno=10"

        当指定多个表时,会对每个表都进行条件过滤,如果指定的表不存在条件列,则导出时会出现警告信息,此时该表导出失败,但不影响其他表的导出。

表存在时的操作:往表中插入数据:TABLE_EXISTS_ACTION=APPEND  
主键冲突时的操作:PRIMARY_CONFLICT=IGNORE

windows备份恢复命令

备份与恢复命令均要到达梦安装目录bin目录下执行

全表备份导出

dexp 模式名/密码@IP:端口号 file=dexp_tab02.dmp log=dexp_tab02.log

全表导入 TABLE_EXISTS_ACTION:TABLE_EXISTS_ACTION 用于要导入的表已经存在时的处理方式。默认为直接报错

dimp 模式名/密码@IP:端口号 file=dexp_tab02.dmp log=dexp_tab03.log TABLE_EXISTS_ACTION=TRUNCATE

自定义表导入导出

自定义表备份导出 file= 将备份文件输出到指定文件,可以加绝对路径(建议不加,直接将文件生成在bin目录下) log= 日志文件名 tables= 要备份的表名,多个表名用,隔开 不加tables=即备份全部的表

dexp 模式名/密码@IP:端口号 file=dexp_tab01.dmp log=dexp_tab01.log tables=user,dept

自定义表导入恢复 file=上次备份导出的文件 log= 新的日志文件名 tables= 要恢复的表名,多个表名用,隔开 不加tables=即恢复全部的表 TABLE_EXISTS_ACTION PRIMARY_CONFLICT:主键冲突时的处理方式: IGNORE|OVERWRITE 默认报错

dimp 模式名/密码@IP:端口号 file=dexp_tab111.dmp log=dexp_tab112.log tables=user,dept TABLE_EXISTS_ACTION=APPEND PRIMARY_CONFLICT=IGNORE
dimp 模式名/密码@IP:端口号 file=dexp_tab01.dmp log=dexp_tab01.log tables=user,dept TABLE_EXISTS_ACTION=TRUNCATE

增量备份导出 加where条件 where created >=‘2023-02-25 00:00:00’; 有where条件时必须加tables=

dexp 模式名/密码@IP:端口号 file=dexp_tab08.dmp log=dexp_tab08.log tables=user,dept  QUERY="where created >= to_date('2022-02-20 00:00:00','yyyy-mm-dd hh24:mi:ss')";

增量备份导入
先执行全量恢复 然后按顺序恢复(直接向现有表中增加数据)

dimp 模式名/密码@IP:端口号 file=dexp_tab08.dmp log=dexp_tab09.log tables=user,dept TABLE_EXISTS_ACTION=APPEND

Linux备份恢复命令

全量备份:

./dexp 模式名/密码@IP:端口号file=/disk/backup/full/add/def_linux/linux_dm8/MYSQL_20230228151106.dmp log=/disk/backup/full/add/def_linux/linux_dm8/MYSQL_20230228151106.log

全量恢复:

./dimp 模式名/密码@IP:端口号file=/disk/backup/full/add/def_linux/linux_dm8/MYSQL_20230228151106.dmp log=restore_20230228151951.log TABLE_EXISTS_ACTION=TRUNCATE

增量备份:
先全备一次 tables= 可指定备份表

./dexp 模式名/密码@IP:端口号file=/disk/backup/full/add/def_linux/linux_dm8/20230228153236/DAMENG_ADDBACKUP_FULL.dmp log=/disk/backup/full/add/def_linux/linux_dm8/20230228153236/DAMENG_ADDBACKUP_FULL.log  tables=user,dept

再加条件备份

./dexp 模式名/密码@IP:端口号file=/disk/backup/full/add/def_linux/linux_dm8/20230228153236/MYSQL_20230228154011.dmp log=/disk/backup/full/add/def_linux/linux_dm8/20230228153236/MYSQL_20230228154011.log  tables=user,dept QUERY="where created >= to_date('2023-02-28 15:02:36','yyyy-mm-dd hh24:mi:ss')"

增量恢复:
先恢复全量的:

./dimp 模式名/密码@IP:端口号file=/disk/backup/full/add/def_linux/linux_dm8/20230228153236/DAMENG_ADDBACKUP_FULL.dmp log=restore_20230228154502.log  tables=user,dept TABLE_EXISTS_ACTION=TRUNCATE

然后按顺序恢复 表存在时的操作:往表中插入数据:TABLE_EXISTS_ACTION=APPEND 主键冲突时的操作:PRIMARY_CONFLICT=IGNORE

./dimp 模式名/密码@IP:端口号 file=/disk/backup/full/add/def_linux/linux_dm8/20230228153236/MYSQL_20230228154255.dmp log=restore_20230228154502.log  tables=user,dept TABLE_EXISTS_ACTION=APPEND PRIMARY_CONFLICT=IGNORE

备份与恢复压缩文件

文件备份:
   linux:
       tar -czvf /disk/backup/full/add/def_linux/files/uploadFiles-backup-20230228112504.tar.gz /disk/files/
       解压
       tar -zxvf /disk/backup/full/add/def_linux/files/uploadFiles-backup-20230228112504.tar.gz -C /
   windows:
      tar -czvf C:\disk\backup\full\add\def_linux\files\uploadFiles-backup-20230228112504.tar.gz C:\disk\files\
      解压
      tar -zxvf C:\disk/backup\full\add\def_linux\files\uploadFiles-backup-20230228112504.tar.gz -C

Java 代码实现

	@ApiOperation("执行数据备份")
    @PostMapping(Routes.BackupRoutes.INIT)
    @PreAuthorize("@ss.hasPermi('data:backup:start')")
    @Log(title = "数据备份", businessType = BusinessType.START)
    public JsonData initBackup(@RequestBody BackupInsertParams operLogParam) {
        try {
            boolean flag = false;
            if(dataSourceFlag.equals("MYSQL")){
                flag = mySqlBackupService.initBackup(operLogParam);
            }else {
                flag = damengBackupService.initBackup(operLogParam);
            }
            // 返回结果
            if(flag){
                backupMapper.updateStatusById(operLogParam.getId(),2);
                return JsonData.buildSuccess("执行成功");
            }else{
                return JsonData.buildSuccess("执行失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return JsonData.buildSuccess("执行失败");
        }
    }


	@ApiOperation("执行数据恢复")
    @GetMapping(Routes.BackupRoutes.RESTORE)
    @PreAuthorize("@ss.hasPermi('data:restore:start')")
    @Log(title = "数据恢复", businessType = BusinessType.START)
    public JsonData restoreBackUp(@RequestParam String id,@RequestParam(required = false) String fileName) {
        try {
            boolean flag = false;
            if(dataSourceFlag.equals("MYSQL")){
                flag = mySqlBackupService.restoreBackUp(id,fileName);
            }else {
                flag = damengBackupService.restoreBackUp(id,fileName);
            }
            // 返回结果
            if(flag){
                return JsonData.buildSuccess("执行成功");
            }else{
                return JsonData.buildSuccess("执行失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return JsonData.buildSuccess("执行失败");
        }
    }

import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@AllArgsConstructor
@NoArgsConstructor
@Data
public class BackupParams {

    @ApiModelProperty("主机IP")
    private String host;

    @ApiModelProperty("数据库用户名")
    private String userName;

    @ApiModelProperty("数据库密码")
    private String password;

    @ApiModelProperty("数据库端口号")
    private String port;

    @ApiModelProperty("备份的路径/上传文件的路径")
    private String backupFolderPath;

    @ApiModelProperty("备份的文件名")
    private String fileName;

    @ApiModelProperty("需要备份的数据库名称")
    private String database;

    @ApiModelProperty("mysql bin 目录所在位置")
    private String mysqlPath;

    @ApiModelProperty("备份类型 1:全量备份  2:增量备份   3:自定义全量备份")
    private int backupType;

    @ApiModelProperty("全量备份生成的备份文件的目录/上传文件压缩备份的路径")
    private String backupFolder;

    @ApiModelProperty("全量备份生成的备份文件的名称")
    private String backupFileName;

    @ApiModelProperty("操作是否成功")
    private boolean resultStatus;

    @ApiModelProperty("自定义全量备份的表名")
    private String[] tables;

    @ApiModelProperty("原始备份文件的名称(用于下次备份时删除该文件)")
    private String originalBackupFileName;

    @ApiModelProperty("是否为首次备份")
    private boolean firstBackUpFlag = false;

    @ApiModelProperty("上次备份时间")
    private String lastTime ;

    @ApiModelProperty("所有的表名")
    private String allTables ;

}


mySqlBackupService.initBackup

@Override
    public boolean initBackup(BackupInsertParams insertParams) throws Exception {
        //ip
        String host = properties.getHost();
        //数据库用户名
        String userName = properties.getUserName();
        //数据库密码
        String password = properties.getPassword();
        //数据库名称
        String database = properties.getDatabase();

        String port=properties.getPort();
        String mysqlPath = winMysqlPath;
        String backupFolder = windowsBackupFolder;
        if(systemLinuxFlag){
            mysqlPath = linuxMysqlPath;
            backupFolder = linuxBackupFolder;
        }
        //文件名
        String fileName = dataSourceFlag +"_" + DateUtils.format(new Date(),BackupConstants.DATE_FORMAT)+BackupConstants.BACKUP_FILE_NAME;
        //备份数据地址
        String backupFolderPath = "";
        if (StringUtils.isNotBlank(insertParams.getSavePath())){
            backupFolderPath=insertParams.getSavePath();
        }else {
            backupFolderPath = backupFolder ;
        }
        /* 查询备份方式 */
        DictVo dict = dictService.selectById(insertParams.getBackupTypeId());
        insertParams.setBackupType(1);
        if(dict != null){
            if(dict.getDictItem().contains("全量")){
                insertParams.setBackupType(1);
            }else if(dict.getDictItem().contains("增量")){
                insertParams.setBackupType(2);
            }else if(dict.getDictItem().contains("自定义")){
                insertParams.setBackupType(2);
            }
        }
        BackupParams backupParams = new BackupParams(host, userName, password, port, backupFolderPath, fileName, database,mysqlPath,insertParams.getBackupType(),backupFolder,null,false,insertParams.getTables()!=null?insertParams.getTables().split(","):null,insertParams.getFileName(), insertParams.isFirstBackUpFlag(), insertParams.getStartTime(),null);

        // 备份数据库
        backupParams = mySQLBackupService.backup(backupParams);
        // 备份数据库生成的文件目录
        String dataBackupFolder = backupParams.getBackupFolderPath();
        //将文件名更新到数据库中
        BackupDO backupDO=new BackupDO();
        // 全量备份可能生成新的文件名
        String newFileName =  backupParams.getFileName();
        // 备份上传文件
        backupParams.setOriginalBackupFileName(insertParams.getUploadFileSaveName());
        BackupParams backupParams1 = filesBackUpService.backup(backupParams);
        // 备份上传文件
        // 备份数据库
        if (backupParams.isResultStatus()){
            BeanUtils.copyProperties(insertParams,backupDO);
            backupDO.setSavePath(dataBackupFolder);
            backupDO.setFileName(newFileName);
            // 更新上次执行时间
            backupDO.setLastTime(DateUtils.format(new Date(),BackupConstants.DATE_FORMAT1));
            if (backupParams1.isResultStatus()){
                backupDO.setUploadFileSavePath(backupParams1.getBackupFolder());
                backupDO.setBackupStatus(1);
                backupDO.setUploadFileSaveName(backupParams1.getFileName());
            }
            backupMapper.updateById(backupDO);
        }
        return backupParams.isResultStatus();

    }

damengBackupService.initBackup

@Override
    public boolean  initBackup(BackupInsertParams insertParams) throws Exception {
        //ip
        String host = properties.getHost();
        //数据库用户名
        String userName = properties.getUserName();
        //数据库密码
        String password = properties.getPassword();
        //数据库名称
        String database = properties.getDatabase();

        String port=properties.getPort();
        String mysqlPath = winMysqlPath;
        String backupFolder = windowsBackupFolder;
        if(systemLinuxFlag){
            mysqlPath = linuxMysqlPath;
            backupFolder = linuxBackupFolder;
        }
        //文件名
        String fileName = dataSourceFlag +"_" + DateUtils.format(new Date(),BackupConstants.DATE_FORMAT)+BackupConstants.DAMENG_EXT;
        //备份数据地址
        String backupFolderPath = "";
        if (StringUtils.isNotBlank(insertParams.getSavePath())){
            backupFolderPath=insertParams.getSavePath();
        }else {
            backupFolderPath = backupFolder ;
        }
        /* 查询备份方式 */
        DictVo dict = dictService.selectById(insertParams.getBackupTypeId());
        insertParams.setBackupType(1);
        if(dict != null){
            if(dict.getDictItem().contains("全量")){
                insertParams.setBackupType(1);
            }else if(dict.getDictItem().contains("增量")){
                insertParams.setBackupType(2);
            }else if(dict.getDictItem().contains("自定义")){
                insertParams.setBackupType(2);
            }
        }
        // 备份路径为空则代表为首次备份
        if(StringUtils.isBlank(insertParams.getSavePath())){
            insertParams.setFirstBackUpFlag(true);
        }else{
            insertParams.setFirstBackUpFlag(false);
        }

        // 增量备份指定文件夹 固定首次备份文件的名称
        if(insertParams.getBackupType() == 2){
            if(systemLinuxFlag){
                backupFolderPath = backupFolderPath ;
                if(insertParams.isFirstBackUpFlag()){
                    backupFolderPath = backupFolderPath + "/"+DateUtils.format(new Date(),BackupConstants.DATE_FORMAT);
                }
            }else{
                backupFolderPath = backupFolderPath ;
                if(insertParams.isFirstBackUpFlag()){
                    backupFolderPath = backupFolderPath + "\\"+DateUtils.format(new Date(),BackupConstants.DATE_FORMAT);
                }
            }

        }
        BackupParams backupParams = new BackupParams(host, userName, password, port, backupFolderPath, fileName, database,mysqlPath,insertParams.getBackupType(),
                backupFolder,null,false,insertParams.getTables()!=null?insertParams.getTables().split(","):null,insertParams.getFileName(),insertParams.isFirstBackUpFlag(),insertParams.getStartTime(), daMengBackupService.selectAllTables());

        // 备份数据库
        backupParams = daMengBackupService.backup(backupParams);
        // 备份数据库生成的文件目录
        String dataBackupFolder = backupParams.getBackupFolderPath();
        // 全量备份可能生成新的文件名
        String newFileName =  backupParams.getFileName();
        // 备份上传文件
        backupParams.setOriginalBackupFileName(insertParams.getUploadFileSaveName());
        BackupParams backupParams1 = filesBackUpService.backup(backupParams);
        // 备份上传文件
        // 备份数据库
        if (backupParams.isResultStatus()){
            //将文件名更新到数据库中
            BackupDO backupDO=new BackupDO();
            BeanUtils.copyProperties(insertParams,backupDO);
            // 更新上次执行时间
            backupDO.setLastTime(DateUtils.format(new Date(),BackupConstants.DATE_FORMAT1));
            backupDO.setSavePath(dataBackupFolder);
            backupDO.setFileName(newFileName);
            if (backupParams1.isResultStatus()){
                backupDO.setUploadFileSavePath(backupParams1.getBackupFolder());
                // 将状态改为执行中
                backupDO.setBackupStatus(1);
                backupDO.setUploadFileSaveName(backupParams1.getFileName());
            }
            backupMapper.updateById(backupDO);
        }
        return backupParams.isResultStatus();

    }

mySQLBackupService.backup

@Override
    public BackupParams backup(BackupParams backupParams) throws Exception {
        if(backupParams.getBackupType() != 2){
            // 全量备份
            MySQLBackupRestoreUtils.backup(backupParams);
        }else {
            // 增量备份
            MySQLBackupRestoreUtils.addBackup(backupParams);
        }
        return backupParams;
    }

daMengBackupService.backup

@Override
    public BackupParams backup(BackupParams backupParams) throws Exception {
        if(backupParams.getBackupType() != 2){
            // 全量备份
            DamengBackupRestoreUtils.backup(backupParams);
        }else {
            // 增量备份
            DamengBackupRestoreUtils.addBackup(backupParams);
        }
        return backupParams;
    }
MySQLBackupRestoreUtils Mysql备份与恢复工具类

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import java.io.*;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Mysql备份与恢复工具类
 */
@Slf4j
public class MySQLBackupRestoreUtils {

    @Value("${backup.path.linux}")
    private static String linuxBackupFolder;
    @Value("${backup.path.windows}")
    private static String windowsBackupFolder;

    /**
     *
     * 备份数据库
     * @return
     * @throws Exception
     */
    public static BackupParams backup(BackupParams backupParams) throws Exception {
        File backupFolderFile = new File(backupParams.getBackupFolderPath());
        if(!backupFolderFile.exists()) {
            // 如果目录不存在则创建
            backupFolderFile.mkdirs();
        }
        if(!backupParams.getBackupFolderPath().endsWith(File.separator) && !backupParams.getBackupFolderPath().endsWith("/")) {
            if(systemLinuxFlag){
                backupParams.setBackupFolderPath(backupParams.getBackupFolderPath() + "/") ;
            }else{
                backupParams.setBackupFolderPath(backupParams.getBackupFolderPath() + File.separator) ;
            }
        }
        // 拼接执行命令
        String backupFilePath = backupParams.getBackupFolderPath() + backupParams.getFileName();
        backupParams.setBackupFolder(backupParams.getBackupFolderPath());
        backupParams.setBackupFileName(backupParams.getFileName());

        StringBuilder stringBuilder = new StringBuilder();
        //MySQLdump在的目录,防止打不开

        File file=new File("");
        if(StringUtils.isNotBlank(backupParams.getOriginalBackupFileName())){
            if(systemLinuxFlag){
                stringBuilder.append("rm -f ");
            }else{
                stringBuilder.append("del /f/s/q ");
            }
            stringBuilder.append(backupParams.getBackupFolder()).append(backupParams.getOriginalBackupFileName()).append(" && ");
        }

        stringBuilder.append(file.getAbsolutePath()).append("\\");
        stringBuilder.append("mysqldump ");
        //端口号
        stringBuilder.append(" -h").append(backupParams.getHost()).append(" -u").append(backupParams.getUserName()).append(" -p").append(backupParams.getPassword()).append(" -P").append(backupParams.getPort());

        // 自定义备份表
        if(backupParams.getTables() != null && backupParams.getTables().length > 0 ){
            stringBuilder.append(" ").append(backupParams.getDatabase()).append(" --tables ");
            List<String> tableList = Arrays.asList(backupParams.getTables());
            for(int i=0;i< tableList.size();i++){
                if(StringUtils.isNotBlank(tableList.get(i).replaceAll("\"",""))){
                    stringBuilder.append(tableList.get(i).replaceAll("\"",""));
                }
                if(i!=tableList.size()-1){
                    stringBuilder.append(" ");
                }
            }
        }else{
            stringBuilder.append(" ").append(backupParams.getDatabase());
        }
        // 添加--ssl-mode=DISABLED 防止出现 SSL 2026的错误
        stringBuilder.append(" --ssl-mode=DISABLED");
        stringBuilder.append(" --result-file=").append(backupFilePath).append(" --default-character-set=utf8 ");

        // 调用外部执行 exe文件的Java API
        System.out.println("MYSQL备份命令===============》 "+ String.valueOf(stringBuilder));
        Process process = Runtime.getRuntime().exec(getCommand(stringBuilder.toString()));
        FileInputStream errorStream = (FileInputStream) process.getErrorStream();
        // 读取错误信息
        InputStreamReader isr = new InputStreamReader(errorStream,"gbk");
        System.out.println(isr.getEncoding());
        BufferedReader bufr = new BufferedReader(isr);
        String line = null;
        while ((line = bufr.readLine()) != null){
            System.out.println(line);
        }
        isr.close();
        bufr.close();

        log.error("输出值:" + process.waitFor());
        if(process.waitFor() == 0) {
            // 0 表示线程正常终止
            log.info("数据完成备份,备份至 " + backupFilePath + " 文件中。");
            // 替换insert into 为 replace into
            try {
                File replaceFile = new File(backupFilePath);
                backupParams.setFileName(replaceSql(backupFilePath));
                replaceFile.delete();
            } catch (Exception e) {
                e.printStackTrace();
            }
            backupParams.setResultStatus(true);
            return backupParams;
        }
//        backupParams.setResultStatus(true);
        backupParams.setResultStatus(false);
        return backupParams;
    }

    /**
     * 增量备份时刷新数据库日志
     * @param restoreParams
     * @return
     * @throws Exception
     */
    public static boolean refreshLog(RestoreParams restoreParams) throws Exception {
        StringBuilder stringBuilder = new StringBuilder();
        if(systemLinuxFlag){
            stringBuilder.append("cd ").append(restoreParams.getMysqlPath()).append(" && ");
            stringBuilder.append("./mysql -h").append(restoreParams.getHost()).append(" -u").append(restoreParams.getUserName()).append(" -p").append(restoreParams.getPassword()).append(" -P").append(restoreParams.getPort());
            stringBuilder.append(" -A -D ").append(restoreParams.getDatabase()).append(" -e \"SOURCE "+ restoreParams.getRestoreFilePath() +"\"");
        }else {
            stringBuilder.append(restoreParams.getMysqlPath().substring(0,restoreParams.getMysqlPath().indexOf(":")).toLowerCase()).append(":").append(" && ");
            stringBuilder.append("cd ").append(restoreParams.getMysqlPath()).append(" & ");
            stringBuilder.append("./mysqladmin -h").append(restoreParams.getHost()).append(" -u").append(restoreParams.getUserName()).append(" -p").append(restoreParams.getPassword()).append(" -P").append(restoreParams.getPort());
            stringBuilder.append(" flush-logs");
        }
        Process process = Runtime.getRuntime().exec(getCommand(stringBuilder.toString()));
        log.error("输出值:" + process.waitFor());
        if(process.waitFor() == 0) {
            // 0 表示线程正常终止
            log.info("数据库增量备份日志刷新成功!!!!");
            return true;
        }
        return false;
//        return true;
    }


    /**
     * 恢复数据库
     * @return
     * @throws Exception
     */
    public static RestoreParams restore(RestoreParams restoreParams) throws Exception {
        StringBuilder stringBuilder = new StringBuilder();
        // 全量恢复
        if(restoreParams.getRestoreType() == 1){
            //     stringBuilder.append("C:\\Users\\panfei\\IdeaProjects\\train-software-server6\\train-software-serverdev\\bin\\") ;
            File file=new File("");
//        stringBuilder.append(file.getAbsolutePath()).append("\\");
            if(systemLinuxFlag){
                stringBuilder.append("cd ").append(restoreParams.getMysqlPath()).append(" && ");
                stringBuilder.append("./mysql -h").append(restoreParams.getHost()).append(" -u").append(restoreParams.getUserName()).append(" -p").append(restoreParams.getPassword()).append(" -P").append(restoreParams.getPort());
                stringBuilder.append(" -A -D ").append(restoreParams.getDatabase()).append(" -e \"SOURCE "+ restoreParams.getRestoreFilePath()+restoreParams.getFileName() +"\"");
            }else {
                stringBuilder.append(restoreParams.getMysqlPath().substring(0,restoreParams.getMysqlPath().indexOf(":")).toLowerCase()).append(":").append(" && ");
                stringBuilder.append("cd ").append(restoreParams.getMysqlPath()).append(" & ");
                stringBuilder.append("mysql -h").append(restoreParams.getHost()).append(" -u").append(restoreParams.getUserName()).append(" -p").append(restoreParams.getPassword()).append(" -P").append(restoreParams.getPort());
                stringBuilder.append(" -A -D ").append(restoreParams.getDatabase()).append(" -e \"SOURCE "+ restoreParams.getRestoreFilePath()+restoreParams.getFileName() +"\"");
            }
            try {
                System.out.println("MYSQL数据全量恢复命令========> "+stringBuilder.toString());
                Process process = Runtime.getRuntime().exec(getCommand(stringBuilder.toString()));
                FileInputStream errorStream = (FileInputStream) process.getErrorStream();
                // 读取错误信息
                InputStreamReader isr = new InputStreamReader(errorStream,"gbk");
                System.out.println(isr.getEncoding());
                BufferedReader bufr = new BufferedReader(isr);
                String line = null;
                while ((line = bufr.readLine()) != null){
                    System.out.println(line);
                }
                isr.close();
                bufr.close();
                System.out.println("输出值:" + process.waitFor());
                if(process.waitFor() == 0) {
                    log.info("数据已从 " + restoreParams.getRestoreFilePath() + restoreParams.getFileName() + " 导入至数据库中。");
                }
            } catch (Exception e) {
                e.printStackTrace();
                restoreParams.setResultStatus(false);
                return  restoreParams;
            }
            restoreParams.setResultStatus(true);
        }else{
            // 增量备份恢复
            // 先执行第一次全量备份恢复
            restoreParams.setRestoreType(1);
            String fileName = restoreParams.getFileName();
            restoreParams.setFileName("MYSQL_ADDBACKUP_FULL.sql");
            restoreParams = restore(restoreParams);
            restoreParams.setFileName(fileName);
            restoreParams.setRestoreType(2);
            if(restoreParams.isResultStatus()){
                // 第一次全量备份恢复成功后获取增量备份文件夹下所有文件
                File logfile = new File(restoreParams.getAddBackUpFilePath());
                String logFileName = restoreParams.getAddBackUpFileName();
                // 排除.index文件并按修改时间正序排序
                List<File> fileList = Arrays.asList(logfile.listFiles()).stream().filter(p -> p.getName().contains(logFileName) && !p.getName().endsWith(".index")).sorted(Comparator.comparing(File::lastModified)).collect(Collectors.toList());
                for(File file : fileList){
                    // 删除Mysql二进制日志命令:在bin目录下执行: mysql -uroot -proot testbackup -e "reset master;"
                    // 循环执行增量恢复脚本  mysqlbinlog --no-defaults D:\mysql-8.0.28-winx64\Data\mysql-bin.000012 |mysql -uroot -proot
                    StringBuilder newStringBuilder = new StringBuilder();

                        if(systemLinuxFlag){
                            newStringBuilder.append("cd ").append(restoreParams.getMysqlPath()).append(" && ");
                            newStringBuilder.append("./mysqlbinlog --no-defaults ").append(file.getAbsolutePath()).append(" |mysql").append(" -h");
                            newStringBuilder.append(restoreParams.getHost()).append(" -u").append(restoreParams.getUserName()).append(" -p").append(restoreParams.getPassword()).append(" -P").append(restoreParams.getPort());
                        }else {
                            newStringBuilder.append(restoreParams.getMysqlPath().substring(0,restoreParams.getMysqlPath().indexOf(":")).toLowerCase()).append(":").append(" && ");
                            newStringBuilder.append("cd ").append(restoreParams.getMysqlPath()).append(" & ");
                            newStringBuilder.append("mysqlbinlog --no-defaults ").append(file.getAbsolutePath()).append(" |mysql").append(" -h");
                            newStringBuilder.append(restoreParams.getHost()).append(" -u").append(restoreParams.getUserName()).append(" -p").append(restoreParams.getPassword()).append(" -P").append(restoreParams.getPort());
                        }
                        try {
                            System.out.println("MYSQL增量备份数据恢复命令========> "+ newStringBuilder.toString());
                            Process process = Runtime.getRuntime().exec(getCommand(newStringBuilder.toString()));
                            FileInputStream errorStream = (FileInputStream) process.getErrorStream();
                            // 读取错误信息
                            InputStreamReader isr = new InputStreamReader(errorStream,"gbk");
                            System.out.println(isr.getEncoding());
                            BufferedReader bufr = new BufferedReader(isr);
                            String line = null;
                            while ((line = bufr.readLine()) != null){
                                System.out.println(line);
                            }
                            isr.close();
                            bufr.close();
                            System.out.println("输出值:" + process.waitFor());
                            if(process.waitFor() == 0) {
                                log.info("数据已从 " + file.getAbsolutePath() + " 导入至数据库中。");
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                            restoreParams.setResultStatus(false);
                            return  restoreParams;
                        }
                    // 循环到页面选择的恢复时间为止
                    if(file.getName().equals(restoreParams.getFileName())){
                        break;
                    }
                }
                restoreParams.setResultStatus(true);
            }else{
                restoreParams.setResultStatus(false);
            }

            return  restoreParams;
        }
        restoreParams.setResultStatus(true);
        return  restoreParams;
    }

    private static String[] getCommand(String command) {
        String os = System.getProperty("os.name");
        String shell = "/bin/bash";
        String c = "-c";
        if(os.toLowerCase().startsWith("win")){
            shell = "cmd.exe";
            c = "/c";
        }
        String[] cmd = { shell, c, command};
        return cmd;
    }

    /**
     *
     * 增量备份数据库
     *
     * 增量备份的思路是先进行一次全量备份  然后定时刷新生成的二进制日志 恢复时先全量恢复  然后按顺序增量恢复所有日志
     * @return
     * @throws Exception
     */
    public static BackupParams addBackup(BackupParams backupParams) throws Exception {
        // 首先全量备份一次
//        String backupFolder = windowsBackupFolder +"\\addbackup";
        if(systemLinuxFlag){
            backupParams.setBackupFolder(backupParams.getBackupFolder()+ "/addbackup");
        }else{
            backupParams.setBackupFolder(backupParams.getBackupFolder()+ "\\addbackup");
        }
        // fileName 在增量恢复时要用到
        //
        String filename = backupParams.getFileName();
//        backupParams.setFileName("MYSQL_ADDBACKUP_FULL.sql");
        BackupParams backupParams1 = new BackupParams();
        BeanUtils.copyProperties(backupParams,backupParams1);
        backupParams1.setFileName("MYSQL_ADDBACKUP_FULL.sql");
        backup(backupParams1);
//        backupParams.setFileName(filename);
        File backupFolderFile = new File(backupParams.getBackupFolderPath());
        if(!backupFolderFile.exists()) {
            // 如果目录不存在则创建
            backupFolderFile.mkdirs();
        }
        if(!backupParams.getBackupFolderPath().endsWith(File.separator) && !backupParams.getBackupFolderPath().endsWith("/")) {
//            backupParams.setBackupFolderPath(backupParams.getBackupFolderPath()+ File.separator) ;
            if(systemLinuxFlag){
                backupParams.setBackupFolderPath(backupParams.getBackupFolderPath() + "/") ;
            }else{
                backupParams.setBackupFolderPath(backupParams.getBackupFolderPath() + File.separator) ;
            }
        }
        return addBackUpFlushLogs(backupParams);
    }

    /**
     * 增量备份刷新二进制日志
     * @return
     * @throws IOException
     * @throws InterruptedException
     */
    public static BackupParams addBackUpFlushLogs(BackupParams backupParams) throws IOException, InterruptedException {
        // 拼接执行命令
        String backupFilePath = backupParams.getBackupFolderPath() ;

        StringBuilder stringBuilder = new StringBuilder();
        //MySQLdump在的目录,防止打不开

        if(systemLinuxFlag){
            stringBuilder.append("cd ").append(backupParams.getMysqlPath()).append(" && ");
            stringBuilder.append("./mysqladmin ");
        }else {
            stringBuilder.append(backupParams.getMysqlPath().substring(0,backupParams.getMysqlPath().indexOf(":")).toLowerCase()).append(":").append(" && ");
            stringBuilder.append("cd ").append(backupParams.getMysqlPath()).append(" & ");
            stringBuilder.append("mysqladmin.exe ");
        }
//        //端口号
        stringBuilder.append(" -h").append(backupParams.getHost()).append(" -u").append(backupParams.getUserName()).append(" -p").append(backupParams.getPassword()).append(" -P").append(backupParams.getPort());
        stringBuilder.append(" flush-logs");
//        stringBuilder.append(" --result-file=").append(backupFilePath).append("00001").append(" --default-character-set=utf8 ").append(database);
        System.out.println("增量备份刷新二进制日志命令============》"+stringBuilder.toString());

        // 调用外部执行 exe文件的Java API
        Process process = Runtime.getRuntime().exec(getCommand(stringBuilder.toString()));
        log.error("输出值:" + process.waitFor());
        FileInputStream errorStream = (FileInputStream) process.getErrorStream();
        // 读取错误信息
        InputStreamReader isr = new InputStreamReader(errorStream,"gbk");
        System.out.println(isr.getEncoding());
        BufferedReader bufr = new BufferedReader(isr);
        String line = null;
        while ((line = bufr.readLine()) != null){
            System.out.println(line);
        }
        isr.close();
        bufr.close();
        if(process.waitFor() == 0) {
            // 0 表示线程正常终止
            log.info("数据完成备份,备份至 " + backupFilePath + " 文件中。");
            backupParams.setResultStatus(true);
            return backupParams;
        }
        backupParams.setResultStatus(false);
//        backupParams.setResultStatus(true);
        return backupParams;
    }


    /**
     * 将MySQL备份脚本中的insert into 替换为 replace into
     * @param fileName
     * @throws Exception
     */
    private static String replaceSql(String fileName) throws Exception {
        BufferedReader br = null;
        BufferedWriter bw = null;
        String line = null;
        StringBuffer buf = new StringBuffer();
        InputStreamReader read = new InputStreamReader(new FileInputStream(new File(fileName)), "utf-8");
        br = new BufferedReader(read);
        String newFileName = fileName.substring(0,fileName.lastIndexOf(".")) + "replace"+ DateUtils.format(new Date(), BackupConstants.DATE_FORMAT) +".sql";
        OutputStreamWriter write = new OutputStreamWriter(new FileOutputStream(new File(newFileName)),"utf-8");
        bw = new BufferedWriter(write);
        try {
            while((line = br.readLine()) != null) {
                line = line.replaceAll("INSERT INTO","REPLACE INTO");
                buf.append(line.toString()).append("\n");
            }
            bw.write(buf.toString());
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            read.close();
            write.flush();
            bw.flush();
            write.close();
            bw.close();
        }
        return newFileName.substring(newFileName.lastIndexOf("\\")+1);
    }

}

DamengBackupRestoreUtils 达梦数据库备份与恢复工具类

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import java.io.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;



/**
 * 达梦数据库备份与恢复工具类
 */
@Slf4j
public class DamengBackupRestoreUtils {

    /**
     *
     * 备份数据库
     * @return
     * @throws Exception
     */
    public static BackupParams backup(BackupParams backupParams) throws Exception {
        File backupFolderFile = new File(backupParams.getBackupFolderPath());
        if(!backupFolderFile.exists()) {
            // 如果目录不存在则创建
            backupFolderFile.mkdirs();
        }
        if(!backupParams.getBackupFolderPath().endsWith(File.separator) && !backupParams.getBackupFolderPath().endsWith("/")) {
            if(systemLinuxFlag){
                backupParams.setBackupFolderPath(backupParams.getBackupFolderPath() + "/") ;
            }else{
                backupParams.setBackupFolderPath(backupParams.getBackupFolderPath() + File.separator) ;
            }
        }
        // 拼接执行命令
        String backupFilePath = backupParams.getBackupFolderPath() + backupParams.getFileName();
        backupParams.setBackupFolder(backupParams.getBackupFolderPath());
        backupParams.setBackupFileName(backupParams.getFileName());

        StringBuilder stringBuilder = new StringBuilder();
        //DAMENGdump在的目录,防止打不开

        // 先删除上一次备份的文件 del /f/s/q C:\disk\dateBackup\20230220175325copy20230220175326.sql
        if(StringUtils.isNotBlank(backupParams.getOriginalBackupFileName()) && backupParams.getBackupType() != 2){
            if(systemLinuxFlag){
                stringBuilder.append("rm -f ");
            }else{
                stringBuilder.append("del /f/s/q ");
            }
            stringBuilder.append(backupParams.getBackupFolder()).append(backupParams.getOriginalBackupFileName()).append(" && ");
        }
        if(!systemLinuxFlag){
            stringBuilder.append(backupParams.getMysqlPath().substring(0,backupParams.getMysqlPath().indexOf(":")).toLowerCase()).append(":").append(" && ");
            stringBuilder.append("cd ").append(backupParams.getMysqlPath()).append(" & ");
        }else{
            stringBuilder.append("./");
            stringBuilder.append("cd ").append(backupParams.getMysqlPath()).append(" && ");
        }
        stringBuilder.append("dexp ");
        // 用户名 密码 ip 端口号 模式名/密码@IP:5236 file=dexp_tab01.dmp log=dexp_tab01.log tables=表名
        stringBuilder.append(backupParams.getUserName()).append("/").append(backupParams.getPassword()).append("@").append(backupParams.getHost()).append(":").append(backupParams.getPort());
        // 备份文件名
        stringBuilder.append(" file=").append(backupFilePath);
        // 备份的日志文件名
        stringBuilder.append(" log=").append(backupFilePath.replace(BackupConstants.DAMENG_EXT,".log"));

        // 自定义备份表
        if(backupParams.getTables() != null && backupParams.getTables().length > 0 ){
            stringBuilder.append(" ").append(" tables=");
            List<String> tableList = Arrays.asList(backupParams.getTables());
            for(int i=0;i< tableList.size();i++){
                if(StringUtils.isNotBlank(tableList.get(i).replaceAll("\"",""))){
                    stringBuilder.append(tableList.get(i).replaceAll("\"",""));
                }
                if(i!=tableList.size()-1){
                    stringBuilder.append(",");
                }
            }
        }
//        stringBuilder.append(";");
        // 调用外部执行 exe文件的Java API
        System.out.println("DAMENG备份命令===============》 "+ String.valueOf(stringBuilder));
        Process process = Runtime.getRuntime().exec(getCommand(stringBuilder.toString()));
//        FileInputStream errorStream = (FileInputStream) process.getErrorStream();
        // 读取错误信息
        InputStreamReader isr = new InputStreamReader(process.getInputStream(),"gbk");
        System.out.println(isr.getEncoding());
        BufferedReader bufr = new BufferedReader(isr);
        String line = null;
        while ((line = bufr.readLine()) != null){
            System.out.println(line);
        }
        isr.close();
        bufr.close();
        log.error("输出值:" + process.waitFor());
        // 成功终止导出, 但出现警告
        //2023-02-27 11:09:48.692 [ERROR] - 输出值:2
        if(process.waitFor() == 0 || process.waitFor() == 2) {
            // 0 表示线程正常终止
            log.info("数据完成备份,备份至 " + backupFilePath + " 文件中。");
            backupParams.setResultStatus(true);
            return backupParams;
        }
        backupParams.setResultStatus(false);
        return backupParams;
    }

    /**
     * 增量备份时刷新数据库日志
     * @param restoreParams
     * @return
     * @throws Exception
     */
    public static boolean refreshLog(RestoreParams restoreParams) throws Exception {
        StringBuilder stringBuilder = new StringBuilder();
        if(systemLinuxFlag){
            stringBuilder.append("cd ").append(restoreParams.getMysqlPath()).append(" && ");
            stringBuilder.append("./DAMENG -h").append(restoreParams.getHost()).append(" -u").append(restoreParams.getUserName()).append(" -p").append(restoreParams.getPassword()).append(" -P").append(restoreParams.getPort());
            stringBuilder.append(" -A -D ").append(restoreParams.getDatabase()).append(" -e \"SOURCE "+ restoreParams.getRestoreFilePath() +"\"");
        }else {
            stringBuilder.append(restoreParams.getMysqlPath().substring(0,restoreParams.getMysqlPath().indexOf(":")).toLowerCase()).append(":").append(" && ");
            stringBuilder.append("cd ").append(restoreParams.getMysqlPath()).append(" & ");
            stringBuilder.append("DAMENGadmin -h").append(restoreParams.getHost()).append(" -u").append(restoreParams.getUserName()).append(" -p").append(restoreParams.getPassword()).append(" -P").append(restoreParams.getPort());
            stringBuilder.append(" flush-logs");
        }
        Process process = Runtime.getRuntime().exec(getCommand(stringBuilder.toString()));
        log.error("输出值:" + process.waitFor());
        if(process.waitFor() == 0) {
            // 0 表示线程正常终止
            log.info("数据库增量备份日志刷新成功!!!!");
            return true;
        }
        return false;
//        return true;
    }


    /**
     * 恢复数据库
     * @return
     * @throws Exception
     */
    public static RestoreParams restore(RestoreParams restoreParams) throws Exception {
        StringBuilder stringBuilder = new StringBuilder();
        // 全量恢复
        if(restoreParams.getRestoreType() == 1){
            //    dimp 模式/密码@ip:5236 file=dexp_tab01.dmp log=dexp_tab01.log tables=表名 TABLE_EXISTS_ACTION=TRUNCATE
            if(systemLinuxFlag){
                stringBuilder.append("cd ").append(restoreParams.getMysqlPath()).append(" && ");
                stringBuilder.append("./");
            }else {
                stringBuilder.append(restoreParams.getMysqlPath().substring(0,restoreParams.getMysqlPath().indexOf(":")).toLowerCase()).append(":").append(" && ");
                stringBuilder.append("cd ").append(restoreParams.getMysqlPath()).append(" & ");

            }
            stringBuilder.append("dimp ");
            // 用户名 密码 ip 端口号 dexp 模式/密码@ip:5236 file=dexp_tab01.dmp log=dexp_tab01.log tables=xl_user
            stringBuilder.append(restoreParams.getUserName()).append("/").append(restoreParams.getPassword()).append("@").append(restoreParams.getHost()).append(":").append(restoreParams.getPort());
            stringBuilder.append(" file=").append(restoreParams.getRestoreFilePath()+restoreParams.getFileName());
            stringBuilder.append(" log=").append("restore_"+(new SimpleDateFormat(BackupConstants.DATE_FORMAT)).format(new Date())+".log");
            // 自定义备份表
            if(restoreParams.getTables() != null && restoreParams.getTables().length > 0 ){
                stringBuilder.append(" ").append(" tables=");
                List<String> tableList = Arrays.asList(restoreParams.getTables());
                for(int i=0;i< tableList.size();i++){
                    if(StringUtils.isNotBlank(tableList.get(i).replaceAll("\"",""))){
                        stringBuilder.append(tableList.get(i).replaceAll("\"",""));
                    }
                    if(i!=tableList.size()-1){
                        stringBuilder.append(",");
                    }
                }
            }
            // TABLE_EXISTS_ACTION=TRUNCATE 表示表存在时先删除表
            stringBuilder.append(" TABLE_EXISTS_ACTION=TRUNCATE");
            try {
                System.out.println("DAMENG数据全量恢复命令========> "+stringBuilder.toString());
                Process process = Runtime.getRuntime().exec(getCommand(stringBuilder.toString()));
                FileInputStream errorStream = (FileInputStream) process.getErrorStream();
                // 读取错误信息
                InputStreamReader isr = new InputStreamReader(process.getInputStream(),"gbk");
                System.out.println(isr.getEncoding());
                BufferedReader bufr = new BufferedReader(isr);
                String line = null;
                while ((line = bufr.readLine()) != null){
                    System.out.println(line);
                }
                isr.close();
                bufr.close();
                System.out.println("输出值:" + process.waitFor());
                //
                if(process.waitFor() == 0 || process.waitFor() == 2) {
                    log.info("数据已从 " + restoreParams.getRestoreFilePath() + restoreParams.getFileName() + " 导入至数据库中。");
                }
            } catch (Exception e) {
                e.printStackTrace();
                restoreParams.setResultStatus(false);
                return  restoreParams;
            }
            restoreParams.setResultStatus(true);
        }else{
            // 增量备份恢复
            // 先执行第一次全量备份恢复
            String fileName = restoreParams.getFileName();
            RestoreParams restoreParams1 = new RestoreParams();
            BeanUtils.copyProperties(restoreParams,restoreParams1);
            restoreParams1.setRestoreType(1);
            restoreParams1.setFileName("DAMENG_ADDBACKUP_FULL.dmp");
            restoreParams1 = restore(restoreParams1);
            if(restoreParams1.isResultStatus()){
                // 第一次全量备份恢复成功后获取增量备份文件夹下所有文件
                File logfile = new File(restoreParams.getRestoreFilePath());
                // 按修改时间正序排序
                List<File> fileList = Arrays.asList(logfile.listFiles()).stream().filter(p -> !p.getName().contains("DAMENG_ADDBACKUP_FULL.dmp") && !p.getName().endsWith(".log")).sorted(Comparator.comparing(File::lastModified)).collect(Collectors.toList());
                for(File file : fileList){
                    // 删除DAMENG二进制日志命令:在bin目录下执行: DAMENG -uroot -proot testbackup -e "reset master;"
                    // 循环执行增量恢复脚本  DAMENGbinlog --no-defaults D:\DAMENG-8.0.28-winx64\Data\DAMENG-bin.000012 |DAMENG -uroot -proot
                    StringBuilder newStringBuilder = new StringBuilder();

                        if(systemLinuxFlag){
                            newStringBuilder.append("cd ").append(restoreParams.getMysqlPath()).append(" && ");
                            newStringBuilder.append("./");
                        }else {
                            newStringBuilder.append(restoreParams.getMysqlPath().substring(0,restoreParams.getMysqlPath().indexOf(":")).toLowerCase()).append(":").append(" && ");
                            newStringBuilder.append("cd ").append(restoreParams.getMysqlPath()).append(" & ");
                        }
                        newStringBuilder.append("dimp ");
                        // 用户名 密码 ip 端口号 dexp 模式/密码@ip:5236 file=dexp_tab01.dmp log=dexp_tab01.log tables=表名
                        newStringBuilder.append(restoreParams.getUserName()).append("/").append(restoreParams.getPassword()).append("@").append(restoreParams.getHost()).append(":").append(restoreParams.getPort());
                        newStringBuilder.append(" file=").append(file.getAbsolutePath());
                        newStringBuilder.append(" log=").append("restore_"+(new SimpleDateFormat(BackupConstants.DATE_FORMAT)).format(new Date())+".log");
                        // 自定义备份表
                        if(restoreParams.getTables() != null && restoreParams.getTables().length > 0 ){
                            newStringBuilder.append(" ").append(" tables=");
                            List<String> tableList = Arrays.asList(restoreParams.getTables());
                            for(int i=0;i< tableList.size();i++){
                                if(StringUtils.isNotBlank(tableList.get(i).replaceAll("\"",""))){
                                    newStringBuilder.append(tableList.get(i).replaceAll("\"",""));
                                }
                                if(i!=tableList.size()-1){
                                    newStringBuilder.append(",");
                                }
                            }
                        }
                        // TABLE_EXISTS_ACTION=APPEND 表示表存在时追加数据
                        newStringBuilder.append(" TABLE_EXISTS_ACTION=APPEND");
                        // PRIMARY_CONFLICT:主键冲突时的处理方式:  IGNORE|OVERWRITE 默认报错
                        newStringBuilder.append(" PRIMARY_CONFLICT=IGNORE ");
                        try {
                            System.out.println("DAMENG增量备份数据恢复命令========> "+ newStringBuilder.toString());
                            Process process = Runtime.getRuntime().exec(getCommand(stringBuilder.toString()));
                            FileInputStream errorStream = (FileInputStream) process.getErrorStream();
                            // 读取错误信息
                            InputStreamReader isr = new InputStreamReader(process.getInputStream(),"gbk");
                            System.out.println(isr.getEncoding());
                            BufferedReader bufr = new BufferedReader(isr);
                            String line = null;
                            while ((line = bufr.readLine()) != null){
                                System.out.println(line);
                            }
                            isr.close();
                            bufr.close();
                            System.out.println("输出值:" + process.waitFor());
                            if(process.waitFor() == 0) {
                                log.info("数据已从 " + file.getAbsolutePath() + " 导入至数据库中。");
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                            restoreParams.setResultStatus(false);
                            return  restoreParams;
                        }
                        // 循环到页面选择的恢复时间为止
                        if(file.getName().equals(restoreParams.getFileName())){
                            break;
                        }
                }
                restoreParams.setResultStatus(true);
            }else{
                restoreParams.setResultStatus(false);
            }

            return  restoreParams;
        }
        restoreParams.setResultStatus(true);
        return  restoreParams;
    }

    private static String[] getCommand(String command) {
//        String os = System.getProperty("os.name");
        String shell = "/bin/bash";
        String c = "-c";
        if(!systemLinuxFlag){
            shell = "cmd.exe";
            c = "/c";
        }
        String[] cmd = { shell, c, command};
        return cmd;
    }

    /**
     *
     * 增量备份数据库
     *
     * 增量备份的思路是先进行一次全量备份  然后定时备份新的 恢复时先全量恢复  然后按顺序增量恢复所有备份文件
     * @return
     * @throws Exception
     */
    public static BackupParams addBackup(BackupParams backupParams) throws Exception {
        // fileName 在增量恢复时要用到
        String filename = backupParams.getFileName();
        if(backupParams.isFirstBackUpFlag()){
            backupParams.setFileName("DAMENG_ADDBACKUP_FULL.dmp");
            // 首次增量备份要先全量备份一次
            backup(backupParams);
            backupParams.setBackupFileName("DAMENG_ADDBACKUP_FULL.dmp");
        }else{
            backupParams.setFileName(filename);
            File backupFolderFile = new File(backupParams.getBackupFolderPath());
            if(!backupFolderFile.exists()) {
                // 如果目录不存在则创建
                backupFolderFile.mkdirs();
            }
            if(!backupParams.getBackupFolderPath().endsWith(File.separator) && !backupParams.getBackupFolderPath().endsWith("/")) {
//                backupParams.setBackupFolderPath(backupParams.getBackupFolderPath()+ File.separator) ;
                if(systemLinuxFlag){
                    backupParams.setBackupFolderPath(backupParams.getBackupFolderPath() + "/") ;
                }else{
                    backupParams.setBackupFolderPath(backupParams.getBackupFolderPath() + File.separator) ;
                }
            }
            addBackUpFlushLogs(backupParams) ;
        }
        return backupParams;
    }

    /**
     * 增量备份
     * @return
     * @throws IOException
     * @throws InterruptedException
     */
    private static BackupParams addBackUpFlushLogs(BackupParams backupParams) throws IOException, InterruptedException {
        // 拼接执行命令
        String backupFilePath = backupParams.getBackupFolderPath()+backupParams.getFileName() ;
        StringBuilder stringBuilder = new StringBuilder();
        if(!systemLinuxFlag){
            stringBuilder.append(backupParams.getMysqlPath().substring(0,backupParams.getMysqlPath().indexOf(":")).toLowerCase()).append(":").append(" && ");
            stringBuilder.append("cd ").append(backupParams.getMysqlPath()).append(" & ");
            stringBuilder.append("dexp ");
        }else {
            stringBuilder.append("cd ").append(backupParams.getMysqlPath()).append(" && ");
            stringBuilder.append("./dexp ");
        }

        // 用户名 密码 ip 端口号 dexp 模式/密码@ip:5236 file=dexp_tab01.dmp log=dexp_tab01.log tables=表名
        stringBuilder.append(backupParams.getUserName()).append("/").append(backupParams.getPassword()).append("@").append(backupParams.getHost()).append(":").append(backupParams.getPort());
        // 备份文件名
        stringBuilder.append(" file=").append(backupFilePath);
        // 备份的日志文件名
        stringBuilder.append(" log=").append(backupFilePath.replace(BackupConstants.DAMENG_EXT,".log"));

        // 自定义备份表
        if( backupParams.getTables() != null && backupParams.getTables().length > 0 ){
            stringBuilder.append(" ").append(" tables=");
            List<String> tableList = Arrays.asList(backupParams.getTables());
            for(int i=0;i< tableList.size();i++){
                if(StringUtils.isNotBlank(tableList.get(i).replaceAll("\"",""))){
                    stringBuilder.append(tableList.get(i).replaceAll("\"",""));
                }
                if(i!=tableList.size()-1){
                    stringBuilder.append(",");
                }
            }
        }
        // 拼接上次执行时间之后的where条件
        if(backupParams.getLastTime() != null){
            //  QUERY="where created >= to_date('2022-02-20 00:00:00','yyyy-mm-dd hh24:mi:ss')"
            // 为防止数据丢失 每次增量备份时间往前提前30分钟  2023-02-27 20:19:03
            try {
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                String backUpTime = sdf.format(DateUtils.addMinute(sdf.parse(backupParams.getLastTime()),-30));
                if(backupParams.getTables() == null || backupParams.getTables().length == 0){
                    stringBuilder.append(" ").append(" tables=").append(backupParams.getAllTables());
                }
                stringBuilder.append("  QUERY=\"where created >= to_date('").append(backUpTime).append("','yyyy-mm-dd hh24:mi:ss')\"");
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }
        log.info("达梦数据库增量备份命令:"+stringBuilder.toString());

        // 调用外部执行 exe文件的Java API
        Process process = Runtime.getRuntime().exec(getCommand(stringBuilder.toString()));
//        FileInputStream errorStream = (FileInputStream) process.getErrorStream();
        // 读取错误信息
        InputStreamReader isr = new InputStreamReader(process.getInputStream(),"gbk");
        System.out.println(isr.getEncoding());
        BufferedReader bufr = new BufferedReader(isr);
        String line = null;
        while ((line = bufr.readLine()) != null){
            System.out.println(line);
        }
        isr.close();
        bufr.close();
        log.error("输出值:" + process.waitFor());
        if(process.waitFor() == 0 || process.waitFor() == 2) {
            // 0 表示线程正常终止
            log.info("数据完成备份,备份至 " + backupFilePath + " 文件中。");
            backupParams.setResultStatus(true);
            return backupParams;
        }
        backupParams.setResultStatus(false);
        return backupParams;
    }


    /**
     * 将DAMENG备份脚本中的insert into 替换为 replace into
     * @param fileName
     * @throws Exception
     */
    private static String replaceSql(String fileName) throws Exception {
        BufferedReader br = null;
        BufferedWriter bw = null;
        String line = null;
        StringBuffer buf = new StringBuffer();
        InputStreamReader read = new InputStreamReader(new FileInputStream(new File(fileName)), "utf-8");
        br = new BufferedReader(read);
        String newFileName = fileName.substring(0,fileName.lastIndexOf(".")) + "replace"+ DateUtils.format(new Date(), BackupConstants.DATE_FORMAT) +".sql";
        OutputStreamWriter write = new OutputStreamWriter(new FileOutputStream(new File(newFileName)),"utf-8");
        bw = new BufferedWriter(write);
        try {
            while((line = br.readLine()) != null) {
                line = line.replaceAll("INSERT INTO","REPLACE INTO");
                buf.append(line.toString()).append("\n");
            }
            bw.write(buf.toString());
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            read.close();
            write.flush();
            bw.flush();
            write.close();
            bw.close();
        }
        return newFileName.substring(newFileName.lastIndexOf("\\")+1);
    }

}

mySqlBackupService.restoreBackUp

@Override
    public boolean restoreBackUp(String id, String fileName) throws Exception {
        //ip
        String host = properties.getHost();
        //数据库用户名
        String userName = properties.getUserName();
        //数据库密码
        String password = properties.getPassword();
        //数据库名称
        String database = properties.getDatabase();

        String port=properties.getPort();

        BackupDO backupDO = backupMapper.selectById(id);

        String mysqlPath = winMysqlPath;
        if(systemLinuxFlag){
            mysqlPath = linuxMysqlPath;
        }
        DictVo dict = dictService.selectById(backupDO.getBackupTypeId());
        int restoreType = 1;
        if(dict != null){
            if(dict.getDictItem().contains("全量")){
                restoreType = 1;
            }else if(dict.getDictItem().contains("增量")){
                restoreType = 2;
            }
        }

        RestoreParams restoreParams = new RestoreParams();
        restoreParams.setRestoreFilePath(backupDO.getSavePath());
        restoreParams.setHost(host);
        restoreParams.setUserName(userName);
        restoreParams.setPassword(password);
        restoreParams.setPort(port);
        restoreParams.setFileName(backupDO.getFileName());
        if(restoreType == 2 && fileName!= null){
            // 增量恢复时恢复到选择的文件名
            restoreParams.setFileName(fileName);
        }
        restoreParams.setDatabase(database);
        restoreParams.setMysqlPath(mysqlPath);
        restoreParams.setRestoreType(restoreType);
        // mysql增量备份的地址为日志文件夹
        restoreParams.setAddBackUpFilePath(mysqlbinlogpath);
        restoreParams.setAddBackUpFileName(addBackupLogName);
        // 恢复数据库
        restoreParams = mySQLBackupService.restore(restoreParams);
        // 恢复上传文件
        if(restoreParams.isResultStatus()){
            restoreParams.setFileName(backupDO.getUploadFileSaveName());
            restoreParams.setAddBackUpFilePath(backupDO.getUploadFileSavePath());
            restoreParams = filesBackUpService.restore(restoreParams);
        }

//        // 全部恢复完之后将状态改为已恢复
//        backupMapper.updateStatusById(backupDO.getId(),3);
        // 更新上次备份时间
        backupMapper.updateLastRestoreTime(backupDO.getId(),new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        return restoreParams.isResultStatus();
    }

damengBackupService.restoreBackUp

@Override
    public boolean restoreBackUp(String id, String fileName) throws Exception {
        //ip
        String host = properties.getHost();
        //数据库用户名
        String userName = properties.getUserName();
        //数据库密码
        String password = properties.getPassword();
        //数据库名称
        String database = properties.getDatabase();

        String port=properties.getPort();

        BackupDO backupDO = backupMapper.selectById(id);
        DictVo dict = dictService.selectById(backupDO.getBackupTypeId());
        int restoreType = 1;
        if(dict != null){
            if(dict.getDictItem().contains("全量")){
                restoreType = 1;
            }else if(dict.getDictItem().contains("增量")){
                restoreType = 2;
            }
        }
        String mysqlPath = winMysqlPath;
        if(systemLinuxFlag){
            mysqlPath = linuxMysqlPath;
        }
        RestoreParams restoreParams = new RestoreParams();
        restoreParams.setRestoreFilePath(backupDO.getSavePath());
        restoreParams.setHost(host);
        restoreParams.setUserName(userName);
        restoreParams.setPassword(password);
        restoreParams.setPort(port);
        restoreParams.setFileName(backupDO.getFileName());
        if(restoreType == 2 && fileName!= null){
            // 增量恢复时恢复到选择的文件名
            restoreParams.setFileName(fileName);
        }
        restoreParams.setDatabase(database);
        restoreParams.setMysqlPath(mysqlPath);
        restoreParams.setRestoreType(restoreType);
        if(com.jsrd.trainsoftwareserver.common.untils.StringUtils.isNotBlank(backupDO.getTables())){
            restoreParams.setTables(backupDO.getTables().split(","));
        }
        // 恢复数据库
        restoreParams = daMengBackupService.restore(restoreParams);
        if(restoreParams.isResultStatus()){
            // 恢复上传文件
            restoreParams.setFileName(backupDO.getUploadFileSaveName());
            restoreParams.setAddBackUpFilePath(backupDO.getUploadFileSavePath());
            restoreParams = filesBackUpService.restore(restoreParams);
        }

        //  全部恢复完之后将状态改为已恢复
//        backupMapper.updateStatusById(backupDO.getId(),3);
        // 更新上次备份时间
        backupMapper.updateLastRestoreTime(backupDO.getId(),new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        return restoreParams.isResultStatus();
    }

filesBackUpService.backup

/**
     * 备份上传的文件
     * @param backupParams
     * @return
     * @throws Exception
     */
    @Override
    public BackupParams backup(BackupParams backupParams) throws Exception {
        if(systemLinuxFlag){
            backupParams.setBackupFolderPath(uploadPathLinux);
            backupParams.setBackupFolder(backupPathLinux);
        }else{
            backupParams.setBackupFolderPath(uploadPathWindows);
            backupParams.setBackupFolder(backupPathWindows);
        }
        // 压缩包文件名
        backupParams.setFileName(BackupConstants.DEFAULT_BACKUP_PRE + DateUtils.format(new Date(), BackupConstants.DATE_FORMAT) + BackupConstants.DEFAULT_BACKUP_SUFFIX);

        return UploadFileBackupRestoreUtils.backup(backupParams);
    }

filesBackUpService.restore

@Override
    public RestoreParams restore(RestoreParams restoreParams) throws Exception {
        if(systemLinuxFlag){
            restoreParams.setRestoreFilePath(uploadPathLinux);
        }else{
            restoreParams.setRestoreFilePath(uploadPathWindows);
        }
        restoreParams.setPanFu(panFu);

        return UploadFileBackupRestoreUtils.restore(restoreParams);
    }
UploadFileBackupRestoreUtils 文件资源备份恢复工具类

import lombok.extern.slf4j.Slf4j;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;

/**
 * 备份与恢复文件资源
 */
@Slf4j
public class UploadFileBackupRestoreUtils {


    /**
     * 备份上传文件
     * @param backupParams
     * @return
     * @throws Exception
     */
    public static BackupParams backup(BackupParams backupParams) throws Exception {
        File backupFolderFile = new File(backupParams.getBackupFolder());
        if(!backupFolderFile.exists()) {
            // 如果目录不存在则创建
            backupFolderFile.mkdirs();
        }
        // 拼接执行命令
        String backupFilePath = backupParams.getBackupFolder() + backupParams.getFileName();
        if(systemLinuxFlag){
            if(!backupParams.getBackupFolder().endsWith(File.separator) && !backupParams.getBackupFolder().endsWith("/")) {
                backupParams.setBackupFolderPath(backupParams.getBackupFolderPath() + "/") ;
                backupParams.setBackupFolder(backupParams.getBackupFolder() + "/");
                backupFilePath = backupParams.getBackupFolder() + backupParams.getFileName();
            }
        }else{
            if(!backupParams.getBackupFolder().endsWith(File.separator) && !backupParams.getBackupFolder().endsWith("\\")){
                backupParams.setBackupFolder(backupParams.getBackupFolder() + "\\") ;
            }
            backupFilePath = backupParams.getBackupFolder() + backupParams.getFileName();
        }
        backupParams.setBackupFileName(backupParams.getFileName());

        StringBuilder stringBuilder = new StringBuilder();
        if(StringUtils.isNotBlank(backupParams.getOriginalBackupFileName())){
            // 先删除上一次备份的文件 del /f/s/q C:\disk\dateBackup\20230220175325copy20230220175326.sql
            if(systemLinuxFlag){
                stringBuilder.append("rm -f ");
            }else{
                stringBuilder.append("del /f/s/q ");
            }
            stringBuilder.append(backupParams.getBackupFolder()).append(backupParams.getOriginalBackupFileName()).append(" && ");
        }
        stringBuilder.append("tar");
        //端口号
        stringBuilder.append(" -czvf ").append(backupParams.getBackupFolder() + backupParams.getFileName()).append(" ").append(backupParams.getBackupFolderPath());

        // 调用外部执行 exe文件的Java API
        System.out.println("上传文件压缩备份命令===============》 "+ String.valueOf(stringBuilder));
        Process process = Runtime.getRuntime().exec(getCommand(stringBuilder.toString()));
        FileInputStream errorStream = (FileInputStream) process.getErrorStream();
        // 读取错误信息
        InputStreamReader isr = new InputStreamReader(errorStream,"utf-8");
        System.out.println(isr.getEncoding());
        BufferedReader bufr = new BufferedReader(isr);
        String line = null;
        while ((line = bufr.readLine()) != null){
            System.out.println(line);
        }
        isr.close();
        bufr.close();

        log.error("输出值:" + process.waitFor());
        if(process.waitFor() == 0) {
            // 0 表示线程正常终止
            log.info("数据完成备份,备份至 " + backupFilePath + " 文件中。");

            backupParams.setResultStatus(true);
            return backupParams;
        }
        backupParams.setResultStatus(false);
//        backupParams.setResultStatus(true);
        return backupParams;
    }


    /**
     * 恢复上传文件
     * @param restoreParams
     * @return
     * @throws Exception
     */
    public static RestoreParams restore(RestoreParams restoreParams) throws Exception {
        StringBuilder stringBuilder = new StringBuilder();
        // 先删除文件夹所有文件
        if(systemLinuxFlag){
            stringBuilder.append("rm -rf ").append(restoreParams.getRestoreFilePath()).append(" && ");
        }else{
            stringBuilder.append("rd/s/q ").append(restoreParams.getRestoreFilePath()).append(" && ");
        }

        // 再创建文件夹
        if(systemLinuxFlag){
            // 先创建文件夹
            File file = new File(restoreParams.getRestoreFilePath());
            if(!file.exists()){
                file.mkdirs();
            }
        }
        // 解压缩
        stringBuilder.append("tar");
        //端口号
        stringBuilder.append(" -zxvf ").append(restoreParams.getAddBackUpFilePath()).append(restoreParams.getFileName());
        // -C 是将同名文件覆盖并去掉路径信息
        stringBuilder.append(" -C ");
        if(!systemLinuxFlag){
            stringBuilder.append(restoreParams.getPanFu());
        }else{
            // Linux 解压到根目录 自带文件路径
            stringBuilder.append("/");
        }

        try {
            System.out.println("上传文件解压缩恢复命令========> "+stringBuilder.toString());
            Process process = Runtime.getRuntime().exec(getCommand(stringBuilder.toString()));
            FileInputStream errorStream = (FileInputStream) process.getErrorStream();
            // 读取错误信息
            InputStreamReader isr = new InputStreamReader(errorStream,"GBK");
            System.out.println(isr.getEncoding());
            BufferedReader bufr = new BufferedReader(isr);
            String line = null;
            while ((line = bufr.readLine()) != null){
                System.out.println(line);
            }
            isr.close();
            bufr.close();
            System.out.println("输出值:" + process.waitFor());
            if(process.waitFor() == 0) {
                log.info("上传文件已恢复至 " + restoreParams.getRestoreFilePath() );
            }
        } catch (Exception e) {
            e.printStackTrace();
            restoreParams.setResultStatus(false);
            return  restoreParams;
        }
        restoreParams.setResultStatus(true);
        return  restoreParams;
    }

    private static String[] getCommand(String command) {
        String os = System.getProperty("os.name");
        String shell = "/bin/bash";
        String c = "-c";
        if(os.toLowerCase().startsWith("win")){
            shell = "cmd.exe";
            c = "/c";
        }
        String[] cmd = { shell, c, command};
        return cmd;
    }



}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Mysql和达梦数据库备份与恢复 的相关文章

  • POINT 列上的 MySQL INSERT/UPDATE

    我正在尝试用我国家的地理位置填充我的数据库 我的一张表有 4 个字段 ID PK 纬度 经度和地理点 EDIT SCDBs Punto Geografico SET lat 18 469692 SET lon 63 93212 SET g
  • MySQL:计算日期/时间之间的差异 - 仅在周一至周五“工作周”期间

    我需要计算开始日期 时间和结束日期 时间之间的差异 但是 我只想在 5 天的工作周内执行此操作 不包括周六 周日 做这个的最好方式是什么 我的想法是 从日期开始 我必须获取星期几 如果是工作日 那么我将添加到累加器中 如果不是 那么我不会添
  • 从按日期时间排序的 MySQL 表中获取用户的最后一个条目

    我有一张看起来像这样的桌子 USERNAME DATA DATETIME Jhon text1 2010 06 01 16 29 43 Mike text2 2010 06 01 16 29 22 Silver text3 2010 05
  • MySQL - 从临时表插入

    这看起来非常简单 但我坚持使用简单的插入语句 见下文 begin work CREATE TEMPORARY TABLE IF NOT EXISTS insert table AS select r resource id fr file
  • 如果没有找到值,如何让 MySQL 中的 SUM 函数返回“0”?

    假设我在 MySQL 中有一个简单的函数 SELECT SUM Column 1 FROM Table WHERE Column 2 Test 如果没有条目Column 2 包含文本 Test 然后该函数返回NULL 而我希望它返回 0 我
  • MySQL 8 用逗号分割字符串并将其转换为JSON ARRAY

    我有以下字符串 a b c d 我想将它转换成一个 json 数组 像这样 a b c d MySQL 8 有什么函数可以实现这个功能吗 Try SELECT CAST CONCAT REPLACE a b c d AS JSON See
  • db:schema:load 与 db:migrate 使用 capistrano

    我有一个 Rails 应用程序 我正在将其移动到另一台服务器 我认为我应该使用 db schema load 来创建 mysql 数据库 因为这是推荐的 我的问题是我正在使用 capistrano 进行部署 并且它似乎默认为 rake db
  • 合并两个 MYSQL SELECT 查询[重复]

    这个问题在这里已经有答案了 可能的重复 如何将两个 Post Category 表 MYSQL SELECT 查询合并为一个 https stackoverflow com questions 12972130 how to combine
  • MySQL“LIKE”搜索不起作用

    我通过 LOAD DATA INFILE 在 MySQL 中导入了一个 txt 数据库 一切似乎都正常 唯一的问题是 如果我使用以下查询在数据库上搜索记录 SELECT FROM hobby WHERE name LIKE Beading
  • PHP MYSQL文件内容转义问题

    我正在尝试使用 php 将 pdf 文件上传到 mysql 数据库中 除了文件内容之外 一切都很好 无论我如何尝试转义特殊字符 查询总是失败 主要是 未知命令 n 我使用过addslashes mysql real escape strin
  • PHP 和 MySQL - 高效处理多个一对多关系

    我正在寻求一些有关使用 MySQL 和 PHP 检索和显示数据的最佳方法的建议 我有 3 个表 所有一对多关系如下 Each SCHEDULE有很多覆盖每个覆盖都有很多地点 我想检索这些数据 以便它可以全部显示在单个 PHP 页面上 例如列
  • 慢速自动增量重置

    我有很多表 由于某些原因 我需要在应用程序启动时调整这些表的自动增量值 我尝试这样做 mysql gt select max id from item max id 97972232 1 row in set 0 05 sec mysql
  • 如何在 SEQUELIZE (nodeJS) 中创建触发器?

    我正在尝试使用sequelize 创建一个触发器 主要思想是创建一个实例CONFIG创建后USER USER MODEL module exports function sequelize DataTypes var User sequel
  • MySQL/PDO::quote() 尽管使用 PDO::PARAM_INT 参数,但仍在整数周围加上引号

    无论我传递给什么值 数据类型对 它都会出现 pdo gt quote value type 它总是将其引用为字符串 echo pdo gt quote foo PDO PARAM STR foo as expected echo pdo g
  • 如何检测Mysql/innodb中的死锁?

    我知道在 Innodb 中使用事务时不可避免地会发生死锁 并且如果应用程序代码正确处理死锁 它们是无害的 正如手册所说 只需再试一次 所以我想知道 如何检测死锁 死锁是否会发出一些特殊的 mysql 错误号 如果重要的话 我正在使用 PHP
  • 获取带有计数的不同记录

    我有一张桌子personid and msg列 personid msg 1 msg1 2 msg2 2 msg3 3 msg4 1 msg2 我想得到总计msg对于每个personid 我正在尝试这个查询 select distinct
  • MYSQL - 使用逗号分隔字符串作为变量输入的存储过程

    我希望有人能够提供帮助 我已经创建了我的第一个存储过程 没什么花哨的 但是我遇到了问题 我想给它一个字符串输入 例如 1 2 3 4 5 然后它执行一个简单的操作SELECT FROM TABLE WHERE EAN IN VAR 所以存储
  • posts_search 中的自定义查询

    如何使用此查询作为我的自定义搜索查询 add filter posts search my search is perfect 20 2 function my search is perfect search wp query sWord
  • mysql自动存储记录创建时间戳

    mysql 有什么方法可以在创建记录时自动将时间戳存储在记录行中 我试图使用时间戳 数据类型 和 current timestamp 作为默认值 但后来意识到每次更新记录时都会更新 我只需要一些可以存储创建时间戳的东西 Thanks Set
  • MySQL 追加字符串

    How can I append a string to the end of an existing table value Let s say I have the table below And let s say that Mari

随机推荐