如何通过RMAN多节点通道并行配置加速Oracle 19c RAC备份?
- 内容介绍
- 文章标签
- 相关推荐
本文共计985个文字,预计阅读时间需要4分钟。
相关专题:
rman 默认只连一个节点,rac 备份速度上不去是常态,不是配置错误,而是没显式控制通道归属。
为什么 RMAN 在 RAC 里默认不并行
RMAN 启动时若用 / as sysdba 或仅指定 target /,它会随机连接到某个实例(取决于 ORACLE_SID 或本地监听),所有 ALLOCATE CHANNEL 都落在同一个节点上。I/O 和 CPU 瓶颈立刻出现,哪怕开了 8 个通道也无济于事。
关键点在于:CONNECT 子句必须显式写进每个通道定义里,且目标必须是能路由到具体实例的 TNS 别名——不是 SCAN 地址,也不是 service_name。
- 错误写法:
CONNECT 'sys/oracle@racdb_scan'→ 报ORA-12154或随机落点 - 正确写法:
CONNECT 'sys/oracle@racdb1',其中racdb1是tnsnames.ora中定义的、指向 node1 实例的静态条目 - 每个通道的
DEVICE TYPE DISK路径建议挂载在对应节点本地或低争用共享存储(如 ACFS),避免多个节点同时往同一 NFS 目录写导致锁等待
怎么写一个真正跨节点的并行备份脚本
以下是一个双节点 RAC 的最小可行备份块,直接可用:
RUN { ALLOCATE CHANNEL c1 DEVICE TYPE DISK CONNECT 'sys/oracle@racdb1'; ALLOCATE CHANNEL c2 DEVICE TYPE DISK CONNECT 'sys/oracle@racdb2'; BACKUP DATABASE PLUS ARCHIVELOG FORMAT '/bak/rman/%d_%T_%t_%s_%p'; }
注意几个实操细节:
-
FORMAT路径(如/bak/rman/...)必须在两个节点都挂载且 oracle 用户可写;如果是 NFS,需确认 mount 参数含hard,rsize=32768,wsize=32768,vers=3 - 不要在
BACKUP命令里加PARALLELISM—— 它只控制单个通道内的子通道,和跨节点无关 - 若启用 block change tracking(推荐),确保它在所有实例都生效:
ALTER DATABASE ENABLE BLOCK CHANGE TRACKING USING FILE '+DATA';
恢复时通道不匹配的典型报错和修复
备份用了 racdb1 和 racdb2,但恢复时只连了 / 或只配了一个通道,就会触发看似诡异的错误:
-
ORA-19566: exceeded limit of 0 corrupt blocks—— 实际是路径不存在,RMAN 误判为校验失败 -
RMAN-06023: no backup or copy of datafile ... found to restore—— 控制文件里注册了备份片,但当前节点根本访问不到那个路径 - 恢复命令卡住,
V$SESSION_LONGOPS显示大量control file sequential read
修复步骤很明确:
- 先运行
CATALOG START WITH '/bak/rman/';,确保所有备份片被识别进控制文件 - 再执行恢复前,严格复刻备份时的通道结构:
ALLOCATE CHANNEL c1 CONNECT 'sys/oracle@racdb1';、ALLOCATE CHANNEL c2 CONNECT 'sys/oracle@racdb2'; - 即使备份片放在共享 ASM 磁盘组(如
+FRA),也建议恢复时仍按原节点分配通道,减少跨节点元数据竞争
tnsnames.ora 缺少单实例别名是最容易被忽略的前置条件
很多 DBA 只配了 SCAN 名(如 racdb_scan),但 RMAN 的 CONNECT 不支持 service_name 路由,必须有明确指向某实例的 TNS 条目。
示例 tnsnames.ora 片段(每个节点都要有):
racdb1 = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = rac1-vip)(PORT = 1521)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = racdb) (INSTANCE_NAME = racdb1) ) ) racdb2 = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = rac2-vip)(PORT = 1521)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = racdb) (INSTANCE_NAME = racdb2) ) )
漏掉这个,ALLOCATE CHANNEL ... CONNECT 会直接失败,后面所有优化都白搭。
本文共计985个文字,预计阅读时间需要4分钟。
相关专题:
rman 默认只连一个节点,rac 备份速度上不去是常态,不是配置错误,而是没显式控制通道归属。
为什么 RMAN 在 RAC 里默认不并行
RMAN 启动时若用 / as sysdba 或仅指定 target /,它会随机连接到某个实例(取决于 ORACLE_SID 或本地监听),所有 ALLOCATE CHANNEL 都落在同一个节点上。I/O 和 CPU 瓶颈立刻出现,哪怕开了 8 个通道也无济于事。
关键点在于:CONNECT 子句必须显式写进每个通道定义里,且目标必须是能路由到具体实例的 TNS 别名——不是 SCAN 地址,也不是 service_name。
- 错误写法:
CONNECT 'sys/oracle@racdb_scan'→ 报ORA-12154或随机落点 - 正确写法:
CONNECT 'sys/oracle@racdb1',其中racdb1是tnsnames.ora中定义的、指向 node1 实例的静态条目 - 每个通道的
DEVICE TYPE DISK路径建议挂载在对应节点本地或低争用共享存储(如 ACFS),避免多个节点同时往同一 NFS 目录写导致锁等待
怎么写一个真正跨节点的并行备份脚本
以下是一个双节点 RAC 的最小可行备份块,直接可用:
RUN { ALLOCATE CHANNEL c1 DEVICE TYPE DISK CONNECT 'sys/oracle@racdb1'; ALLOCATE CHANNEL c2 DEVICE TYPE DISK CONNECT 'sys/oracle@racdb2'; BACKUP DATABASE PLUS ARCHIVELOG FORMAT '/bak/rman/%d_%T_%t_%s_%p'; }
注意几个实操细节:
-
FORMAT路径(如/bak/rman/...)必须在两个节点都挂载且 oracle 用户可写;如果是 NFS,需确认 mount 参数含hard,rsize=32768,wsize=32768,vers=3 - 不要在
BACKUP命令里加PARALLELISM—— 它只控制单个通道内的子通道,和跨节点无关 - 若启用 block change tracking(推荐),确保它在所有实例都生效:
ALTER DATABASE ENABLE BLOCK CHANGE TRACKING USING FILE '+DATA';
恢复时通道不匹配的典型报错和修复
备份用了 racdb1 和 racdb2,但恢复时只连了 / 或只配了一个通道,就会触发看似诡异的错误:
-
ORA-19566: exceeded limit of 0 corrupt blocks—— 实际是路径不存在,RMAN 误判为校验失败 -
RMAN-06023: no backup or copy of datafile ... found to restore—— 控制文件里注册了备份片,但当前节点根本访问不到那个路径 - 恢复命令卡住,
V$SESSION_LONGOPS显示大量control file sequential read
修复步骤很明确:
- 先运行
CATALOG START WITH '/bak/rman/';,确保所有备份片被识别进控制文件 - 再执行恢复前,严格复刻备份时的通道结构:
ALLOCATE CHANNEL c1 CONNECT 'sys/oracle@racdb1';、ALLOCATE CHANNEL c2 CONNECT 'sys/oracle@racdb2'; - 即使备份片放在共享 ASM 磁盘组(如
+FRA),也建议恢复时仍按原节点分配通道,减少跨节点元数据竞争
tnsnames.ora 缺少单实例别名是最容易被忽略的前置条件
很多 DBA 只配了 SCAN 名(如 racdb_scan),但 RMAN 的 CONNECT 不支持 service_name 路由,必须有明确指向某实例的 TNS 条目。
示例 tnsnames.ora 片段(每个节点都要有):
racdb1 = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = rac1-vip)(PORT = 1521)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = racdb) (INSTANCE_NAME = racdb1) ) ) racdb2 = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = rac2-vip)(PORT = 1521)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = racdb) (INSTANCE_NAME = racdb2) ) )
漏掉这个,ALLOCATE CHANNEL ... CONNECT 会直接失败,后面所有优化都白搭。

