Java和Linux实现MySQL数据库备份

Java和Linux实现MySQL数据库备份

前言:

1、为什么要进行数据库备份?

一、数据丢失应用场景:

  1. 人为操作失误造成某些数据被误操作
  2. 软件 BUG 造成部分数据或全部数据丢失
  3. 硬件故障造成数据库部分数据或全部数据丢失
  4. 安全漏洞被入侵数据恶意破坏

二、非数据丢失应用场景:

  1. 特殊应用场景下基于时间点的数据恢复
  2. 开发测试环境数据库搭建
  3. 相同数据库的新环境搭建
  4. 数据库或者数据迁移

2、数据库备份可以干什么?

  1. 保证数据的安全性
  2. 保证我们因为服务器挂掉导致数据丢失风险降到最低,提高抗风险能力
  3. 当受到网络攻击、入侵、电源故障或者操作失误等事故的发生后,可以完整、快速、简捷、可靠地恢复原有系统,在一定的范围内保障系统的正常运行。

1、如何在Java中实现MySQL数据库备份呢?

我们只需要执行MySQL命令就可以了,Java执行终端命令就是使用exec方法

我们发现Java中的exec方法每次调用执行终端命令都报错

	@Test
    public void test() throws IOException, InterruptedException {
    
    
        Runtime runtime = Runtime.getRuntime();
        Process process = runtime.exec("mysql --version");
        int i = process.waitFor();
    }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xPmpWLWh-1681883761338)(E:\PRD\Images\image-20230414100308852.png)]

在windows下相当于直接调用 /开始/搜索程序和文件 的指令 ,比如

Runtime.getRuntime().exec("notepad.exe");  -------打开windows下记事本。

这是因为我们在Windows系统上面需要打开cmd窗口才能执行终端命令,不然找不到对应的路径

优化:

2、命令执行之Runtime.getRuntime().exec()

在java中,RunTime.getRuntime().exec()实现了调用服务器命令脚本来执行功能需要。

用法:

public Process exec(String command)-----在单独的进程中执行指定的字符串命令。
public Process exec(String [] cmdArray)---在单独的进程中执行指定命令和变量
public Process exec(String command, String [] envp)----在指定环境的独立进程中执行指定命令和变量
public Process exec(String [] cmdArray, String [] envp)----在指定环境的独立进程中执行指定的命令和变量
public Process exec(String command,String[] envp,File dir)----在有指定环境和工作目录的独立进程中执行指定的字符串命令
public Process exec(String[] cmdarray,String[] envp,File dir)----在指定环境和工作目录的独立进程中执行指定的命令和变量

Linux系统下:

使用以下命令就能执行终端命令

Runtime.getRuntime().exec(new String[]{
    
    "/bin/sh","-c", cmds});

Windows下:

使用以下命令就能执行终端命令

Runtime.getRuntime().exec(new String[]{
    
     "cmd", "/c", cmds});

Process的几种用法:

  1. destroy();杀掉子进程

  2. exitValue();返回子进程的出口值,值0表示正常终止

  3. getErrorStream();获取自己进程错误输出的输入流

  4. getInputStream();这里是获取子进程输出的输入流

  5. getOutputStream();获取子进程输入的输出流

  6. waitFor();导致当前线程等待,如有必要,一直要等到由该Process对象表示的进程已经终止,如果已终止该子进程,此方法立即返回,如果没有终止该子进程,调用的线程将被阻塞,直到推出子进程,根据惯例,0表示正常终止

代码实例:

   @Test
    public void test() throws IOException, InterruptedException {
    
    
        Runtime runtime = Runtime.getRuntime();
        String [] cmd = {
    
    "cmd","/c","mysql --version"};
        Process process = runtime.exec(cmd);
        int i = process.waitFor();
        if (i>0){
    
    
            System.out.println("运行终端命令成功");
        }else
        System.out.println("运行终端命令失败");
    }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kKGomzKQ-1681883761339)(E:\PRD\Images\image-20230414103213860.png)]

3、Java实现数据库备份

数据库工具类

/**
 * @author zzw
 * @description TODO
 * @date 2023-04-12 17:35
 */
@Slf4j
public class DataBaseUtils {
    
    
    private static final String MYSQL_HOME = "MySQL安装路径"; // MySQL安装路径(注意如果配置了MySQL全局变量,那么这个参数可有可无,没有配置的话,必须要有这个参数,不然会报错,找不到命令)


