Files
rxthinkcmf-wiki/RXThinkCMF_ThinkPhp6_NaiveVue/zh/deploy/backup.md
T
2026-09-29 10:14:04 +08:00

247 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 11.9 备份与恢复
:::danger 生产环境必须备份
数据库和上传文件必须定期备份,建议每天自动备份。备份文件应存储在独立于服务器的安全位置。
:::
## 数据库备份
### 手动备份
```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/
```
## 备份验证
:::warning 必须定期验证备份
备份文件必须定期恢复验证,确保备份可用。建议每月进行一次恢复测试。
:::
```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) | 高可靠、异地 | 需要付费 |
| 异地服务器 | 灾难恢复 | 需要维护 |
:::tip 最佳实践
- 本地保留最近 7 天的备份
- 异地保留最近 30 天的备份
- 每月进行一次恢复测试
- 备份文件加密存储(如含敏感数据)
:::