Java或Shell脚本实现:定时导出MySQL数据库指定表,并导入到另一数据库同时切换指定字段名(兼容Linux和Windows)

目录

定时导出指定数据库的指定表导出到指定数据库(实现方法:Java代码,sh脚本(普通复制,异步复制 ))

一、Java实现

1、contronller

2、实现类

3、执行结果​编辑二、sh脚本实现

1-1、新建一个.bash脚本(字段名不做任何逻辑变换)

1-2-1、新建一个.bash脚本(英转中  CHANGE)

1-2-2、新建一个.bash脚本(英转中  RENAME 等同)

1-2-3、新建一个.bash脚本(英转中  CREATE)

1-2-4、新建一个.bash脚本(英转中  异步复制)

2、在linux打开定时任务执行脚本(因为定时只有linux 可以执行)

(1)、先赋予文件夹权限

(2)、然后执行

(3)、如果不习惯用这个编译器可以切换vim编译器进行编辑

 (4)、添加定时任务(5分钟一次)


定时导出指定数据库的指定表导出到指定数据库(实现方法:Java代码,sh脚本(普通复制,异步复制 ))

一、Java实现

1、contronller

@Slf4j
@Controller
public class BackupController {
    @Autowired
    BackupService backupService;
    
    //  备份
//    @ResponseBody
//    @PostMapping("/backup/backupByfile")
    @Scheduled(cron="1 * * * * *")
    public void backupByfile() {
        backupService.backupByfile();
    }
}

2、实现类

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.exec.CommandLine;
import org.apache.commons.exec.DefaultExecutor;
import org.apache.commons.exec.ExecuteWatchdog;
import org.apache.commons.exec.PumpStreamHandler;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import vip.xiaonuo.modular.ATest.Backup.service.BackupService;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.nio.file.attribute.BasicFileAttributes;
import java.sql.*;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Slf4j
@Service
public class BackupServiceImpl implements BackupService {
    @Value("${spring.datasource.username}")
    private String username;

    @Value("${spring.datasource.password}")
    private String password;
    // db 源数据库   backupDb  备份数据库
    private String db = "qqq";
    private String backupDb = "aa";
    private String tableName = "user";
    private Duration maxAge = Duration.ofMinutes(3);


    private final Lock lock = new ReentrantLock();
    private final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd-HHmmss.SSS");

    /**
     * 2、备份到指定文件夹
     */
    // 备份目录
    private String dir = "D:\\backups";

    @Override
    public void backupByfile() {
        File directory = new File(dir);

        if (directory.exists() && directory.isDirectory()) {
            File[] files = directory.listFiles();
            if (files != null) {
                for (File file : files) {
                    if (file.delete()) {
                        log.info("File '{}' deleted successfully.", file.getName());
                    }
                }
            }
        }
        if (!this.lock.tryLock()) {
            throw new RuntimeException("备份任务进行中!");
        }

        try {

             String now = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
            Path dir = Paths.get(this.dir);

            // 备份的SQL文件
            Path sqlFile = dir.resolve(Paths.get(now + ".sql"));

            if (Files.exists(sqlFile)) {
                // 文件已经存在,则添加后缀
                for (int i = 1; i >= 1; i++) {
                    sqlFile = dir.resolve(Paths.get(now + "-" + i + ".sql"));
                    if (!Files.exists(sqlFile)) {
                        break;
                    }
                }
            }
            // 初始化目录
            if (!Files.isDirectory(sqlFile.getParent())) {
                Files.createDirectories(sqlFile.getParent());
            }

            // 创建备份文件文件
            Files.createFile(sqlFile);

            // 标准流输出的内容就是 SQL 的备份内容
            try (OutputStream stdOut = new BufferedOutputStream(
                    Files.newOutputStream(sqlFile, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING))) {

                // 监视狗。执行超时时间,1小时
                ExecuteWatchdog watchdog = new ExecuteWatchdog(TimeUnit.HOURS.toMillis(1));

                // 子进程执行器
                DefaultExecutor defaultExecutor = new DefaultExecutor();
                // defaultExecutor.setWorkingDirectory(null); // 工作目录
                defaultExecutor.setWatchdog(watchdog);
                defaultExecutor.setStreamHandler(new PumpStreamHandler(stdOut, System.err));

                // 进程执行命令
                CommandLine commandLine = new CommandLine("mysqldump");
                commandLine.addArgument("-u" + this.username);    // User name
                commandLine.addArgument("-p" + this.password);    // Password
                commandLine.addArgument(this.db);                // Database name
                commandLine.addArgument(this.tableName);               // Table name

                log.info("备份 SQL 数据");

                // 同步执行,阻塞直到子进程执行完毕。
                int exitCode = defaultExecutor.execute(commandLine);

                if (defaultExecutor.isFailure(exitCode)) {
                    throw new RuntimeException("备份任务执行异常:exitCode=" + exitCode);
                }
            }
            // 替换备份文件中的表名
            replaceTableName(sqlFile, this.tableName, this.tableName + "_" + now);
            // 导入 SQL 文件
            String path = sqlFile.toAbsolutePath().toString();
            importSql(path);

        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            this.lock.unlock();
        }
    }


