Apache Derby Bài 35: Sao lưu (Backup) và Phục hồi (Restore) cơ sở dữ liệu
1. Bản chất của việc Sao lưu (Backup) trong Derby
Trong bài trước, chúng ta đã học cách xuất dữ liệu ra file CSV. Tuy nhiên, CSV chỉ dùng để đọc và báo cáo. Khi ổ cứng máy chủ bị hỏng hoặc toàn bộ thư mục CSDL bị xóa nhầm, file CSV không thể giúp bạn khôi phục lại cấu trúc bảng, các ràng buộc (Constraint), View, Trigger, hay tài khoản người dùng.
Để phòng chống thảm họa, bạn cần Sao lưu (Backup). Sao lưu là quá trình chụp lại toàn bộ trạng thái vật lý của cơ sở dữ liệu (bao gồm cả dữ liệu và cấu trúc) tại một thời điểm.
Lưu ý sinh tử: Tuyệt đối KHÔNG sao chép (copy-paste) thư mục cơ sở dữ liệu của Derby (thư mục chứa seg0/) bằng trình quản lý file của hệ điều hành trong lúc ứng dụng Java hoặc máy chủ đang chạy. Việc sao chép khi Engine đang ghi dữ liệu vào đĩa sẽ tạo ra một bản copy bị hỏng (corrupted) và hoàn toàn vô dụng. Bạn bắt buộc phải dùng công cụ do Derby cung cấp.
2. Thực hiện Sao lưu trực tuyến (Online Backup)
Apache Derby hỗ trợ sao lưu trực tuyến (Online Backup), nghĩa là bạn có thể thực hiện backup ngay trong lúc hàng trăm người dùng khác đang truy vấn hoặc chèn dữ liệu mà không cần phải tắt hệ thống.
Để làm điều này, Derby sử dụng thủ tục hệ thống SYSCS_UTIL.SYSCS_BACKUP_DATABASE().
Cú pháp SQL gọi thủ tục:
SQL
CALL SYSCS_UTIL.SYSCS_BACKUP_DATABASE('DUONG_DAN_THU_MOC_SAO_LUU');
Ví dụ: Tạo một bản sao lưu toàn bộ cơ sở dữ liệu hiện tại và lưu vào thư mục D:/derby_backups/.
SQL
CALL SYSCS_UTIL.SYSCS_BACKUP_DATABASE('D:/derby_backups/');
Kết quả: Derby sẽ tự động tạo một thư mục con bên trong D:/derby_backups/ mang tên của cơ sở dữ liệu (ví dụ: my_company_db), chứa toàn bộ dữ liệu an toàn để cất trữ.
(Mẹo: Engine của Derby sẽ tự động đóng băng các giao dịch ghi trong vài mili-giây để chốt sổ trạng thái nhất quán, sau đó đẩy dữ liệu ra thư mục backup, rồi mới cho phép ghi tiếp).
3. Phục hồi cơ sở dữ liệu (Restore & Clone)
Việc phục hồi lại dữ liệu không được thực hiện bằng lệnh SQL. Lý do rất đơn giản: Khi cơ sở dữ liệu gốc đã bị hỏng, bạn thậm chí không thể mở kết nối để gõ lệnh SQL.
Thay vào đó, quá trình phục hồi được thực hiện ngay tại thời điểm khởi tạo kết nối (JDBC Connection URL) bằng cách sử dụng các thuộc tính đặc biệt. Có hai kịch bản phục hồi chính:
Kịch bản 1: Phục hồi đè lên CSDL cũ (restoreFrom)
Dùng khi CSDL gốc bị lỗi và bạn muốn thay thế hoàn toàn nó bằng bản backup. Hành động này sẽ xóa sạch CSDL hiện tại (nếu còn tồn tại) và copy dữ liệu từ bản backup sang.
Chuỗi kết nối JDBC:
Plaintext
jdbc:derby:my_company_db;restoreFrom=D:/derby_backups/my_company_db
Kịch bản 2: Phục chế thành một CSDL mới hoàn toàn (createFrom)
Dùng khi bạn muốn nhân bản (Clone) hệ thống Production về máy tính cá nhân để test mà không làm ảnh hưởng đến dữ liệu gốc. CSDL mới sẽ có tên khác nhưng chứa 100% dữ liệu của bản backup.
Chuỗi kết nối JDBC:
Plaintext
jdbc:derby:my_test_db;createFrom=D:/derby_backups/my_company_db
4. Thực hành: Xây dựng công cụ Backup định kỳ bằng Java
Trong các hệ thống thực tế, quản trị viên thường viết một đoạn mã Java để tự động kích hoạt quá trình backup vào lúc 2 giờ sáng mỗi ngày.
Java
package com.hieu.derby.admin;
import java.io.File;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DerbyBackupManager {
// Kết nối vào Network Server đang chạy
private static final String JDBC_URL = "jdbc:derby://localhost:1527/my_company_db";
public static void main(String[] args) {
// Tạo thư mục backup theo ngày tháng để không ghi đè lẫn nhau
String dateStr = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String backupDir = "/var/backups/derby_db_" + dateStr;
// Đảm bảo thư mục cha tồn tại
new File(backupDir).mkdirs();
System.out.println("Bắt đầu tiến trình sao lưu trực tuyến (Online Backup)...");
try (Connection conn = DriverManager.getConnection(JDBC_URL)) {
// Gọi thủ tục hệ thống
String backupSql = "CALL SYSCS_UTIL.SYSCS_BACKUP_DATABASE(?)";
try (CallableStatement cstmt = conn.prepareCall(backupSql)) {
// Truyền đường dẫn thư mục sao lưu
cstmt.setString(1, backupDir);
cstmt.execute(); // Luồng sẽ tạm dừng cho đến khi quá trình copy hoàn tất
System.out.println("=> Sao lưu thành công! Dữ liệu được an toàn tại: " + backupDir);
}
} catch (SQLException e) {
System.err.println("=> Lỗi nghiêm trọng khi sao lưu CSDL: " + e.getMessage());
}
}
}
Cách phục hồi lại bằng Java (Khi hệ thống sập):
Java
// Sửa chuỗi URL khởi động để trỏ tới bản backup mới nhất
String restoreUrl = "jdbc:derby:my_company_db;restoreFrom=/var/backups/derby_db_20261010_020000/my_company_db";
Connection conn = DriverManager.getConnection(restoreUrl);
System.out.println("Đã phục hồi cơ sở dữ liệu thành công!");
5. Tổng kết
-
Không bao giờ copy thủ công thư mục cơ sở dữ liệu khi hệ thống đang vận hành.
-
Dùng lệnh SQL
CALL SYSCS_UTIL.SYSCS_BACKUP_DATABASE('path')để tiến hành Online Backup an toàn. -
Quá trình Restore được kích hoạt tự động bởi Engine thông qua thuộc tính URL
restoreFrom=...hoặccreateFrom=...khi kết nối. -
Hãy đưa tác vụ Backup vào lịch trình tự động (Scheduled Cron Job) trên máy chủ để đảm bảo dữ liệu luôn có phương án dự phòng.
Đến đây, dữ liệu của bạn đã được bảo vệ trước các thảm họa phần cứng. Tuy nhiên, nếu một kẻ gian đánh cắp ổ cứng máy chủ hoặc copy được thư mục backup, toàn bộ thông tin nhạy cảm vẫn sẽ bị lộ. Bài tiếp theo sẽ giải quyết vấn đề bảo mật mức vật lý này: Apache Derby Bài 36: Mã hóa cơ sở dữ liệu ở cấp độ đĩa (Disk-Level Encryption).
All Rights Reserved