3263 字
约 10 分钟
16
S15-A09 · 备份与恢复:备份存在不等于能恢复

备份任务天天跑、成功率 100%、告警一直安静——然后在真需要它的那天,恢复出来的实例起不来,或者起来后数据停在三天前。共同点不是工具坏了,而是验证对象选错了:团队验的是"备份进程退出码",业务要的是"恢复出一条可用数据链"。

这篇只谈三件事:场景与能力如何配对、可恢复性用什么判据证、验证要付多少代价。


1. 三种场景,三种完全不同的能力

场景 典型起因 需要的备份类型 演练难度
单表误删 脚本写错 WHERE 逻辑备份或延迟从库 低
整库损坏 磁盘故障、升级失败 物理全量 + 增量链 + binlog 中
机房级故障 区域故障、云盘异常 异地副本 + 独立启动依赖 高

第一个设计错误是一套备份应付三种场景:物理全量救不了"把一张表退回 10:05",逻辑导出在大库上恢复全库常超出 RTO。三者须分别回答"靠什么恢复"并分别演练。


2. RPO / RTO 要写成业务语言

定义人人会背,错在写成了平均值、写成了单库口径。

常见写法 问题 可执行写法
"RPO 5 分钟" 平均还是最坏? "故障时最多丢最近 5 分钟写入(按最坏值)"
"RTO 1 小时" 从发现算还是决策算? "确认需恢复起 60 分钟可读、120 分钟可写"
"数据库有备份" 未覆盖缓存与配置 "丢失清单:MySQL 全库、Redis 可重建、对象存储按日增量"
"有异地备份" 未验证能否独立启动 "异地副本不依赖主机房即可启动"

写不出可执行版本,通常说明指标从未被真正需要过;写的过程也暴露了顺序问题。


3. "备份成功"的判据不是退出码

判据层 能证明 不能证明
退出码 0 命令跑完了 文件完整、能导入
校验和匹配 传输无损 语义正确、版本兼容
恢复到临时实例 可恢复 数据完整、业务可用
抽样比对通过 关键数据在 全库一致
业务方跑通一条关键路径 业务可用 —

只有最后一层算可用。前五层是必要条件,常见做法是自动化到第三层就收工——而第三层最容易满足、信息量最少。


4. 一致性:方式 × 写入状态的组合属性

备份方式 写入状态 一致性来源 一致性边界
逻辑导出(快照事务) 持续写入 可重复读快照 只对事务引擎有效
逻辑导出(锁表) 停止写入 表锁 期间业务不可写,窗口极短
在线物理热备 持续写入 脏页/redo 跟踪 恢复前必须做一致性回放
冷拷文件 停服务 停止即一致 仅限停机窗口
卷级快照 持续写入(瞬时冻结) 卷级原子点 多卷逐个不原子

关键是一致性边界写在哪。说明里只有"每天 3 点全量"、没写"该时点是否有业务在写、非事务表是否包含",恢复的库是否自洽就是未知的。

# 一致性点取证:备份前后各记一次位点,与元数据一起归档
mysql -e "SHOW MASTER STATUS\G" > /backup/pos_begin.txt
mysql -e "SHOW MASTER STATUS\G" > /backup/pos_end.txt

5. 可恢复性验证检查什么

检查项 方法 抓到的缺陷
行数对比 两侧按表计数 表缺失、导入中断
关键表抽样 按主键取最新 N 条逐字段比 精度、时区偏移
外键与约束 约束存在、FOREIGN_KEY_CHECKS 已恢复 静默失去完整性
自增/序列 当前值 ≥ 最大主键 新写入撞主键
账号与授权 应用账号存在、权限正确 恢复后应用连不上
mysqldump --no-data --skip-comments db | sed 's/ AUTO_INCREMENT=[0-9]*//' > /tmp/schema.sql
mysql -N -e "SELECT table_name, table_rows FROM information_schema.tables\
             WHERE table_schema='db'" > /tmp/count.txt   # 两侧各跑一次,diff 须为空

结构比对要先抹掉 AUTO_INCREMENT 这类易变值,否则每次 diff 都非空,团队会当噪声忽略。


6. 备份文件本身的可读性

依赖 失效方式 需固化在备份旁边
加密密钥 与备份同机,一起丢 独立保管 + 取用记录
备份工具版本 新版产出、旧版读不了 版本写入元数据
字符集/排序规则 恢复后乱码或排序变化 导出时的字符集参数

最难的是密钥:既要与备份分离(避免一并丢失),又要在需要时取得到(避免"安全到自己打不开")。做法是存独立系统并纳入演练——不带密钥的演练等于没演练。


7. "异地"的真实含义

位置 算异地吗 判据
同机另一块盘 否 同故障域
同机房另一台 否 同电源、同出口
同城另一机房 弱 挡单机房,挡不住区域网络
跨区域/跨云 是 能否独立启动仍需验证

判据不是距离,而是故障域是否独立、恢复时是否仍需源端。陷阱:异地副本靠增量投递,恢复要问源端要基线——源端没了,异地也起不来。


8. 备份窗口与业务高峰