    private void replaceTableName(Path sqlFile, String oldTableName, String newTableName) throws IOException {
        List<String> lines = Files.readAllLines(sqlFile, StandardCharsets.UTF_8);
        for (int i = 0; i < lines.size(); i++) {
            String line = lines.get(i);
            if (line.contains(oldTableName)) {
                lines.set(i, line.replace(oldTableName, newTableName));
            }
        }
        Files.write(sqlFile, lines, StandardCharsets.UTF_8);
    }

    public void importSql(String fPath) {
        try {
            Runtime rt = Runtime.getRuntime();
            Process child = rt.exec("mysql -u" + this.username + " -p" + this.password + " " + this.backupDb);
            OutputStream out = child.getOutputStream();
            String inStr;
            StringBuilder  sb = new StringBuilder ("");
            String outStr;
            BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(fPath), "utf8"));

            while ((inStr = br.readLine()) != null) {
                sb.append(inStr + "\r\n");
            }
            outStr = sb.toString();

            try (OutputStreamWriter writer = new OutputStreamWriter(out, "utf8")) {
                writer.write(outStr);
                writer.flush();
            }

            int exitCode = child.waitFor();
            if (exitCode != 0) {
                throw new RuntimeException("导入 SQL 文件失败,退出码: " + exitCode);
            }
            log.info("导入 SQL 文件成功!");

        } catch (Exception e) {
            throw new RuntimeException("出错了," + e);
        }
    }
}

3、执行结果二、sh脚本实现

这总结的不是很好 3种写法(个人感觉第三种写法更好)
  1. alert table 表名 CHANGE 字段名 字段类型(必须带字段类型)
  2. alert table 表名 RENAME COLUMN 字段名 TO 新字段名  
  3. 创建表的时候指定字段  
  4. 异步复制

1-1、新建一个.bash脚本(字段名不做任何逻辑变换)

#!/bin/bash

# 源数据库配置
SOURCE_DB="qhd"
SOURCE_HOST="localhost"  # 或者改为实际的 IP 地址
SOURCE_PORT="13306"
SOURCE_USER="root"
SOURCE_PASS="123456"

# 目标数据库配置
TARGET_DB="aa"
TARGET_HOST="localhost"  # 或者改为实际的 IP 地址
TARGET_PORT="13306"
TARGET_USER="root"
TARGET_PASS="123456"

# 要导出的表
SOURCE_TABLE="owner"
CURRENT_DATETIME=$(date +"%Y%m%d%H%M%S")
EXPORT_TABLE_NAME="${SOURCE_TABLE}_${CURRENT_DATETIME}"

# 导出 SQL 文件的路径
EXPORT_DIR="/home/mengqingda/program/test/file"
EXPORT_FILE="$EXPORT_DIR/${EXPORT_TABLE_NAME}.sql"

# 创建导出目录(如果不存在)
mkdir -p "$EXPORT_DIR"

echo "开始导出 $EXPORT_TABLE_NAME 表数据..."

# 导出指定表的数据
mysqldump -h$SOURCE_HOST -P$SOURCE_PORT -u$SOURCE_USER -p$SOURCE_PASS $SOURCE_DB $SOURCE_TABLE > $EXPORT_FILE

if [ $? -eq 0 ]; then
    echo "数据导出完成, 开始导入 $EXPORT_TABLE_NAME 表数据到 $TARGET_DB 数据库..."

    # 导入数据到目标数据库
    mysql -h$TARGET_HOST -P$TARGET_PORT -u$TARGET_USER -p$TARGET_PASS $TARGET_DB -e "CREATE TABLE $EXPORT_TABLE_NAME LIKE $SOURCE_DB.$SOURCE_TABLE; INSERT INTO $EXPORT_TABLE_NAME SELECT * FROM $SOURCE_DB.$SOURCE_TABLE;"

    if [ $? -eq 0 ]; then
        echo "数据导入完成!"
    else
        echo "数据导入失败!"
    fi
