Java and Linux realize MySQL database backup

Java and Linux realize MySQL database backup

Foreword:

1. Why do you need to perform database backup?

1. Data loss application scenarios:

  1. Some data is mishandled due to human error
  2. Software BUG causes some or all data loss
  3. Some or all data in the database is lost due to hardware failure
  4. Security breach maliciously compromised by hacked data

2. Non-data loss application scenarios:

  1. Point-in-time data recovery in special application scenarios
  2. Development and testing environment database construction
  3. Create a new environment with the same database
  4. Database or Data Migration

2. What can database backup do?

  1. Ensure data security
  2. Ensure that we minimize the risk of data loss due to server failure and improve the ability to resist risks
  3. When accidents such as network attack, intrusion, power failure or operation error occur, the original system can be restored completely, quickly, simply and reliably, and the normal operation of the system can be guaranteed within a certain range.

1. How to implement MySQL database backup in Java?

We only need to execute MySQL commands, and Java executes terminal commands using the exec method

We found that the exec method in Java reports an error every time it is called to execute a terminal command

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

[External link picture transfer failed, the source site may have an anti-theft link mechanism, it is recommended to save the picture and upload it directly (img-xPmpWLWh-1681883761338)(E:\PRD\Images\image-20230414100308852.png)]

Under Windows, it is equivalent to directly calling/starting/searching for programs and files, such as

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

This is because we need to open the cmd window on the Windows system to execute terminal commands, otherwise we cannot find the corresponding path

optimization:

2. Runtime.getRuntime().exec() for command execution

In java, RunTime.getRuntime().exec() implements the need to call the server command script to execute the function.

usage:

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)----在指定环境和工作目录的独立进程中执行指定的命令和变量

Under Linux system:

Use the following commands to execute terminal commands

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

Under Windows:

Use the following commands to execute terminal commands

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

Several usages of Process:

  1. destroy(); kill the child process

  2. exitValue(); returns the exit value of the child process, a value of 0 means normal termination

  3. getErrorStream(); Get the input stream of the error output of its own process

  4. getInputStream(); here is the input stream to get the output of the subprocess

  5. getOutputStream(); Get the output stream of the subprocess input

  6. waitFor(); causes the current thread to wait, if necessary, until the process represented by the Process object has terminated. If the child process has been terminated, this method returns immediately. If the child process has not been terminated, the calling thread will be terminated. Block until the child process is launched, according to convention, 0 means normal termination

Code example:

   @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("运行终端命令失败");
    }

[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-kKGomzKQ-1681883761339)(E:\PRD\Images\image-20230414103213860.png)]

3. Java implements database backup

Database tools

/**
 * @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", "数据库", "用户名", "密码"));
    }
} 

Timing task tools: If you want to learn timing tasks, you can click this link: 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();
	   }
	}
}

Realize Database Backup in Linux

1. Scheduled automatic backup and keep 7 days and data

移动到home文件夹下

cd  /home

创建文件夹 

mkdir sqlbackup

移动到sqlbackup

cd /home/sqlbackup

创建并编辑备份shell脚本

vim DatabaseName.sh

按键i插入

粘贴代码

[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (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 input colon: wq save and exit q exit followed by ! mandatory effect

Test whether the script is normal: ./DatabaseName.sh

insert image description here

Normally this kind of file is generated:

[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-WuXDJ4S4-1681883761340)(E:\PRD\Images\image-20230418133635524.png)]

Error: -bash: ./DatabaseName.sh: Permission denied

No permission: need to add permission

chmod 777 DatabaseName.sh

2. Create a scheduled task

Timing task rules: https://blog.csdn.net/qq_32923745/article/details/78286385

enter

[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-2oUoYEMD-1681883761340)(E:\PRD\Images\wps2.jpg)]

crontab -e

Enter the following code after entering the automatic task setting file

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

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

This code represents the execution of the DatabaseName.sh file in the /home/sqlbackup folder every minute

The five * represent time-sharing day, month and week respectively

[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-OhRS60q6-1681883761341)(E:\PRD\Images\wps3.jpg)]

重启crond服务:service crond restart

Timed task restart error solution:
Error: Redirecting to /bin/systemctl restart crond.service

/bin/systemctl restart crond

Related solutions: https://blog.csdn.net/qq_43203949/article/details/109521690

3. Restore the backup file

Create my_mysql.cnf file

[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-QqIh8EVL-1681883761341)(E:\PRD\Images\wps4.jpg)]

vim my_mysql.cnf

[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (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'

Create the mysql_restore.sh file

[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-7JiaXrwP-1681883761341)(E:\PRD\Images\wps6.jpg)]

vim mysql_restore.sh

paste code

[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-ZrNjeOZH-1681883761342)(E:\PRD\Images\wps7.jpg)]

Script content:

#!/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 input colon: wq save and exit q exit followed by ! mandatory effect

start test

[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-nAoF04Ya-1681883761342)(E:\PRD\Images\wps8.jpg)]

Note: If the entire library is deleted, you need to create the library first, otherwise an error will be reported

[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-GyKDQrUr-1681883761342)(E:\PRD\Images\wps9.jpg)]

Thanks to the blogger: 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

Guess you like

Origin blog.csdn.net/ITKidKid/article/details/130242494