服务器备份策略怎么制定?全量、增量与差异备份对比

凌晨两点,运维收到告警:业务库主表被一条误执行的 UPDATE 覆盖了三万行数据。翻备份时发现,上一份可用的全量备份是九天前的,增量链条里有两天因为磁盘满失败了,差异备份目录里只躺着最后一次的副本——而那份副本是在误操作之后生成的。这不是段子,是绝大多数中小团队第一次真正"用"备份时的真实场景。

备份这件事的残酷之处在于:它在 99% 的时间里毫无存在感,而在剩下 1% 的时间里决定公司能不能活下去。制定服务器备份策略,本质上不是选一个工具,而是回答三个问题:能丢多少数据(RPO)、要多久恢复(RTO)、愿意为此付出多少存储与运维成本。全量、增量、差异三种备份类型,就是在这三个约束之间做排列组合。

一、先立地基:3-2-1 备份原则

在讨论全量还是增量之前,必须先确认备份的"拓扑"是对的。业界通行的 3-2-1 备份原则是所有备份策略的地基:

  • 3 份数据副本:1 份生产数据 + 至少 2 份备份。只保留一份备份等于没有备份,因为备份本身也会损坏。
  • 2 种不同介质:例如本地磁盘 + 对象存储,或本地 NAS + 异地服务器。同一台机器的两块硬盘不算两种介质。
  • 1 份异地/离线副本:至少一份放在物理隔离的位置,用于抵御火灾、盗窃、机房故障,以及最关键的——勒索软件的横向加密。

很多团队跳过了这一步,直接纠结"增量还是差异",结果做出来的方案是"同一台机器上按天保留 7 个增量",这在逻辑删除、误操作、勒索加密面前完全失效。合理的变体是 3-2-1-1-0:在 3-2-1 基础上,再加 1 份不可变(immutable)或离线副本,并确保恢复测试的错误数为 0。

需要特别说明:不可变副本可以通过对象存储的 WORM/对象锁定(Object Lock)实现,也可以通过把备份盘在备份完成后卸载(umount)实现。前者依赖云厂商能力,后者成本更低但需要脚本纪律。

二、三种备份类型到底差在哪

全量、增量、差异的区别,只看一个维度就够了:每次备份的数据范围以什么为基准。

2.1 全量备份(Full Backup)

全量备份把选定的全部数据完整地复制一份,不依赖任何其他备份集。它的优点是恢复极快:只需要一份文件,恢复路径最短,出错概率最低。缺点是占用空间大、备份窗口长,对生产 I/O 有压力。

2.2 增量备份(Incremental Backup)

增量备份只备份上一次备份(无论全量还是增量)之后发生变化的数据。它的链条是串行的:全量 → 增量1 → 增量2 → 增量3。优点是每次备份量最小、速度最快;缺点是恢复时必须按顺序回放整条链,链条中任意一环损坏或缺失,其后的所有增量全部作废。

2.3 差异备份(Differential Backup)

差异备份只备份上一次全量备份之后发生变化的数据。链条是星形的:全量 → 差异1 → 差异2 → 差异3,每个差异都是相对同一份全量而言。优点是恢复只需"全量 + 最后一次差异"两份,链条风险远低于增量;缺点是随着时间推移,差异备份的体积会越来越大,接近下一份全量的大小。

对比项全量备份增量备份差异备份
备份范围基准全部数据上一次任意备份之后上一次全量备份之后
单次备份体积最大最小随时间递增
备份速度最慢最快中等
恢复所需份数1 份全量 + 全部增量(N 份)全量 + 最后1次差异(2 份)
链条脆弱性无依赖高(断链即失效)低
存储成本最高最低中等
典型适用小数据量、核心库、周/月基线大数据量、带宽紧张、日级备份中等数据量、要求快速恢复

三、用 tar 理解三种备份的实际写法

Linux 上最朴素、也最容易验证的备份方式就是 tar 配合快照文件(snapshot file)。下面这组命令可以直接在本地跑一遍,体会三者的差异。

3.1 全量备份

# 全量备份 /data,记录快照文件用于后续判断变化
tar --create --gzip \
    --file=/backup/full-$(date +%F).tar.gz \
    --listed-incremental=/backup/snap.dat \
    --exclude=/data/cache \
    --exclude=/data/tmp \
    /data

# 查看备份体积与耗时对比
ls -lh /backup/

说明:--listed-incremental(简写 -g)指向的快照文件记录了每个文件的 inode 状态与时间戳。当快照文件不存在时,tar 自动执行全量备份(level 0)。

3.2 增量备份

# 第一次增量:复制快照后执行,只打包自上次备份后变化的文件
cp /backup/snap.dat /backup/snap.dat.bak
tar --create --gzip \
    --file=/backup/inc-$(date +%F-%H%M).tar.gz \
    --listed-incremental=/backup/snap.dat \
    --exclude=/data/cache \
    /data

# 恢复时必须按备份顺序依次解包
tar --extract --gzip --listed-incremental=/dev/null -f /backup/full-2025-01-01.tar.gz -C /
tar --extract --gzip --listed-incremental=/dev/null -f /backup/inc-2025-01-02.tar.gz -C /

注意恢复时的 --listed-incremental=/dev/null:这个参数告诉 tar 只做解包、不更新快照,同时会正确删除"本次备份中被标记为已删除"的文件。如果漏掉它,删除操作不会被还原,恢复出来的目录会残留垃圾文件。

