java程序使用cmd备份和恢复数据库

项目中需要提供程序上去备份数据库,基础代码来自网上,但是却留了个坑,好不容易才趟过去……

直接上代码:

一、备份(2018/01/03 )

/** 
     * 备份mysql数据库 
     * @param root  mysql登录名 
     * @param rootPass  登录密码 
     * @param dbName  要备份的数据库名称 
     * @param backupsPath  备份的路径 
     * @param backupsSqlFileName  备份文件的名字 
     * @return 
     */  
    public static String dbBackUp(String root,String rootPass,String dbName,String backupsPath,String backupsSqlFileName)  
    {  
        //生成临时备份文件  
//      SimpleDateFormat sd=new SimpleDateFordckupsSqlFileName;  
        String pathSql = backupsPath+backupsSqlFileName;  
        try {  
            File fileSql = new File(pathSql);  
            if(!fileSql.exists()){  
                fileSql.createNewFile();  
            }  
            StringBuffer sbs = new StringBuffer();  
            sbs.append(CMDPrefix+"mysqldump ");  
            sbs.append(" -h 127.0.0.1 ");  
            sbs.append(" -u ");  
            sbs.append(root+" ");  
            sbs.append("-p"+rootPass+" ");  
            sbs.append(dbName);  
            sbs.append(" --default-character-set=utf8 ");  
//          sbs.append(">"+pathSql);  
            sbs.append(" --result-file="+pathSql);  
            System.out.println("cmd命令为:——>>>"+sbs.toString());  
            Runtime runtime = Runtime.getRuntime();  
            Process child = runtime.exec(sbs.toString());  
              
            //读取备份数据并生成临时文件  
            InputStream in = child.getInputStream();  
            OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(pathSql), "utf8");  
            BufferedReader reader = new BufferedReader(new InputStreamReader(in, "utf8"));  
            String line=reader.readLine();  
            while (line != null) {  
                writer.write(line+"\n");  
                line=reader.readLine();  
                System.out.println(line);
             }  
             writer.flush();  
             System.out.println("数据库已备份到——>>"+pathSql);  
        } catch (Exception e) {  
              
        }  
        return pathSql;  
    }  
      

注意这里的--default-character-set=utf8设置了编码

二、恢复

出现坑的地方--default-character-set=utf8设置了编码,如果不加这一句,很有可能出现通道关闭的错误提示,另外,流的关闭顺序也要注意 

            writer.close();    
            br.close();    
            out.close();  

代码:

 public static boolean load() {//还原    
        try {  
            String fPath = "e:/emaster2000DB_20180103151600.sql";    
            Runtime rt = Runtime.getRuntime();    
        
            // 调用 mysql 的 cmd:    
            Process child = rt.exec(CMDPrefix+"mysql -uroot -ptime emaster2000 --default-character-set=utf8 ");    
            OutputStream out = child.getOutputStream();//控制台的输入信息作为输出流    
            String inStr;    
            StringBuffer sb = new StringBuffer("");    
            String outStr;    
            BufferedReader br = new BufferedReader(new InputStreamReader(    
                    new FileInputStream(fPath), "utf8"));    
            OutputStreamWriter writer = new OutputStreamWriter(out, "utf8");  
            int i=0;
            while ((inStr = br.readLine()) != null) { 
            	sb.append(inStr+"\r\n");
                System.out.println(inStr);
                
            }    
            outStr = sb.toString();    
            writer.write(outStr);
           
            // 别忘记关闭输入输出流    
            writer.close();    
            br.close();    
            out.close();    
                
            System.out.println("/* Load OK! */");    
        } catch (Exception e) {    
            e.printStackTrace();    
        }    
        return true;    
    }    

 

三、补充(2018/01/08)

    1.补充的原因:备份的方式没有问题,但是恢复的方式会有一定的问题,当备份出来的SQL文件很大时,在恢复时,由于代码是将SQL文件全部转成流发送给cmd命令窗口,这样会导致内存溢出。解决方式将SQL文件一部分一部分的写,也就是使用缓存,但是由于SQL执行的原因,个人很担心会出现SQL执行问题(本人未测试),另外一种方式是使用类似我们在cmd下执行mysql的source + SQL文件路径 这样的命令,此处选择第二种方式。

2.备份

