12c可插拔数据库的几种克隆迁移方法

这是以前的一篇文章,无意间看到,记录到这里吧。 

12c 可插拔数据库的几种克隆迁移方法

Oacle 多租户环境包含一个容器数据库(CDB)和零个或多个可插拔数据库(PDB),这种让数据库系统扩展也变得非常的灵活,oracle 12c提供了许多种关于多租户模式下数据库的克隆迁移方式,以下对于几种克隆迁移的方式进行实验介绍。

一.通过现有PDB直接创建(CREATE PLUGGABLE DATABASE..FROM..)

1. 从本地PDB创建

(1)克隆完整PDB

创建语句:

CREATE PLUGGABLE DATABASE pdb3 FROM pdb2

    PATH_PREFIX = ' /u01/app/oracle/oradata/ ' --- 指定pdb相关联的目录,可以不设置

    FILE_NAME_CON VERT = (' /u01/app/oracle/oradata/orclcwd/pdb2/',   '/u01/app/oracle/oradata/orclcwd/pdb3/' ) - 数据文件存放路径,在ASM中可以指定DG

SERVICE_NAME_CONVERT = ('pdb2','pdb3') – 服务名转换

    NOLOGGING;

12c可插拔数据库的几种克隆迁移方法

SQL> SQL>   CREATE PLUGGABLE DATABASE pdb3 FROM pdb2

  2      PATH_PREFIX = '/u01/app/oracle/oradata/'

  3      FILE_NAME_CONVERT =   ('/u01/app/oracle/product/12.1.0/dbhome_1/dbs/u01/app/oracle/oradata/orclcwd/',   '/u01/app/oracle/oradata/orclcwd/pdb3/')

  4    SERVICE_NAME_CONVERT = ('pdb2','pdb3');

Pluggable database   created.

 

12c可插拔数据库的几种克隆迁移方法

主要的选项说明:

PATH_PREFIX :将 PDB 的相 对 目 录对 象路径 设置为 特定目 录 。 因此,需要 设 置 PATH_PREFIX

FILE_NAME_CONVERT :指定数据文件的转换路径

Storage: 如果需要限制新建pdb的大小,可以使用storage=xxG 来限制。

创建的过程日志:

CREATE PLUGGABLE DATABASE pdb3 FROM pdb2

    PATH_PREFIX = '/u01/app/oracle/oradata/'

    FILE_NAME_CONVERT =   ('/u01/app/oracle/product/12.1.0/dbhome_1/dbs/u01/app/oracle/oradata/orclcwd/',   '/u01/app/oracle/oradata/orclcwd/pdb3/')

SERVICE_NAME_CONVERT = ('pdb2','pdb3') <<<<<<<<<< 创建命令开始

Fri Aug 18 14:22:11 2017

Opatch XML is skipped for PDB PDB2 (conid=3) <<<<< 跳过PDB2(源)Opatch   XML,看起来与版本检查有关

 APEX_040200.WWV_FLOW_ADVISOR_CHECKS   (CHECK_STATEMENT) - CLOB populated

Fri Aug 18 14:24:15 2017 <<<< 开始创建新的PDB3,但此时的状态先为UNUSABLE

****************************************************************

Pluggable Database PDB3 with pdb id - 4 is   created as UNUSABLE.

If any errors are encountered before the pdb   is marked as NEW,

then the pdb must be dropped

****************************************************************

Database Characterset for PDB3 is ZHS16GBK <<< 字符集检查

Fri Aug 18 14:24:26 2017 <<<<<<<< 删除换旧的数据文件并生成新的数据文件

Deleting old file#8 from file$

Deleting old file#9 from file$

Adding new file#11 to file$(old file#8)

Adding new file#12 to file$(old file#9)

Successfully created internal service pdb3 at   open <<<<<< 创建服务成功

ALTER SYSTEM: Flushing buffer cache inst=0   container=4 local <<<<< 刷新新PDB的buffer

****************************************************************

Post plug operations are now complete.  <<<<< 插入PDB操作

Pluggable database PDB3 with pdb id - 4 is   now marked as NEW. <<<<PDB 状态定位NEW

****************************************************************