    /**
     * @description Java代码实现MySQL数据库导出
     *
     * @author zzw
     * @param hostIP MySQL数据库所在服务器地址IP
     * @param userName 进入数据库所需要的用户名
     * @param password 进入数据库所需要的密码
     * @param savePath 数据库导出文件保存路径
     * @param fileName 数据库导出文件文件名
     * @param databaseName 要导出的数据库名
     * @return 返回true表示导出成功,否则返回false。
     */
    public static boolean exportDatabaseTool(String hostIP, String userName, String password, String savePath, String fileName, String databaseName) throws InterruptedException {
    
    
        File saveFile = new File(savePath);
        if (!saveFile.exists()) {
    
    // 如果目录不存在
            saveFile.mkdirs();// 创建文件夹
        }
        if(!savePath.endsWith(File.separator)){
    
    
            savePath = savePath + File.separator;
        }
        PrintWriter pw = null;
        BufferedReader bufferedReader = null;
        try {
    
    
            String cmd1 = "/bin/sh";
            String cmd2 = "-c";
            String os_name = System.getProperty("os.name");
            // 判断是否是windows系统
            if (os_name.toLowerCase().startsWith("win")){
    
    
                cmd1 = "cmd";
                cmd2 = "/c";
            }
            pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(savePath + fileName), "utf8"));
            String stmt = DataBaseUtils.MYSQL_HOME + "mysqldump -h" + hostIP + " -u" + userName + " -p" + password + " --set-charset=UTF8 " + databaseName;
            log.info(stmt);
            String[] cmd = {
    
     cmd1, cmd2 , stmt };
            Process process = Runtime.getRuntime().exec(cmd);
            InputStreamReader inputStreamReader = new InputStreamReader(process.getInputStream(), "utf8");
            bufferedReader = new BufferedReader(inputStreamReader);
            String line;
            while((line = bufferedReader.readLine())!= null){
    
    
                pw.println(line);
            }
            pw.flush();
            if(process.waitFor() == 0){
    
    //0 表示线程正常终止。
                return true;
            }
        }catch (IOException e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            try {
    
    
                if (bufferedReader != null) {
    
    
                    bufferedReader.close();
                }
                if (pw != null) {
    
    
                    pw.close();
                }
            } catch (IOException e) {
    
    
                e.printStackTrace();
            }
        }
        return false;
    }


    /**
     * 用来恢复数据库
     * @param filepath 数据库备份的脚本路径
     * @param ip IP地址
     * @param database 数据库名称
     * @param userName 用户名
     * @param password 密码
     * @return
     */
    public static boolean recover(String filepath,String ip,String database, String userName,String password) {
    
    
        String cmd1 = "/bin/sh";
        String cmd2 = "-c";
        String os_name = System.getProperty("os.name");
        // 判断是否是windows系统
        if (os_name.toLowerCase().startsWith("win")){
    
    
            cmd1 = "cmd";
            cmd2 = "/c";
        }
        String stmt2 = DataBaseUtils.MYSQL_HOME + "mysqldump -h "+ip+" -u"+userName+" -p"+password+" "+database+" < " + filepath;
        String[] cmd = {
    
     cmd1, cmd2, stmt2 };
        try {
    
    
            log.info(cmd[2]);
            Runtime.getRuntime().exec(cmd);
            log.info("数据已从 " + filepath + " 导入到数据库中");
        } catch (IOException e) {
    
    
            e.printStackTrace();
            return false;
        }
        return true;
    }

    @Test
    public void test() throws IOException, InterruptedException {
    
    
        System.out.println(exportDatabaseTool("IP", "用户名", "密码", "下载位置",
                "文件名.sql", "数据库"));
//        System.out.println(recover("下载位置.sql", "IP", "数据库", "用户名", "密码"));
    }
} 

定时任务工具类:想学习定时任务的可以点击此链接:https://blog.csdn.net/ITKidKid/article/details/126386738

/**
 * @author zzw
 * @description TODO 定时任务实现数据库备份
 * @date 2023-04-12 17:32
 */
@Configuration
@EnableScheduling
public class Schedule {
    
    
@Scheduled(cron = "*/5 * * * * ?") // 每五秒钟执行一次定时任务
	private void ddd(){
    
    
	   try {
    
    
	        DataBaseUtils.exportDatabaseTool("IP", "用户名", "密码", "下载位置",
	                  "文件名.sql", "数据库");
	   } catch (InterruptedException e) {
    
    
	             e.printStackTrace();
	   }
	}
}

Linux实现数据库备份

1、定时自动备份并保留7天及数据

移动到home文件夹下

cd  /home

创建文件夹 

mkdir sqlbackup

移动到sqlbackup

cd /home/sqlbackup

创建并编辑备份shell脚本

vim DatabaseName.sh

按键i插入

粘贴代码

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0PqAoXg8-1681883761340)(E:\PRD\Images\image-20230418115910390.png)]

#!/bin/bash

baseDir="/home/sqlbackup/";

cd "$baseDir";

echo "开始备份数据库";

#不压缩(压缩不压缩可自行选择)

