Oracle 19C熱克隆應用避坑指南

本文由 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 本地PDB克隆

圖2 遠程PDB克隆

圖3 遠程non-cdb克隆

四、常見應用場景

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優化,參與多個電信行業核心系統的優化。

原文鏈接

https://mp.weixin.qq.com/s?__biz=MzI4NTA1MDEwNg==&mid=2650791392&idx=1&sn=b44a752c58c8818de6577b5c9ea1fd67&chksm=f3f96875c48ee163af6813d4d509ee8bfc313fbdf000c58efda3766fb241a6e66be4f71c8b05&scene=27#wechat_redirect

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章