Completed: CREATE PLUGGABLE DATABASE pdb3   FROM pdb2 <<<< 完成

    PATH_PREFIX = '/u01/app/oracle/oradata/'

    FILE_NAME_CONVERT =   ('/u01/app/oracle/product/12.1.0/dbhome_1/dbs/u01/app/oracle/oradata/orclcwd/',   '/u01/app/oracle/oradata/orclcwd/pdb3/')

SERVICE_NAME_CONVERT = ('pdb2','pdb3')

 

 

(2) 仅克隆PDB元数据

有时并不需要克隆表里的数据,可使用NO DATA来克隆一个PDB,但仅仅克隆元数据。

以下示例:

1) 源PDB中表存在多行数据,这里特意选择了三种情况,看看是否NO DATA的机制如何:

A.   SYS 用户的表,表空间在SYSTEM

B.   个人用户的表,表空间在SYSTEM

C.   个人用户的表,表空间在普通表空间

12c可插拔数据库的几种克隆迁移方法

12c可插拔数据库的几种克隆迁移方法

 

 

2 )将源PDB打开到read only模式下:

ALTER PLUGGABLE DATABASE pdb1 OPEN READ ONLY;

12c可插拔数据库的几种克隆迁移方法

 

3 )克隆PDB:

CREATE PLUGGABLE DATABASE pdb4 FROM pdb3 NO DATA  FILE_NAME_CONVERT = ('/u01/app/oracle/oradata/orclcwd/pdb3/', '/u01/app/oracle/oradata/orclcwd/pdb4/');

SQL> SQL> CREATE PLUGGABLE DATABASE   pdb4 FROM pdb3 NO DATA;

CREATE PLUGGABLE DATABASE pdb4 FROM pdb3 NO   DATA

                                               *

ERROR at line 1:

ORA-65016: FILE_NAME_CONVERT must be   specified

SQL>    CREATE PLUGGABLE DATABASE pdb4 FROM pdb3 NO DATA

    2    FILE_NAME_CONVERT =   ('/u01/app/oracle/oradata/orclcwd/pdb3/',   '/u01/app/oracle/oradata/orclcwd/pdb4/');

 

Pluggable database created.

4 )打开新克隆的PDB:

ALTER PLUGGABLE DATABASE pdb4 OPEN;

12c可插拔数据库的几种克隆迁移方法

 

5 )到新的PDB下查询表数据:

 

从查询结果来看,使 用NO DATA的方式克隆PDB时,SYSTEM表空间下的表数据是会克隆过去,但用户表空间下表数据库就仅克隆了元数据。

 12c可插拔数据库的几种克隆迁移方法

2. 从远程PDB或non-CDB创建

  通过远程方式创建克隆主要依靠的是dblink,因此需要源库和目标库之间网络保持畅通,而远处创建的方式和本地创建相差不大,远程模式可以增加从一个NON-CDB数据库克隆到CDB中。

(1) 从PDB创建

)查看目标CDB当前情况:

 

)在目标CDB创建连接远程CDB的dblink:

SQL> create   public database link cdb1 connect to system identified by "111111"   using 'cdb1';

Database link   created.

 

12c可插拔数据库的几种克隆迁移方法

)使用dblink远程创建

SQL>  CREATE PLUGGABLE DATABASE pdb5 FROM   [email protected]                                                            

  2      FILE_NAME_CONVERT = ('/u01/app/oracle/oradata/orclcwd/pdb4/',   '/u01/app/oracle/oradata/orclcwd/pdb5/');

 

Pluggable   database created.

)完成创建:

 

 12c可插拔数据库的几种克隆迁移方法

(2)从NOCDB创建

)在目标CDB创建连接远程非CDB的dblink:

SQL> create   public database link nocdb1 connect to system identified by   "111111" using 'nocdb1';

Database link   created.

 

12c可插拔数据库的几种克隆迁移方法

)使用dblink远程创建

SQL> CREATE   PLUGGABLE DATABASE pdb6 FROM [email protected]                                                            

  2      FILE_NAME_CONVERT = ('/u01/app/oracle/oradata/nocdb1/',   '/u01/app/oracle/oradata/orclcwd/pdb6/');

 

Pluggable   database created.

)创建完成

12c可插拔数据库的几种克隆迁移方法

 

)执行PDB转换脚本

