引言
在项目中经常会用到Java程序备份和还原MySQL数据库的内容,都是大同小异,但程序也会出现各种各样的问题(运行时异常,乱码等)。实现上都是用Runtime执行MySQL的命令行工具,然后读写IO流数据;也有可能是由于使用Java的Runtime来实现备份还原功能,而由于大家的运行时环境有差异才导致代码运行不成功。在这里记录一下自己使用的工具和方法。
使用MySQL自带工具
备份
备份使用MySQL的mysqldump
命令来实现,示例代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| final static Logger logger = LoggerFactory.getLogger(MySQLDatabaseBackupAndRestore.class);
public static boolean backUpDatabase(String hostIP, String userName, String password, String databaseName, String savePath, String fileName) 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(" D:\\DevTools\\MySQL\\MySQL5.7\\bin\\mysqldump.exe -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) { logger.info("数据库已备份到——>>" + savePath); 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; }
|
还原
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
| final static Logger logger = LoggerFactory.getLogger(MySQLDatabaseBackupAndRestore.class);
public static boolean restoreDatabase(String hostIP, String userName, String password, String databaseName, String path, String fileName) throws InterruptedException {
OutputStream out = null; BufferedReader br = null; PrintStream ps = null; try { Process process = Runtime.getRuntime().exec("cmd /c start /b D:\\DevTools\\MySQL\\MySQL5.7\\bin\\mysql -h" + hostIP + " -u" + userName + " -p" + password + " --default-character-set=utf8 " + databaseName); out = process.getOutputStream(); StringBuffer sb = new StringBuffer(""); br = new BufferedReader(new InputStreamReader(new FileInputStream(path + fileName), "utf8")); String outStr; String line; while ((line = br.readLine()) != null) { sb.append(line + "\r\n"); } outStr = sb.toString();
ps = new PrintStream(out, true, "utf8"); ps.write(outStr.getBytes());
if (process.waitFor() == 0) { return true; } } catch (Exception e) { e.printStackTrace(); return false; } finally { try { if (ps != null) { ps.close(); } if (br != null) { br.close(); } if (out != null){ out.close(); } } catch (IOException e1) { e1.printStackTrace(); } } return false; }
|
测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| public static void main(String[] args){
try { if (restoreDatabase("localhost", "root", "root", "taotao", "D:/", "taotao.sql")) { logger.info("数据库恢复成功!!"); } else { logger.info("数据库恢复失败!!"); } } catch (InterruptedException e) { e.printStackTrace(); } }
|
代码下载点击:下载
Windows下bat命令
工作环境 Windows Server 2003 ,MySQL
安装目录 D:\DevTools\MySQL ,
WinRAR
安装目录 C:\Program Files\WinRAR\WinRAR.exe
备份数据存储的路径为 D:\数据备份,好了下面开始写DOS批处理命令
了。代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| color 9 rem ---------------------数据库备份开始----------------------- @echo off
set "Ymd=%DATE:~0,4%%DATE:~5,2%%DATE:~8,2%%TIME:~0,2%%TIME:~3,2%%TIME:~6,2%" REM 日期格式:20170924200727 md "D:\%ymd%" "D:\DevTools\MySQL\MySQL5.7\bin\mysqldump.exe" --opt -Q taotao -uroot -proot > D:\%Ymd%\taotao.sql REM ..... 这里可以添加更多的命令,要看你有多少个数据库,其中 -Q 后面是数据库名称 -p紧跟后面是密码 REM echo Winrar loading... REM "C:\Program Files\WinRAR\WinRAR.exe" a -ep1 -r -o+ -m5 -df "D:\数据备份\%Ymd%.rar" "D:\数据备份\%Ymd%" @echo on rem ---------------------数据库备份完成-----------------------
pause
|
把上面的命令保存为 backup.bat ,双击运行,就开始备份数据了。
第 一句是建立一个变量 %Ymd% ,通过 %date% 这个系统变量得到日期,%date:,4% 表示取日期的前面4个字符就是年份,%%date:5,2% 表示取日期第5个字符开始的2个字符就是月份,%date:~8,2% 这个就是日期号数,如 2017-09-24 这个日期最后得到的结果是 20170924
第二句就是使用变量 %Ymd% 的值建立一个空的文件夹。
第三句开始就是使用MySQL的命令对数据库mysql进行备份,并存储在 D:\数据备份%ymd% 这个文件夹下面,这里可以有很多类似的命令,备份多个数据库。
最后就是使用 WinRAR 对备份的数据进行压缩,并存储为以 %Ymd% 变量值建立的RAR文件名,同时删除备份的 %Ymd% 目录。
如果你想让系统自动定期备份,就可以通过系统的任务计划定期执行这个命令。
但是用windows下bat命令备份有一个致命缺点:备份时数据库会暂时断开。(30M断开5s左右)
总结
第二种方式的缺点太致命:备份时数据库会暂时断开。
所以第一种方式将会是我们在开发中首选的方式,因为第二种方式的缺点对用户体验的影响太大了。