else
    echo "数据导出失败!"
fi

1-2-1、新建一个.bash脚本(英转中  CHANGE)

#!/bin/bash

# 源数据库配置
SOURCE_DB="qhd"
SOURCE_HOST="localhost" # 或者改为实际的 IP 地址
SOURCE_PORT="3306"
SOURCE_USER="root"
SOURCE_PASS="123456"

# 目标数据库配置
TARGET_DB="aa"
TARGET_HOST="localhost" # 或者改为实际的 IP 地址
TARGET_PORT="3306"
TARGET_USER="root"
TARGET_PASS="123456"

# 要导出的表
SOURCE_TABLE="user"
CURRENT_DATETIME=$(date +"%Y%m%d%H%M%S")
EXPORT_TABLE_NAME="${SOURCE_TABLE}_${CURRENT_DATETIME}"

# 导出 SQL 文件的路径
EXPORT_DIR="D:\ProgramFiles\programSoftware\backups"
EXPORT_FILE="$EXPORT_DIR/${EXPORT_TABLE_NAME}.sql"

# 创建导出目录(如果不存在)
mkdir -p "$EXPORT_DIR"

echo "开始导出 $EXPORT_TABLE_NAME 表数据..."

# 导出指定表的数据
mysqldump -h$SOURCE_HOST -P$SOURCE_PORT -u$SOURCE_USER -p$SOURCE_PASS $SOURCE_DB $SOURCE_TABLE >$EXPORT_FILE

if [ $? -eq 0 ]; then
    echo "数据导出完成, 开始修改 SQL 文件..."

    echo "SQL 文件修改完成, 开始创建目标表..."

    # 创建目标表
    mysql -h$TARGET_HOST -P$TARGET_PORT -u$TARGET_USER -p$TARGET_PASS $TARGET_DB -e "
    CREATE TABLE IF NOT EXISTS $EXPORT_TABLE_NAME LIKE $SOURCE_DB.$SOURCE_TABLE;
    ALTER TABLE $EXPORT_TABLE_NAME 
        CHANGE xm 姓名 VARCHAR(255),
        CHANGE bj 班级 VARCHAR(255),
        CHANGE xh 学号 VARCHAR(255),
        CHANGE wx 微信 VARCHAR(255),
        CHANGE qq qq号 VARCHAR(255),
        CHANGE zw 职位 VARCHAR(255),
        CHANGE xl 学历 VARCHAR(255);
"
    echo "目标表创建完成, 开始导入数据..."

    # 导入数据到目标表
    mysql -h$TARGET_HOST -P$TARGET_PORT -u$TARGET_USER -p$TARGET_PASS $TARGET_DB -e "
    INSERT INTO $EXPORT_TABLE_NAME SELECT * FROM $SOURCE_DB.$SOURCE_TABLE;
"
    if [ $? -eq 0 ]; then
        echo "数据导入完成!"
    else
        echo "数据导入失败!"
    fi
else
    echo "数据导出失败!"
fi

1-2-2、新建一个.bash脚本(英转中  RENAME 等同)

1-2-3、新建一个.bash脚本(英转中  CREATE)

#!/bin/bash

# 源数据库配置
SOURCE_DB="user"
SOURCE_HOST="localhost" # 或者改为实际的 IP 地址
SOURCE_PORT="3306"
SOURCE_USER="root"
SOURCE_PASS="123456"

# 目标数据库配置
TARGET_DB="aa"
TARGET_HOST="localhost" # 或者改为实际的 IP 地址
TARGET_PORT="3306"
TARGET_USER="root"
TARGET_PASS="123456"

# 要导出的表
SOURCE_TABLE="owner"
CURRENT_DATETIME=$(date +"%Y%m%d%H%M%S")
EXPORT_TABLE_NAME="${SOURCE_TABLE}_${CURRENT_DATETIME}"

# 导出 SQL 文件的路径
EXPORT_DIR="D:\ProgramFiles\programSoftware\backups"
EXPORT_FILE="$EXPORT_DIR/${EXPORT_TABLE_NAME}.sql"

