Bối cảnh & Lý do: Giới hạn của Logical Dump trên môi trường Production
Thời gian đầu khi mới làm nghề, tôi từng nghĩ chỉ cần chạy một cron job mysqldump đơn giản là đã đủ. Nhưng quan điểm đó thay đổi hoàn toàn khi database production chính của chúng tôi vượt mốc 150 GB. Tác vụ dump dữ liệu hàng đêm gây ra hiện tượng query spike nghiêm trọng, làm tràn và loãng InnoDB buffer pool, đồng thời khóa các bảng ngay trong các đợt xử lý batch cao điểm. Tệ hơn nữa, việc khôi phục một file dump duy nhất đó trong đợt diễn tập khắc phục sự cố (disaster recovery) đã mất hơn sáu tiếng đồng hồ.
Với các hệ thống MySQL có lưu lượng truy cập lớn (high-throughput), logical dump đơn giản là không thể đáp ứng được khả năng mở rộng. Logical backup phải tái tạo lại toàn bộ tập dữ liệu theo từng dòng thông qua hàng triệu câu lệnh SQL INSERT. Ngược lại, physical backup hoạt động trực tiếp ở tầng lưu trữ, sao chép các data file thô, tablespace và index ở cấp độ block.
Percona XtraBackup giải quyết bài toán downtime bằng cách thực hiện hot backup hoàn toàn không gây nghẽn (non-blocking). Trong khi database vẫn đang xử lý hàng nghìn query mỗi giây, XtraBackup sao chép các data page của InnoDB và đồng thời theo dõi (tail) các thay đổi phát sinh từ redo log theo thời gian thực. Điều này đảm bảo một snapshot crash-consistent tại một thời điểm xác định mà không cần khóa bảng hay làm suy giảm hiệu năng của người dùng.
Cài đặt và cấu hình Repository
Đối với hệ thống MySQL 8.0, hãy cài đặt Percona XtraBackup 8.0. Lưu ý rằng các phiên bản major phải tương thích với nhau: XtraBackup 8.0 không thể backup cho MySQL 5.7, và XtraBackup 2.4 không thể backup cho MySQL 8.0.
1. Cài đặt Percona Repository
Trên hệ thống Debian và Ubuntu, hãy đăng ký gói release chính thức của Percona:
# Tải về và đăng ký repository của Percona
wget https://repo.percona.com/apt/percona-release_latest.generic_all.deb
sudo dpkg -i percona-release_latest.generic_all.deb
# Bật repository tools cho XtraBackup 8.0
sudo percona-release enable-only tools release
sudo apt-get update
# Cài đặt package
sudo apt-get install -y percona-xtrabackup-80
Trên hệ thống RHEL, Rocky Linux hoặc AlmaLinux:
sudo yum install -y https://repo.percona.com/yum/percona-release-latest.noarch.rpm
sudo percona-release enable-only tools release
sudo yum install -y percona-xtrabackup-80
2. Tạo User chuyên dụng để Backup Database
Tuyệt đối không nên chạy tác vụ backup tự động bằng tài khoản superuser root của MySQL. Thay vào đó, hãy tạo một tài khoản riêng với quyền tối thiểu cần thiết để đọc các data page, kiểm tra trạng thái replication và flush log:
sudo mysql -u root -p
CREATE USER 'xtrabackup'@'localhost' IDENTIFIED BY 'StrongBackupPass123!';
GRANT BACKUP_ADMIN, PROCESS, RELOAD, LOCK TABLES, REPLICATION CLIENT
ON *.* TO 'xtrabackup'@'localhost';
FLUSH PRIVILEGES;
EXIT;
Cấu hình: Xây dựng Pipeline cho Full và Incremental Backup
Một chiến lược backup vững chắc thường kết hợp giữa bản base backup hàng tuần và các bản incremental backup hàng ngày. Incremental backup chỉ sao chép các data page đã bị thay đổi kể từ lần backup gần nhất. Với một database dung lượng 200 GB nhưng chỉ thay đổi khoảng 5 GB mỗi ngày, phương pháp này giúp rút ngắn thời gian chạy backup từ 40 phút xuống còn dưới 3 phút.
1. Thiết lập thư mục lưu trữ
Nên đặt thư mục backup trên một ổ đĩa riêng biệt hoặc network mount point để tránh làm cạn kiệt dung lượng ổ đĩa hệ điều hành:
sudo mkdir -p /var/backups/mysql/{full,inc}
sudo chown -R mysql:mysql /var/backups/mysql
sudo chmod -R 700 /var/backups/mysql
2. Chạy Full Backup thủ công
Thực hiện bản full backup đầu tiên để kiểm tra phân quyền và đánh giá hiệu năng cơ bản:
xtrabackup --backup \
--user=xtrabackup \
--password='StrongBackupPass123!' \
--target-dir=/var/backups/mysql/full/base_$(date +%F)
Khi lệnh hoàn tất, hãy kiểm tra dòng cuối cùng của output xem có thông báo completed OK! hay không. Thư mục đích sẽ chứa các file dữ liệu thô cùng một file metadata có tên xtrabackup_checkpoints, dùng để lưu trữ các checkpoint Log Sequence Number (LSN).
3. Chạy Incremental Backup
Incremental backup sẽ so sánh thư mục đích với bản base backup, chỉ sao chép các page có giá trị LSN lớn hơn checkpoint trước đó:
xtrabackup --backup \
--user=xtrabackup \
--password='StrongBackupPass123!' \
--target-dir=/var/backups/mysql/inc/inc_$(date +%F) \
--incremental-basedir=/var/backups/mysql/full/base_2026-10-01
4. Script tự động hóa cho Production
Môi trường production luôn cần sự tự động hóa tin cậy. Script Bash dưới đây sẽ thực hiện full backup vào mỗi Chủ Nhật và incremental backup từ Thứ Hai đến Thứ Bảy. Script cũng tự động cập nhật các symlink thư mục và dọn dẹp các bản backup cũ hơn 14 ngày.
Lưu script này vào đường dẫn /usr/local/bin/mysql-backup.sh:
#!/usr/bin/env bash
set -euo pipefail
BACKUP_ROOT="/var/backups/mysql"
FULL_DIR="${BACKUP_ROOT}/full"
INC_DIR="${BACKUP_ROOT}/inc"
USER="xtrabackup"
PASS="StrongBackupPass123!"
TODAY=$(date +%Y-%m-%d)
DAY_OF_WEEK=$(date +%u) # 7 = Chủ Nhật
mkdir -p "${FULL_DIR}" "${INC_DIR}"
if [ "$DAY_OF_WEEK" -eq 7 ] || [ ! -d "${FULL_DIR}/latest" ]; then
echo "[$(date)] Bắt đầu Full Backup..."
TARGET="${FULL_DIR}/full_${TODAY}"
xtrabackup --backup \
--user="${USER}" \
--password="${PASS}" \
--target-dir="${TARGET}"
ln -sfn "${TARGET}" "${FULL_DIR}/latest"
rm -rf "${INC_DIR}"/*
echo "[$(date)] Full Backup hoàn tất: ${TARGET}"
else
echo "[$(date)] Bắt đầu Incremental Backup..."
LAST_INC=$(find "${INC_DIR}" -maxdepth 1 -mindepth 1 -type d | sort | tail -n 1)
if [ -z "${LAST_INC}" ]; then
BASE_DIR="${FULL_DIR}/latest"
else
BASE_DIR="${LAST_INC}"
fi
TARGET="${INC_DIR}/inc_${TODAY}"
xtrabackup --backup \
--user="${USER}" \
--password="${PASS}" \
--target-dir="${TARGET}" \
--incremental-basedir="${BASE_DIR}"
echo "[$(date)] Incremental Backup hoàn tất dựa trên base ${BASE_DIR}: ${TARGET}"
fi
# Xóa các bản full backup cũ hơn 14 ngày
find "${FULL_DIR}" -maxdepth 1 -mindepth 1 -type d -mtime +14 -exec rm -rf {} +
Phân quyền thực thi và thêm tác vụ vào crontab:
sudo chmod +x /usr/local/bin/mysql-backup.sh
# Lập lịch chạy hàng đêm vào lúc 02:00 AM
(crontab -l 2>/dev/null; echo "0 2 * * * /usr/local/bin/mysql-backup.sh >> /var/log/mysql-backup.log 2>&1") | crontab -
Kiểm tra & Khôi phục: Thử nghiệm Restore trước khi sự cố xảy ra
Một bản backup chưa từng được thử nghiệm thì không thể coi là bản backup—đó chỉ là sự hy vọng suông. Do physical backup ghi lại các data page trực tiếp ngay khi các transaction vẫn đang diễn ra, dữ liệu sẽ chứa cả những thay đổi chưa được commit. Bạn bắt buộc phải thực hiện prepare bản backup trước khi MySQL có thể sử dụng dữ liệu một cách an toàn.
1. Chuẩn bị (Prepare) chuỗi Backup
Để khôi phục một bản base backup cùng các thay đổi incremental, bạn cần roll-forward các transaction đã commit từ từng thư mục incremental vào thư mục base. Sử dụng cờ --apply-log-only cho tất cả các bước trung gian để giữ cho bản base backup ở trạng thái mở, sẵn sàng nhận các bản diff tiếp theo:
# Bước 1: Prepare bản full base backup (giữ log mở cho các bản incremental)
xtrabackup --prepare \
--apply-log-only \
--target-dir=/var/backups/mysql/full/full_2026-10-01
# Bước 2: Apply bản incremental backup vào thư mục base
xtrabackup --prepare \
--apply-log-only \
--target-dir=/var/backups/mysql/full/full_2026-10-01 \
--incremental-dir=/var/backups/mysql/inc/inc_2026-10-02
# Bước 3: Prepare lần cuối trên thư mục base (rollback các transaction chưa commit)
xtrabackup --prepare \
--target-dir=/var/backups/mysql/full/full_2026-10-01
2. Khôi phục dữ liệu về thư mục Data của MySQL
Khi bản base backup đã được prepare hoàn tất, hãy sao chép các data file thô trở lại thư mục MySQL:
# Dừng service database
sudo systemctl stop mysql
# Backup thư mục data hiện tại và tạo thư mục đích rỗng
sudo mv /var/lib/mysql /var/lib/mysql.bak_$(date +%F)
sudo mkdir -p /var/lib/mysql
# Khôi phục các data file đã được prepare
xtrabackup --copy-back \
--target-dir=/var/backups/mysql/full/full_2026-10-01
# Phân quyền lại quyền sở hữu và quyền truy cập file
sudo chown -R mysql:mysql /var/lib/mysql
sudo chmod 750 /var/lib/mysql
# Khởi động service MySQL và kiểm tra trạng thái
sudo systemctl start mysql
sudo systemctl status mysql
3. Giám sát và Health Check
Hãy tích hợp bốn bước kiểm tra vận hành sau vào hệ thống giám sát của bạn (Prometheus node-exporter, Datadog hoặc Zabbix):
- Exit Code của tiến trình: Cảnh báo ngay lập tức nếu lệnh
xtrabackuptrả về exit code khác0. - Kiểm tra log string: Phân tích file
/var/log/mysql-backup.logđể đảm bảo luôn xuất hiện chuỗi xác nhậncompleted OK!. - Kiểm tra tính liên tục của LSN: Đọc file
xtrabackup_checkpointsđể đối soát rằngfrom_lsncủa mỗi lần chạy incremental khớp chính xác vớito_lsncủa bản backup liền trước. - Tự động restore trên môi trường Sandbox: Thiết lập CI/CD runner hàng tuần để khôi phục chuỗi backup mới nhất lên một instance staging độc lập và chạy các query kiểm thử tính toàn vẹn trên các bảng quan trọng.

