本文由 dbaplus 社羣授權轉載。
一、背景
隨着Oracle 11g進入擴展支持階段,Oracle 19C作爲12C家族中最終穩定版,已被多數公司熟知及應用於生產。本人所在公司也在嘗試對19C進行部署、測試、升級、遷移,於是藉此機會將熱克隆這個特性做了一番測試。
二、使用熱克隆的前提
1、需要12C R2及以上版本
在12C R1中,要克隆PDB,源PDB必須在克隆操作期間處於靜止狀態,因此它需要源PDB停機,通俗的講這是種“冷克隆”。
從12C R2及以後的版本中開始支持“熱克隆”,即Oracle數據庫支持使用聯機克隆的功能。當源PDB以讀寫方式打開的狀態下,完全不需要中斷源PDB中的操作,無須應用程序停機,就可以進行克隆操作。
2、必須使用local undo
當使用share undo的情況下,需要將share undo轉成local undo後纔可以使用熱克隆。可以在upgrade模式下用alter database local undo on進行轉換。
三、工作原理
從下面三張圖可以看出不管是本地克隆、遠程克隆,還是non-cdb克隆,都是類似rman方式進行備份恢復。熱克隆會有以下3個階段:
第一階段:當熱克隆開始時(t0),對源PDB的數據文件按塊進行讀取,直到源PDB最後一個塊被讀取並將其複製到目標PDB時(t1),此時t0-t1時間段內可能對已經複製的一些塊進行了更改。那麼,在此階段,目標PDB可能與源PDB在物理上不一致。
第二階段:將t0-t1之間對源PDB所做的更改傳至目標PDB,進行重做應用。在此階段,目標PDB將成爲t1時源PDB的物理副本,但這裏即包括了已提交的事務,也包括未提交的事務,因此可能在事務上不一致。
第三階段:截止至t1時,源PDB中包含所有已提交的事務,所有未提交的事務將進行回滾,目標PDB將是截至t1時源PDB的事務一致的副本。由此可見,實現熱克隆的關鍵是本地撤銷,因此熱克隆必須使用local undo。
四、常見應用場景
1、本地克隆
1)通過seed模板克隆
此方式主要應用於使用seed模板創建一個全新的PDB。
① 查看pdb的狀態
SYS@ora19c>show pdbs;
CON_ID CON_NAME OPEN MODE RESTRICTED
---------- ---------------- -------------- ----------
2 PDB$SEED READ ONLY NO
② 查看seed模板的datafile
SYS@ora19c>select con_id,name from v$datafile where con_id=2;
CON_ID NAME
---------- ------------------------------------------------------------
2 /u01/app/oracle/oradata/ORA19C/pdbseed/system01.dbf
2 /u01/app/oracle/oradata/ORA19C/pdbseed/sysaux01.dbf
2 /u01/app/oracle/oradata/ORA19C/pdbseed/undotbs01.dbf
③ 利用seed模板進行新PDB的克隆,無需對源庫執行任何操作,指定數據文件轉換目錄映射
SYS@ora19c>CREATE PLUGGABLE DATABASE pdb1 ADMIN USER pdb_mgr1 IDENTIFIED BY oracle roles=(dba) file_name_convert=('/u01/app/oracle/oradata/ORA19C/pdbseed','/u01/app/oracle/oradata/ORA19C/pdb1');
Pluggable database created.
④ 打開新的PDB進行驗證
SYS@ora19c>show pdbs;
CON_ID CON_NAME OPEN MODE RESTRICTED
---------- ------------------------------ ---------- ----------
2 PDB$SEED READ ONLY NO
3 PDB1 MOUNTED
SYS@ora19c>alter pluggable database pdb1 open;
Pluggable database altered.
SYS@ora19c>show pdbs;
CON_ID CON_NAME OPEN MODE RESTRICTED
---------- ------------------------------ ---------- ----------
2 PDB$SEED READ ONLY NO
3 PDB1 READ WRITE NO
SYS@ora19c>select con_id,name from v$datafile where con_id=3;
CON_ID NAME
---------- -----------------------------------------------------------------
3 /u01/app/oracle/oradata/ORA19C/pdb1/system01.dbf
3 /u01/app/oracle/oradata/ORA19C/pdb1/sysaux01.dbf
3 /u01/app/oracle/oradata/ORA19C/pdb1/undotbs01.dbf
2)克隆一個已存在的PDB
此方式常用於將已存在的PDB快速的在本地創建鏡像,擁有與源PDB完全相同的數據、結構、用戶、權限等。
① 將剛創建的PDB1創建一個u1用戶並授權,驗證克隆是否會克隆用戶及權限
SYS@ora19c>alter session set container=pdb1;
Session altered.
SYS@ora19c>create user u1 identified by oracle;
User created.
SYS@ora19c>grant connect,resource to u1;
Grant succeeded.
② 通過已存在的PDB1克隆出PDB2,源庫可以在read write模式下直接進行操作
SYS@ora19c>show pdbs;
CON_ID CON_NAME OPEN MODE RESTRICTED
---------- ------------------------------ ---------- ----------
2 PDB$SEED READ ONLY NO
3 PDB1 READ WRITE NO
SYS@ora19c>create pluggable database pdb2 from pdb1 file_name_convert=('pdb1','pdb2');
Pluggable database created.
SYS@ora19c>show pdbs;
CON_ID CON_NAME OPEN MODE RESTRICTED
---------- ------------------------------ ---------- ----------
2 PDB$SEED READ ONLY NO
3 PDB1 READ WRITE NO
4 PDB2 MOUNTED
③ 打開新創建的PDB進行驗證
SYS@ora19c>alter pluggable database pdb2 open;
Pluggable database altered.
SYS@ora19c>select con_id,name from v$datafile where con_id=4;
CON_ID NAME
---------- -----------------------------------------------------------------
4 /u01/app/oracle/oradata/ORA19C/pdb2/system01.dbf
4 /u01/app/oracle/oradata/ORA19C/pdb2/sysaux01.dbf
4 /u01/app/oracle/oradata/ORA19C/pdb2/undotbs01.dbf
④ 驗證克隆的新庫是否存在源庫的用戶及權限
SYS@ora19c>conn u1/[email protected]/pdb2
Connected.
[email protected]/pdb2>select * from session_privs;
PRIVILEGE
----------------------------------------
SET CONTAINER
CREATE INDEXTYPE
CREATE OPERATOR
CREATE TYPE
CREATE TRIGGER
CREATE PROCEDURE
CREATE SEQUENCE
CREATE CLUSTER
CREATE TABLE
CREATE SESSION
[email protected]/pdb2>select * from session_roles;
ROLE
--------------------------------------------------------
CONNECT
RESOURCE
SODA_APP
2、遠程克隆
1)克隆遠程已存在的PDB
此方式常用於將已存在的PDB快速的在異機之間創建鏡像,擁有與源PDB完全相同的數據、結構、用戶、權限等。
①源庫pdb_mgr1用戶授create pluggable database權限
SYS@ora19c>alter session set container=pdb1;
Session altered.
SYS@ora19c>grant create pluggable database to pdb_mgr1;
Grant succeeded.
② 目標CDB中創建db link
SYS@ora19c>create public database link lk_pdb1 connect to pdb_mgr1 identified by oracle using '(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=192.168.8.101)(PORT=1521))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=pdb1)))';
Database link created.
③ 執行遠程克隆操作,源庫無須進行其它操作,可以在read write下操作
SYS@ora19c>CREATE PLUGGABLE DATABASE pdb1_r FROM pdb1@lk_pdb1 file_name_convert=('pdb1','pdb1_r');
Pluggable database created.
④ 打開新創建的PDB進行驗證
SYS@ora19c>alter pluggable database pdb1_r open;
Pluggable database altered.
SYS@ora19c>show pdbs;
CON_ID CON_NAME OPEN MODE RESTRICTED
---------- ------------------------------ ---------- ----------
2 PDB$SEED READ ONLY NO
3 PDB1_R READ WRITE NO
SYS@ora19c>select con_id,name from v$datafile where con_id=3;
CON_ID NAME
---------- --------------------------------------------------------------
3 /u01/app/oracle/oradata/ORA19C/pdb1_r/system01.dbf
3 /u01/app/oracle/oradata/ORA19C/pdb1_r/sysaux01.dbf
3 /u01/app/oracle/oradata/ORA19C/pdb1_r/undotbs01.dbf
2)遠程克隆Non-CDB
此方式常用於Non-CDB異機遷移CDB生成新的PDB。
① 查看源庫的狀態
SYS@noncdb>select name,cdb,con_id from v$database;
NAME CDB CON_ID
--------------------------- --------- ----------
NONCDB NO 0
② 源庫pdb_mgr1用戶授create pluggable database權限
SYS@noncdb>grant create pluggable database to system;
Grant succeeded.
③ 目標CDB中創建db link
SYS@ora19c>create public database link lk_noncdb connect to system identified by oracle using '(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=192.168.8.101)(PORT=1521))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=noncdb)))';
Database link created.
SYS@ora19c>select name,cdb,con_id from v$database@lk_noncdb;
NAME CDB CON_ID
--------------------------- --------- ----------
NONCDB NO 0
④ 執行noncdb的遠程克隆
SYS@ora19c>CREATE PLUGGABLE DATABASE noncdb_pdb FROM noncdb@lk_noncdb file_name_convert=('/u01/app/oracle/oradata/NONCDB','/u01/app/oracle/oradata/ORA19C/noncdb_pdb');
Pluggable database created.
⑤ 打開新的PDB進行驗證
SYS@ora19c>show pdbs;
CON_ID CON_NAME OPEN MODE RESTRICTED
---------- ------------------------------ ---------- ----------
2 PDB$SEED READ ONLY NO
3 PDB1_R READ WRITE NO
5 NONCDB_PDB MOUNTED
SYS@ora19c>alter pluggable database NONCDB_PDB open;
Warning: PDB altered with errors.
⑥ open失敗,執行nocdb to pdb的腳本
SYS@ora19c>alter session set container=NONCDB_PDB;
Session altered.
SYS@ora19c>@?/rdbms/admin/noncdb_to_pdb.sql
⑦ 打開新創建的PDB進行驗證
SYS@ora19c>alter pluggable database NONCDB_PDB open;
Pluggable database altered.
SYS@ora19c>show pdbs;
CON_ID CON_NAME OPEN MODE RESTRICTED
---------- ------------------------------ ---------- ----------
2 PDB$SEED READ ONLY NO
3 PDB1_R READ WRITE NO
5 NONCDB_PDB READ WRITE NO
SYS@ora19c>select con_id,name from v$datafile where con_id=5;
CON_ID NAME
---------- ---------------------------------------------------------------------
5 /u01/app/oracle/oradata/ORA19C/noncdb_pdb/system01.dbf
5 /u01/app/oracle/oradata/ORA19C/noncdb_pdb/sysaux01.dbf
5 /u01/app/oracle/oradata/ORA19C/noncdb_pdb/undotbs01.dbf
5 /u01/app/oracle/oradata/ORA19C/noncdb_pdb/users01.dbf
五、特殊應用場景
1、子集克隆
從12.1.0.2開始,引入了User Tablespaces,簡單的說就是可以按表空間(用戶創建的)來克隆PDB。比如,當前PDB1中,用戶新建了兩個表空間ts1,ts2,克隆只需要ts1表空間中的數據,那麼我們可以用USER_TABLESPACES子句只克隆PDB1中的ts1表空間,這樣大大的縮短了時間和不必要的空間開銷。對於拆分數據也很有用,可以把一個庫按照表空間拆分。
語法:
- USER_TABLESPACES=ALL 默認,所有表空間都克隆;
- USER_TABLESPACES=NONE 所有用戶創建的表空間都不克隆;
- USER_TABLESPACES=(‘ts1’) 指定只克隆ts1;
- USER_TABLESPACES=ALL EXCEPT(‘ts1’) 除了ts1之外,其他表空間都克隆。
1)源庫創建表空間ts1,ts2
SYS@ora19c>create tablespace ts1 datafile '/u01/app/oracle/oradata/ORA19C/pdb1/ts1.dbf' size 10m;
Tablespace created.
SYS@ora19c>create tablespace ts2 datafile '/u01/app/oracle/oradata/ORA19C/pdb1/ts2.dbf' size 10m;
Tablespace created.
2)進行子集克隆,只克隆ts1表空間
SYS@ora19c>CREATE PLUGGABLE DATABASE pdb1_z FROM pdb1 file_name_convert=('pdb1','pdb1_z') user_tablespaces=('ts1');
Pluggable database created.
3)打開新創建的PDB進行驗證
SYS@ora19c>alter pluggable database pdb1_z open;
Pluggable database altered.
SYS@ora19c>show pdbs;
CON_ID CON_NAME OPEN MODE RESTRICTED
---------- ------------------------------ ---------- ----------
2 PDB$SEED READ ONLY NO
3 PDB1 READ WRITE NO
4 PDB2 READ WRITE NO
6 PDB1_Z READ WRITE NO
SYS@ora19c>select con_id,name from v$datafile where con_id=6;
CON_ID NAME
---------- ------------------------------------------------------------
6 /u01/app/oracle/oradata/ORA19C/pdb1_z/system01.dbf
6 /u01/app/oracle/oradata/ORA19C/pdb1_z/sysaux01.dbf
6 /u01/app/oracle/oradata/ORA19C/pdb1_z/undotbs01.dbf
6 /u01/app/oracle/oradata/ORA19C/pdb1_z/ts1.dbf
僅元數據的子集克隆,使用no data,創建語法:
create pluggable database pdb_nodata from pdb1 file_name_convert=('pdb1','pdb1_nodata') no data;
2、利用可刷新PDB的功能進行數據遷移
可刷新PDB功能是建立在熱克隆的基礎之上的。
當生產PDB數據量非常大,需要在很短的窗口時間進行數據遷移,當有了可刷新PDB和熱克隆的功能後,一切將變得簡單。無需考慮克隆需要花多長時間,因爲源數據庫無需停機。當目標PDB變得陳舊時,我們可以對其刷新,應用自上次刷新以來積累的所有增量。即使源數據庫非常龐大,增量重做通常也將小得多。最後只在需要做割接時將源PDB置爲read only後進行一次增量刷新。
刷新PDB須注意以下幾點:
- 源庫必須開啓歸檔日誌和local undo;
- 可以手動刷新或者自動定時刷新,但刷新時目標端必須是mounted狀態;
- 在不刷新期間,目標端可以以只讀模式打開;
- 如果需以讀寫模式打開目標端,則必須將refresh mode設置爲none,設置none之後就無法再回退回其它刷新模式;
- 刷新PDB必須使用dblink,dblink可以指向同一個CDB,也可以指向不同CDB。
1)在目標PDB創建db link
SYS@ora19c>create public database link lk_pdb1 connect to pdb_mgr1 identified by oracle using '(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=192.168.8.101)(PORT=1521))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=pdb1)))';
Database link created.
2)通過db link創建refresh PDB
SYS@ora19c>CREATE PLUGGABLE DATABASE pdb1_ref FROM pdb1@lk_pdb1 file_name_convert=('pdb1','pdb1_ref') REFRESH MODE EVERY 60 MINUTES;
Pluggable database created.
SYS@ora19c>show pdbs;
CON_ID CON_NAME OPEN MODE RESTRICTED
---------- ------------------------------ ---------- ----------
2 PDB$SEED READ ONLY NO
3 PDB1_R READ WRITE NO
4 PDB1_REF MOUNTED
5 NONCDB_PDB READ WRITE NO
3)當PDB處於REFRESH模式時只能有mounted和read only兩種狀態
SYS@ora19c>alter pluggable database pdb1_ref open;
alter pluggable database pdb1_ref open
*
ERROR at line 1:
ORA-65341: cannot open pluggable database in read/write mode
SYS@ora19c>alter pluggable database pdb1_ref open read only;
Pluggable database altered.
SYS@ora19c>select pdb_id,pdb_name,refresh_mode from cdb_pdbs;
PDB_ID PDB_NAME REFRES
---------- --------------- ------
2 PDB$SEED NONE
4 PDB1_REF AUTO
5 NONCDB_PDB NONE
3 PDB1_R NONE
4)PDB只能在mounted狀態下使用REFRESH功能
SYS@ora19c>alter pluggable database refresh;
alter pluggable database refresh
*
ERROR at line 1:
ORA-65025: Pluggable database PDB1_REF is not closed on all instances.
Alert log:
PDB1_REF(4):PDB1_REF(4):ERROR:PDB needs to be closed for auto refresh
PDB1_REF(4):Completed: alter pluggable database refresh
5)源PDB創建測試數據
[email protected]/pdb1>create table t1 as select * from dba_objects;
Table created.
[email protected]/pdb1>select count(*) from t1;
COUNT(*)
----------
72359
6)模擬應用側停應用,將源端PDB置爲read only
SYS@ora19c>alter pluggable database pdb1 close immediate;
Pluggable database altered.
SYS@ora19c>alter pluggable database pdb1 open read only;
Pluggable database altered.
7)目標端手動刷新,應用最近的增量,觀察目志是否正常
SYS@ora19c>alter pluggable database pdb1_ref refresh;
Pluggable database altered.
Alert log:
2020-02-19T13:23:44.457060+08:00
alter pluggable database pdb1_ref refresh
2020-02-19T13:23:45.940479+08:00
Applying media recovery for pdb-4099 from SCN 2793352 to SCN 2793357
Remote log information: count-1
thr-1, seq-12, logfile-/u01/app/oracle/product/db_1/dbs/archparlog_1_12_4aa635f6_1029786031.arc, los-2752894, nxs-18446744073709551615
PDB1_REF(4):Media Recovery Start
2020-02-19T13:23:45.942469+08:00
PDB1_REF(4):Serial Media Recovery started
PDB1_REF(4):max_pdb is 9
2020-02-19T13:23:45.996021+08:00
PDB1_REF(4):Media Recovery Log /u01/app/oracle/product/db_1/dbs/archparlog_1_12_4aa635f6_1029786031.arc
2020-02-19T13:23:46.257650+08:00
PDB1_REF(4):Incomplete Recovery applied until change 2793357 time 02/19/2020 13:23:09
2020-02-19T13:23:46.264473+08:00
PDB1_REF(4):Media Recovery Complete (ora19c)
Completed: alter pluggable database pdb1_ref refresh
8)目標端PDB關閉刷新模式
SYS@ora19c>ALTER PLUGGABLE DATABASE pdb1_ref REFRESH MODE NONE;
Pluggable database altered
9)拉起目標端PDB
SYS@ora19c>ALTER PLUGGABLE DATABASE pdb1_ref open read write;
Pluggable database altered.
SYS@ora19c>show pdbs;
CON_ID CON_NAME OPEN MODE RESTRICTED
---------- ------------------------------ ---------- ----------
2 PDB$SEED READ ONLY NO
3 PDB1_R MOUNTED
4 PDB1_REF READ WRITE NO
5 NONCDB_PDB MOUNTED
10)應用連接新PDB,校驗業務
SYS@ora19c>conn u1/[email protected]/pdb1_ref
Connected.
[email protected]/pdb1_ref>select count(*) from t1;
COUNT(*)
----------
72359
六、熱克隆中常見的錯誤
-
錯誤一:
ORA-65040: operation not allowed from within a pluggable database
解決方法: alter session set container=cdb$root;
-
錯誤二:
ORA-17628: Oracle error 1031 returned by remote Oracle server ORA-01031: insufficient privileges
解決方法: 到源庫裏對用戶授create pluggable database權限即可。
-
錯誤三:
ORA-19504: failed to create file '/u01/app/oracle/oradata/ORA19C/pdb1' ORA-27038: created file already exists
解決方法: 文件映射路徑問題,將“文件夾—文件夾”或“文件—文件”進行一一對應。
-
錯誤四:
ORA-65005: missing or invalid file name pattern for file-/u01/app/oracle/oradata/ORA19C/pdb1/system01.dbf
解決方法: 路徑錯誤或注意路徑中的大小寫。
-
錯誤五:
ORA-01578: ORACLE data block corrupted (file # 72, block # 33609) ORA-01110: data file 72: '/u01/app/oracle/oradata/ORA19C/pdb1_ref/system01.dbf' ORA-26040: Data block was loaded using the NOLOGGING option
解決方法: 創建可刷新PDB時,源端未開啓歸檔模式。
七、小結
熱克隆的方式目前都已經比較成熟,並且可以靈活使用,適合多種應用場景。既可以應用於快速創建生產環境的完整副本或子集副本,也可以應用於較短停機時間的遷移。業務中斷時間短,甚至無需業務中斷,操作簡單,不易出錯,但某些場景下對環境要求較高。
作者介紹:
王毅斌, 新炬網絡數據庫專家。精通Oracle、MySQL等數據庫運維技術,擁有Oracle OCM、MySQL OCP等認證,具有豐富的系統架構設計、數據遷移等經驗,擅長Oracle SQL優化,參與多個電信行業核心系統的優化。
原文鏈接: