Oracle database PDB clone

Transfer database from on database to another

浏览量 加载中...

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;
错误2ORA-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 密钥的导出导入,可以完美处理加密数据库的迁移需求。

🚀 加载中...
Sean's blog
使用 Hugo 构建 | 主题 StackJimmy 设计