Skip to content

11.9 备份与恢复 ​

生产环境必须备份

数据库和上传文件必须定期备份,建议每天自动备份。备份文件应存储在独立于服务器的安全位置。

数据库备份 ​

手动备份 ​

bash
# -----------------------------------------------------------------------------
# MySQL 全量备份(结构 + 数据)
# -----------------------------------------------------------------------------
# -u root          → 数据库用户名
# -proot         → 数据库密码(生产环境建议用 -p 后不跟密码,交互式输入)
# rxthinkcmf...    → 要备份的数据库名
# > backup_*.sql   → 输出到文件,$(date +%Y%m%d) 自动生成日期后缀
mysqldump -u root -proot rxthinkcmf.thinkphp6.elevue > backup_$(date +%Y%m%d).sql

# -----------------------------------------------------------------------------
# 压缩备份(推荐 — 可节省 70%+ 磁盘空间)
# -----------------------------------------------------------------------------
# | gzip → 将 mysqldump 输出通过管道传给 gzip 压缩
mysqldump -u root -proot rxthinkcmf.thinkphp6.elevue | gzip > backup_$(date +%Y%m%d).sql.gz

# -----------------------------------------------------------------------------
# 仅备份表结构(不含数据 — 用于对比表结构变更)
# -----------------------------------------------------------------------------
# --no-data → 只导出 CREATE TABLE 语句,不导出数据
mysqldump -u root -proot --no-data rxthinkcmf.thinkphp6.elevue > schema_$(date +%Y%m%d).sql

# -----------------------------------------------------------------------------
# 仅备份数据(不含表结构 — 用于数据迁移)
# -----------------------------------------------------------------------------
# --no-create-info → 只导出 INSERT 语句,不导出 CREATE TABLE
mysqldump -u root -proot --no-create-info rxthinkcmf.thinkphp6.elevue > data_$(date +%Y%m%d).sql

自动备份脚本 ​

bash
#!/bin/bash
# =============================================================================
# backup_db.sh — 数据库自动备份脚本
# =============================================================================
# 用途:自动备份 MySQL 数据库,压缩存储,自动清理过期备份
# 用法:crontab 定时调用,或手动执行 bash backup_db.sh
# =============================================================================

# -----------------------------------------------------------------------------
# 配置参数(按实际环境修改)
# -----------------------------------------------------------------------------
BACKUP_DIR="/backup/mysql"                              # 备份文件存放目录
DB_NAME="rxthinkcmf.thinkphp6.elevue"                   # 要备份的数据库名
DB_USER="root"                                          # 数据库用户名
DB_PASS="root"                                        # 数据库密码
DATE=$(date +%Y%m%d_%H%M%S)                            # 当前时间戳(年月日_时分秒)
KEEP_DAYS=30                                            # 保留最近 N 天的备份

# -----------------------------------------------------------------------------
# 创建备份目录(-p 参数:目录不存在时自动创建)
# -----------------------------------------------------------------------------
mkdir -p $BACKUP_DIR

# -----------------------------------------------------------------------------
# 执行备份(mysqldump 输出通过管道传给 gzip 压缩)
# -----------------------------------------------------------------------------
mysqldump -u $DB_USER -p$DB_PASS $DB_NAME | gzip > $BACKUP_DIR/backup_$DATE.sql.gz

# -----------------------------------------------------------------------------
# 检查备份结果($? 为上一条命令的退出码,0=成功)
# -----------------------------------------------------------------------------
if [ $? -eq 0 ]; then
    echo "[$(date)] 备份成功: backup_$DATE.sql.gz"
else
    echo "[$(date)] 备份失败!"
    exit 1      # 非零退出码表示失败,便于监控系统捕获
fi

# -----------------------------------------------------------------------------
# 清理过期备份
# -----------------------------------------------------------------------------
# find 参数说明:
#   -name "backup_*.sql.gz" → 匹配备份文件名格式
#   -mtime +$KEEP_DAYS      → 修改时间超过 N 天的文件
#   -delete                 → 删除匹配的文件
find $BACKUP_DIR -name "backup_*.sql.gz" -mtime +$KEEP_DAYS -delete

echo "[$(date)] 清理完成,保留最近 $KEEP_DAYS 天的备份"

配置定时备份 ​

bash
# 编辑当前用户的 crontab 定时任务
crontab -e

# -----------------------------------------------------------------------------
# 定时备份规则
# -----------------------------------------------------------------------------
# 格式:分 时 日 月 周 命令
# 0 3 * * *  → 每天凌晨 3:00 执行
# 0 4 * * 0  → 每周日凌晨 4:00 执行(0=周日)
# >> /var/log/backup.log 2>&1 → 追加日志(2>&1 将错误也写入日志)
# -----------------------------------------------------------------------------
0 3 * * * /www/scripts/backup_db.sh >> /var/log/backup.log 2>&1
0 4 * * 0 /www/scripts/backup_db_full.sh >> /var/log/backup.log 2>&1

上传文件备份 ​

bash
# -----------------------------------------------------------------------------
# 备份上传目录为压缩包
# -----------------------------------------------------------------------------
# tar 参数说明:
#   -c  → 创建新归档
#   -z  → 用 gzip 压缩
#   -f  → 指定输出文件名
#   $(date +%Y%m%d) → 自动生成日期后缀
tar -czf /backup/uploads_$(date +%Y%m%d).tar.gz /opt/data/uploads/

