Oracle 19c 通过 DB Link 远程克隆 PDB 完整指南 概述 在多租户架构下,Oracle 19c 支持通过数据库链接(DB Link)将远程 CDB 中的 PDB 克隆到本地 CDB。这种方法无需中间存储,数据直接通过网络传输,特别适合 OCI 环境中 DBCS 到 RAC 的迁移场景。
本文以实际环境为例:
源库:单实例 DBCS,19.21,包含 3 个 PDB(PDB1、PDB2、PDB3)
目标库:RAC,19.31,新建空 CDB
网络:同 VCN 同子网,网络互通
一、前置条件检查
1.1 版本兼容性 源和目标均为 19c,支持远程克隆。跨小版本(19.21 → 19.31)克隆完全兼容。
1.2 网络连通性 确认源库和目标库之间网络互通:
bash
从 RAC 节点测试源库连通性
tnsping <source_tns_alias>
测试端口
nc -zv <source_host> 1521
1.3 用户权限要求 源库:需要具有 CREATE PLUGGABLE DATABASE 权限的用户
目标库:同样需要 CREATE PLUGGABLE DATABASE 权限
二、源库准备
2.1 创建克隆专用用户 在源库 CDB 级别创建用于克隆的用户:
-- 连接到源库 CDB
sqlplus / as sysdba
-- 创建公共用户(放在 CDB$ROOT)
CREATE USER c##clone_user IDENTIFIED BY "ClonePass2024" CONTAINER=ALL;
GRANT CREATE SESSION, CREATE PLUGGABLE DATABASE TO c##clone_user CONTAINER=ALL;
GRANT SELECT ON V$PDBS TO c##clone_user;
GRANT SELECT ON DBA_PDBS TO c##clone_user;
2.2 导出 TDE 密钥(如启用加密) 如果源 PDB 使用了 TDE 加密,需要先导出主密钥:
-- 源库导出主密钥
sqlplus / as sysdba
-- 确认 wallet 状态
ADMINISTER KEY MANAGEMENT SET KEYSTORE OPEN IDENTIFIED BY "源库wallet密码";
-- 导出主密钥到文件
ADMINISTER KEY MANAGEMENT EXPORT ENCRYPTION KEYS WITH SECRET "CloneSecretKey"
TO '/tmp/tde_source.exp'
IDENTIFIED BY "源库wallet密码";
2.3 确认 PDB 状态
-- 查看源库 PDB 状态
SELECT NAME, OPEN_MODE, RESTRICTED FROM V$PDBS;
NAME OPEN_MODE RESTRICTED
------------- ----------- ----------
PDB$SEED READ ONLY NO
PDB1 READ WRITE NO
PDB2 READ WRITE NO
PDB3 READ WRITE NO
注意:被克隆的 PDB 需要处于打开状态(READ WRITE 或 READ ONLY),但克隆过程中会短暂锁定。
三、目标库准备
3.1 导入 TDE 密钥(如源库有加密) 将源库导出的密钥文件复制到 RAC 所有节点:
# 复制到 RAC 节点1
scp /tmp/tde_source.exp oracle@exa-node1:/tmp/
# 复制到 RAC 节点2(RAC 所有节点都需要)
scp /tmp/tde_source.exp oracle@exa-node2:/tmp/
在目标库导入密钥:
-- 连接到目标库 CDB(每个节点都需要执行)
sqlplus / as sysdba
-- 导入主密钥
ADMINISTER KEY MANAGEMENT IMPORT ENCRYPTION KEYS WITH SECRET "CloneSecretKey"
FROM '/tmp/tde_source.exp'
IDENTIFIED BY "目标库wallet密码"
WITH BACKUP;
3.2 创建数据库链接 在目标库 CDB 级别创建指向源库的 DB Link:
-- 连接到目标库 CDB
sqlplus / as sysdba
-- 创建 DB Link
CREATE DATABASE LINK source_db_link
CONNECT TO c##clone_user IDENTIFIED BY "ClonePass2024"
USING '(DESCRIPTION=
(ADDRESS=(PROTOCOL=TCP)(HOST=<源库IP或SCAN>)(PORT=1521))
(CONNECT_DATA=(SERVICE_NAME=<源库CDB服务名>))
)';
3.3 测试 DB Link 连通性
-- 测试 DB Link 是否正常
SELECT 'Link OK' AS STATUS FROM DUAL@source_db_link;
-- 查询远程 PDB 信息
SELECT NAME, OPEN_MODE FROM V$PDBS@source_db_link;
-- 如果上面查询报错,先查询远程数据库版本
SELECT BANNER FROM V$VERSION@source_db_link WHERE ROWNUM=1;
预期输出:
text
STATUS
-------
Link OK
NAME OPEN_MODE
------------- ----------
PDB1 READ WRITE
PDB2 READ WRITE
PDB3 READ WRITE
3.4 验证目标目录结构
-- 查看目标库 ASM 目录结构(RAC 使用 ASM)
SELECT NAME FROM V$ASM_DISKGROUP;
NAME
----------
DATA
RECO
-- 确认目标路径
-- RAC 通常使用 +DATA/<CDB_NAME>/ 作为数据文件目录
四、执行 PDB 远程克隆
4.1 克隆第一个 PDB
-- 连接到目标库 CDB
sqlplus / as sysdba
-- 执行远程克隆
CREATE PLUGGABLE DATABASE PDB1
FROM PDB1@source_db_link
FILE_NAME_CONVERT = (
'/u01/app/oracle/oradata/SRCDB/PDB1/',
'+DATA/TGTCDB/PDB1/'
)
PARALLEL 8;
参数说明:
FROM PDB1@source_db_link:指定源 PDB 和 DB Link
FILE_NAME_CONVERT:文件路径转换规则
PARALLEL 8:并行度(根据网络带宽和源库性能调整)
4.2 监控克隆进度 在另一个会话中监控进度:
-- 查看克隆进度
SELECT PDB_NAME, STATUS, MESSAGE
FROM CDB_PDBS
WHERE PDB_NAME = 'PDB1';
-- 查看数据文件生成进度
SELECT NAME, BYTES/1024/1024 AS SIZE_MB
FROM V$DATAFILE
WHERE CON_ID = (SELECT CON_ID FROM V$PDBS WHERE NAME='PDB1');
4.3 依次克隆其余 PDB
-- 克隆 PDB2
CREATE PLUGGABLE DATABASE PDB2
FROM PDB2@source_db_link
FILE_NAME_CONVERT = (
'/u01/app/oracle/oradata/SRCDB/PDB2/',
'+DATA/TGTCDB/PDB2/'
)
PARALLEL 8;
-- 克隆 PDB3
CREATE PLUGGABLE DATABASE PDB3
FROM PDB3@source_db_link
FILE_NAME_CONVERT = (
'/u01/app/oracle/oradata/SRCDB/PDB3/',
'+DATA/TGTCDB/PDB3/'
)
PARALLEL 8;
五、克隆后处理
– 查看各 PDB 的补丁状态
SELECT CON_ID, PDB_NAME, PATCH_ID, VERSION, STATUS
FROM CDB_REGISTRY_SQLPATCH
ORDER BY CON_ID, PATCH_ID;
预期输出示例:
text
CON_ID PDB_NAME PATCH_ID VERSION STATUS
------ --------- ---------- -------- --------
1 CDB$ROOT 35943157 19.31.0 SUCCESS
3 PDB1 (null) 19.21.0 (null)
4 PDB2 (null) 19.21.0 (null)
5 PDB3 (null) 19.21.0 (null)
判断标准:
CDB$ROOT 的 PATCH_ID 为 35943157(19.31 的 RU 补丁号),STATUS 为 SUCCESS
PDB 没有任何补丁记录,说明 PDB 的数据字典还是旧版本
– 如果 PDB 未打开,先打开
ALTER PLUGGABLE DATABASE PDB1 OPEN;
ALTER PLUGGABLE DATABASE PDB2 OPEN;
ALTER PLUGGABLE DATABASE PDB3 OPEN;
– 确认所有 PDB 都是 READ WRITE 模式
SELECT NAME, OPEN_MODE FROM V$PDBS WHERE NAME IN ('PDB1','PDB2','PDB3');
2.2 确认监听和网络配置 Datapatch 需要通过 SQL*Net 连接到各 PDB:
bash
确认各 PDB 的服务已注册到监听
lsnrctl status
测试连接
sqlplus system/password@//localhost:1521/pdb1
sqlplus system/password@//localhost:1521/pdb2
sqlplus system/password@//localhost:1521/pdb3
2.3 设置环境变量
# 确保 ORACLE_HOME 正确
export ORACLE_HOME=/u01/app/oracle/product/19.0.0/dbhome_1
export PATH=$ORACLE_HOME/bin:$PATH
export ORACLE_SID=<目标CDB实例名>
验证 datapatch 可执行
which datapatch
datapatch -version
三、执行 Datapatch
3.1 对特定 PDB 运行 Datapatch
# 方法1:使用 -pdbs 参数指定 PDB
datapatch -pdbs PDB1,PDB2,PDB3
方法2:对所有 PDB 运行
datapatch 3.2 监控 Datapatch 执行 Datapatch 执行过程中会显示详细日志:
text SQL Patching tool version 19.31.0.0.0 Production on Sat Aug 15 10:30:00 2026 Copyright (c) 2012, 2024, Oracle. All rights reserved.
Connecting to database…OK Determining current state…done Adding patches to installation queue and performing prereq checks…done Installation queue: For the following PDBs: PDB1 PDB2 PDB3 Nothing to roll back The following patches will be applied: 35943157 (19.31.0.0.0)
-- 连接到目标库 CDB
sqlplus / as sysdba
-- 查看各 PDB 的补丁状态
SELECT CON_ID, PDB_NAME, PATCH_ID, VERSION, STATUS, ACTION_TIME
FROM CDB_REGISTRY_SQLPATCH
ORDER BY CON_ID, PATCH_ID;
预期结果:
text
CON_ID PDB_NAME PATCH_ID VERSION STATUS ACTION_TIME
------ --------- ---------- -------- -------- -------------------
1 CDB$ROOT 35943157 19.31.0 SUCCESS 2026-08-01 10:00:00
3 PDB1 35943157 19.31.0 SUCCESS 2026-08-15 11:30:00
4 PDB2 35943157 19.31.0 SUCCESS 2026-08-15 11:35:00
5 PDB3 35943157 19.31.0 SUCCESS 2026-08-15 11:40:00
4.2 验证数据字典一致性
-- 检查每个 PDB 的数据字典
ALTER SESSION SET CONTAINER = PDB1;
-- 验证数据字典版本
SELECT VERSION FROM DBA_REGISTRY WHERE COMP_ID = 'CATALOG';
-- 检查无效对象
SELECT COUNT(*) AS INVALID_OBJECTS FROM DBA_OBJECTS WHERE STATUS = 'INVALID';
-- 检查组件状态
SELECT COMP_ID, COMP_NAME, VERSION, STATUS
FROM DBA_REGISTRY
ORDER BY COMP_ID;
4.3 验证补丁应用完整性
-- 对比 CDB 和 PDB 的补丁列表
-- CDB 级别
SELECT PATCH_ID, VERSION, STATUS FROM DBA_REGISTRY_SQLPATCH;
-- PDB 级别(对每个 PDB 执行)
ALTER SESSION SET CONTAINER = PDB1;
SELECT PATCH_ID, VERSION, STATUS FROM DBA_REGISTRY_SQLPATCH;
修改PDB参数
5.2 修改 PDB 相关参数
-- 连接到 PDB1
ALTER SESSION SET CONTAINER = PDB1;
-- 修改 PDB 级参数(根据业务需求)
ALTER SYSTEM SET SGA_TARGET = 4G SCOPE=BOTH;
ALTER SYSTEM SET PGA_AGGREGATE_TARGET = 2G SCOPE=BOTH;
ALTER SYSTEM SET OPEN_CURSORS = 1000 SCOPE=BOTH;
ALTER SYSTEM SET PROCESSES = 300 SCOPE=BOTH;
-- 修改其他业务相关参数
ALTER SYSTEM SET NLS_SORT = 'BINARY' SCOPE=SPFILE;
ALTER SYSTEM SET OPTIMIZER_ADAPTIVE_PLANS = TRUE SCOPE=BOTH;
5.3 处理 PDB 服务
-- 查看 PDB 服务
SELECT NAME, PDB, NETWORK_NAME FROM DBA_SERVICES
WHERE PDB IN ('PDB1','PDB2','PDB3');
-- 如需修改服务名
BEGIN
DBMS_SERVICE.MODIFY_SERVICE(
service_name => 'pdb1_svc',
network_name => 'pdb1_new.example.com'
);
END;
/
5.4 验证数据完整性
-- 对比源和目标的对象数量
-- 在源库执行
SELECT COUNT(*) AS OBJECTS_COUNT FROM DBA_OBJECTS WHERE OWNER NOT IN ('SYS','SYSTEM');
-- 在目标库 PDB1 执行相同查询
ALTER SESSION SET CONTAINER = PDB1;
SELECT COUNT(*) AS OBJECTS_COUNT FROM DBA_OBJECTS WHERE OWNER NOT IN ('SYS','SYSTEM');
5.5 处理无效对象
-- 检查无效对象
SELECT COUNT(*) FROM DBA_OBJECTS WHERE STATUS = 'INVALID';
-- 编译无效对象
BEGIN
DBMS_UTILITY.COMPILE_SCHEMA('SCHEMA_NAME');
END;
/
– 或者使用 utlrp.sql 脚本 @?/rdbms/admin/utlrp.sql
六、注意事项与最佳实践
6.1 性能优化建议 并行度设置:根据网络带宽设置合适的 PARALLEL 值,过大可能影响源库性能
网络优化:确保源和目标之间的网络延迟小于 5ms,带宽足够
时间窗口选择:选择业务低峰期执行克隆
6.2 TDE 处理要点 RAC 环境所有节点都必须导入密钥
Wallet 文件位置必须在所有节点一致
使用共享存储存放 wallet 是最佳实践
6.3 常见错误处理 错误1:ORA-65005 权限不足
-- 解决方案:确认用户权限
GRANT CREATE PLUGGABLE DATABASE TO c##clone_user CONTAINER=ALL;
错误2:ORA-17628 文件转换错误
```sql
-- 解决方案:检查 FILE_NAME_CONVERT 路径是否正确
-- 查看源 PDB 数据文件路径
SELECT FILE_NAME FROM DBA_DATA_FILES WHERE CON_ID = (SELECT CON_ID FROM V$PDBS WHERE NAME='PDB1');
错误3:TDE 密钥不匹配
-- 解决方案:重新导出导入密钥
-- 确认目标库已导入所有主密钥
SELECT KEY_ID FROM V$ENCRYPTION_KEYS;
七、完整脚本总结
源库脚本
-- 1. 创建克隆用户
CREATE USER c##clone_user IDENTIFIED BY "ClonePass2024" CONTAINER=ALL;
GRANT CREATE SESSION, CREATE PLUGGABLE DATABASE TO c##clone_user CONTAINER=ALL;
GRANT SELECT ON V$PDBS TO c##clone_user;
GRANT SELECT ON DBA_PDBS TO c##clone_user;
-- 2. 导出 TDE 密钥(如需要)
ADMINISTER KEY MANAGEMENT SET KEYSTORE OPEN IDENTIFIED BY "源库wallet密码";
ADMINISTER KEY MANAGEMENT EXPORT ENCRYPTION KEYS WITH SECRET "CloneSecretKey"
TO '/tmp/tde_source.exp' IDENTIFIED BY "源库wallet密码";
目标库脚本
-- 1. 导入 TDE 密钥(如需要)
ADMINISTER KEY MANAGEMENT IMPORT ENCRYPTION KEYS WITH SECRET "CloneSecretKey"
FROM '/tmp/tde_source.exp' IDENTIFIED BY "目标库wallet密码" WITH BACKUP;
-- 2. 创建 DB Link
CREATE DATABASE LINK source_db_link
CONNECT TO c##clone_user IDENTIFIED BY "ClonePass2024"
USING '(DESCRIPTION=
(ADDRESS=(PROTOCOL=TCP)(HOST=<源库IP>)(PORT=1521))
(CONNECT_DATA=(SERVICE_NAME=<源库CDB服务名>))
)';
-- 3. 测试 DB Link
SELECT 'Link OK' AS STATUS FROM DUAL@source_db_link;
-- 4. 执行克隆
CREATE PLUGGABLE DATABASE PDB1 FROM PDB1@source_db_link
FILE_NAME_CONVERT = ('源路径', '目标路径') PARALLEL 8;
-- 5. 打开并验证
ALTER PLUGGABLE DATABASE PDB1 OPEN;
ALTER SESSION SET CONTAINER = PDB1;
SELECT COUNT(*) FROM DBA_OBJECTS;
总结
通过 DB Link 远程克隆 PDB 是 Oracle 19c 中最高效的数据库迁移方案之一,特别适合:
同版本或相近版本的 Oracle 数据库
网络条件良好的环境(同 VCN/数据中心)
需要最小化停机时间的场景
该方法避免了备份恢复的复杂性,数据直接通过网络传输,同时保持了数据的一致性和完整性。配合 TDE 密钥的导出导入,可以完美处理加密数据库的迁移需求。