7.1 备份与恢复


7.1 备份与恢复

本节摘要:备份的目标不是"有文件",而是"能在承诺的时间内把数据恢复到指定时刻"。本节讲逻辑备份与物理备份的取舍、全量加增量的组合、binlog 时点恢复的完整演练,以及恢复演练的验收标准。位置:运维三本账的保命账,第 6 章一切高可用设计的最后兜底。

图 17 · 备份策略矩阵:频率 × 范围 × 验证

图 17 · 备份策略矩阵:频率 × 范围 × 验证

先把两个指标谈清楚

评审备份方案先问两个数。RPO(恢复点目标):最多能接受丢多久的数据?每天凌晨全量备份的系统 RPO 是 24 小时——白天挂掉,一天的数据没了;配合 binlog 做时点恢复可把 RPO 压到秒级。RTO(恢复时间目标):从故障到恢复能用要多久?物理备份恢复快(拷文件加重放),逻辑备份要逐行重放 SQL,几百 GB 的库 RTO 差出一个量级。这两个数由业务方拍板、技术方报价,评审会上别让任何一方替对方做决定。

逻辑备份与物理备份

维度 mysqldump(逻辑) XtraBackup 类(物理)
产物 SQL 文本 数据文件快照
恢复速度 慢,逐条重放 快,拷回加崩溃恢复
备份速度 慢,单线程为主 快,热备份
灵活性 可单库单表、可编辑 整库为主
适用规模 百 GB 以内、单表恢复 大库、需要低 RTO

组合拳是标准答案:每天凌晨物理全量 + 全天 binlog 实时归档,RPO 秒级、RTO 小时级;对个别核心小表再加每日 mysqldump 便于快速取用。备份文件三原则:异地存储(本机磁盘损坏不能连备份一起带走)、加密与权限管控(备份是最全的数据泄露源)、保留策略分级(7 天日备、8 周周备、12 月月备,按合规要求调整)。

演练:误删表后的时点恢复

背景:周三 14:30,开发误执行 DROP TABLE orders_tmp(本以为是测试库)。要求恢复到删除前一秒。操作五步:

-- 第一步:止血。锁库或停写入,防止 binlog 位点继续推进 FLUSH TABLES WITH READ LOCK; -- 第二步:找最近的物理全量备份(周二 03:00) -- 第三步:恢复全量备份到临时实例,或直接在备机操作 -- (物理备份按工具流程拷回数据目录并执行恢复前准备) -- 第四步:用 binlog 把数据重放到误删前一刻 -- 先定位 binlog 中 DROP 的位置 SHOW BINLOG EVENTS IN 'binlog.000437'; -- 找到 DROP TABLE orders_tmp 的起始位点 156822313 -- 重放从全量备份时刻到 DROP 之前的所有变更 -- 命令行执行(示意):按起止位点把 binlog 段转 SQL 应用到库 -- mysqlbinlog --start-position=备份时位点 --stop-position=156822313 binlog.000436 binlog.000437 -- 第五步:验证数据完整性(行数、最新订单时间戳),恢复业务写入

结果:数据回到 14:29:59,丢失窗口为零——因为 binlog 从删除前的最后一位点截断。解读:这次演练暴露了两个此前被忽视的问题——全量备份间隔 24 小时导致重放耗时 40 分钟(RTO 不达标,改为每 6 小时增量);binlog 归档策略原本只保留 3 天(这次事故发生在第 3 天,再晚一天就无药可救)。每一次真实演练都会修正策略,这就是演练的意义。变式:表级误删如果只涉及单表且库还在,恢复到临时实例后把表数据导回,比整库回滚影响面小得多——恢复方案要按影响半径选择。

备份有效性验证

备份文件存在不等于备份有效。验证三层次:完整性(文件大小、校验和、恢复前准备能否通过);可用性(每月把备份恢复到临时实例,跑基本查询与业务核心校验);时效性(恢复演练计时,确认 RTO 承诺仍然成立)。团队守则一句话:恢复演练进排期,每季度一次,演练报告存档。多少公司的备份策略死在这条上——备份脚本跑了两年,第一次真正恢复时发现从某个月起就一直是坏的。

易错点与评审清单

  • 备份跑在主库上拖垮业务:物理备份也有 IO 压力,标准做法在从库备份,顺带验证从库数据可用性;
  • binlog 只在主库本机:主盘损坏连日志一起丢,binlog 必须实时归档到远端;
  • 逻辑备份忘字符集参数:mysqldump 不显式指定字符集时可能按连接默认导出,中文乱码且不可逆;
  • 恢复只演不练自动化:恢复手册要具体到命令与顺序,写清楚每一步的校验点,故障时没时间读思路性文档。

要点回顾:RPO 与 RTO 的报价先于方案选择;物理全量加 binlog 是标准组合;时点恢复五步法——止血、取全量、重放、截断、验证;恢复演练季度化,验证备份的是"能恢复"三个字。保命账记完,下一本账是看得见的效益账。

演练:误删一张表后的三十分钟恢复

场景:运维执行了一条没有 WHERE 条件的 DELETE,订单明细表少了十二万行,业务仍在写入。恢复的目标是把数据补回到误操作前那一刻,且不能中断线上服务。

前提检查(决定恢复路径):

  • 有没有可用的全量备份?有,昨晚 02:00 的物理备份(XtraBackup 生成);
  • binlog 是否完整保留?是,保留 7 天,且格式为 ROW;
  • 误删的确切时间点?通过应用日志与 binlog 定位到 14:23:41,误删语句的 GTID 或位点已知。

恢复路径:全量备份 + binlog 增量前滚到误删前。

# 1) 在恢复机上准备一份备份(apply-log 让数据文件达到一致状态) xtrabackup --prepare --target-dir=/data/backup/full-2026-09-01 # 2) 把备份恢复到临时实例(绝不直接覆盖生产) cp -r /data/backup/full-2026-09-01 /data/restore/inst_tmp # 启动临时实例,端口与生产隔离 # 3) 前滚 binlog 到误删前一刻(--stop-datetime 排除误删语句本身) mysqlbinlog --stop-datetime='2026-09-01 14:23:40' binlog.000318 binlog.000319 | mysql -h127.0.0.1 -P3307 # 4) 从临时实例导出被误删的那部分数据 mysqldump -h127.0.0.1 -P3307 db_order order_item --where="id BETWEEN 500000 AND 620000" > item_recover.sql # 5) 校验后回灌生产(先灌到影子表,比对行数与校验和,再换名)

几个决定成败的细节:

  • 绝不直接往生产实例前滚 binlog。生产仍在写入,前滚会与正常业务冲突。正确姿势永远是"恢复到临时实例 → 取出需要的数据 → 校验 → 回灌";
  • --stop-datetime 要精确到秒并留一秒余量。误删语句本身不能被执行,宁可少恢复一秒的数据,也不要把删除再放一遍;
  • ROW 格式是恢复粒度的前提。STATEMENT 格式下,非确定性语句的重放结果可能与当时不同;
  • 回灌前先建影子表比对。把恢复出来的十二万行灌到一张临时表,与业务侧记录的行数、金额总和逐项核对,一致后再换名或 INSERT 回主表。

演练之外的制度化动作:把这类恢复写成一页纸的应急手册(含命令、参数、负责人、预计耗时),每季度演练一次并记录实际耗时。备份的价值不在备份文件本身,而在于有人真的用它恢复成功过。没演练过的备份,在事故现场等于没有备份——这是无数次事故复盘后最一致的一条结论。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U