# -----------------------------------------------------------------------------
# 上传文件自动备份脚本
# -----------------------------------------------------------------------------
#!/bin/bash
BACKUP_DIR="/backup/uploads"                            # 备份存放目录
DATE=$(date +%Y%m%d)                                    # 日期后缀
mkdir -p $BACKUP_DIR                                    # 创建目录(如不存在)
tar -czf $BACKUP_DIR/uploads_$DATE.tar.gz /opt/data/uploads/  # 压缩打包
find $BACKUP_DIR -name "uploads_*.tar.gz" -mtime +30 -delete   # 清理 30 天前的备份

恢复 ​

恢复数据库 ​

bash
# -----------------------------------------------------------------------------
# 从 SQL 文件恢复(全量覆盖)
# -----------------------------------------------------------------------------
# < backup_*.sql → 将文件内容作为 mysql 命令的输入
mysql -u root -proot rxthinkcmf.thinkphp6.elevue < backup_20260920.sql

# -----------------------------------------------------------------------------
# 从压缩文件恢复(gunzip 解压后传给 mysql)
# -----------------------------------------------------------------------------
# gunzip < file.sql.gz → 解压并输出到标准输出
# | mysql → 通过管道传给 mysql 命令执行
gunzip < backup_20260920.sql.gz | mysql -u root -proot rxthinkcmf.thinkphp6.elevue

# -----------------------------------------------------------------------------
# 恢复到新数据库(安全起见 — 先验证再切换)
# -----------------------------------------------------------------------------
# 1. 创建临时验证数据库
mysql -u root -proot -e "CREATE DATABASE `rxthinkcmf.thinkphp6.elevue_restore`;"
# 2. 恢复备份到临时库
mysql -u root -proot rxthinkcmf.thinkphp6.elevue_restore < backup_20260920.sql
# 3. 验证数据无误后,重命名数据库(需停机操作)

恢复上传文件 ​

bash
# -----------------------------------------------------------------------------
# 恢复上传目录到原始位置
# -----------------------------------------------------------------------------
# tar 参数说明:
#   -x  → 解压归档
#   -z  → 解压 gzip
#   -f  → 指定归档文件
#   -C  → 解压到指定目录(/ 表示按归档内的绝对路径还原)
tar -xzf /backup/uploads_20260920.tar.gz -C /

# -----------------------------------------------------------------------------
# 仅恢复特定子目录(如只恢复文章附件)
# -----------------------------------------------------------------------------
# 在归档文件名后追加要解压的路径前缀
tar -xzf /backup/uploads_20260920.tar.gz -C / www/uploads/article/

备份验证 ​

必须定期验证备份

备份文件必须定期恢复验证,确保备份可用。建议每月进行一次恢复测试。

bash
#!/bin/bash
# =============================================================================
# verify_backup.sh — 备份验证脚本
# =============================================================================
# 用途:将备份恢复到临时数据库,验证数据完整性后清理
# 用法:bash verify_backup.sh backup_20260920.sql.gz
# =============================================================================

BACKUP_FILE=$1                                          # 第一个参数:备份文件路径
VERIFY_DB="rxthinkcmf.thinkphp6.elevue_verify"          # 临时验证数据库名

# -----------------------------------------------------------------------------
# 创建验证数据库(先删除旧的,再创建新的)
# -----------------------------------------------------------------------------
# DROP DATABASE IF EXISTS → 如果存在则删除(避免同名冲突)
mysql -u root -p -e "DROP DATABASE IF EXISTS $VERIFY_DB; CREATE DATABASE $VERIFY_DB;"

# -----------------------------------------------------------------------------
# 恢复备份到验证数据库
# -----------------------------------------------------------------------------
gunzip < $BACKUP_FILE | mysql -u root -p $VERIFY_DB

# -----------------------------------------------------------------------------
# 验证数据完整性
# -----------------------------------------------------------------------------
# -N → 不输出表头(只输出数据值)
# information_schema.tables → MySQL 系统表,存储所有表的元信息
TABLE_COUNT=$(mysql -u root -p -N -e "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema='$VERIFY_DB';")
echo "恢复的表数量: $TABLE_COUNT"

# 检查用户表数据量(验证核心数据是否完整)
USER_COUNT=$(mysql -u root -p -N -e "SELECT COUNT(*) FROM $VERIFY_DB.think_user;")
echo "用户数量: $USER_COUNT"

# -----------------------------------------------------------------------------
# 清理验证数据库(验证完毕后删除临时库)
# -----------------------------------------------------------------------------
mysql -u root -p -e "DROP DATABASE $VERIFY_DB;"

echo "备份验证完成"

备份存储建议 ​

存储方式优点缺点
本地磁盘速度快服务器故障可能丢失
NAS / 网络存储独立于服务器需要网络
云存储(OSS/S3)高可靠、异地需要付费
异地服务器灾难恢复需要维护

最佳实践

  • 本地保留最近 7 天的备份
  • 异地保留最近 30 天的备份
  • 每月进行一次恢复测试
  • 备份文件加密存储(如含敏感数据)

小蚂蚁云团队 · 提供技术支持