接手这套 Linux 环境下的 Oracle 11g 数据库没多久,就被一次凌晨的误操作给教育了。运维同事在业务表上做批量更新时 where 条件漏了关键值,影响了近 20 万行数据,而当时手里只有每天凌晨 2 点通过 expdp 定时导出的逻辑备份。最后恢复倒是恢复了,但是整个链路走了差不多三个小时,中间还夹杂着表结构依赖、触发器重放、序列不同步这些乱七八糟的问题。那次之后我做的第一件事,就是把这套库的备份体系从 expdp 逻辑备份切换成 RMAN 物理备份,并按"全量+增量+crontab 定时任务"的节奏落地运行。这篇就是把整个实施过程、脚本设计和踩过的坑完整梳理一遍。
我这边环境是 CentOS 7.9,Oracle 11.2.0.4 单实例,没有上 RAC,数据库也不是特别大,数据体量大概在 700GB 左右,归档产生速度每天约 5GB 到 8GB。这个量级也是我想重点说的地方:RMAN 全量+增量+定时任务的方案,其实最适合的就是这种几百 GB 到几 TB 的中小型库。如果你手上有几十 TB 的仓库系统,那大概率要上增量备份 + 磁带 + 更多容灾手段的组合,本文这个思路可以当参考,但别直接套用。
1. 为什么最终选了 RMAN 全量+增量这套组合,而不是 expdp 或冷备份
先说清楚一个容易被忽略的点:备份方案的选择,本质上是"恢复时间"和"备份成本"之间的博弈。很多人一上来就问"用什么备份工具",其实应该先问"如果数据库坏了,你准备花多长时间恢复、能接受丢多少数据"。
1.1 expdp 逻辑备份的问题在哪里
expdp 导出的只是逻辑数据,不是数据库文件级别的物理副本。它本身并不是不能用,而是当你的恢复目标变成"把数据库恢复到 N 分钟前那个状态"时,逻辑备份会非常吃力。
举个例子,原来我们每天凌晨用 expdp 做全库导出,但是白天某张表被误删了数据,你想恢复到误删之前,怎么办?你只有昨天凌晨 2 点的 expdp 文件,恢复出来之后,昨天凌晨 2 点到今天上午之间所有的新增数据全部丢失。如果这个间隔里恰好有重要的业务单据、账务流水,那就只能补录或者回溯上游接口,这个工作量通常比恢复本身还要大。
另外 expdp 恢复是"数据导入"的过程,如果源库有非常复杂的对象依赖、自增序列、触发器、外键约束,导入时顺序搞错会导致大量的报错。再加上几百万行的表导入本来就慢,这个恢复速度在灾难场景下是致命的。
1.2 冷备份为什么没进入候选
冷备份(数据库正常 shutdown 之后把数据文件、控制文件、日志文件直接拷贝一份)在理论上是可靠的,一致性也最好,但是它对业务的影响是"整个数据库必须停机"。700GB 的库,正常 shutdown 其实几秒钟就完成了,但是 cp 700GB 文件,走千兆网络、普通 SAS 盘,差不多要一个小时以上。如果数据库是 7x24 小时有业务在跑,这个停机时间基本无法接受。
而且冷备恢复虽然简单,但它没有任何增量机制。今天冷备完,明天数据库崩了,只能恢复到昨天晚上冷备那个时间点,中间丢了一天。这个数据丢失量在很多业务场景下是不合格的。
1.3 RMAN 全量+增量真正解决的是什么
RMAN 是 Oracle 自带的物理备份工具,它备份的是真实的数据文件、控制文件、spfile,并且能在备份件里记录 SCN 信息。这意味着它支持真正的"增量"概念——以 SCN 为基准,只备份自上次备份以来发生过变化的块。
在恢复侧,RMAN 的能力就很直观了:用全量备份件把数据库恢复到全量那个点,然后用增量备份把数据推进到增量那个点,最后再通过应用归档日志把数据库推到故障前那一刻。这个恢复路径比 expdp 导入要快得多,因为备份件是 Oracle 内部直接识别的文件格式,不需要重新组装表结构、约束、触发器等逻辑对象。
所以最终我选择的是这样一套节奏:
- 每周日凌晨做一次 RMAN 全量备份(Level 0);
- 周一到周六凌晨做一次 RMAN 增量备份(Level 1);
- 每次备份时顺便备份归档日志,并在确认归档日志备份成功后删除本地的归档文件;
- 通过 crontab 定时任务每天自动执行,并加上日志和告警机制;
- 每个月底做一次恢复演练。
这套方案能保证:任何时间点发生故障,理想情况下最多丢失上一次归档日志备份之后重新产生的少量归档,恢复时间也就是"全量恢复+增量应用+归档应用"的总时长。对于量级在 TB 以下的生产库,这个 RTO/RPO 在可控范围内。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 开工前的三件事:归档模式、备份目录、磁盘空间预算
很多第一次搭 RMAN 的人容易一头扎进脚本里,结果跑到一半发现数据库没开归档,或者备份目录所在的文件系统空间不足。准备工作其实比写脚本重要得多。
2.1 确认并切换归档模式
RMAN 如果不开归档,那么你只能做一致性冷备份,增量备份是跑不了的,因为联机重做日志切换后旧日志会被覆盖,没有历史归档可供增量恢复时使用。
可以通过下面的 SQL 确认当前数据库是否为归档模式:
sql复制SQL> SELECT log_mode FROM v$database;
LOG_MODE
------------
NOARCHIVELOG
如果返回 NOARCHIVELOG,就需要执行以下操作切换:
sql复制SQL> SHUTDOWN IMMEDIATE;
SQL> STARTUP MOUNT;
SQL> ALTER DATABASE ARCHIVELOG;
SQL> ALTER DATABASE OPEN;
SQL> ALTER SYSTEM ARCHIVE LOG START;
SQL> SELECT log_mode FROM v$database;
切换完成后建议设置一个显式的归档目录。常见的做法有两种:一是使用快速恢复区(FRA),二是单独指定 log_archive_dest。我这边没有把归档和数据库文件放在同一个文件系统上,而是单独挂了一块盘,路径为 /u01/archivelog。
sql复制SQL> ALTER SYSTEM SET log_archive_dest_1='LOCATION=/u01/archivelog' SCOPE=BOTH;
SQL> ALTER SYSTEM SET log_archive_format='arch_%t_%s_%r.arc' SCOPE=SPFILE;
因为 log_archive_format 是静态参数,所以我用 SCOPE=SPFILE 让它下次启动生效。
2.2 备份目录结构规划
备份目录如果不提前规划,跑一段时间后就会变成一锅粥。我这边设计的目录结构如下:
code复制/u01/rman_backup/
├──