#echo 'mysqldump -uroot -pt84QBp^@mb6x DatabaseName > /home/sqlbackup/DatabaseName_$(date +%Y%m%d_%H%M%S).sql';

#压缩

# mysql_location 安装路径,如果配置了全局路径就可以把这个参数去掉

mysql_location="MySQL安装路径/bin/"

echo `${
    
    mysql_location}mysqldump -uroot -proot test| gzip > /home/sqlbackup/test_$(date +%Y%m%d_%H%M%S).sql.gz`;

echo "备份数据完成";

oldDate=`date --date='-7 minutes' +%Y%m%d_%H%M`;

#删除当前日期-七天前的备份

echo `rm -rf test_$oldDate*`;

echo "删除$oldDate的备份成功"

#now=$(date +"%Y-%m-%d_%H-%M-%S");

#old=$(date --date="-7 minutes" +"%Y-%m-%d_%H-%M");

#echo `mysqldump -uroot -proot test | gzip > $now.sql.gz`;

#echo `find . -type f -name "*.sql.gz" -mtime +0 -newermt "$oldDate" -delete`;

ESC 输入冒号 :wq 保存并退出 q 退出 后面加!强制效果

测试脚本是否正常: ./DatabaseName.sh

在这里插入图片描述

正常是生成这种文件:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WuXDJ4S4-1681883761340)(E:\PRD\Images\image-20230418133635524.png)]

报错:-bash: ./DatabaseName.sh: Permission denied

没有权限:需要添加权限

chmod 777 DatabaseName.sh

2、创建定时任务

定时任务规则:https://blog.csdn.net/qq_32923745/article/details/78286385

输入

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2oUoYEMD-1681883761340)(E:\PRD\Images\wps2.jpg)]

crontab -e

进入自动任务设置文件后 输入以下代码

*/1 * * * * /home/sqlbackup/DatabaseName.sh  每分钟执行

0 2 * * * /home/sqlbackup/DatabaseName.sh  每天2点执行

此代码 代表每分钟执行一次/home/sqlbackup文件夹下的DatabaseName.sh文件

五个*分别代表 分 时 天 月 周

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OhRS60q6-1681883761341)(E:\PRD\Images\wps3.jpg)]

重启crond服务:service crond restart

定时任务重启报错解决方案:
错误:Redirecting to /bin/systemctl restart crond.service

/bin/systemctl restart crond

相关解决方案:https://blog.csdn.net/qq_43203949/article/details/109521690

3、恢复备份文件

创建my_mysql.cnf 文件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QqIh8EVL-1681883761341)(E:\PRD\Images\wps4.jpg)]

vim my_mysql.cnf

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VuS7Utsv-1681883761341)(E:\PRD\Images\wps5.jpg)]

[mysqldump]

max_allowed_packet= 400M

host=127.0.0.1

user=root

password='123456' # 设置为自己的密码例如我的为123456

[mysql]

host=127.0.0.1

user=root

password='123456'

创建mysql_restore.sh文件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7JiaXrwP-1681883761341)(E:\PRD\Images\wps6.jpg)]

vim mysql_restore.sh

粘贴代码

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZrNjeOZH-1681883761342)(E:\PRD\Images\wps7.jpg)]

脚本内容:

#!/bin/bash

if [ -z $1 ] || [ ! -f $1 ]

then

  echo "请输入sql压缩文件(*.sql.gz)"

  exit 1

fi

db_name='test ' #需要导入的的文件名

base_dir='/home/sqlbackup/'

gz_sql_file=`basename $1`

file_ext=${
    
    gz_sql_file##*.}

if [ $file_ext != 'gz' ]

then

  echo '文件格式不正确,请输入 .sql.gz 文件'

  exit 1

fi

sql_file=${
    
    gz_sql_file%.*}

echo '解压文件中...'

gzip -dc $base_dir$gz_sql_file > $base_dir$sql_file

echo '解压完成.'

echo '开始导入数据库...'

mysql --defaults-extra-file=/home/sqlbackup/my_mysql.cnf $db_name < $base_dir$sql_file

if [ -f $base_dir$sql_file ]

then

  echo '删除临时文件.'

  rm -f $base_dir$sql_file

fi

echo '导入完成.'i

ESC 输入冒号 :wq 保存并退出 q 退出 后面加!强制效果

启动测试

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nAoF04Ya-1681883761342)(E:\PRD\Images\wps8.jpg)]

注意:如果整个库被被删了 需要先创建库 否则报错

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GyKDQrUr-1681883761342)(E:\PRD\Images\wps9.jpg)]

感谢博主:https://blog.csdn.net/chaochao2113/article/details/120179439

https://blog.csdn.net/qq_32923745/article/details/78286385

https://blog.csdn.net/hou_ge/article/details/124475716

猜你喜欢

转载自blog.csdn.net/ITKidKid/article/details/130242494