java实现mysql数据库备份

目标

为了实现定时数据库备份。每天零晨启动,备份指定环境mysql数据库到另一机器上,并最多保存一周数据就好。

分析

1、mysql数据库备份,数据库自己提供了工具mysqldump

示例如下:

mysqldump -h $dbhost -u $username -p$password $database_name > $backup_dir/$database_name-$dd.sql

2、定时任务实现,最直接就是一个shell脚本实现,但是corntab没用明白,这里只好Java实现,主要用Timer实现

对Timer定时任务我们另说,路径如下:

 

工具

JDK1.8

intellij idea

mysql 8.0.15

实现

1、

bash.sh

这个脚本也是网上找的,只修改了JAVA_HOME和APP_HOME,分别是我本地JDK安装路径、工程jar路径

https://www.cnblogs.com/wangfajun/p/9585530.html

#!/bin/bash
export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_202.jdk/Contents/Home
export JRE_HOME=/$JAVA_HOME/jre
export CLASSPATH=.:$JAVA_HOME/jre/lib/rt.jar:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
export PATH=$PATH:$JAVA_HOME/bin:$JRE_HOME/bin

#这里可替换为你自己的执行程序,其他代码无需更改

APP_NAME=/Users/****/Desktop/temp/dbtemp.jar
#使用说明,用来提示输入参数
usage() {
    echo "Usage: sh robotcenter.sh [start|stop|restart|status]"
    exit 1
}

#检查程序是否在运行
is_exist(){
  pid=`ps -ef|grep $APP_NAME|grep -v grep|awk '{print $2}'`
  #如果不存在返回1,存在返回0
  if [ -z "${pid}" ]; then
   return 1
  else
    return 0
  fi
}

#启动方法
start(){
  is_exist
  if [ $? -eq 0 ]; then
    echo "${APP_NAME} is already running. pid=${pid}"
  else
    nohup java -jar ${APP_NAME}  >robotcenter.out 2>&1 &
  fi
}

#停止方法
stop(){
  is_exist
  if [ $? -eq "0" ]; then
    kill -9 $pid
  else
    echo "${APP_NAME} is not running"
  fi
}

#输出运行状态
status(){
  is_exist
  if [ $? -eq "0" ]; then
    echo "${APP_NAME} is running. Pid is ${pid}"
  else
    echo "${APP_NAME} is NOT running."
  fi
}

#重启
restart(){
  stop
  sleep 5
  start
}

#根据输入参数,选择执行对应方法,不输入则执行使用说明
case "$1" in
  "start")
    start
    ;;
  "stop")
    stop
    ;;
  "status")
    status
    ;;
  "restart")
    restart
    ;;
  *)
    usage
    ;;
esac

2、

DBController.class

代码中,数据库导出和文件删除两个方法也是网上找的

import java.io.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author ydx
 * @date 2019-02-22 15:38
 */
public class DBController {

    private static String basePath = System.getProperty("user.dir") + File.separator + "dbBackFile";
    //localhost   altc1-appinfra-app-registry-1.vm.elenet.me
    private static String dbHost = "localhost";
    //root
    private static String dbUser = "root";
    //root
    private static String dbPwd = "ydx";
    //local_data  qa_data
    private static String dbName = "local_data";

    private static String dateFormat = "yyyy-MM-dd-HH-mm-ss";
    // 最多保留文件数
    private static int saveFileMax = 2;
    //文件格式
    private static String fileFormat = "_" + dbName + ".sql";

