後端工程師或 SRE (Site Reliability Engineer) 常常需要備份資料庫數據,以確保硬碟損壞時,還有數據還可以還原。除了手動備份資料外,如果可以寫排程 (Scheduler) 定時備份資料的話,不但省力,還不怕忘記備份。讓我們來看看,如何用 Spring Boot 備份和還原資料庫數據。
Table of Contents
備份 (Backup)
資料庫的備份,主要是利用 mysqldump 指令來實現。mysqldump 會將資料庫數據匯出成 .sql 格式的檔案。它有很多的參數,下面是最基本的使用方式:
% mysqldump -uroot -p123456 --add-drop-table --database Example -r example.sql
- -uroot:root 是 MySQL 的登入帳號。和 -u 之間沒有空格。
- -p123456:123456 是 MySQL 的登入密碼。和 -p 之間沒有空格。
- –add-drop-table:在匯出的 .sql 檔中,加入
DROP TABLE,這樣方便匯入。 - –database:Example 是要匯出的資料庫名稱。
- -r example.sql:example.sql 是匯出的目標檔案。
可以先在命令列上,測試指令是否正確。確定指令正確無誤後,我們就可以開始用 Spring Boot 來執行指令。
新增 DatabaseUtil,在裡面我們實作 backup() 方法。它主要是利用 Runtime.getRuntime().exec() 來執行命令列指令。
public final class DatabaseUtil {
public static boolean backup(String dbUsername, String dbPassword, String dbName, String outputFile)
throws IOException, InterruptedException {
String command = String.format("mysqldump -u%s -p%s --add-drop-table --databases %s -r %s",
dbUsername, dbPassword, dbName, outputFile);
Process process = Runtime.getRuntime().exec(command);
int processComplete = process.waitFor();
return processComplete == 0;
}
}然後,我們可以實作 RestController 來讓前端發起被備份工作,或是實作 Scheduler 排成來定時發起備份工作。
還原 (Restore)
和備份一樣,還原也是用指令實現。用 mysql 指令就可以還原,使用方式如下:
% mysql -uroot -p123456 -e "source example.sql"
- -e command, –execute=command:這個 option 是指執行後面的 SQL statement。
- source example.sql:這個 SQL statement 是指執行 example.sql 裡面的 SQL statements。
所以說,匯入數據其實就是執行 .sql 檔裡面的所有 SQL statement。這也是因為我們在匯出時,要加上 --add-drop-table 的原因。不然,在執行 .sql 檔時,裡面會有 CREATE TABLE,因為 table 已經存在,所以這個 CREATE TABLE statement 會失敗。再不然,就是在執行前,先手動刪除 table。當然,最方便的方式還是加上 --add-drop-table。
在 DatabaseUtil 裡,加上 restore() 方法。也是用 Runtime.getRuntime().exec() 來執行指令。不過,因為 source example.sql 是一個參數,不能將指令串好成一個字串去執行。要改用將指令分成陣列的方式去執行才行。
public final class DatabaseUtil {
public static boolean restore(String dbUsername, String dbPassword, String dbName, String sourceFile)
throws IOException, InterruptedException {
String[] command = new String[]{
"mysql",
"-u" + dbUsername,
"-p" + dbPassword,
"-e",
" source " + sourceFile,
dbName
};
Process runtimeProcess = Runtime.getRuntime().exec(command);
int processComplete = runtimeProcess.waitFor();
return processComplete == 0;
}
}最後,實作 RestController 來讓前端發起還原的工作吧。









