Java+xxl-job实现MySql的定时备份

目录

原因

准备

实现

效果图

原因

        当实现数据库备份的时候又不想在服务器以脚本文件的形式暴露数据库账号密码时,我们可以使用java代码来运行shell脚本代码(不生成脚本文件)实现mysql的dumb文件的生成。

准备

        我这里的定时任务是交给xxl-job来配置的,这里不多叙说了,不清楚的可以使用注解@Scheduled来实现定时调用。

实现

1.pom文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.7</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <groupId>org.example.activiti</groupId>
    <artifactId>ttoa</artifactId>
    <version>1.0-SNAPSHOT</version>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.24</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.2.4</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <!-- thymeleaf和springSecurity的扩展依赖-->
        <dependency>
            <groupId>org.thymeleaf.extras</groupId>
            <artifactId>thymeleaf-extras-springsecurity5</artifactId>
        </dependency>

        <dependency>
            <groupId>com.xuxueli</groupId>
            <artifactId>xxl-job-core</artifactId>
            <version>2.4.1</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.1.2</version>
        </dependency>

        <!-- mybatis-plus代码生成器依赖 -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>3.1.2</version>
        </dependency>

        <!-- 默认模板引擎 -->
        <dependency>
            <groupId>org.apache.velocity</groupId>
            <artifactId>velocity-engine-core</artifactId>
            <version>2.1</version>
        </dependency>

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-extension</artifactId>
            <version>3.1.2</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <build>
        <finalName>${project.artifactId}-${project.version}</finalName>
        <defaultGoal>package</defaultGoal>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <!-- 如果加了上面的配置,必须加入这个配置,不然resources目录下的东西不会进编译目录 -->
                    <include>**/*.*</include>
                </includes>
            </resource>
        </resources>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <includeSystemScope>true</includeSystemScope>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                    <!-- 指定该Main Class为全局的唯一入口 -->
                    <mainClass>com.example.ActivitiApplication</mainClass>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>9</source>
                    <target>9</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

   2.application.yml文件

spring:
  #thymeleaf模板引擎的配置
  thymeleaf:
    #开发环境,不建议开启缓存
    cache: false
  ####################################数据源配置#######################################
  datasource:
    druid:
      #数据源配置
      driver-class-name: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://19.12.100.123:3306/oa?useSSL=false&serverTimezone=GMT%2b8&useUnicode=true&characterEncoding=utf-8&autoReconnect=true&failOverReadOnly=false&rewriteBatchedStatements=true&connectTimeout=1000&socketTimeout=30000&allowMultiQueries=true
      username: root
      password: ****

####################################自定义文件配置###################################
sqlbackup:
  path: /home/oa/files/sqlDumb/

3.BackupsMysqlJob数据库备份实现

package com.example.task;

import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.handler.annotation.XxlJob;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.IOException;
import java.util.Date;

/**
 * <p>
 * 定时备份dumb文件
 * </p>
 *
 * @custom.date 2024/12/20 16:32
 */
@Component
public class BackupsMysqlJob {

    private static final Logger log = LoggerFactory.getLogger(BackupsMysqlJob.class);

    @Value("${spring.datasource.druid.driver-class-name}")
    private String driverClassName;
    @Value("${spring.datasource.druid.url}")
    private String url;
    @Value("${spring.datasource.druid.username}")
    private String userName;
    @Value("${spring.datasource.druid.password}")
    private String password;
    @Value("${sqlbackup.path}")
    private String sqlPath;
    /**
     * 获取数据库名
     */
    public String getDataBaseName() {
        return url.substring(url.indexOf("3306"), url.indexOf("?")).replaceAll("/", "").replaceAll("3306", "");
    }
    /**
     * 获取主机地址
     */
    private String getHost() {
        return url.substring(url.indexOf("mysql"), url.indexOf("3306")).replace(":", "").replace("//", "").replace("mysql", "");
    }
    /**
     * 导出 sql 并返回相关信息
     */
    @XxlJob("regularBackupsMysql")
    public ReturnT<String> regularBackupsMysql() {
        //如果文件超过3天删除最早的文件
        // 获取文件夹路径
        File folder = new File(sqlPath);
        // 获取文件夹中的所有文件
        File[] files = folder.listFiles();
        if(files.length>3){
            // 初始化最早文件
            File earliestFile = files[0];
            // 遍历所有文件,找到最早的文件
            for (File file : files) {
                if (file.lastModified() < earliestFile.lastModified()) {
                    earliestFile = file;
                }
            }
            // 删除最早的文件
            earliestFile.delete();
        }
        // 指定导出的 sql 存放的文件夹
        File saveFile = new File(sqlPath);
        if (!saveFile.exists()) {
            saveFile.mkdirs();
        }
        String host = getHost();
        String dataBaseName = getDataBaseName();
        String fileName = new Date().getTime()+"_"+dataBaseName+ ".sql";
        StringBuilder sb = new StringBuilder();
        // 拼接备份命令
        sb.append("mysqldump").append(" --opt").append(" -h ").append(host).append(" --user=").append(userName).append(" --password=").append(password);
        sb.append(" --result-file=").append(sqlPath + fileName).append(" --default-character-set=utf8 ").append(dataBaseName);
        try {
            Process exec = Runtime.getRuntime().exec(sb.toString());
            if (exec.waitFor() == 0) {
                log.info("数据库备份成功,保存路径:" + sqlPath);
                return ReturnT.SUCCESS;
            } else {
                System.out.println("process.waitFor()=" + exec.waitFor());
            }
        } catch (IOException e) {
            log.error("备份 数据库 出现 IO异常 ", e);
            return ReturnT.FAIL;
        } catch (InterruptedException e) {
            log.error("备份 数据库 出现 线程中断异常 ", e);
            return ReturnT.FAIL;
        } catch (Exception e) {
            log.error("备份 数据库 出现 其他异常 ", e);
            return ReturnT.FAIL;
        }
        return ReturnT.SUCCESS;
    }
}

我这里额外添加了文件限制在4个之内的代码,超过3个的时候会删除最早备份的文件。

思路:使用

mysqldump --opt -h hostname --user=username --password=password  --result-file=/dir/filename --default-character-set=utf8 dbname 

命令

hostname :数据库所在主机

username:数据库连接用户名

password:数据库连接密码

result-file:结果文件。指定目录+文件名

dbname:需要导出的数据库名

效果图

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值