java程序使用cmd備份和恢復數據庫

項目中須要提供程序上去備份數據庫,基礎代碼來自網上,可是卻留了個坑,好不容易纔趟過去……java

直接上代碼:mysql

1、備份(2018/01/03 )sql

/** 
     * 備份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設置了編碼數據庫

2、恢復緩存

出現坑的地方--default-character-set=utf8設置了編碼,若是不加這一句,頗有可能出現通道關閉的錯誤提示,另外,流的關閉順序也要注意  app

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

代碼:ui

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;    
    }

 

3、補充(2018/01/08)編碼

    1.補充的緣由:備份的方式沒有問題,可是恢復的方式會有必定的問題,當備份出來的SQL文件很大時,在恢復時,因爲代碼是將SQL文件所有轉成流發送給cmd命令窗口,這樣會致使內存溢出。解決方式將SQL文件一部分一部分的寫,也就是使用緩存,可是因爲SQL執行的緣由,我的很擔憂會出現SQL執行問題(本人未測試),另一種方式是使用相似咱們在cmd下執行mysql的source + SQL文件路徑 這樣的命令,此處選擇第二種方式。spa

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.備份和恢復,都要設置相同的字符編碼

相關文章
相關標籤/搜索