3.3 差异备份的实现思路

tar 原生只有增量语义,做差异备份需要保留一份"全量时刻的快照"不动,每次备份前先把它复制成工作快照:

# 全量时保留基线快照
cp /backup/snap.dat /backup/snap.level0

# 每天做差异:先从基线快照复制一份工作快照,再备份
cp /backup/snap.level0 /backup/snap.work
tar --create --gzip \
    --file=/backup/diff-$(date +%F).tar.gz \
    --listed-incremental=/backup/snap.work \
    /data

# 恢复只需两份:全量 + 最后一次差异
tar --extract --gzip --listed-incremental=/dev/null -f /backup/full-2025-01-01.tar.gz -C /
tar --extract --gzip --listed-incremental=/dev/null -f /backup/diff-2025-01-07.tar.gz -C /

四、怎么组合出一套可落地的策略

单一类型无法同时满足成本与恢复速度,真实策略一定是组合。下面给出两套经过验证的模板,可按数据量级选择。

4.1 模板 A:中小数据量(< 500GB),优先恢复速度

  1. 每周日凌晨 02:00 做一次全量备份,作为周基线;
  2. 周一至周六每天 02:00 做一次差异备份,相对本周日全量;
  3. 保留最近 4 周的全量 + 差异,第 5 周滚动覆盖;
  4. 每天全量完成后,用 rsync 把当日备份同步到异地服务器;
  5. 每周一抽查一次恢复演练,把备份文件真正解包到临时目录并校验。

4.2 模板 B:大数据量(> 2TB),优先备份窗口

  1. 每月 1 日做一次全量备份;
  2. 每天做增量备份,链条控制在 30 环以内;
  3. 每周日额外做一次差异备份,作为"中间还原点",把最长回放链条从 30 环压到 7 环;
  4. 增量链条每 7 天做一次合并(consolidate),生成新的合成全量(synthetic full),避免链条过长;
  5. 全量与合成全量上传对象存储,开启对象锁定或版本控制。

判断标准:如果单次全量备份耗时超过业务低峰窗口的 70%,就必须引入增量;如果恢复链条超过 10 环,就必须插入差异或合成全量。这两个阈值是实践中最常用的平衡点。

五、数据库备份不能只看文件

对 MySQL/PostgreSQL 这类有缓存和事务的服务,直接 tar 数据目录得到的是"崩溃一致性"备份,恢复后需要走崩溃恢复流程,且有概率失败。逻辑备份应使用事务一致性快照。

# MySQL InnoDB 一致性逻辑备份(不锁表)
mysqldump -u backup -p \
    --single-transaction \
    --master-data=2 \
    --routines \
    --triggers \
    --events \
    --default-character-set=utf8mb4 \
    --databases appdb | gzip > /backup/appdb-$(date +%F).sql.gz

# 校验备份文件可用性(不要只看文件大小)
zcat /backup/appdb-$(date +%F).sql.gz | head -30
zcat /backup/appdb-$(date +%F).sql.gz | tail -5

参数解释:--single-transaction 在 RR 隔离级别下开启一致性快照,避免锁表;--master-data=2 以注释形式写入 binlog 位点,便于做时间点恢复(PITR);--routines 与 --triggers 保证存储过程和触发器不丢失——这两个参数漏掉是备份"看起来成功但恢复后业务报错"的高频原因。

六、保留周期与校验:备份策略的最后两块拼图

保留周期需要同时满足业务需求与合规要求。常见配置是"日备保留 7 天、周备保留 4 周、月备保留 12 个月"。金融、医疗等行业通常有更长的法定留存要求,需按监管口径调整。

# 生成校验值,随备份一同保存
sha256sum /backup/*.tar.gz > /backup/$(date +%F).sha256

# 异地同步后重新校验,验证传输完整性
sha256sum -c /backup/$(date +%F).sha256

# 清理超过保留周期的历史备份(先 dry-run 确认)
find /backup -name "full-*.tar.gz" -mtime +90 -print
find /backup -name "full-*.tar.gz" -mtime +90 -delete

sha256sum 校验必须在备份生成时和异地传输后各做一次。前者防静默写入错误(bit rot),后者防网络传输截断。很多团队只做了一步,结果异地那份是坏的,本地那份也被误删了。

小结

制定服务器备份策略的顺序是:先定 RPO/RTO,再选备份类型组合,最后设计拓扑与校验。全量备份是唯一不依赖任何其他备份集的底座,增量用最低成本换取最短备份窗口但链条脆弱,差异在两者之间取得了恢复速度的最优解。三者不是互斥选项,而是时间轴上的不同角色。

避坑清单

  • 不要把备份放在生产机同一块磁盘上——磁盘故障时生产数据和备份一起消失。
  • 增量链条必须有长度上限,超过 10-15 环就做合成全量。
  • tar 恢复时务必带 --listed-incremental=/dev/null,否则删除操作不会被还原。
  • mysqldump 必须带 --routines --triggers,否则存储过程和触发器丢失。
  • 备份脚本必须检查退出码,磁盘满导致的"假成功"是最常见的失败模式。
  • 校验值(sha256sum)要与备份文件分开存放,否则备份损坏时校验值也会一起损坏。
  • 没有任何恢复演练的备份,只能算"文件副本",不能算备份。