文章目录
- Java和Linux实现MySQL数据库备份
- 前言:
- 1、为什么要进行数据库备份?
- 2、数据库备份可以干什么?
- 1、如何在Java中实现MySQL数据库备份呢?
- 2、命令执行之Runtime.getRuntime().exec()
- 3、Java实现数据库备份
- Linux实现数据库备份
- 1、定时自动备份并保留7天及数据
- 2、创建定时任务
- 3、恢复备份文件
Java和Linux实现MySQL数据库备份
前言:
1、为什么要进行数据库备份?
一、数据丢失应用场景:
- 人为操作失误造成某些数据被误操作
- 软件 BUG 造成部分数据或全部数据丢失
- 硬件故障造成数据库部分数据或全部数据丢失
- 安全漏洞被入侵数据恶意破坏
二、非数据丢失应用场景:
- 特殊应用场景下基于时间点的数据恢复
- 开发测试环境数据库搭建
- 相同数据库的新环境搭建
- 数据库或者数据迁移
2、数据库备份可以干什么?
- 保证数据的安全性
- 保证我们因为服务器挂掉导致数据丢失风险降到最低,提高抗风险能力
- 当受到网络攻击、入侵、电源故障或者操作失误等事故的发生后,可以完整、快速、简捷、可靠地恢复原有系统,在一定的范围内保障系统的正常运行。
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();
}
在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的几种用法:
- destroy();杀掉子进程
- exitValue();返回子进程的出口值,值0表示正常终止
- getErrorStream();获取自己进程错误输出的输入流
- getInputStream();这里是获取子进程输出的输入流
- getOutputStream();获取子进程输入的输出流
- 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("运行终端命令失败");
}
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", "数据库", "用户名", "密码"));
}
}
定时任务工具类:想学习定时任务的可以点击此链接:
/**
* @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插入
粘贴代码
#!/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
正常是生成这种文件:
报错:-bash: ./DatabaseName.sh: Permission denied
没有权限:需要添加权限
chmod 777 DatabaseName.sh
2、创建定时任务
定时任务规则:
输入
crontab -e
进入自动任务设置文件后 输入以下代码
*/1 * * * * /home/sqlbackup/DatabaseName.sh 每分钟执行
0 2 * * * /home/sqlbackup/DatabaseName.sh 每天2点执行
此代码 代表每分钟执行一次/home/sqlbackup文件夹下的DatabaseName.sh文件
五个*分别代表 分 时 天 月 周
重启crond服务:service crond restart
定时任务重启报错解决方案:
错误:Redirecting to /bin/systemctl restart crond.service
/bin/systemctl restart crond
相关解决方案:
3、恢复备份文件
创建my_mysql.cnf 文件
vim my_mysql.cnf
[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文件
vim mysql_restore.sh
粘贴代码
脚本内容:
#!/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 退出 后面加!强制效果
启动测试
注意:如果整个库被被删了 需要先创建库 否则报错