接手过不少 RMAN 环境之后,我越来越觉得,备份脚本本身不难写,难的是把“增量备份的依赖关系”真正理顺。很多 DBA 开口就是“我做了全备、做了增量”,但一遇到恢复演练,问题就全暴露出来了。今天要聊的这几个点和这个标题直接相关:RMAN 0级不等于全备、1级可能和0级一样大但不可用于恢复、备份分片管理,以及 delete backup 之后为什么要先安排一次0级备份。这些话看着像绕口令,实际上是事故高发区的真实经验总结,值得仔细拆一遍。
1. 0级备份和全量备份:数据块相同,身份完全不同
1.1 从块的角度看,两者确实长得一样
先明确一个基础结论:BACKUP INCREMENTAL LEVEL 0 DATABASE和BACKUP DATABASE(全备)在数据块层面做的事情几乎一样——都是把数据文件中所有被使用过的块读出来,写入备份集。
所以常有人误以为“0级就是全备,全备就是0级”,从内容上看没问题。但从 RMAN 的管理逻辑和恢复依赖关系上看,完全不是一回事。
全备在 RMAN 的备份记录里是一个独立可用的完整镜像,它的典型标识是F(Full)。而0级备份是增量备份策略中的“锚点”,它的典型标识是0(Level 0),后续的1级增量备份必须建立在这个锚点之上。
你可以用这条命令看备份类型:
RMAN> LIST BACKUP SUMMARY;输出中的 Level 列会明确标出F、0、1。这个区别不是给人看的备注字段,而是 RMAN 在做恢复计算时真正使用的依据。
1.2 为什么说“0级不等于全备”
如果只是磁盘上留下的物理文件,两者都是“完整备份”。但在增量恢复链路里,只有0级能被当作增量链的父备份。普通全备不能承担这个角色。
这意味着什么?举个例子:某环境每天都执行BACKUP DATABASE,同时每天也执行BACKUP INCREMENTAL LEVEL 1 DATABASE。从业务方角度看,RMAN 既做了“全备”,也做了“增量”,感觉天衣无缝。但实际上,这个1级增量备份没有对应的0级基础备份,它在恢复时根本派不上用场。
真正的隐患在于:RMAN 执行BACKUP INCREMENTAL LEVEL 1 DATABASE时不一定立刻报错。它可能正常跑、正常生成备份文件,甚至在备份集里还记录了完整的检查点S CN。直到你需要恢复时,才发现RESTORE DATABASE找不到一个合法的0级备份作为起点,于是整个恢复链条断掉。
所以我的建议很直接:如果打算用增量备份策略,就别把普通全备当成“基础备份”用。需要基础备份时,明确写成BACKUP INCREMENTAL LEVEL 0 DATABASE。全备可以用于归档日志恢复,但不要指望它扛起后续的增量链。
提示:全备加归档日志是可用组合,全备加1级增量不是。0级加1级加归档日志才是正确的增量恢复组合。
2. 1级备份为何可能和0级一样大,却救不了场
2.1 1级备份到底备份了什么
RMAN 的1级增量备份分为两种常见形式:
- 差异增量(Differential):备份自最近一次0级或1级备份以来所有发生过变化的块。
- 累积增量(Cumulative):备份自最近一次0级备份以来所有发生过变化的块。
不管哪种,核心逻辑都是“只备份变化的块”,所以正常情况下1级备份应该明显小于0级。
但“正常情况”在真实系统里很短暂。一个繁忙的库,尤其是一些在线交易系统或批处理系统,每天可能有大范围的数据更新。比如某个大表经常被定时任务整体刷写、大量行被无条件 UPDATE、索引频繁重建、分区表天天做交换分区和合并操作,这时候变化块的范围会非常广。
当数据库块变化率接近100%时,一级备份的内容自然也会接近0级备份的大小。
2.2 大小虚胖的本质
有的 DBA 会犯一个经验主义错误:看到1级备份和0级一样大,就认为“既然内容都全了,那它应该也能单独用来恢复”。
这个想法很危险。
1级备份的元数据里清楚地记录着它的父备份信息。它是一份“基于某个0级备份的增量”,不是完整的、可独立的备份。就算它碰巧把所有块都包含进来了,RMAN 在恢复时也不会把它当成一个独立基础备份来使用。它会去找那个0级父备份,找不到就恢复失败。
我用一个场景来说明:
某个 50GB 的数据库,周日晚上跑0级备份,周一到周五跑1级差异备份。因为业务活动很重,周一的1级备份就跑去45GB,几乎和0级一样大。周四发现磁盘空间紧张,有人把周日的0级备份删了,只留下周四的1级备份。这时候有人觉得:“反正1级45GB,和全备差不多,恢复应该没问题吧?”真到恢复时就会发现,这45GB的备份无法单独恢复数据库,因为它不是一个完整的恢复起点。
2.3 判断备份可用性不能只看大小
判断一个备份能不能用于恢复,核心看它的类型和依赖关系,而不是看它占用了多少空间。下面这张表值得贴在值班文档里:
| 备份组合 | 能否恢复 | 说明 |
|---|---|---|
| 全备 + 归档日志 | 可以 | 全备独立可用,配合归档日志可以做恢复 |
| 全备 + 1级增量 | 不可以 | 1级增量不属于该全备的增量链 |
| 0级 + 1级增量 | 可以 | 1级增量应用在0级基础之上 |
| 只有1级增量 | 不可以 | 缺少父级0级备份,无法作为恢复起点 |
以后看到“1级备份和0级一样大”这类情况,不要高兴太早。它只说明系统的变化块很多、增量备份收益在下降,不代表备份的安全性提升了。真正要做的是去排查变化率为什么这么高,以及增量策略是否需要调整。
3. 备份分片:并行、切片和恢复依赖
3.1 备份集与备份片的关系
RMAN 备份里有两个容易混淆的名词:备份集(Backup Set)和备份片(Backup Piece)。
备份集是逻辑概念,一次BACKUP DATABASE可能产生一个备份集。备份片是物理文件,一个备份集由一个或多个备份片组成。配置了多个通道并行时,RMAN 会把备份集拆成多个备份片,交给多个通道分别写,这样就缩短了备份时间。
这个“分片”过程不是随便拆的,它受几个因素影响:
- 通道个数。
- 每个通道的格式串。
- 备份集大小限制参数,比如
MAXPIECESIZE。 - 大文件是否使用
SECTION SIZE切片。
实际查看备份片,可以用这条命令:
RMAN> LIST BACKUPPIECE;如果备份文件不在 RMAN 的记录里,即使物理文件还摆在磁盘上,RMAN 也无法用它做恢复。这一点在手工清理备份时特别容易踩坑。
3.2 用多通道给备份“分片”提速
最常见的分片方式是加大并行度。比如:
CONFIGURE DEVICE TYPE DISK PARALLELISM 4; CONFIGURE CHANNEL DEVICE TYPE DISK FORMAT '/backup/%U' MAXPIECESIZE 8G;这样配置之后,执行BACKUP DATABASE时,RMAN 会尽量把备份内容分散到多个通道。多个备份片同时写入,整体耗时往往能明显降下来。
需要注意,RMAN 默认对单个数据文件不会并行处理。如果一个库里有几个几百GB的大数据文件,就算你把并行度调到8,单个大文件也可能只由一个通道单独处理,其他通道只能干等。解决办法是使用SECTION SIZE。
3.3 大文件切片备份
对于超大文件,RMAN 提供了按区间切分的功能:
BACKUP DATABASE SECTION SIZE 10G;意思是把每个数据文件按 10GB 一段切分,每个段生成独立的备份片,可以由不同通道并行处理。这样既能利用并行能力,也能把单个备份片控制在一个合理大小,方便管理和传输。
但切片带来的副作用是:恢复时的依赖关系变多了。一个数据文件被切成 N 段,恢复时就要把 N 个备份片全部找齐。任何一个切片丢失、损坏、没被CROSSCHECK扫描到,都会导致这个数据文件无法完整恢复。所以分片提高的是性能,增加的是管理复杂度,这两者需要一起考虑。
3.4 备份片缺失时的恢复风险
有人习惯在操作系统层面直接删掉某些大的备份文件来腾空间,但 RMAN 控制文件里的记录还在。这时候做恢复,RMAN 会去找一个不存在的备份片,然后报文件找不到。
正确做法是让 RMAN 重新核对一遍:
RMAN> CROSSCHECK BACKUP; RMAN> DELETE EXPIRED BACKUP;这样物理文件和 RMAN 记录才能保持一致。不要直接rm掉备份片,除非你已经确认这条备份记录不再需要,并且所有依赖它的增量备份也都不需要了。
4. delete backup 之后,为什么必须先安排0级备份
4.1 删除备份不只是删了几个文件
DELETE BACKUP在 RMAN 里是一个“重操作”。它会同时处理物理备份片和控制文件里的备份记录。如果误用,可能把所有可用备份一次性清掉。
但真正危险的场景不是“删得一件不剩”,而是“删完之后旧的增量链断了,新的基础还没建立”。
比如原来有一套备份链:0级 + 1级 + 1级 + 1级。为了腾空间,执行了一次DELETE BACKUP,把历史备份全部删掉。接着备份任务照常触发了一个1级增量备份。这个新的1级备份虽然成功完成,但它是一个“孤儿备份”——因为没有0级基础。
等到下次恢复时,RMAN 对这个1级备份的处理结果就是:无法作为独立备份使用,同时找不到父级0级备份,恢复失败。
4.2 为什么 delete obsolete 也会踩雷
有人觉得,只要用DELETE OBSOLETE而不是DELETE BACKUP就安全了。其实不然。
DELETE OBSOLETE是根据保留策略来删除的。假设保留策略是REDUNDANCY 1,RMAN 在判断时可能会把已经不具备恢复价值的旧0级备份标记为 obsolete。如果新的0级备份还没完成,或者完成得不完整,那么旧0级被删掉后,后续的1级增量照样会变成孤儿。
尤其常见的一种值班顺序错误是:
早上先 DELETE OBSOLETE; 晚上再跑 0级备份; 凌晨再跑1级增量;在“删除旧0级”到“新0级完成”之间的窗口内,如果数据库出了问题,你手里只有一堆1级增量和归档日志,没有可用的基础备份,恢复会非常被动。
所以我的操作习惯是:先完成新的0级备份并验证通过,再执行DELETE OBSOLETE。顺序反过来,恢复风险会显著上升。
4.3 正确的操作顺序
如果你确实想把备份体系整体重置一遍,推荐按这个顺序来:
# 1. 确认当前数据文件状态和数据库可用性 RMAN> LIST DATABASE; # 2. 做新的 0 级备份 RMAN> BACKUP INCREMENTAL LEVEL 0 DATABASE FORMAT '/backup/lv0_%U.bak'; # 3. 再做 1 级增量备份(如果策略里需要) RMAN> BACKUP INCREMENTAL LEVEL 1 DATABASE FORMAT '/backup/lv1_%U.bak'; # 4. 最后再清理旧备份 RMAN> DELETE NOPROMPT OBSOLETE;核心原则就一句话:新基础备份安全落地之前,旧基础备份绝对不能提前删。
如果是因为磁盘空间紧张,实在没法先做完0级再删旧备份,那也要先把空间问题拆开处理。可以分通道、分文件、分表空间来做0级备份,边备份边释放空间,但一定要保证在某个时间点有一个完整的0级备份先存在。
5. 一套可落地的增量备份与分片策略
5.1 备份方案选型
根据不同容灾要求,RMAN 备份方案通常可以归为三类:
- 只做全备 + 归档日志。
- 做0级 + 1级差异增量。
- 做0级 + 1级累积增量。
第一种方案简单可靠,恢复时直接拿全备做起点,配合归档日志恢复。缺点是备份时间长、空间占用大,不适合变化量大的库做高频备份。
第二种方案最常见:周末做0级,工作日每天做1级差异。备份窗口短,恢复时从0级起步,再应用最近一次1级差异,最后应用归档日志。
第三种方案适合恢复要求更快、不想在恢复时应用太多段1级备份的场景。累积1级的备份内容比差异1级大,但恢复时只需要0级 + 最近一次累积1级,链路更短。
5.2 关键配置和脚本示例
假设数据库每天业务量重,但恢复窗口要求比较严格,我一般会这样配置:
RMAN> CONFIGURE CONTROLFILE AUTOBACKUP ON; RMAN> CONFIGURE RETENTION POLICY TO REDUNDANCY 2; RMAN> CONFIGURE DEVICE TYPE DISK PARALLELISM 4; RMAN> CONFIGURE CHANNEL DEVICE TYPE DISK FORMAT '/backup/%U' MAXPIECESIZE 8G;周日0级备份脚本:
RMAN> BACKUP INCREMENTAL LEVEL 0 DATABASE PLUS ARCHIVELOG DELETE INPUT FORMAT '/backup/lv0_%U.bak';周一到周六1级备份脚本:
RMAN> BACKUP INCREMENTAL LEVEL 1 DATABASE PLUS ARCHIVELOG DELETE INPUT FORMAT '/backup/lv1_%U.bak';如果想减少一级备份的大小,可以打开变更追踪功能:
SQL> ALTER DATABASE ENABLE BLOCK CHANGE TRACKING;开启之后,RMAN 在计算变化块时不需要扫描全表数据文件,增量备份速度会快很多,二级备份的体积也更容易控制。但要注意:这个功能只是提升备份性能,不能让1级备份单独用于恢复。备份依赖关系并不会变。
5.3 验证备份是否有效
很多备份事故不是没做备份,而是备份做了但没验证。我习惯在每次备份任务结束后,再补一条验证命令:
RMAN> RESTORE DATABASE VALIDATE;这个命令不会真正落盘恢复数据,但会检查备份片是否完整、能否被正常读取。如果备份片有损坏,这里就能提前暴露,而不是等到真出故障时才发现。
还可以用RESTORE DATABASE PREVIEW来预览恢复时将使用哪些备份。如果发现恢复计划里缺少预期的0级基础,命令会给出明显提示。
5.4 恢复演练怎么设计
真正检验备份策略是否安全的手段,只有恢复演练。
我建议在测试环境里做一次完整的“0级 + 1级 + 归档日志”恢复,记录整个恢复时间、应用的增量备份数量、有没有碰到缺失分片等问题。演练频率不用太高,但每次大版本升级、存储变更、备份脚本调整之后都要做。
演练时重点看两件事:
- RMAN 是否找到了正确的0级备份。
- 1级备份能否顺利应用到0级之上。
如果这两步都顺畅,那么这个备份链才是可用的。
6. 常见问题与排查技巧实录
6.1 备份记录里看不到0级备份
执行LIST BACKUP SUMMARY时,如果只看到F和1级别的备份,说明增量链缺了0。这种情况通常是历史脚本里写的是全备,而不是INCREMENTAL LEVEL 0。
解决方式很简单:手动补一次0级备份,或者修改备份脚本,把全备命令改成BACKUP INCREMENTAL LEVEL 0 DATABASE。
6.2 删除备份后遇到恢复失败
某一次值班场景是这样的:周一清理磁盘,执行了DELETE BACKUP删掉一批旧备份;周二早上数据库故障,恢复时发现只有周三前的1级增量,没有0级基础。恢复命令一直报“找不到可用备份”。
排查命令:
RMAN> LIST BACKUP SUMMARY; RMAN> LIST BACKUP OF DATABASE;如果发现缺少0级备份,而归档日志完整,只能从最早的全备(如果有)加归档日志恢复,1级增量备份基本作废。这也是为什么我反复强调:删除备份前,先确认新基础备份已经生成。
6.3 1级备份体积突然变大
一级备份异常变大,通常意味着数据库变化块比例飙升。处理思路不要只落在“怎么压缩备份”上,先排查业务变更或数据操作:
- 是否有大表重建。
- 是否有批量 UPDATE 或 DELETE。
- 是否做过分区表拆合。
- 是否迁移了大量数据。
如果是正常业务变化导致的变化块增加,可以评估是否调整为累积增量、是否调大0级备份频率。
如果确实存在低效操作,比如一次性更新一张大部分行都变化的表,与其用1级增量承载这种变化,不如考虑在业务低峰期直接做一次0级备份,把恢复链路重新拉直。
6.4 备份分片缺失的处理
备份片文件丢失,一般先CROSSCHECK BACKUP确认哪些备份记录失效。如果确认失效的备份片没有其他依赖,直接DELETE EXPIRED BACKUP清理。如果失效的是当前恢复链上的基础备份,就要立刻安排新的0级备份,不能拖着不管。
在清理备份前评估依赖关系,最省事的方法是先把LIST BACKUP SUMMARY和RESTORE DATABASE PREVIEW的输出留档。这样每次删除之前,都知道当前恢复链最关键的备份是哪一组。
6.5 一个更稳妥的日常习惯
接手新环境时,不要急着调优备份速度,先把现有备份情况摸一遍:0级在哪、1级在哪、全备在哪、归档日志覆盖范围是什么。然后再决定要不要调整备份策略。
我自己实践的固定动作是:每周末跑完0级备份后,顺手导出一次LIST BACKUP SUMMARY放到值班文档里。这样任何人接到这个环境,都能在十分钟内判断出当前恢复链是否完整。这套方法不复杂,但真的能避免很多“看起来备份都正常、恢复时却各种失败”的尴尬。
备份管理这个事,最怕的不是命令不会写,而是概念不清晰。0级、全备、1级增量、备份分片、delete backup,每一个词背后都牵着一套完整的依赖逻辑。把这些依赖关系理顺了,恢复演练才有底气。