2026年3月7日

数据库备份策略 - 数据安全守护指南

数据是企业和个人最重要的资产之一,合理的备份策略是数据安全的重要保障。本文介绍数据库备份的方法和策略。

备份的重要性

为什么需要备份

  • 硬件故障
  • 人为误操作
  • 恶意攻击
  • 自然灾害
  • 软件故障

备份原则

  1. 3-2-1 原则:3 份备份,2 种介质,1 份异地
  2. 定期测试:定期验证备份可恢复
  3. 自动化:减少人为失误
  4. 加密存储:保护敏感数据

MySQL 备份

mysqldump 备份

全量备份

# 备份单个数据库
mysqldump -u root -p database_name > backup.sql

# 备份多个数据库
mysqldump -u root -p --databases db1 db2 > backup.sql

# 备份所有数据库
mysqldump -u root -p --all-databases > all_backup.sql

# 备份指定表
mysqldump -u root -p database_name table1 table2 > tables.sql

备份选项

# 完整备份选项
mysqldump -u root -p \
  --single-transaction \
  --routines \
  --triggers \
  --events \
  --hex-blob \
  --master-data=2 \
  --flush-logs \
  database_name > backup.sql

压缩备份

# 直接压缩
mysqldump -u root -p database_name | gzip > backup.sql.gz

# 解压恢复
gunzip < backup.sql.gz | mysql -u root -p database_name

自动备份脚本

#!/bin/bash

# 配置
DB_USER="root"
DB_PASS="password"
BACKUP_DIR="/backup/mysql"
DATE=$(date +%Y%m%d_%H%M%S)
KEEP_DAYS=7

# 创建备份目录
mkdir -p $BACKUP_DIR

# 备份所有数据库
mysqldump -u$DB_USER -p$DB_PASS --all-databases --single-transaction | gzip > $BACKUP_DIR/all_$DATE.sql.gz

# 删除旧备份
find $BACKUP_DIR -name "*.sql.gz" -mtime +$KEEP_DAYS -delete

# 记录日志
echo "$(date) - Backup completed" >> $BACKUP_DIR/backup.log

定时任务

# 编辑 crontab
crontab -e

# 每天凌晨 2 点备份
0 2 * * * /path/to/backup.sh

物理备份

使用 Percona XtraBackup

# 安装
apt install percona-xtrabackup-80

# 全量备份
xtrabackup --backup --target-dir=/backup/full

# 准备备份
xtrabackup --prepare --target-dir=/backup/full

# 恢复
xtrabackup --copy-back --target-dir=/backup/full

增量备份

# 全量备份
xtrabackup --backup --target-dir=/backup/base

# 第一次增量
xtrabackup --backup --target-dir=/backup/inc1 --incremental-basedir=/backup/base

# 第二次增量
xtrabackup --backup --target-dir=/backup/inc2 --incremental-basedir=/backup/inc1

# 恢复
xtrabackup --prepare --apply-log-only --target-dir=/backup/base
xtrabackup --prepare --apply-log-only --target-dir=/backup/base --incremental-dir=/backup/inc1
xtrabackup --prepare --target-dir=/backup/base --incremental-dir=/backup/inc2
xtrabackup --copy-back --target-dir=/backup/base

PostgreSQL 备份

pg_dump 备份

# 备份单个数据库
pg_dump -U postgres database_name > backup.sql

# 备份为自定义格式
pg_dump -U postgres -Fc database_name > backup.dump

# 备份所有数据库
pg_dumpall -U postgres > all_backup.sql

# 只备份结构
pg_dump -U postgres --schema-only database_name > schema.sql

# 只备份数据
pg_dump -U postgres --data-only database_name > data.sql

恢复数据

# 恢复 SQL 文件
psql -U postgres database_name < backup.sql

# 恢复自定义格式
pg_restore -U postgres -d database_name backup.dump

物理备份

使用 pg_basebackup

# 全量物理备份
pg_basebackup -U postgres -D /backup/base -Ft -z -P

# 恢复
# 1. 停止 PostgreSQL
# 2. 清空数据目录
# 3. 解压备份文件到数据目录
# 4. 启动 PostgreSQL

WAL 归档

# postgresql.conf
wal_level = replica
archive_mode = on
archive_command = 'cp %p /backup/wal/%f'

MongoDB 备份

mongodump 备份

# 备份所有数据库
mongodump --out /backup/mongodb/$(date +%Y%m%d)

# 备份指定数据库
mongodump --db database_name --out /backup/mongodb/

# 备份指定集合
mongodump --db database_name --collection collection_name --out /backup/

# 远程备份
mongodump --host mongodb.example.com --port 27017 --username user --password --out /backup/

mongorestore 恢复

