1. 程式人生 > >Java備份mysql資料庫及錯誤總結

Java備份mysql資料庫及錯誤總結

今天給專案加了個數據庫自動備份功能,免得以後都要用工具手動備份挺麻煩的。沒用做過相關的,於是上網找下這種的一些解決方案,發現大都大同小異,都是使用Runtime.getRuntime().exec(command),引數傳入的是mysql的備份命令,用的是mysql自帶的mysqldump.exe執行命令,那麼就隨便粘了網上的現成做起來,雖然是照這做的,不過過程還是遇到一些問題,所以還是做了一些修改。

這是網上的現成備份程式碼,用的是定時器備份,這裡我只是放了主要的程式碼,關於定時器的使用請自行百度。

  1. package cn.edu.pzxx.scampus.utils;  
  2. import
     java.io.IOException;  
  3. import java.io.InputStream;  
  4. import java.text.SimpleDateFormat;  
  5. import java.util.Date;  
  6. import java.util.Properties;  
  7. import java.util.TimerTask;  
  8. publicclass MySqlExport extends TimerTask{  
  9.     @Override
  10.     publicvoid run() {  
  11.         //獲取當前系統時間
  12.         SimpleDateFormat df = new
     SimpleDateFormat("yyyy-MM-dd_HHmmss");  
  13.         String date=df.format(new Date());  
  14.         try {  
  15.             export(getProperties(),date);  
  16.         } catch (IOException e) {  
  17.             e.printStackTrace();  
  18.         }  
  19.     }  
  20.     publicstaticvoid export(Properties properties,String date) 
    throws IOException {    
  21.         Runtime runtime = Runtime.getRuntime();    
  22.         String command = getExportCommand(properties,date);    
  23.         runtime.exec(command);  
  24.     }    
  25.     privatestatic String getExportCommand(Properties properties,String date) {    
  26.         StringBuffer command = new StringBuffer();    
  27.         String username = properties.getProperty("jdbc.username");//使用者名稱  
  28.         String password = properties.getProperty("jdbc.password");//使用者密碼  
  29.         String exportDatabaseName = properties.getProperty("jdbc.exportDatabaseName");//需要匯出的資料庫名  
  30.         String host = properties.getProperty("jdbc.host");//從哪個主機匯出資料庫,如果沒有指定這個值,則預設取localhost  
  31.         String port = properties.getProperty("jdbc.port");//使用的埠號  
  32.         String exportPath = properties.getProperty("jdbc.exportPath")+date+"_"+properties.getProperty("jdbc.exportDatabaseName")+".sql";//匯出路徑  
  33.         //這裡如果想直接使用mysqldump的話需要在環境變數path下配mysql的bin目錄的路徑,不然的話就得用絕對路徑
  34.         command.append("mysqldump -u").append(username).append(" -p").append(password)//密碼是用的小p,而埠是用的大P。  
  35.         .append(" -h").append(host).append(" -P").append(port).append(" ").append(exportDatabaseName).append(" -r ").append(exportPath);    
  36.         return command.toString();    
  37.     }   
  38.     publicstatic Properties getProperties(){          
  39.         try {  
  40.             InputStream is = MySqlImportAndExport.class.getClassLoader().getResourceAsStream("jdbc.properties");    
  41.             Properties properties = new Properties();   
  42.             properties.load(is);  
  43.             return properties;  
  44.         } catch (IOException e) {  
  45.             e.printStackTrace();  
  46.             returnnull;  
  47.         }  
  48.     }  
  49. }  
資料庫源配置檔案:
  1. jdbc.username=root  
  2. jdbc.password=root  
  3. jdbc.host=localhost   
  4. jdbc.port=3306  
  5. jdbc.exportDatabaseName=test  
  6. jdbc.exportPath=D\:\\apache-tomcat-8.0.9-windows-x64\\apache-tomcat-8.0.9\\webapps\\pzxxsc\\exportdatabase\\  
  7. jdbc.importDatabaseName=test  
  8. #jdbc.importPath=D\:\\ex8136.sql    


這裡的程式碼本身是沒有什麼問題的,我在myeclipse下調式也是成功可以備份的。但是問題來了,如果通過手動去啟動tomcat,執行備份功能竟然會出現錯誤


這就奇怪了,同樣的程式碼為什麼在myeclipse就沒問題,手動去啟動tomcat就出問題了,難道跟程序間的呼叫有關係,只是猜測,,無奈之下我只能試試其他資料庫的備份命令,後面綜合了好幾個答案的命令才得出一個真正用的上的命令。修改下命令的拼接程式碼。

  1. command.append("cmd /c ").append(mysqldumpPath).append(" -u").append(username).append(" -p").append(password)//密碼是用的小p,而埠是用的大P。  
  2.         .append(" -h").append(host).append(" -P").append(port).append(" --opt ").append(exportDatabaseName).append(">").append(exportPath);    