    public static void main(String[] args) throws Exception {

        //定时执行,时间过了,立即执行
        System.out.println("### job time:" + getTime());
        System.out.println(Thread.currentThread().getName() + new Date().toString() + " run ");

        new Timer("lun xun timer - ").schedule(new TimerTask() {

            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + new Date().toString() + " run ");

                String backName = new SimpleDateFormat(dateFormat).format(new Date()) + fileFormat;

                try {
                    exportDatabaseTool(dbHost, dbUser, dbPwd, basePath, backName, dbName);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                deleteFurthestFile(basePath, dateFormat, fileFormat, saveFileMax);
            }
        }, getTime(), 24 * 60 * 60 * 60 * 1000);//轮询 天 时 分 秒 毫秒
    }

    public static Date getTime() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.HOUR_OF_DAY, 2);
        calendar.set(Calendar.MINUTE, 30);
        calendar.set(Calendar.SECOND, 00);
        Date time = calendar.getTime();

        return time;
    }

    /**
     * Java代码实现MySQL数据库导出
     *
     * @param hostIP       MySQL数据库所在服务器地址IP
     * @param userName     进入数据库所需要的用户名
     * @param password     进入数据库所需要的密码
     * @param savePath     数据库导出文件保存路径
     * @param fileName     数据库导出文件文件名
     * @param databaseName 要导出的数据库名
     * @return 返回true表示导出成功,否则返回false。
     * @author GaoHuanjie
     */
    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 printWriter = null;
        BufferedReader bufferedReader = null;
        try {
            printWriter = new PrintWriter(new OutputStreamWriter(new FileOutputStream(savePath + fileName), "utf8"));
            Process process = Runtime.getRuntime().exec(" mysqldump --column-statistics=0 -h" + hostIP + " -u" + userName + " -p" + password + " --set-charset=UTF8 " + databaseName);
            InputStreamReader inputStreamReader = new InputStreamReader(process.getInputStream(), "utf8");
            bufferedReader = new BufferedReader(inputStreamReader);
            String line;
            while ((line = bufferedReader.readLine()) != null) {
                printWriter.println(line);
            }
            printWriter.flush();
            if (process.waitFor() == 0) {//0 表示线程正常终止。
                return true;
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (bufferedReader != null) {
                    bufferedReader.close();
                }
                if (printWriter != null) {
                    printWriter.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return false;
    }

    /**
     * 删除文件夹中最早产生的一个文件,如csv文件夹永远只保留max=30个最新的文件,超过30则删除一个文件
     * 注意:是根据文件命名来delete的,所以必须要有公共的命名规则
     *
     * @param commonFileSuffix 文件夹下的文件名的公共后缀:如_log.txt
     * @param fileDir          文件夹名称
     * @param max              文件夹下最多的文件数量
     * @param format           时间格式
     */
    public static void deleteFurthestFile(String fileDir, String format, final String commonFileSuffix, final int max) {
        try {
            File dir = new File(fileDir);
            if (!dir.exists()) {
                return;
            }
            int currentNum = 0;
            if (dir.exists()) {
                File[] youxiaoFile = dir.listFiles(new FileFilter() {
                    public boolean accept(File pathname) {
                        return pathname.getName().endsWith(fileFormat);
                    }
                });

                currentNum = youxiaoFile.length;  //得到当前文件夹文件数目
            }

            if (currentNum > max) {
                do {
                    //得到文件名的一个map
                    SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
                    Map<Long, String> map = new HashMap();
                    for (File file1 : dir.listFiles()) {
                        if (file1.getName().startsWith(".")) {
                            continue;
                        }
                        String time = file1.getName().replace(commonFileSuffix, "");
                        try {
                            Date date = simpleDateFormat.parse(time);
                            map.put(date.getTime(), file1.getName()); //<1233282716409,2018-2-1_log.txt>
                        } catch (RuntimeException e) {
                            System.out.println(" file:" + file1.getName());
                        }
                    }

                    //产生时间最早的文件名
                    long lt = Long.valueOf(Collections.min(map.keySet()).toString());
                    File f1 = new File(fileDir + File.separator + map.get(lt));
                    if (f1.exists()) {
                        System.out.println(" delete file:" + f1.getName());
                        f1.delete();
                        currentNum--;
                    }
                } while (currentNum > max);
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }


}

 

总结

1、文件删除代码中,do while是后加的,原因是先前的代码只会删除最晚的一个文件。与这里的需求不合,这边只要最近一周时间的数据,其它的都可以删除,所以这里加了个循环

2、文件删除代码中,在获取当前文件下有多少个文件的实现,这里对文件名做了判断,原因是我这边用Mac开发的,文件夹里会有隐藏文件,为了不影响日期格式解析,这里做了过滤

3、intellij打包时,习惯性用maven打包,但是运行jar时,会找不会入口,原因是MANIFEST.MF中没有Main-Class配置,改用intellij自己的build打包就好。

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值