/**
	 * 备份mysql数据库
	 * 
	 * @param root
	 *            mysql登录名
	 * @param rootPass
	 *            登录密码
	 * @param dbName
	 *            要备份的数据库名称
	 * @param backupsPath
	 *            备份的路径
	 * @param backupsSqlFileName
	 *            备份文件的名字
	 * @return
	 */
	public static String dbBackUp(String root, String rootPass, String dbName, String host,String CMDPrefix, String backupsPath,
			String backupsSqlFileName) {
		  try {
			Runtime rt = Runtime.getRuntime();
		    Process pro = rt.exec(getBackupCommand(root, rootPass, dbName, host, CMDPrefix, backupsPath, backupsSqlFileName));
		    BufferedReader br = new BufferedReader(new InputStreamReader(pro.getErrorStream()));
		    String errorLine = null;
		    while ((errorLine = br.readLine()) != null) {
		        logger.error("####################"+errorLine+"##################");
		    }
		    br.close();
		    int result = pro.waitFor();
		    if (result != 0) {
		    	logger.error("####################数据库备份失败##################");
		    }
		} catch (IOException e) {
			logger.error("####################数据库备份失败,"+e.getMessage()+"##################");
		} catch (InterruptedException e) {
			logger.error("####################数据库备份失败,"+e.getMessage()+"##################");
		} catch (Exception e) {
			logger.error("####################数据库备份失败,"+e.getMessage()+"##################");
		}
		return backupsSqlFileName;
	}
	
	/**
	 * 
	 * (Javadoc) 
	 * @Title: getBackupCommand 
	 * @Description:  
	 * @param @param root 数据库用户名
	 * @param @param rootPass 数据库用户密码
	 * @param @param dbName 数据库名称
	 * @param @param host 主机好
	 * @param @param CMDPrefix 命令前缀 最后需要加上\\
	 * @param @param backupsPath 备份路径
	 * @param @param backupsSqlFileName SQL文件名称
	 * @param @return  
	 * @return String[]  
	 * @throws
	 */
	private static String[] getBackupCommand(String root, String rootPass, String dbName, String host,String CMDPrefix, String backupsPath,
			String backupsSqlFileName) {
		BackupsDB.CMDPrefix=CMDPrefix;
	    String[] cmd = new String[3];
	    String os = System.getProperties().getProperty("os.name");
	    if (os.startsWith("Win")) {
	        cmd[0] = "cmd.exe";
	        cmd[1] = "/c";
	    } else {
	        cmd[0] = "/bin/sh";
	        cmd[1] = "-c";
	    }
	    StringBuilder arg = new StringBuilder();
	    arg.append(BackupsDB.CMDPrefix+"mysqldump ");
	    arg.append("-u");
	    arg.append(root);
	    arg.append(" -p");
	    arg.append(rootPass);
	    arg.append(" --default-character-set=");
	    arg.append(CHARSET);
	  //  arg.append(" --skip-opt ");
	    arg.append(" --add-drop-database ");
	   // arg.append("--routines ");
	    arg.append("--triggers ");
	    //arg.append("--compress ");
	    arg.append("-r ");
	    arg.append(backupsPath);
	    arg.append(backupsSqlFileName);
	    arg.append(".sql ");
	    arg.append("--databases ");
	    arg.append(dbName);
	    cmd[2] = arg.toString();
	    return cmd;
	} 

3.恢复

/**
	 * 
	 * @param root
	 *            数据库用户名
	 * @param rootPass
	 *            数据库密码
	 * @param backupsPath
	 *            备份文件路径
	 * @param dbName
	 *            数据库名
	 * @return true 备份成功,false 备份失败
	 */
	public static boolean load(String root, String rootPass, String host,String CMDPrefix,String backupsPath, String dbName) {// 还原
		//BackupsDB.CMDPrefix=CMDPrefix;
		
		Runtime rt = Runtime.getRuntime();
	    try {
			Process pro = rt.exec(getLoadCommand(root, rootPass, host, CMDPrefix, backupsPath, dbName));
			BufferedReader br = new BufferedReader(new InputStreamReader(pro.getErrorStream()));
			String errorLine = null;
			while ((errorLine = br.readLine()) != null) {
			    System.out.println(errorLine);
			}
			br.close();
			int result = pro.waitFor();
			if (result != 0) {
				logger.error("####################数据库恢复失败##################");
				return false;
			}
			return true;
		} catch (IOException e) {
			e.printStackTrace();
			logger.error("####################数据库恢复失败,"+e.getMessage()+"##################");
		} catch (InterruptedException e) {
			logger.error("####################数据库恢复失败,"+e.getMessage()+"##################");
		} catch (Exception e) {
			logger.error("####################数据库恢复失败,"+e.getMessage()+"##################");
		}
		return false;
	}
	/**
	 * 
	 * (Javadoc) 
	 * @Title: getLoadCommand 
	 * @Description:  
	 * @param @param root 数据库用户名
	 * @param @param rootPass 数据库密码
	 * @param @param host 数据库主机好
	 * @param @param CMDPrefix 命令前缀路径
	 * @param @param backupsPath SQL文件路径
	 * @param @param dbName 数据库名
	 * @param @return  
	 * @return String[]  
	 * @throws
	 */
	private static String[] getLoadCommand(String root, String rootPass, String host,String CMDPrefix,String backupsPath, String dbName) {
	    String[] cmd = new String[3];
	    String os = System.getProperties().getProperty("os.name");
	    if (os.startsWith("Win")) {
	        cmd[0] = "cmd.exe";
	        cmd[1] = "/c";
	    } else {
	        cmd[0] = "/bin/sh";
	        cmd[1] = "-c";
	    }
	    StringBuilder arg = new StringBuilder();
	    arg.append(BackupsDB.CMDPrefix+"mysql ");
	    arg.append("-u");
	    arg.append(root);
	    arg.append(" -p");
	    arg.append(rootPass);
	    arg.append(" --default-character-set=");
	    arg.append(CHARSET);
	    arg.append(" ");
	    arg.append(dbName);
	    arg.append(" <");
	    arg.append(backupsPath);
	    cmd[2] = arg.toString();
	    return cmd;
	}

注意点:1.CMDPrefix 命令前缀路径一定是你的mysqldump和mysql的路径

            2.此处命令执行的写法是有原因的(主要指我们使用 < 这个符号,在java中没有这个定向符,cmd中是有的,所有就算拼接好的命令使用java执行和使用cmd执行是不一样的),

            3.备份和恢复,都要设置相同的字符编码

转载于:https://my.oschina.net/u/2528990/blog/1601187

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值