# 创建导出目录(如果不存在)
mkdir -p "$EXPORT_DIR"

echo "开始导出 $EXPORT_TABLE_NAME 表数据..."

# 导出指定表的数据
mysqldump -h$SOURCE_HOST -P$SOURCE_PORT -u$SOURCE_USER -p$SOURCE_PASS $SOURCE_DB $SOURCE_TABLE > $EXPORT_FILE

if [ $? -eq 0 ]; then
    echo "数据导出完成, 开始导入数据..."

    # 导入数据到目标表
    mysql -h$TARGET_HOST -P$TARGET_PORT -u$TARGET_USER -p$TARGET_PASS $TARGET_DB --execute "
    CREATE TABLE $EXPORT_TABLE_NAME AS
SELECT
    xm  as 姓名,
    nj  as 年级
    FROM $SOURCE_DB.$SOURCE_TABLE;
    "

    if [ $? -eq 0 ]; then
        echo "数据导入完成!"
    else
        echo "数据导入失败!"
    fi
else
    echo "数据导出失败!"
fi

1-2-4、新建一个.bash脚本(英转中  异步复制)

#!/bin/bash

# 源数据库配置
SOURCE_DB="qq"
SOURCE_HOST="localhost"
SOURCE_PORT="3306"
SOURCE_USER="root"
SOURCE_PASS="123456"

# 目标数据库配置
TARGET_DB="aa"
TARGET_HOST="localhost"
TARGET_PORT="3306"
TARGET_USER="root" 
TARGET_PASS="123456"

# 要导出的表
SOURCE_TABLE="owner"
CURRENT_DATETIME=$(date +"%Y%m%d%H%M%S")
EXPORT_TABLE_NAME="${SOURCE_TABLE}_${CURRENT_DATETIME}"

# 导出 SQL 文件的路径
EXPORT_DIR="D:\ProgramFiles\programSoftware\backups"
EXPORT_FILE="$EXPORT_DIR/${EXPORT_TABLE_NAME}.sql"

echo "开始同步数据..."

# 获取主库的二进制日志文件名和位置
source_status=$(mysql -h$SOURCE_HOST -P$SOURCE_PORT -u$SOURCE_USER -p$SOURCE_PASS -e "SHOW MASTER STATUS\G")
source_file=$(echo "$source_status" | grep 'File:' | awk '{print $2}')
source_position=$(echo "$source_status" | grep 'Position:' | awk '{print $2}')

# 导出源表数据到临时表
mysqldump -h$SOURCE_HOST -P$SOURCE_PORT -u$SOURCE_USER -p$SOURCE_PASS $SOURCE_DB $SOURCE_TABLE > $EXPORT_FILE
mysql -h$TARGET_HOST -P$TARGET_PORT -u$TARGET_USER -p$TARGET_PASS $TARGET_DB -e "CREATE TABLE $EXPORT_TABLE_NAME AS
   SELECT
    GUID as 唯一标识,
    AUTHCHGDATE as 授权修改过期时间
    FROM $SOURCE_DB.$SOURCE_TABLE;
    "

# 在目标库上配置复制
mysql -h$TARGET_HOST -P$TARGET_PORT -u$TARGET_USER -p$TARGET_PASS -e "CHANGE MASTER TO 
MASTER_HOST='$SOURCE_HOST',
MASTER_USER='$SOURCE_USER',
MASTER_PASSWORD='$SOURCE_PASS',
MASTER_LOG_FILE='$source_file',
MASTER_LOG_POS=$source_position,
MASTER_PORT=$SOURCE_PORT;"

# 启动目标库复制
mysql -h$TARGET_HOST -P$TARGET_PORT -u$TARGET_USER -p$TARGET_PASS -e "START SLAVE;"

echo "数据同步已经启动。"
# echo "导出的 SQL 文件保存在: $EXPORT_FILE"

2、在linux打开定时任务执行脚本(因为定时只有linux 可以执行)

(1)、先赋予文件夹权限
chmod -R 777 /home/mengqingda/program/test
(2)、然后执行
crontab -e

(3)、如果不习惯用这个编译器可以切换vim编译器进行编辑

export EDITOR="/usr/bin/vim" ; 

 (4)、添加定时任务(5分钟一次)

*/5 * * * * /home/mengqingda/program/test/backup.sh

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

帐篷帐篷,下雨不愁

如果感到幸福你就拍拍手!!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值