数据库专题25:备份与恢复演练——没有做过恢复,就不算有备份

发布时间:2026/9/16 11:00:33
数据库专题25:备份与恢复演练——没有做过恢复,就不算有备份 数据库专题25备份与恢复演练——没有做过恢复就不算有备份备份文件存在磁盘上只能说明“复制成功”不能说明系统能恢复。真正的目标是给博客项目定义 RPO最多丢多少数据和 RTO多久恢复服务然后分别对 PostgreSQL、MongoDB、Redis 做可重复的导出、破坏、恢复和校验。本篇所有命令都可在projects/database-platform的 Docker Compose 中练习。上一篇练习讲解上一篇的安全练习应创建blog_report只读账号、Redis ACL并用注入字符串测试搜索。若测试失败优先检查应用是否绕过 ORM 使用了字符串拼接权限错误应在数据库端出现而不是只依赖接口代码。备份也要使用专用只读账号不能把管理员密码写入脚本。1. 明确 RPO/RTO 和备份对象本项目设定文章和用户的 RPO 为 15 分钟、RTO 为 30 分钟Redis 排行榜是可重建缓存RPO 可为 24 小时。PostgreSQL 要做逻辑备份加 WAL/PITRMongoDB 保存文章版本和审计需保留时间点Redis 只备份持久计数普通缓存不必恢复。PostgreSQL 业务事实 ── pg_dump WAL ── 对象存储 MongoDB 版本/审计 ─── mongodump ── 加密归档 Redis 持久计数 ────── BGSAVE/导出 ── 可选 ↓ 每月进行一次“破坏后恢复”演练2. PostgreSQL 逻辑备份先在容器内生成自定义格式备份。密码通过环境变量传递避免出现在命令历史$env:PGPASSWORD blogdocker compose exec-T postgres pg_dump-U blog-d blog-Fc.\backup\blog-$(Get-Date-Format yyyyMMdd-HHmm).dump自定义格式支持并行恢复和选择性恢复如果只需要 schema可使用--schema-only。备份完成后检查文件大小和目录清单pg_restore-l.\backup\blog-latest.dump|Select-Object-First 12 pg_restore--list.\backup\blog-latest.dump|Select-StringTABLE DATA恢复到临时数据库不要直接覆盖生产库docker compose exec-T postgres createdb-U blog blog_restoreGet-Content.\backup\blog-latest.dump-AsByteStream|docker compose exec-T postgres pg_restore-U blog-d blog_restore--clean--if-exists docker compose exec-T postgres psql-U blog-d blog_restore-cselect count(*) from articles;验证行数、关键用户、文章版本和约束。恢复成功后再切换连接串或进行逻辑复制不能只看到pg_restore返回 0 就宣布完成。3. MongoDB 文章版本与审计备份New-Item-ItemType Directory-Force.\backup\mongo|Out-Nulldocker compose exec-T mongo mongodump--db blog--archive--gzip .\backup\mongo\blog.archive.gz恢复到隔离数据库进行比对Get-Content.\backup\mongo\blog.archive.gz-AsByteStream|docker compose exec-T mongo mongorestore--archive--gzip--nsFromblog.*--nsToblog_restore.*--drop docker compose exec-T mongo mongosh--quiet--evaldb.getSiblingDB(blog_restore).article_versions.countDocuments({})生产副本集可使用--oplog保证导出期间的一致时间点大集合恢复时注意磁盘和索引重建时间。审计集合涉及合规备份文件必须加密并限制读取角色。4. Redis 备份的边界Redis 的缓存 key 可以在 PostgreSQL/Mongo 恢复后重建。若排行榜计数还没落库使用 AOF 或 RDB 作为短期补救docker compose exec redis redis-cliBGSAVE docker compose exec redis redis-cliLASTSAVE docker compose exec redis redis-cli--user blog_app--pass change-me-redis GET blog:article:42:views不要把dump.rdb当作跨版本长期备份恢复 Redis 后先让应用以只读降级启动确认 key 命名空间和 TTL再开放写流量。敏感 session 应设置短 TTL恢复旧 session 可能带来账号安全问题。5. 破坏与恢复实验在测试环境插入标记数据insertintoarticles(title,body,author_id,status)values(restore-check,backup marker,1,published);记录当前时间和三类数据库行数然后删除restore-check再从备份恢复到临时库。验收脚本示例importpsycopgdefassert_restore(dsn:str)-None:withpsycopg.connect(dsn)asconn:rowconn.execute(select title, body from articles where title%s,(restore-check,)).fetchone()assertrow(restore-check,backup marker)如果恢复后缺少该行说明备份时间晚于插入或备份文件路径错误。若行存在但外键失败检查恢复顺序和--disable-triggers的使用范围不要为了让命令成功而永久禁用约束。6. 自动化与保留策略备份脚本应输出成功/失败、耗时、文件大小、校验和并在失败时告警。保留策略可以是每日 7 份、每周 4 份、每月 12 份删除旧备份前确认最新一份已经通过恢复抽检。对象存储启用版本控制和服务端加密下载恢复时使用临时凭证。验收记录pg_dump blog-latest.dump - 文件可由 pg_restore -l 读取 blog_restore articles 行数 原库行数restore-check 存在 mongorestore blog_restore.article_versions 原集合数量 Redis BGSAVE 返回 Background saving started 恢复演练从停止写入到校验通过耗时 6 分钟满足 RTO 30 分钟课后练习写backup.ps1创建带日期的目录导出 PostgreSQL/MongoDB计算 SHA-256 并输出 JSON 报告写restore-check.ps1自动创建临时库并验证标记数据。报告中记录 RPO/RTO下一篇使用这些数据做慢查询和压测基线。