# 恢复所有数据库
mongorestore /backup/mongodb/20240101

# 恢复指定数据库
mongorestore --db database_name /backup/mongodb/database_name

# 恢复指定集合
mongorestore --db database_name --collection collection_name /backup/dump/collection.bson

Redis 备份

RDB 备份

# 触发备份
redis-cli BGSAVE

# 备份文件位置
# 默认: /var/lib/redis/dump.rdb

# 复制备份文件
cp /var/lib/redis/dump.rdb /backup/redis/$(date +%Y%m%d).rdb

AOF 备份

# redis.conf
appendonly yes
appendfilename "appendonly.aof"

# 触发重写
redis-cli BGREWRITEAOF

自动备份脚本

#!/bin/bash

BACKUP_DIR="/backup/redis"
DATE=$(date +%Y%m%d)
KEEP_DAYS=7

mkdir -p $BACKUP_DIR

# 触发 RDB 备份
redis-cli BGSAVE

# 等待备份完成
sleep 5

# 复制备份文件
cp /var/lib/redis/dump.rdb $BACKUP_DIR/dump_$DATE.rdb

# 删除旧备份
find $BACKUP_DIR -name "*.rdb" -mtime +$KEEP_DAYS -delete

SQLite 备份

# 在线备份
sqlite3 database.db ".backup 'backup.db'"

# 文件复制(需要确保无写入)
cp database.db backup.db

# 导出 SQL
sqlite3 database.db .dump > backup.sql

# 恢复
sqlite3 new.db < backup.sql

备份存储策略

本地存储

# 目录结构
/backup/
├── mysql/
│   ├── daily/
│   ├── weekly/
│   └── monthly/
├── postgresql/
└── mongodb/

远程存储

rsync 同步

# 同步到远程服务器
rsync -avz /backup/ user@remote:/backup/

# 定时同步
rsync -avz --delete /backup/ user@remote:/backup/

对象存储上传

# AWS S3
aws s3 sync /backup/ s3://bucket/backup/

# 阿里云 OSS
ossutil cp -r /backup/ oss://bucket/backup/

# 腾讯云 COS  
coscmd upload -r /backup/ /backup/

备份保留策略

类型 保留时间 频率
每日备份 7 天 每天
每周备份 4 周 每周日
每月备份 12 月 每月 1 日
每年备份 永久 每年 1 月 1 日

备份验证

完整性检查

# MySQL 检查
mysqlcheck --all-databases --check

# PostgreSQL 检查
pg_verifybackup /backup/base

# MongoDB 检查
mongod --dbpath /test_restore --fork

恢复测试

# 定期进行恢复测试
# 1. 创建测试数据库
# 2. 恢复备份
# 3. 验证数据完整性
# 4. 记录恢复时间

监控告警

备份监控脚本

#!/bin/bash

BACKUP_DIR="/backup/mysql"
ALERT_EMAIL="admin@example.com"

# 检查最新备份
LATEST=$(ls -t $BACKUP_DIR/*.sql.gz | head -1)
BACKUP_TIME=$(stat -c %Y "$LATEST")
CURRENT_TIME=$(date +%s)
DIFF=$((CURRENT_TIME - BACKUP_TIME))

# 如果超过 25 小时没有备份,发送告警
if [ $DIFF -gt 90000 ]; then
    echo "Warning: No backup in last 25 hours" | mail -s "Backup Alert" $ALERT_EMAIL
fi

备份大小监控

# 检查备份大小
du -sh /backup/mysql/

# 检查磁盘空间
df -h /backup

加密备份

GPG 加密

# 加密备份
gpg -c backup.sql.gz

# 解密
gpg -d backup.sql.gz.gpg > backup.sql.gz

OpenSSL 加密

# 加密
openssl enc -aes-256-cbc -salt -in backup.sql -out backup.sql.enc -pass pass:your_password

# 解密
openssl enc -aes-256-cbc -d -in backup.sql.enc -out backup.sql -pass pass:your_password

常见问题

Q: 备份影响性能?

解决方案:

  1. 在从库备份
  2. 使用物理备份
  3. 限速备份
  4. 在低峰期备份

Q: 备份文件太大?

解决方案:

  1. 压缩备份
  2. 增量备份
  3. 分库分表备份
  4. 清理历史数据

Q: 恢复速度慢?

解决方案:

  1. 使用物理备份
  2. 并行恢复
  3. 临时关闭索引
  4. 增加缓冲区

总结

数据库备份最佳实践:

  1. 定期备份:自动化备份流程
  2. 多重备份:遵循 3-2-1 原则
  3. 验证测试:定期恢复测试
  4. 监控告警:及时发现问题
  5. 文档记录:记录备份恢复流程

备份是数据安全的最后一道防线,务必重视。