跳到主要内容

数据备份与恢复

问题

如何制定数据库备份策略?出现故障时如何恢复?

答案

备份类型

类型说明优点缺点
全量备份备份整个数据库恢复简单耗时长、占空间
增量备份仅备份自上次备份后的变更快速、省空间恢复需要依次应用
差异备份备份自上次全量备份后的变更恢复比增量简单比增量占空间

备份策略

MySQL 备份

# 逻辑备份(mysqldump)
mysqldump -u root -p --single-transaction --routines \
--databases myapp > backup_$(date +%Y%m%d).sql

# 恢复
mysql -u root -p myapp < backup_20240101.sql

# 物理备份(大数据量推荐 xtrabackup)
xtrabackup --backup --target-dir=/backup/full

# 二进制日志(Point-in-Time Recovery)
mysqlbinlog --start-datetime="2024-01-01 10:00:00" \
--stop-datetime="2024-01-01 11:00:00" binlog.000001 | mysql -u root -p

自动化备份脚本

backup-script.ts
import { exec } from 'child_process';
import { promisify } from 'util';

const execAsync = promisify(exec);

async function backupDatabase() {
const timestamp = new Date().toISOString().slice(0, 10);
const filename = `backup_${timestamp}.sql.gz`;

// 1. 导出并压缩
await execAsync(
`mysqldump -u ${process.env.DB_USER} -p${process.env.DB_PASS} \
--single-transaction ${process.env.DB_NAME} | gzip > /backups/${filename}`,
);

// 2. 上传到 S3
await execAsync(
`aws s3 cp /backups/${filename} s3://my-backups/mysql/${filename}`,
);

// 3. 清理 30 天前的本地备份
await execAsync('find /backups -name "*.sql.gz" -mtime +30 -delete');

// 4. 通知
console.log(`Backup completed: ${filename}`);
}

恢复验证

关键

备份不验证等于没备份!定期恢复到测试环境验证备份完整性。


常见面试问题

Q1: RPO 和 RTO 是什么?

答案

  • RPO(Recovery Point Objective):可容许的数据丢失量。RPO = 1 小时意味着最多丢 1 小时数据
  • RTO(Recovery Time Objective):可容许的恢复时间。RTO = 30 分钟意味着 30 分钟内必须恢复

Q2: 逻辑备份和物理备份怎么选?

答案

  • 逻辑备份(mysqldump):SQL 可读、跨版本兼容,但慢,适合小数据量(< 50GB)
  • 物理备份(xtrabackup):直接拷贝文件,速度快,适合大数据量

Q3: 如何防止误删数据?

答案

  1. 使用软删除deleted_at 字段)
  2. 开启 Binlog(可按时间点恢复)
  3. 生产数据库禁止直接 DELETE/DROP 权限
  4. 重要操作前手动备份

相关链接