凌晨两点,运维收到告警:业务库主表被一条误执行的 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),优先恢复速度
- 每周日凌晨 02:00 做一次全量备份,作为周基线;
- 周一至周六每天 02:00 做一次差异备份,相对本周日全量;
- 保留最近 4 周的全量 + 差异,第 5 周滚动覆盖;
- 每天全量完成后,用
rsync把当日备份同步到异地服务器; - 每周一抽查一次恢复演练,把备份文件真正解包到临时目录并校验。
4.2 模板 B:大数据量(> 2TB),优先备份窗口
- 每月 1 日做一次全量备份;
- 每天做增量备份,链条控制在 30 环以内;
- 每周日额外做一次差异备份,作为"中间还原点",把最长回放链条从 30 环压到 7 环;
- 增量链条每 7 天做一次合并(consolidate),生成新的合成全量(synthetic full),避免链条过长;
- 全量与合成全量上传对象存储,开启对象锁定或版本控制。
判断标准:如果单次全量备份耗时超过业务低峰窗口的 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)要与备份文件分开存放,否则备份损坏时校验值也会一起损坏。 - 没有任何恢复演练的备份,只能算"文件副本",不能算备份。
企业QQ咨询