但是事情還沒有完全結束。雖然可以備份出來檔案了,但是為什麼開啟檔案,裡面竟然是空白的。於是又的上網找答案,看到一前輩也遇到這問題,http://www.cnblogs.com/aDust/archive/2012/10/19/mysqldump.html,大概問題是mysqldump在我安裝的Program Files,帶有空格導致的,於是果斷將mysqldump移到其他地方去了,備份也成功了,這事也算告一段落。

貼出修改後的程式碼:

package cn.edu.pzxx.scampus.utils;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Properties;
import java.util.TimerTask;

public class MySqlExport extends TimerTask{

	@Override
	public void run() {
		//獲取當前系統時間
		SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd_HHmmss");
		String date=df.format(new Date());
		try {
			export(getProperties(),date);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

    public static void export(Properties properties,String date) throws IOException {  
        Runtime runtime = Runtime.getRuntime();  
        String command = getExportCommand(properties,date);  
        runtime.exec(command);
    }  
    
    private static String getExportCommand(Properties properties,String date) {  
        StringBuffer command = new StringBuffer();  
        String username = properties.getProperty("jdbc.username");//使用者名稱  
        String password = properties.getProperty("jdbc.password");//使用者密碼  
        String exportDatabaseName = properties.getProperty("jdbc.exportDatabaseName");//需要匯出的資料庫名  
        String host = properties.getProperty("jdbc.host");//從哪個主機匯出資料庫,如果沒有指定這個值,則預設取localhost  
        String port = properties.getProperty("jdbc.port");//使用的埠號  
        String exportPath = properties.getProperty("jdbc.exportPath")+date+"_"+properties.getProperty("jdbc.exportDatabaseName")+".sql";//匯出路徑  
        System.out.println(exportPath);
        /*try {
			exportPath=new String(exportPath.getBytes("ISO-8859-1"),"GBK");
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
        System.out.println(exportPath);*/
        String mysqldumpPath=properties.getProperty("jdbc.mysqldumpPath");
        //在tomcat啟動執行web應用需要用到這個 
        command.append("cmd /c ")
        //mysqldump的路徑,這裡最好用mysqldump的絕對路徑
        .append(mysqldumpPath)
        //密碼是用的小p,而埠是用的大P。  
        .append(" -u").append(username).append(" -p").append(password)
        //地址埠
        .append(" -h").append(host).append(" -P").append(port)
        /*
         * 這只是一個快捷選項,等同於同時新增 
         * --add-drop-table,--add-locks,--create-options,--quick,--extended-insert, 
         * --lock-tables,--set-charset,--disable-keys選項。 
         * 本選項能讓 mysqldump 很快的匯出資料,並且匯出的資料能很快導回。 
         * 該選項預設開啟,但可以用 --skip-opt 禁用。 
         */ 
        .append(" --opt ")
        //該選項在匯出大表時很有用,它強制 mysqldump 從伺服器查詢取得記錄直接輸出而不是取得所有記錄後將它們快取到記憶體中  
        .append("-q ")
        //  
        //sbu.append("--lock-all-tables=true ");  
        //  
        //sbu.append("--complete-insert=false ");  
        //每條記錄對應一個insert語句  
        .append("--extended-insert=false ")
        //定位檔案路徑
        .append("--result-file=")
        //匯出路徑
        .append(exportPath)  
        //編碼方式
        .append(" ").append("--default-character-set=utf8 ")
        //資料庫名
        .append(" ").append(exportDatabaseName);
        //匯出單個表使用
        //.append(" ").append("hr_teacher");
        System.out.println(command.toString());
        return command.toString();  
    } 
	
    public static Properties getProperties(){		 
        try {
        	InputStream is = MySqlImportAndExport.class.getClassLoader().getResourceAsStream("jdbc.properties");  
            Properties properties = new Properties(); 
			properties.load(is);
			return properties;
		} catch (IOException e) {
			e.printStackTrace();
			return null;
		}
	}
}

這裡感謝這兩位作者的文章給予了很大的幫助

  1. jdbc.username=root  
  2. jdbc.password=root  
  3. jdbc.host=localhost   
  4. jdbc.port=3306
  5. jdbc.exportDatabaseName=test  
  6. jdbc.exportPath=D\:\\apache-tomcat-8.0.9-windows-x64\\apache-tomcat-8.0.9\\webapps\\pzxxsc\\exportdatabase\\  
  7. jdbc.importDatabaseName=test  
  8. jdbc.mysqldumpPath=D\:\\apache-tomcat-8.0.9-windows-x64\\mysqldump  
  9. #jdbc.importPath=D\:\\ex8136.sql