MỤC TIÊU:
- Backup Database của MySQL, lưu backup giữ lại bao nhiêu ngày gần nhất
- File .env chứa các thông tin Username, password, database cần backup, số ngày cần lưu, lưu trữ ở đâu
- Code chính backup bằng Power Shell
- Tạo file .bat gọi file Power Shell (.ps1) để thực backup
- Lập lịch backup theo thời gian
- Backup có ghi lại log đâ làm những gì
Cấu trúc thư mục:
- Souce Code:
C:\vck\TestMySQL\
├── bkDB\
├── .env
├── bkMySQL.ps1
└── bkMySQL.bat
- Cấu trúc thư mục backup tạo ra:
C:\vck\TestMySQL\bkDB\
├── vck_test_1\
│ ├── users.sql
│ ├── orders.sql
│ └── backup_log_2026-06-20_103000.log <-- Log riêng của vck_test
├── tonyteo_v2_1\
│ ├── products.sql
│ ├── customers.sql
│ └── backup_log_2026-06-20_103115.log <-- Log riêng của tony teo
└── company_db_1\
├── employees.sql
└── backup_log_2026-06-20_103240.log <-- Log riêng của company_db
THỰC HIỆN:
1. Nội dung file .env
#DB_NAME=vck_test,tonyteo_v2 # nhiều Database, đặt cách nhau dấu phẩy
DB_NAME=vck_test
DB_USER=root
DB_PASS=pk123456
DB_PORT=3308
DB_HOST=127.0.0.1
# Muốn lưu bao nhiêu ngày, giữ lại bao nhiêu ngày gần nhất
MAX_DAYS=4
MYSQL_BIN=C:\Program Files\MariaDB 12.3\bin\mysql.exe
MYSQLDUMP_BIN=C:\Program Files\MariaDB 12.3\bin\mysqldump.exe
# File backup lưu ở đâu
BASE_BACKUP_DIR=C:\vck\TestMySQL\bkDB
2. Nội dung file bkMySQL.ps1
# ==========================================
# ĐỌC VÀ LÀM SẠCH CẤU HÌNH TỪ FILE .ENV
# ==========================================
$envFile = Join-Path $PSScriptRoot ".env"
if (-not (Test-Path $envFile)) {
Write-Error "KHÔNG TÌM THẤY file .env nằm cùng thư mục với script!"
exit 1
}
Get-Content $envFile | ForEach-Object {
$line = $_.Trim()
if ($line -and -not $line.StartsWith('#') -and $line.Contains('=')) {
$index = $line.IndexOf('=')
$key = $line.Substring(0, $index).Trim()
$value = $line.Substring($index + 1).Trim().Trim('"').Trim("'")
Set-Variable -Name $key -Value $value -Force
}
}
# Tách chuỗi DB_NAME trong .env thành một mảng các Database
$dbList = $DB_NAME -split ',' | ForEach-Object { $_.Trim() }
# Kiểm tra đường dẫn công cụ trước khi vào vòng lặp
if (-not (Test-Path $MYSQL_BIN)) {
Write-Error "KHÔNG TÌM THẤY file mysql.exe tại: $MYSQL_BIN"
exit 1
}
# ==========================================
# VÒNG LẶP DUYỆT QUA TỪNG DATABASE
# ==========================================
foreach ($currentDB in $dbList) {
if ([string]::IsNullOrWhiteSpace($currentDB)) { continue }
# Đã sửa lỗi chính tả từ Magentas -> Magenta để giao diện chạy mượt mà
Write-Host "--------------------------------------------------" -ForegroundColor Magenta
Write-Host "XỬ LÝ DATABASE: $currentDB" -ForegroundColor Magenta
Write-Host "--------------------------------------------------" -ForegroundColor Magenta
# 1. Tính toán cấu trúc xoay vòng (Retention) cho từng DB
$currentDayOfMonth = (Get-Date).Day
$xx = ($currentDayOfMonth % [int]$MAX_DAYS) + 1
$FOLDER_NAME = "${currentDB}_$xx"
$BACKUP_DIR = Join-Path $BASE_BACKUP_DIR $FOLDER_NAME
# 2. Xử lý dọn dẹp / tạo mới thư mục của DB hiện tại
if (Test-Path $BACKUP_DIR) {
Write-Host "Thu muc $FOLDER_NAME da ton tai. Dang xoa file cu de lam rong..." -ForegroundColor Yellow
Remove-Item -Path "$BACKUP_DIR\*" -Recurse -Force -ErrorAction SilentlyContinue
} else {
Write-Host "Dang tao thu muc backup moi: $FOLDER_NAME" -ForegroundColor Cyan
New-Item -ItemType Directory -Path $BACKUP_DIR | Out-Null
}
# 3. Định nghĩa file log nằm trong thư mục backup riêng của DB đó
$TIMESTAMP = Get-Date -Format "yyyy-MM-dd_HHmmss"
$PROCESS_LOG = Join-Path $BACKUP_DIR "backup_log_$TIMESTAMP.log"
$ERROR_LOG_FILE = Join-Path $PSScriptRoot "table.log"
# Hàm ghi log cục bộ (Inline function)
function Log-CurrentMessage ($msg) {
$timeStr = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
"[$timeStr] $msg" | Out-File -FilePath $PROCESS_LOG -Append -Encoding utf8
}
Log-CurrentMessage "=== BAT DAU TIEN TRINH BACKUP DATABASE: $currentDB ==="
Log-CurrentMessage "Thu muc luu tru: $BACKUP_DIR"
# 4. Kiểm tra kết nối tới Database hiện tại (Health Check)
# Thêm Out-Null để không bị in đè số 1 1 thừa thãi ra màn hình console của bạn
& $MYSQL_BIN -h $DB_HOST -u $DB_USER "-p$DB_PASS" -P $DB_PORT -e "USE $currentDB; SELECT 1;" 2>$null | Out-Null
if ($LASTEXITCODE -ne 0) {
$errorMsg = "ERROR: Khong the ket noi MySQL hoac Database '$currentDB' khong ton tai."
Set-Content -Path $ERROR_LOG_FILE -Value $errorMsg
Log-CurrentMessage "ERROR: Ket noi den '$currentDB' that bai. Bo qua DB nay."
Write-Warning "Ket noi that bai toi database '$currentDB'. Chi tiet ghi tai table.log. Dang chuyen sang DB tiep theo..."
continue
}
Log-CurrentMessage "Ket noi database thanh cong. Dang lay danh sach cac bang..."
# 5. Lấy danh sách bảng của DB hiện tại
$tables = & $MYSQL_BIN -h $DB_HOST -u $DB_USER "-p$DB_PASS" -P $DB_PORT -N -e "SHOW TABLES FROM $currentDB;"
# 6. Vòng lặp Backup từng bảng dữ liệu
$successCount = 0
foreach ($table in $tables) {
if (-not [string]::IsNullOrWhiteSpace($table)) {
$outputFile = Join-Path $BACKUP_DIR "$table.sql"
& $MYSQLDUMP_BIN -h $DB_HOST -u $DB_USER "-p$DB_PASS" -P $DB_PORT $currentDB $table --result-file=$outputFile
if ($LASTEXITCODE -eq 0) {
Log-CurrentMessage "Backup thanh cong table: $table -> $table.sql"
$successCount++
} else {
Log-CurrentMessage "ERROR: Backup THAT BAI table: $table"
}
}
}
Log-CurrentMessage "=== KET THUC TIEN TRINH: Da backup thanh cong $successCount tables cua DB $currentDB ==="
Write-Host "Finished export database [$currentDB] to folder: $BACKUP_DIR" -ForegroundColor Green
}
Write-Host "`n================================================--" -ForegroundColor Green
Write-Host "HOÀN THÀNH TẤT CẢ TIẾN TRÌNH BACKUP DỮ LIỆU!" -ForegroundColor Green
3. Nội dung file bkMySQL.bat
@echo off
:: Di chuyển terminal về đúng thư mục chứa file .bat này
cd /d "%~dp0"
:: Gọi PowerShell chạy script với quyền Bypass/RemoteSigned tạm thời
powershell -NoProfile -ExecutionPolicy Bypass -File "bkMySQL.ps1"
exit /b %errorlevel%
4. Lập lịch Task Sheduler
(này đơn giản nên không hướng dẫn)