冲突 表现 处理方向
与高峰重叠 IO/网络被抢占 限速、错峰、增量替全量
与批处理重叠 两件重 IO 互放大 调度层串行,而非都"避开白天"
冻结时间过长 写入挂起,请求超时 缩短窗口,接受多卷非原子

判据朴素:备份窗口的最坏耗时必须小于业务可接受的减速时长,而非"平均看着还行"。


9. 存储成本与保留期的账

策略 空间放大 恢复链条 成本结构
每日全量 高(N 天 N 份) 1 空间贵、恢复简单
全量 + 每日增量 低 1 + N 空间省、链条长
归档层长期保留 极低单价 取回有延迟 取回时间要计入 RTO

压缩比按格式核对(文本型收益明显,已压缩的二进制几乎没有),别照搬倍数。账可写成一句:"保留 90 天"的真实成本 = 空间 × 策略 × 取回延迟的业务代价,最后一项最常漏——归档取回可能小时级,RTO 却是分钟级。


10. 备份被删掉的风险

风险 机制 隔离手段
运维误删 通配符过宽、路径打错 目录只读、清理走白名单
入侵/勒索 有写权限即可删 不可变存储、对象锁、离线副本
演练覆盖生产 脚本指向生产 隔离目标 + 二次确认

最后一条不是理论风险:一个环境变量没覆盖、白名单没加,备份就灌进了生产。

mount -o remount,ro /backup    # 备份目录只读挂载,删除前必须先解挂

11. 恢复时的应用协同

顺序 组件 为什么这个顺序 停写要求
1 数据库 一切状态之源 是,且要有停写证据
2 缓存 缓存里是旧值,必须先清 先清后放流量
3 消息/队列 积压需与新数据对齐 停消费,处理重复
4 搜索索引 从数据库重建,不单独恢复 重建期降级查询
5 应用实例 最后启动,避免向坏库写入 全恢复前不接流量
# 停写的证据:位点不再前进 + 写入 QPS 归零 + 业务方确认,三条都要有
mysql -e "SHOW MASTER STATUS\G" | grep Position
redis-cli --scan --pattern 'order:*' | xargs -r -n 100 redis-cli DEL   # 分批清缓存

一个常被踩的细节:"停写"不能靠"我已经通知了",只能靠证据。否则恢复完立刻被写脏。


12. 演练的频率与范围

形态 覆盖 成本 频率
抽样单表恢复 逻辑备份可用性、熟练度 分钟级、单人 每两周
单实例整库恢复 物理链、增量链、版本 小时级、需隔离环境 每月
全链路接管(含应用) 顺序、缓存、切流量 半天、跨团队 每季度
不带密钥的盲演 流程是否自洽 半天、暴露隐性知识 每半年
# 演练脚本的第一行必须是目标守卫:指向生产就直接退出
[ "${RESTORE_TARGET}" = "prod" ] && { echo "refuse"; exit 1; }

只做抽样恢复会得到错觉:文件没问题、流程也没问题。真实事故最常见的失败点是"恢复后没人知道该清缓存、该按什么顺序放流量"——这类知识只能靠全链路演练获得。演练还要换人执行:写脚本的人会跳过他自己知道、别人不知道的步骤。


13. 度量:两个数字就够

指标 定义 判据
最近成功恢复时间 真恢复出可用实例的时刻 超过保留期一半即风险
演练覆盖率 已演练/全部资产 关键资产 100%
增量链完整率 链条不断裂的备份集占比 任何时候都须 100%

指标不必多,但必须有一项端到端(成功恢复时间),否则度量会退化成"备份任务成功率"这个自我安慰的数字。


14. 排错:八种"备份在、恢复不了"

现象 原因 处理
恢复实例起不来 物理备份未回放一致性 补 redo 回放
导入报语法或模式错 版本或 sql_mode 不同 恢复前对齐会话参数
数据停在更早时刻 增量断档或时点参数错 校验父节点,按位点重放
新写入撞主键 自增计数器未对齐 恢复后校正计数器
演练覆盖了生产 脚本未隔离目标 默认隔离 + 生产二次确认

15. 边界:这些数据不必做完整策略

数据 更合适的做法 理由
可从上游重新同步的派生数据 只备份生成逻辑与配置 重建成本低于备份成本
缓存类数据 不备份,冷启动重建 恢复旧缓存反而有害
有严格版本的代码与配置 版本库即备份 无需另建文件级备份

判据一句话:能重建的不需要备份,不能重建的才需要验证。两类混在一套策略里,重要的部分会被稀释。


16. 自测

  1. 退出码 0、校验和匹配,还差哪一层才能称"备份可用"?
  2. 单表误删与整库损坏各依赖哪种备份?为什么一套应付不了两种场景?
  3. 在线物理热备的"一致性"由什么决定,恢复前还缺哪一步?
  4. 为什么"同城另一机房"只能算弱异地?
  5. 恢复顺序里缓存为什么必须排在应用之前且先清?
  6. 只做抽样恢复的团队,最可能缺哪类知识?
S15-A09 · 备份与恢复:备份存在不等于能恢复
https://www.clxhxhhr.top/posts/6246/
作者
clxstart
发布于
2024-12-31
许可协议
CC BY-NC-SA 4.0
评论
0 条
还没有评论,先写一条吧。