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; |
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. <<<<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. 個人用戶的表,表空間在普通表空間
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表空間下的表數據是會克隆過去,但用戶表空間下表數據庫就僅克隆了元數據。
2. 從遠程PDB或non-CDB創建
通過遠程方式創建克隆主要依靠的是dblink,因此需要源庫和目標庫之間網絡保持暢通,而遠處創建的方式和本地創建相差不大,遠程模式可以增加從一個NON-CDB數據庫克隆到CDB中。
(1) 從PDB創建
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 )完成創建:
(2)從NOCDB創建
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; 更改,如果在 實際應 用中就要事先注意 檢查 字符集是否相同。
二.通過插拔方式創建(CREATE PLUGGABLE DATABASE..USING ‘XML’..)
插拔的方式,是將一個PDB從CDB中拔出,之後插入到另外一個CDB的過程,一個拔掉的 PDB 由描述 PDB 的 XML 文件和其相關數據文件 組 成。
1. 從PDB插拔
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了。
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) 傳輸備份片到目標庫
[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; |
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; |
(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 方式可能會出現一些不可預估的錯誤,經過測試,也非致命問題。