Spring Boot 備份與還原 MySQL

Photo by Max Langelott on Unsplash
Photo by Max Langelott on Unsplash
後端工程師或 SRE (Site Reliability Engineer) 常常需要備份資料庫數據,以確保硬碟損壞時,還有數據還可以還原。除了手動備份資料外,如果可以寫排程 (Scheduler) 定時備份資料的話,不但省力,還不怕忘記備份。讓我們來看看,如何用 Spring Boot 備份和還原資料庫數據。

後端工程師或 SRE (Site Reliability Engineer) 常常需要備份資料庫數據,以確保硬碟損壞時,還有數據還可以還原。除了手動備份資料外,如果可以寫排程 (Scheduler) 定時備份資料的話,不但省力,還不怕忘記備份。讓我們來看看,如何用 Spring Boot 備份和還原資料庫數據。

備份 (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"

所以說,匯入數據其實就是執行 .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 來讓前端發起還原的工作吧。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

You May Also Like
Photo by Charles Jackson on Unsplash
Read More

Springdoc-OpenAPI 教學

Springdoc 是一個整合 OpenAPI Specification 和 Spring Boot 的套件。和 SpringFox 套件一樣,它產出 Swagger 文件。兩者不同在於,Springdoc 是用 Swagger 3,而 SpringFox 是用 Swagger 2。
Read More