SQL> alter   session set container=pdb6;

SQL>   @?/rdbms/admin/ noncdb_to_pdb.sql

… 一系列日志

Plug 过程的一些问题提示:

通过PDB_PLUG_IN_VIOLATIONS视图可以查询plug过程中的问题,例如以下,源PDB和当前CDB的字符集不同导致PDB open 后是限制模式,这个可以通过 ALTER DATABASE CHARACTER SET internal_use ZHS16GBK; 更改,如果在 实际应 用中就要事先注意 检查 字符集是否相同。

 

 12c可插拔数据库的几种克隆迁移方法

二.通过插拔方式创建(CREATE PLUGGABLE DATABASE..USING ‘XML’..)

插拔的方式,是将一个PDB从CDB中拔出,之后插入到另外一个CDB的过程,一个拔掉的 PDB 由描述 PDB 的 XML 文件和其相关数据文件 组成。

1. 从PDB插拔

)选择准备拔出的 PDB ,这里选择 PDB4.

12c可插拔数据库的几种克隆迁移方法

 

2) 关闭 PDB

12c可插拔数据库的几种克隆迁移方法

 

3) 生成PDB的描述XML文件

ALTER PLUGGABLE DATABASE PDB4 UNPLUG INTO '/home/oracle/PDB4.xml';

 12c可插拔数据库的几种克隆迁移方法

4 )将PDB4的文件传输到目标库相同路径下:

12c可插拔数据库的几种克隆迁移方法

 

5 )将生成的XML文件传输到目标库

12c可插拔数据库的几种克隆迁移方法

 

)执行DBMS_PDB.CHECK_PLUG_COMPATIBILITY 检查要插入PDB是否和目标CDB兼容。

SET   SERVEROUTPUT ON

DECLARE

 compatible CONSTANT VARCHAR2(3) :=

  CASE DBMS_PDB.CHECK_PLUG_COMPATIBILITY(

      pdb_descr_file =>   '/home/oracle/PDB4.xml')

  WHEN TRUE THEN 'YES'

  ELSE 'NO'

END;

BEGIN

 DBMS_OUTPUT.PUT_LINE(compatible);

END;

/

 

SQL>   SET SERVEROUTPUT ON

SQL>   DECLARE

  2     compatible CONSTANT VARCHAR2(3) :=

  3      CASE DBMS_PDB.CHECK_PLUG_COMPATIBILITY(

  4          pdb_descr_file => '/home/oracle/PDB4.xml')

  5      WHEN TRUE THEN 'YES'

  6      ELSE 'NO'

  7    END;

  8    BEGIN

  9     DBMS_OUTPUT.PUT_LINE(compatible);

 10    END;

 11  /

NO  < <<< 检查 不通 过 ,原来出 现 字符集不同

SQL>   ALTER SYSTEM ENABLE RESTRICTED SESSION;  

System   altered.

SQL> ALTER DATABASE CHARACTER SET internal_use ZHS16GBK;

Database   altered.

SQL>   SET SERVEROUTPUT ON

SQL>   DECLARE

  2     compatible CONSTANT VARCHAR2(3) :=

  3      CASE DBMS_PDB.CHECK_PLUG_COMPATIBILITY(

  4          pdb_descr_file => '/home/oracle/PDB4.xml')

  5      WHEN TRUE THEN 'YES'

  6      ELSE 'NO'

  7    END;

  8    BEGIN

  9     DBMS_OUTPUT.PUT_LINE(compatible);

 10    END;

 11  /

YES 《 《《《 检查 通 

PL/SQL   procedure successfully completed.

 

对于插入一个PDB,必须满足以下条件:

  • 目 标 CDB 必 须 与源 CDB 具有相同的字 节码(主要涉及平台问题) 。 
•CDB 必 须 安装相同的 选项 。 
• 源 CDB 和目 标 CDB 必 须 具有兼容的字符集和国家字符集。

 

)使用XML元数据文件把PDB插入(克隆模式)

create pluggable database MYPDB3 AS CLONE  using '/home/oracle/PDB4.xml'  NOCOPY  TEMPFILE REUSE;

12c可插拔数据库的几种克隆迁移方法

 

这里使用NOCOPY是因为将目标库数据文件路径设成了与源库相同。

打开新的插入的PDB,但出现错误

12c可插拔数据库的几种克隆迁移方法

 

SQL> !oerr ora 65054

65054, 00000, "Cannot   open a pluggable database in the desired mode."

// *Cause:  An attempt was made to open a pluggable   database in a mode

//          incompatible with that of the CDB.

// *Action: Open the CDB   in a compatible mode first and retry the operation.

看起来是新的PDB和CDB OPEN时不兼容,这里我尝试重启整个CDB后竟然可以顺利打开新插入的PDB了。

 

12c可插拔数据库的几种克隆迁移方法 

2. 从 NON-CDB 插拔

从NON-CDB转换克隆的模式实际与从CDB相差不大,与从现有NOCDB创建的模式一样,这里也需要执行noncdb_to_pdb.sql脚本来转换数据字典等。

以下列举出执行的语句:

1 )关闭原NONCDB数据库,并开启到只读模式

sqlplus / as sysdba

sql> shutdown immediate

sql> startup open read   only

2 )生成数据库的XML元数据文件。

BEGIN

DBMS_PDB.DESCRIBE(pdb_descr_file   => '/home/oracle/12cNonPDB.xml');

END;

/

3 )关闭数据库

sql> shutdown immediate

4 )同样将原数据库文件传输到新数据库磁盘中。

5 )检查兼容性

SET SERVEROUTPUT ON;

DECLARE

compatible CONSTANT   VARCHAR2(3) := CASE DBMS_PDB.CHECK_PLUG_COMPATIBILITY(pdb_descr_file => '/home/oracle   /12cNonPDB.xml')

WHEN TRUE THEN 'YES'

ELSE 'NO'

END;

BEGIN

DBMS_OUTPUT.PUT_LINE(compatible);

END;

/

6 )检查是否有错误

col cause for a20

col name for a20

col message for a35   word_wrapped

select   name,cause,type,message,status from PDB_PLUG_IN_VIOLATIONS where   name='<noncdb database name>';

7 )创建PDB

CREATE PLUGGABLE DATABASE PDB8   USING ' /home/oracle/12cNonPDB.xml'

COPY

FILE_NAME_CONVERT =   ('/u01/app/oracle/12c/oradata/12cNonPDB/', '/u01/app/oracle/oradata/12c/ PDB8/');

8 )执行转换脚本

sql> ALTER SESSION SET   CONTAINER= PDB8;

sql>   @$ORACLE_HOME/rdbms/admin/noncdb_to_pdb.sql

9 )打开新的PDB

ALTER PLUGGABLE DATABASE   PDB8 OPEN;

 

三.通过RMAN备份恢复

1. 整体数据库备份恢复

有时可能需要迁移的仅仅是其中某几个PDB,在整库数据量不大情况下,可以直接备份整库来异机恢复即可,这样和普通的的数据库模式是相同的。

(1)整库备份

run{

allocate channel CH1 device type disk format  '/home/oracle/backup/full_db_%U';

backup database include current controlfile plus   archivelog  ;

release    channel CH1 ;

}

BACKUP current controlfile  format '/home/oracle/backup/control_%d_%T_%u.ctl';

 (2) 传输备份片到目标库

[[email protected] ~]$ pwd

/home/oracle

[[email protected] ~]$  scp -r backup 172.16.155.67:/home/oracle/

(3) 恢复控制文件

Startup nomout

restore controlfile from '/home/oracle/backup/control_ORCLCWD_20170819_1esc91u4.ctl';

alter database mount;

(4)恢复全库

run{

allocate channel CH1;

restore database ;

recover database;

release    channel CH1 ;

}

alter database open resetlogs;

2. 只恢复CDB、pdb$seed和需要的PDB

(1)备份数据库

这里使用上一步骤的全库备份,这里有个问题,就是我只需要恢复其中某一个PDB,那么,是否可以直接备份root database ,种子pdb 和所要的pdb来单独恢复,这个在后面进行详细实验。

(2)创建参数文件.

这个不做说明

(3)恢复控制文件

Startup nomout

restore controlfile from   '/home/oracle/backup/control_ORCLCWD_20170819_1esc91u4.ctl';

alter database mount;

 

12c可插拔数据库的几种克隆迁移方法

(4)恢复所需要的 CDB$ROOT,PDB$SEED 和PDB4

run {

  ALLOCATE   CHANNEL c1 TYPE disk;

 restore database root ;  ------------------------->CDB$ROOT

 restore database "PDB$SEED";   -------->PDB$SEED is required

 restore database PDB4; -------------->PDB   we want to restore

RELEASE CHANNEL c1;

}

 

12c可插拔数据库的几种克隆迁移方法 

如果源库和目标库的数据文件路径不同,这使用set new name 方式来更改文件路径。

(5) 跳过不需要的PDB的表空间来做recover.

在本示例中, 数据库中除了CDB$ROOT 和 PDB$SEED,还有PDB2和PDB4,选择恢复的是PDB4,因此PDB2在recover时必须进行排除。

un   {

                      recover   database skip forever tablespace PDB2:SYSTEM,PDB2:SYSAUX; }

 

 

 

 12c可插拔数据库的几种克隆迁移方法

12c可插拔数据库的几种克隆迁移方法

(6) 打开数据库.

12c可插拔数据库的几种克隆迁移方法

 

  打开后查看发现有pdb2,这个实际时不可用的,且没有实际数据,直接drop掉即可。

SQL> show   pdbs

 

    CON_ID CON_NAME                       OPEN MODE  RESTRICTED

----------   ------------------------------ ---------- ----------

         2 PDB$SEED                       MOUNTED

         3 PDB2                           MOUNTED

         5 PDB4                           MOUNTED

SQL> alter   pluggable database PDB2 open;

alter   pluggable database PDB2 open

*

ERROR at line   1:

ORA-01147: SYSTEM   tablespace file 8 is offline

SQL> drop   pluggable database pdb2 including datafiles;

 

Pluggable   database dropped.

而在打开PDB4时报出了ORA-65086,这里可以试下插拔一次。

SQL> alter   pluggable database pdb4 open;

alter   pluggable database pdb4 open

*

ERROR at line   1:

ORA-65086:   cannot open/close the pluggable database

 

SQL> alter   pluggable database pdb4 unplug into '/tmp/pdb41.xml';

Pluggable   database altered.

 

1* select   pdb_name,status from dba_pdbs

SQL> /

 

PDB_NAME             STATUS

--------------------   ---------

PDB$SEED             NEW

PDB4                 UNPLUGGED

 

SQL> drop   pluggable database pdb4 keep datafiles;

 

Pluggable   database dropped.

 

SQL> select   pdb_name,status from dba_pdbs;

 

PDB_NAME             STATUS

--------------------   ---------

PDB$SEED             NEW

 

SQL> create   pluggable database PDB4 using '/tmp/pdb41.xml' nocopy tempfile reuse;

Pluggable   database created.

SQL> select   pdb_name,status from dba_pdbs;

PDB_NAME             STATUS

--------------------   ---------

PDB4                 NEW

PDB$SEED             NEW

SQL> alter   pluggable database pdb4 open;

Pluggable   database altered.

 

SQL> show   pdbs

 

    CON_ID CON_NAME                       OPEN MODE  RESTRICTED

----------   ------------------------------ ---------- ----------

         2 PDB$SEED                       MOUNTED

         3 PDB4                           READ WRITE NO

 

  经过测试,可以只对需要的PDB进行备份后进行恢复即可,在迁移时并不需要整个库都备份,这样的话可以节省不少时间和空间。

run{

allocate   channel CH1 device type disk format    '/home/oracle/backup/full_db_%U';

 backup database root include current   controlfile plus archivelog; 

 backup    database "PDB$SEED";

 backup pluggable database PDB4 include   current controlfile plus archivelog;

release  channel CH1 ;

}

BACKUP current   controlfile  format '/home/oracle/backup/control_%d_%T_%u.ctl';

后面恢复的方法与以上相同。

 

总结:

   oracle 12c 随着可插拔数据推出的 CREATE PLUGGABLE DATABASE 的方法都已经比较成熟,并且可以灵活使用,适合多种应用场景,而通过传统的 rman 方式可能会出现一些不可预估的错误,经过测试,也非致命问题。