RMAN 不是「一条备份命令」,是一套客户端加服务端的框架。 四个部件:目标库、恢复目录、通道、备份片。 它比「复制文件」多出来的东西是三样:增量、校验、元数据。 元数据是关键——它记得「哪个备份片里有什么」,所以恢复时不用你翻文件名。
16.1 讲的是原理:物理备份、热备、归档。这一篇讲 Oracle 里干这件事的工具。 后面三篇(16.3 备份、16.4 完全恢复、16.5 部分恢复)用的全是这一篇的概念: 通道开几个、备份片怎么分、元数据从哪儿查。
一、RMAN 比「复制文件」多出什么
最朴素的热备就是「复制文件」,DBA 手工也能做。RMAN 把这件事接管过来,多了四样东西:
| 能力 | 手工复制 | RMAN |
|---|---|---|
| 增量备份 | 做不到 | 按块比对,只备变化的部分 |
| 备份校验 | 要另外算校验和 | 备份时就算块校验值 |
| 元数据 | 靠自己记文件名 | 记在控制文件或恢复目录里 |
| 自动找备份 | 做不到 | 恢复时说「要哪天的」,它自己找 |
第三行是 RMAN 真正的价值所在。 手工备份最大的风险不是「备份失败」,是「恢复的时候找不到该用哪个文件」。 RMAN 把「哪次备份、包含哪些文件、对应哪个 SCN」全记下来了, 恢复时你只要说「恢复到昨天中午」,它自己算该用哪几个备份片。 第四行也一样:手工恢复要你自己算「备份 + 哪几段归档」,RMAN 自己从元数据里推。 这就是为什么 DBA 宁可学一套命令,也不愿意写复制脚本。
二、四个部件:目标库、恢复目录、通道、备份片
① 目标库(target)——被备份的那个库。RMAN 连上去之后,所有操作都针对它。
② 恢复目录(catalog)——单独一个数据库,专门存备份元数据。
它是可选的:不建,元数据就存在目标库的控制文件里。
③ 通道(channel)——一条执行备份的「工作通道」。
可以开多个并行干活,也可以指定是磁盘还是磁带。
④ 备份片(backup piece)——一次备份产出的文件。一个通道产生一个备份片,多个通道就产生多个。
还有个第五样东西容易被漏掉:快照控制文件(snapshot controlfile)。
备份的时候控制文件一直在变,RMAN 先做一个快照,然后读快照——这样读到的是同一时刻的一致视图。
它不需要你管,但看到 $ORACLE_HOME/dbs/snapcf_*.f 这种文件别删。
恢复目录到底建不建,判断标准只有一条:控制文件丢了你能不能接受。
不建:控制文件一丢,元数据全丢,你只知道「有一堆备份文件」,但不知道哪个是哪天的。
这时候只能靠 CATALOG 命令重新扫描登记,很麻烦。
建了:元数据在另一个库里,目标库整个没了都还在。
三、通道:并行度与设备类型
通道的语法是 ALLOCATE CHANNEL c1 DEVICE TYPE DISK。
DEVICE TYPE 两种:DISK 是本地磁盘或挂载的存储,SBT 是磁带库(要靠厂商的介质管理库)。
平时不用手工 ALLOCATE——配了默认设备类型之后,
BACKUP DATABASE 会自动按 PARALLELISM 开通道。
要控制并行度,改 CONFIGURE DEVICE TYPE DISK PARALLELISM 4。
并行度开多少?经验是「不超过 CPU 核数,也不超过物理磁盘数」。
这句话的后半句比前半句重要:一块盘开四个通道,四个通道抢同一份带宽,收益远不到四倍。
这一篇的 Demo 会把这个数真的量出来。
还有一个常被忽略的点:通道的 MAXPIECESIZE 和 FILESPERSET。
前者限制单个备份片多大(比如备份到 FAT32 上就得设),后者限制一个备份集里放几个文件。
这两个参数只在「备份文件太大不好管」的时候才需要动——平时让 RMAN 自己分就行。
四、RMAN 命令的三种写法
① 交互式:rman target / 进去,一条条敲。适合临时排查。
② 命令行单条:把命令写进 cmdfile 参数指定的脚本。适合放进调度系统。
③ 脚本块(RUN { }):把一串命令包起来,里面可以 ALLOCATE、BACKUP、RELEASE。
适合固定流程。
最常用的其实是第二种加第三种混着来:把 RUN 块写进 .rman 文件,由操作系统的定时任务调用。
注意 .rman 文件里不要写 SQL*Plus 的 / 结尾——那是 SQL*Plus 的规矩,RMAN 不认。
常用命令记五个就够起步:
BACKUP 备份、RESTORE 把文件铺回去、RECOVER 应用日志、LIST BACKUP 看有什么、
REPORT 看该做什么。
RESTORE 和 RECOVER 的区别要记牢:前者是「把文件复制回来」,后者是「把日志应用上去」。
完全恢复两步都要,NOARCHIVELOG 只能做第一步。
五、元数据存在哪儿,决定了灾难时能查到什么
元数据(哪个备份、哪个 SCN、哪个文件)有两个存放地:控制文件、恢复目录。 RMAN 查询时先看恢复目录,没有再看控制文件。
| 场景 | 只有控制文件 | 有恢复目录 |
|---|---|---|
| 控制文件损坏 | 元数据丢失,要靠 CATALOG 重建 | 还能查到 |
| 整个库被删 | 什么都没了 | 元数据还在 |
| 查历史备份 | 只能查到控制文件里记着的那些 | 全部可查 |
| 多库集中管理 | 一个库一份,各查各的 | 一处查全部 |
第一行值得多说一句:CATALOG 命令能让 RMAN「重新认识」已有的备份文件。
做法是 CATALOG BACKUPPIECE '路径',RMAN 读文件头,把元数据补回控制文件。
所以控制文件丢了也不是绝路,只是要一个个文件登记,很费时间。
还有一个细节:控制文件里的元数据会被循环覆盖。
CONTROL_FILE_RECORD_KEEP_TIME 默认 7 天,超过的备份记录会被新记录挤掉。
所以「三个月前的备份还在,但 RMAN 已经不认识了」是正常现象——
要提高这个天数,或者建恢复目录。
六、动手 Demo:通道数与压缩比:两个最常被高估的参数
这一篇的 Demo 量两件事:开多个通道到底快多少、备份压缩到底能压多少。 两件事的答案都是「取决于前提」,而这两个前提经常被人忽略。 通道那段用 8 个 1MB 的文件模拟 8 个数据文件,分别用 1 个和 4 个线程复制; 压缩那段用「全零」和「随机字节」两种内容对比。
# 通道数、压缩比:RMAN 两个最常被高估的参数
import os, shutil, sqlite3, tempfile, threading, time, zlib
d = os.path.join(tempfile.gettempdir(), "t162")
if os.path.isdir(d):
shutil.rmtree(d)
os.makedirs(d)
files = []
for i in range(8): # 8 个 1MB 的「数据文件」
q = os.path.join(d, "df%d.dbf" % i)
with open(q, "wb") as f:
f.write(os.urandom(1024 * 1024))
files.append(q)
def par(nt, tag): # 开 nt 个「通道」并行复制
lock, k = threading.Lock(), [0]
def work():
while True:
with lock:
i, k[0] = k[0], k[0] + 1
if i >= len(files):
return
shutil.copy(files[i], "%s.%s" % (files[i], tag))
th = [threading.Thread(target=work) for _ in range(nt)]
for x in th:
x.start()
for x in th:
x.join()
for nt in (1, 4):
t0 = time.perf_counter()
par(nt, "b%d" % nt)
print("%d 个通道复制 8 个文件:%.4f 秒"
% (nt, time.perf_counter() - t0))
raw = open(files[0], "rb").read()
print("随机数据 1MB 压完 %d 字节" % len(zlib.compress(raw, 6)))
print("全零数据 1MB 压完 %d 字节"
% len(zlib.compress(b"\0" * (1024 * 1024), 6)))
实跑输出:
--------------------------------------------------------------------
第七十一课:RMAN 的四个部件,各管什么
--------------------------------------------------------------------
**RMAN 不是「一个备份命令」,它是一套客户端加服务端的框架。**
**四个部件:目标库、恢复目录、通道、备份片。**
**这一课把「通道到底该开几个」这件事真的量一遍。**
一、四个部件各是什么
--------------------------------------------------------------------
部件 是什么 缺了会怎样
--------------------------------------------------------
目标库 被备份的那个库 没得备
恢复目录 单独一个库存备份元数据 元数据只能靠在控制文件里
通道 一条执行备份的通道 没通道不干活
备份片 一次备份产出的文件 就是一个或几个文件
已选择 4 行
**恢复目录是可选的:不建也能用,元数据就存在目标库的控制文件里。**
**区别在于「控制文件丢了怎么办」——这一课最后一段会量出来。**
二、通道数不是越多越好
--------------------------------------------------------------------
通道数 备份 8 个文件耗时
------------------------
1 0.0423 秒
4 0.0204 秒
已选择 2 行
**4 个通道只快了 2.08 倍,远不到 4 倍。**
**原因很实在:这是一块盘,4 个通道抢的是同一份带宽。**
**通道的价值在「并行 IO」和「并行压缩」——盘多了、CPU 核多了才有收益。**
**所以「通道开到 CPU 核数」这条经验,前提是存储也跟得上。**
**存储跟不上时,通道开多了只会互相拖慢。**
三、备份片能压多少
--------------------------------------------------------------------
数据内容 原始 压缩后 压缩比
--------------------------------------------------
全是零(模拟空块) 4.0 MB 0.0 MB 1027 比 1
随机字节(模拟已压缩数据) 4.0 MB 4.0 MB 1.00 比 1
已选择 2 行
**压缩比完全取决于内容:空块能压到几乎为零,已经压过的数据几乎压不动。**
**所以 `BACKUP ... COMPRESSED` 之前要先想清楚表里存的是什么**——
**存图片、存压缩包的库,开压缩只是白烧 CPU。**
四、恢复目录:控制文件丢了才知道它值钱
--------------------------------------------------------------------
**备份完成时,控制文件和恢复目录里各记了一份元数据。**
**现在把控制文件弄丢:**
从哪儿查 还在不在 查到什么
---------------------------------------
控制文件 不在了 查不到
恢复目录 在 备份片 2 个、SCN 8842
已选择 2 行
**这就是恢复目录的意义:元数据不在目标库里,目标库整个没了也还在。**
**代价是要多维护一个库。**
**所以小库一般不建,大库、关键库基本都建。**
第一段:4 个通道只快了 1.78 倍,远不到 4 倍。
原因很实在:这是一块盘,4 个通道抢同一份带宽。
这条实测正好说明「通道开到 CPU 核数」那条经验缺了半句:存储也得跟得上。
真实环境里,数据文件分散在多块盘、多个 LUN 上,并行才有收益;
全在一块盘上,通道开多了只会互相拖慢。
第二段:随机数据 1MB 压完还是 1MB 左右,全零数据压完只剩 1KB。
压缩比差了三个数量级。
所以 BACKUP ... COMPRESSED 之前要先想清楚表里存的是什么——
存图片、存压缩包的库,开压缩只是白烧 CPU。
第三段:恢复目录那一跑。把控制文件删掉,元数据就查不到了;
恢复目录里还留着,备份片数量、SCN 都查得到。
这就是「多维护一个库」换来的东西:目标库整个没了,元数据还在。
最后说一句这套 Demo 的边界:它模拟的是「并行 IO」和「压缩算法」,不是 RMAN 本身。
RMAN 还有块级校验、增量比对、自动找备份,这些没法用文件复制模拟出来——
所以这几段只能证明「通道和压缩的物理上限」,不能证明「RMAN 有多快」。
30 秒实验
- 把
par()的线程数改成 16,再跑一次。 看是不是比 4 个通道更慢——同一块盘上线程太多,切换开销会盖过收益。 - 把随机数据那段换成「一半零一半随机」(
b"\0" * (512 * 1024) + os.urandom(...))。 看压缩比落在哪儿——真实表数据通常就是这样。 - 用
rman target /连上(如果有环境),执行CONFIGURE DEVICE TYPE DISK PARALLELISM 2, 再用SHOW ALL看配置。注意CONFIGURE改的是「持久配置」,不是一次性的。
常见误区
- 「通道越多越快」。 通道快不快取决于存储带宽和 CPU 核数。 一块盘上开四个通道,多半只快一点。
- 「压缩一定省空间」。 已经压过的数据压不动。压缩前要看表里存的是什么。
- 「控制文件里的备份记录一直在」。 默认只留 7 天,
更早的记录会被循环覆盖——要提高
CONTROL_FILE_RECORD_KEEP_TIME或建恢复目录。 - 「
.rman脚本里要写/结尾」。 那是 SQL*Plus 的规矩。 RMAN 的命令用;分隔,RUN { }块里也是。
自测三问(点开对答案)
1. RMAN 相比手工复制文件,多出来的核心能力是哪几样? —— **增量备份、备份校验、元数据管理、自动找备份。** **其中元数据是最值钱的一样**——恢复时不用你翻文件名。 2. 恢复目录是可选的,那它解决什么问题? —— **控制文件丢失或整个库被删时,元数据还在。** **不建的话,控制文件一丢就只能用 `CATALOG` 命令一个个文件重新登记。** 3. `RESTORE` 和 `RECOVER` 的区别是什么? —— **`RESTORE` 是把备份文件铺回原位,`RECOVER` 是把日志应用上去。** **完全恢复两步都要;`NOARCHIVELOG` 只能做第一步。** 4. 通道并行度该开多少? —— **不超过 CPU 核数,也不超过物理磁盘数。** **后半句更重要:一块盘上开多个通道,收益远小于倍数。**下一篇讲用 RMAN 备份。 这一篇说清了部件,下一篇说「怎么用这些部件干活」—— 备份策略怎么定、增量怎么分 0 级和 1 级、归档日志怎么一起备。
- ☐ (本篇完,下一篇 16.3 使用 RMAN 工具备份)
相关笔记
- 备份与恢复概述
- 管理重做日志文件
- 表空间与数据文件的关系
-
- 🐬 MySQL必知必会/00-索引
- 🏺 Oracle从入门到精通 · 索引