这是以前的一篇文章,无意间看到,记录到这里吧。
Oacle 多租户环境包含一个容器数据库(CDB)和零个或多个可插拔数据库(PDB),这种让数据库系统扩展也变得非常的灵活,oracle 12c提供了许多种关于多租户模式下数据库的克隆迁移方式,以下对于几种克隆迁移的方式进行实验介绍。
创建语句:
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; |
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. |
主要的选项说明:
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. <<< **************************************************************** 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')
|
有时并不需要克隆表里的数据,可使用NO DATA来克隆一个PDB,但仅仅克隆元数据。
以下示例:
1) 源PDB中表存在多行数据,这里特意选择了三种情况,看看是否NO DATA的机制如何:
A. SYS 用户的表,表空间在SYSTEM
B. 个人用户的表,表空间在SYSTEM
C. 个人用户的表,表空间在普通表空间
2 )将源PDB打开到read only模式下:
ALTER PLUGGABLE DATABASE pdb1 OPEN READ ONLY;
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;
5 )到新的PDB下查询表数据:
从查询结果来看,使 用NO DATA的方式克隆PDB时,SYSTEM表空间下的表数据是会克隆过去,但用户表空间下表数据库就仅克隆了元数据。
通过远程方式创建克隆主要依靠的是dblink,因此需要源库和目标库之间网络保持畅通,而远处创建的方式和本地创建相差不大,远程模式可以增加从一个NON-CDB数据库克隆到CDB中。
1 )查看目标CDB当前情况:
2 )在目标CDB创建连接远程CDB的dblink:
SQL> create public database link cdb1 connect to system identified by "111111" using 'cdb1'; Database link created. |
3 )使用dblink远程创建
SQL> CREATE PLUGGABLE DATABASE pdb5 FROM pdb4@cdb1 2 FILE_NAME_CONVERT = ('/u01/app/oracle/oradata/orclcwd/pdb4/', '/u01/app/oracle/oradata/orclcwd/pdb5/');
Pluggable database created. |
4 )完成创建:
1 )在目标CDB创建连接远程非CDB的dblink:
SQL> create public database link nocdb1 connect to system identified by "111111" using 'nocdb1'; Database link created. |
3 )使用dblink远程创建
SQL> CREATE PLUGGABLE DATABASE pdb6 FROM nocdb1@nocdb1 2 FILE_NAME_CONVERT = ('/u01/app/oracle/oradata/nocdb1/', '/u01/app/oracle/oradata/orclcwd/pdb6/');
Pluggable database created. |
4 )创建完成
5 )执行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; 更改,如果在 实际应 用中就要事先注意 检查 字符集是否相同。
插拔的方式,是将一个PDB从CDB中拔出,之后插入到另外一个CDB的过程,一个拔掉的 PDB 由描述 PDB 的 XML 文件和其相关数据文件 组 成。
1 )选择准备拔出的 PDB ,这里选择 PDB4.
2) 关闭 PDB
3) 生成PDB的描述XML文件
ALTER PLUGGABLE DATABASE PDB4 UNPLUG INTO '/home/oracle/PDB4.xml';
4 )将PDB4的文件传输到目标库相同路径下:
5 )将生成的XML文件传输到目标库
6 )执行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 必 须 具有兼容的字符集和国家字符集。
7 )使用XML元数据文件把PDB插入(克隆模式)
create pluggable database MYPDB3 AS CLONE using '/home/oracle/PDB4.xml' NOCOPY TEMPFILE REUSE;
这里使用NOCOPY是因为将目标库数据文件路径设成了与源库相同。
打开新的插入的PDB,但出现错误
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了。
从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=' 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; |
有时可能需要迁移的仅仅是其中某几个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) 传输备份片到目标库
[oracle@redhat1 ~]$ pwd
/home/oracle
[oracle@redhat1 ~]$ 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; |
(1)备份数据库
这里使用上一步骤的全库备份,这里有个问题,就是我只需要恢复其中某一个PDB,那么,是否可以直接备份root database ,种子pdb 和所要的pdb来单独恢复,这个在后面进行详细实验。
(2)创建参数文件.
这个不做说明
(3)恢复控制文件
Startup nomout restore controlfile from '/home/oracle/backup/control_ORCLCWD_20170819_1esc91u4.ctl'; alter database mount; |
(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; } |
如果源库和目标库的数据文件路径不同,这使用set new name 方式来更改文件路径。
(5) 跳过不需要的PDB的表空间来做recover.
在本示例中, 数据库中除了CDB$ROOT 和 PDB$SEED,还有PDB2和PDB4,选择恢复的是PDB4,因此PDB2在recover时必须进行排除。
R un { recover database skip forever tablespace PDB2:SYSTEM,PDB2:SYSAUX; }
|
(6) 打开数据库.
打开后查看发现有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 方式可能会出现一些不可预估的错误,经过测试,也非致命问题。
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/29863023/viewspace-2651242/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/29863023/viewspace-2651242/