之前的文章里提到的使用数据泵 expdp 进行数据库备份的 dump 文件只能算"逻辑备份",它不能配合归档日志做"时间点恢复",只能"回到导出那一刻",而且单表级、对象级可用,整库灾难恢复基本靠不住,所以这边介绍一下Oracle 数据库中的物理备份。
简单介绍一下物理备份和逻辑备份的区别:
| 类型 | 工具 | 能否做时间点恢复 | 能否救硬件级灾难 | 备注 |
|---|---|---|---|---|
| 物理备份 | RMAN / 冷备 / 热备 | √(靠归档日志) | √(块级、坏盘、勒索) | 必须备份数据文件、控制文件、归档 |
| 逻辑备份 | expdp / exp / pg_dump | × | × | 只能"回到导出瞬间",单表/对象级恢复快 |
这里使用 RMAN 备份,以下是详细步骤(本次演示采用 Windows 10 + Oracle19c 环境,以下命令全部基于命令行窗口执行)。
开始物理备份
1、准备工作,命令行进入SQL窗口,查看是否开启归档模式,如果是禁用的话,可以参考上一篇文章Oracle 开启归档日志 开启一下。
sql
C:\> sqlplus
SQL> archive log list;

2、创建一个保存备份文件的物理目录。

3、启动 RMAN(同一 cmd 窗口即可)
sql
C:\Users\AO>rman target /
4、打开控制文件自动备份(一次性配置,永久生效)
sql
# 以后任何 backup 命令都会自动带一份控制文件
RMAN> CONFIGURE CONTROLFILE AUTOBACKUP ON;
5、设置备份文件路径和压缩格式(一次性配置,可反复改,这里的路径写刚才自己建的)
sql
# %d = 库名,%T = 年月日,%U = 唯一序列
RMAN> CONFIGURE CHANNEL DEVICE TYPE DISK FORMAT 'D:\Oracle19c\rmanBackup\%d_%T_%U.bkp';
6、设置并行度 2(CPU 核数少可改成 1)
这个并行度可以影响到下面的备份时设置的通道数量,两个通道执行会快一点。
sql
# 以后凡是用磁盘做备份,一律默认开 2 个通道(并行度=2)同时写,并且把数据压成压缩备份集(COMPRESSED BACKUPSET)
RMAN> CONFIGURE DEVICE TYPE DISK PARALLELISM 2 BACKUP TYPE TO COMPRESSED BACKUPSET;
7、设置保留策略:至少留 2 份全备
sql
RMAN> CONFIGURE RETENTION POLICY TO REDUNDANCY 2;
这里就完成了RMAN的基本配置,执行情况如图:

8、开始备份(如果备份不想删除归档日志,可以把 DELETE INPUT 给去掉)
这里设置了两个通道,有必要提一句,设置两个通道的话,一个备份集可能生成多个文件,如: system01.dbf (1GB)、users01.dbf (2GB)、undotbs01.dbf (3GB)
RMAN可能这样分配:备份片1:包含system01.dbf + users01.dbf的一部分
备份片2:包含users01.dbf剩余部分 + undotbs01.dbf,
具体执行情况我下面会展示:
sql
RUN {
ALLOCATE CHANNEL c1 DEVICE TYPE DISK;
ALLOCATE CHANNEL c2 DEVICE TYPE DISK;
BACKUP ARCHIVELOG ALL FORMAT 'D:\Oracle19c\rmanBackup\arch_%T_%U.bkp' DELETE INPUT;
BACKUP DATABASE FORMAT 'D:\Oracle19c\rmanBackup\db_%T_%U.bkp' TAG='FULL_20251112';
BACKUP CURRENT CONTROLFILE FORMAT 'D:\Oracle19c\rmanBackup\ctl_%T_%U.bkp';
BACKUP SPFILE FORMAT 'D:\Oracle19c\rmanBackup\spfile_%T_%U.bkp';
RELEASE CHANNEL c1;
RELEASE CHANNEL c2;
}
这里的内容比较多,注释就放在下面写了。
%T - 日期格式:当前日期,格式为 YYYYMMDD,如果今天是 2025年4月15日,%T 会生成 20250415;
%U - 唯一标识符:RMAN 自动生成的唯一字符串(基于 DBID、时间戳、序列号等);
sql
RUN {
# 分配第一个磁盘通道 c1(只是相当于一个变量名,随便取的),用于并行备份操作
ALLOCATE CHANNEL c1 DEVICE TYPE DISK;
# 分配第二个磁盘通道 c2,用于并行备份操作(提升备份速度)
ALLOCATE CHANNEL c2 DEVICE TYPE DISK;
# 备份所有归档日志文件,并使用指定格式命名备份文件
# 备份完成后删除已备份的归档日志(DELETE INPUT)
# 注意:如果某些归档日志文件缺失,此命令会报错,建议加上 SKIP INACCESSIBLE
BACKUP ARCHIVELOG ALL FORMAT 'D:\Oracle19c\rmanBackup\arch_%T_%U.bkp' DELETE INPUT;
# 执行完整数据库备份,使用指定格式命名备份文件,并打上标签便于识别
BACKUP DATABASE FORMAT 'D:\Oracle19c\rmanBackup\db_%T_%U.bkp' TAG='FULL_20251112';
# 备份当前控制文件,使用指定格式命名备份文件
BACKUP CURRENT CONTROLFILE FORMAT 'D:\Oracle19c\rmanBackup\ctl_%T_%U.bkp';
# 备份服务器参数文件(SPFILE),使用指定格式命名备份文件
BACKUP SPFILE FORMAT 'D:\Oracle19c\rmanBackup\spfile_%T_%U.bkp';
# 释放第一个通道 c1
RELEASE CHANNEL c1;
# 释放第二个通道 c2
RELEASE CHANNEL c2;
}
实操如图:

在刚才创建的目录下就可以看到已经备份好的文件了,这里就是刚才说的,一个备份集可以分成好几个备份片。

虽然被分成了多个备份片,但是 RMAN 会自动识别这是同一个备份集的两个片,自动读取两个备份片来恢复完整的数据库,所以并不需要担心。
但是有人可能不太喜欢这种分散的,希望每个备份文件都是独立完整的,不希望被分割成多个片,推荐的方式就是,只使用一个通道,就是上面说的,并且备份不删除归档日志,如:
sql
RUN {
ALLOCATE CHANNEL c1 DEVICE TYPE DISK;
BACKUP ARCHIVELOG ALL FORMAT 'D:\Oracle19c\rmanBackup\arch_%T_%U.bkp';
BACKUP DATABASE FORMAT 'D:\Oracle19c\rmanBackup\db_%T_%U.bkp' TAG='FULL_20251112';
BACKUP CURRENT CONTROLFILE FORMAT 'D:\Oracle19c\rmanBackup\ctl_%T_%U.bkp';
BACKUP SPFILE FORMAT 'D:\Oracle19c\rmanBackup\spfile_%T_%U.bkp';
RELEASE CHANNEL c1;
}
实操如下:

这样备份的文件,每个都是独立文件:

删除备份文件
这里的删除跟删除归档日志一样,也不能直接去硬盘目录直接删除,不然会导致 RMAN资料库记录与实际文件不一致、可能导致后续备份/恢复失败、无法正确管理备份生命周期等问题。
删除前,先查询一下,有哪些备份集。
sql
# 查看所有备份集
RMAN> LIST BACKUPSET;
# 2025-11-12 00:00:00 后的备份集(可以不用精确到秒)
RMAN> LIST BACKUPSET COMPLETED BEFORE "TO_DATE('2025-11-12 00:00:00', 'YYYY-MM-DD HH24:MI:SS')";
1、根据日期删除(删除 7 天前的备份):
sql
## 删除7天前的备份
RMAN> DELETE BACKUPSET COMPLETED BEFORE 'SYSDATE-7';
2、根据配置的保留策略来进行删除(先配置保留策略)。
# 2. 定期清理过期备份
RMAN> DELETE OBSOLETE;
常见保留策略如下:
sql
# 1. 恢复窗口策略 - 保留最近7天可恢复
RMAN> CONFIGURE RETENTION POLICY TO RECOVERY WINDOW OF 7 DAYS;
# 2. 备份份数策略 - 保留至少2个完整备份
RMAN> CONFIGURE RETENTION POLICY TO REDUNDANCY 2;
# 3. 不保留任何备份(不推荐)
RMAN> CONFIGURE RETENTION POLICY TO NONE;
我这里展示删除所有的备份集(没加日期,注意):

还原备份文件
1、启动RMAN并连接
sql
rman target /
2、启动数据库到 nomount 状态,如果数据库已经启动,要先关掉。
sql
# 如果实例正在 open/mount,先关掉
RMAN> shutdown immediate;
# 启动到 nomount(内存+进程已起,控制文件尚未就位)
RMAN> startup nomount;
3、把备份片注册进控制文件,这里的路径就是放置备份文件的位置(确保RMAN能找到)。
sql
RMAN> catalog start with 'D:\Oracle19c\rmanBackup\';
4、若需要还原 spfile(新机器无参数文件)
sql
RMAN> restore spfile from 'D:\Oracle19c\rmanBackup\SPFILE_20251113_0H48LRLE_1_1.BKP';
RMAN> shutdown immediate;
RMAN> startup nomount; -- 用刚还原的 spfile 重新启动
5、还原控制文件,并挂载数据库
sql
RMAN> restore controlfile from 'D:\Oracle19c\rmanBackup\CTL_20251113_0G48LRLC_1_1.BKP';
RMAN> alter database mount;
6、还原数据文件并恢复,RMAN 会自动搜索归档日志备份文件
sql
RMAN> restore database;
RMAN> recover database;
7、打开数据库(重置日志)
sql
RMAN> alter database open resetlogs;
最基本的恢复就是这样,但是一开始提到的,物理备份是可以精确到秒级恢复的,在还原数据库这一步,就是上面第 6 步,开始操作:
sql
# 在恢复数据库前,加一个精确恢复到指定时间点,如果只需要精确到某一天,也可以把后面的删了
RMAN> set until time "to_date('2025-11-13 14:30:00','YYYY-MM-DD HH24:MI:SS')";
RMAN> restore database;
RMAN> recover database;
查询可以恢复的备份时间段
sql
RMAN> list backup of archivelog all;
有的人打印出来可能是不能精确到秒的,就像这样

这个不是 RMAN 不能到秒,而是 NLS 日期格式默认只显示到"日",可以把会话的日期格式改一下,就能立刻看到"秒"。
进入 Windows 命令行(先设 NLS 格式,再启 RMAN)
sql
C:\Users\AO>set NLS_DATE_FORMAT=yyyy-mm-dd hh24:mi:ss
完整查看:
