如何设计数据库备份、恢复与灾难演练
不要先背 3-2-1;先解释“误删已经复制到从库,为什么有从库也救不了”
这一页只解决一个问题: 数据库被误删、误更新或坏脚本写坏以后,怎样回到可信业务状态。备份的目标不是有文件,而是能在指定时间内恢复指定对象,并知道会丢什么、不能撤回什么。
清理脚本按 tenant.env='test' 删除账目,但历史脏数据里有真实租户也被标成 test。删除语句提交后很快复制到从库,从库也一起删了。
| 错误反应 | 为什么失败 | 逼出的设计 |
| 切到从库 | 误删已经复制过去 | 主从不是备份 |
| 恢复凌晨全量 | 会丢凌晨到事故前的正常新增 | 需要 PITR |
| 直接覆盖生产库 | 可能二次破坏新写入 | 先恢复到隔离库 |
| 问题 | 例子 |
| 最多能丢多久数据 | 账目流水 RPO 可能要小于 5 分钟 |
| 最长能停多久 | 新增账目 2 小时内恢复,报表可更晚 |
| 全量备份之后的事务在哪里 | binlog / WAL 必须连续归档 |
| 恢复目标点怎么找 | 停在坏 DELETE 事务之前,而不是按感觉停 |
| 恢复后怎么证明业务对 | 账目数、余额、预算、审计记录都要校验 |
| 整库回滚还是定向修复 | 事故后正常新增不能随便覆盖 |
restore_chain
- full_backup_id
- backup_started_at
- backup_finished_at
- log_start_lsn
- archived_log_ranges
- checksum
- db_version
- encryption_key_ref
restore_target
- target_time
- stop_before_transaction
- reason
吸收点: “有备份文件”不等于“能恢复”。全量备份、连续日志、元数据、密钥、校验和目标点必须连成链。
| 边界 | 不能混成什么 | 正确理解 |
| 高可用副本 | 不等于备份 | 副本会复制误删,备份能回到过去 |
| 全量备份 | 不等于时间机器 | 没有连续日志,只能回到备份时刻 |
| 恢复库 | 不等于生产库 | 先隔离恢复和校验,再决定回填或切换 |
| 数据库恢复 | 不等于业务恢复 | 余额、报表、缓存、外部副作用都要收口 |
关键判断: 恢复不是“把生产库倒回去”。多数真实事故更像:从恢复库抽可信旧值,再定向修复生产。
| 样本 | 通过标准 |
| 恢复到坏 DELETE 前一秒 | 坏事务没有重放,之前正常事务保留 |
| 日志归档缺一段 | 演练能发现断链,而不是事故时才发现 |
| 备份文件损坏 | checksum 或抽样恢复能发现 |
| 密钥轮换后恢复 | 能拿到正确密钥,不被权限卡住 |
| 只恢复一个租户 | 不覆盖其他租户事故后的正常数据 |
| 恢复后业务校验 | 账目、余额、预算、审计记录一致 |
总结: 数据库备份恢复的核心不是 3-2-1,而是恢复链可信:主从不是备份,全量要接连续日志,恢复先到隔离库,业务校验比数据库启动更重要,整库回滚和定向修复要分开。