本文为Oracle LiveLabs中实验Pluggables, Clones and Containers: Oracle Multitenant Fundamentals Workshop的过程记录。
实验指南请参见文档。

实验虽然也包括Application containers部分,但由于其应用较少,本文不涉及此部分。
整个实验预计耗时4个小时,其实如果概念熟悉的话,2个小时就够。

实验默认的界面是通过noVNC,但图形界面操作不便,而且会较慢。因此建议使用noVNC的粘贴板将私钥加入到虚拟机中,然后就可以用PuTTY登录。公网地址在页面顶端有显示。

cd $HOME; mkdir .ssh; cd .ssh
vi authorized_keys

Lab 2: Initialize Environment

验证所需的进程已启动并正在运行。

[CDB1:oracle@dbhol:~]$ ps -ef|grep LIST|grep -v grep
oracle    3188     1  0 08:37 ?        00:00:00 /opt/oracle/product/19c/dbhome_1/bin/tnslsnr LISTENER -inherit
oracle    3189     1  0 08:37 ?        00:00:00 /opt/oracle/product/19c/dbhome_1/bin/tnslsnr LISTCDB2 -inherit
[CDB1:oracle@dbhol:~]$ ps -ef|grep ora_|grep pmon|grep -v grep
oracle    3387     1  0 08:37 ?        00:00:00 ora_pmon_CDB1
oracle    3847     1  0 08:38 ?        00:00:00 ora_pmon_CDB2
[CDB1:oracle@dbhol:~]$ systemctl status oracle-database
● oracle-database.service - The Oracle Database ServiceLoaded: loaded (/etc/systemd/system/oracle-database.service; enabled; vendor preset: disabled)Active: active (running) since Mon 2021-12-13 08:38:44 GMT; 34min agoProcess: 3109 ExecStart=/bin/bash -c /home/oracle/scripts/startall.sh >> /home/oracle/log/startup_shutdown.log 2>&1 (code=exited, status=0/SUCCESS)Tasks: 123Memory: 9.3GCGroup: /system.slice/oracle-database.service├─3188 /opt/oracle/product/19c/dbhome_1/bin/tnslsnr LISTENER -inherit├─3387 ora_pmon_CDB1├─3391 ora_clmn_CDB1├─3395 ora_psp0_CDB1├─3401 ora_vktm_CDB1├─3407 ora_gen0_CDB1├─3411 ora_mman_CDB1├─3417 ora_gen1_CDB1├─3420 ora_diag_CDB1├─3422 ora_ofsd_CDB1├─3425 ora_dbrm_CDB1├─3429 ora_vkrm_CDB1├─3431 ora_svcb_CDB1├─3433 ora_pman_CDB1├─3437 ora_dia0_CDB1├─3439 ora_dbw0_CDB1├─3444 ora_lgwr_CDB1├─3448 ora_ckpt_CDB1├─3452 ora_lg00_CDB1├─3454 ora_smon_CDB1├─3458 ora_lg01_CDB1├─3460 ora_smco_CDB1├─3462 ora_reco_CDB1├─3464 ora_w000_CDB1├─3466 ora_lreg_CDB1├─3470 ora_w001_CDB1├─3472 ora_pxmn_CDB1├─3478 ora_mmon_CDB1├─3480 ora_mmnl_CDB1├─3482 ora_d000_CDB1├─3484 ora_s000_CDB1├─3486 ora_tmon_CDB1├─3495 ora_m000_CDB1├─3502 ora_tt00_CDB1├─3504 ora_tt01_CDB1├─3506 ora_tt02_CDB1├─3511 ora_w002_CDB1├─3513 ora_aqpc_CDB1├─3517 ora_p000_CDB1├─3519 ora_p001_CDB1├─3521 ora_p002_CDB1├─3523 ora_p003_CDB1├─3525 ora_p004_CDB1├─3527 ora_p005_CDB1├─3529 ora_p006_CDB1├─3531 ora_p007_CDB1├─3626 ora_w003_CDB1├─3723 ora_cjq0_CDB1├─3843 ora_w004_CDB1├─3847 ora_pmon_CDB2├─3851 ora_clmn_CDB2├─3855 ora_psp0_CDB2├─3872 ora_vktm_CDB2├─3887 ora_gen0_CDB2├─3900 ora_mman_CDB2├─3912 ora_gen1_CDB2├─3919 ora_diag_CDB2├─3946 ora_ofsd_CDB2├─3968 ora_dbrm_CDB2├─4004 ora_vkrm_CDB2├─4025 ora_svcb_CDB2├─4038 ora_pman_CDB2├─4053 ora_dia0_CDB2├─4063 ora_dbw0_CDB2├─4087 ora_lgwr_CDB2├─4114 ora_ckpt_CDB2├─4141 ora_lg00_CDB2├─4156 ora_smon_CDB2├─4162 ora_qm02_CDB1├─4181 ora_lg01_CDB2├─4188 ora_smco_CDB2├─4193 ora_reco_CDB2├─4203 ora_w000_CDB2├─4221 ora_lreg_CDB2├─4233 ora_q003_CDB1├─4235 ora_w001_CDB2├─4243 ora_pxmn_CDB2├─4275 ora_mmon_CDB2├─4287 ora_mmnl_CDB2├─4299 ora_d000_CDB2├─4304 ora_s000_CDB2├─4310 ora_tmon_CDB2├─4452 ora_m000_CDB2├─4691 ora_m001_CDB1├─4694 ora_m002_CDB1├─4717 ora_tt00_CDB2├─4730 ora_tt01_CDB2├─4746 ora_tt02_CDB2├─5255 ora_m003_CDB1├─5358 ora_w002_CDB2├─5745 ora_aqpc_CDB2├─5750 ora_qm02_CDB2├─5773 ora_p000_CDB2├─5775 ora_p001_CDB2├─5777 ora_p002_CDB2├─5780 ora_p003_CDB2├─5782 ora_p004_CDB2├─5784 ora_w003_CDB2├─5786 ora_p005_CDB2├─5788 ora_p006_CDB2├─5790 ora_p007_CDB2├─5883 ora_w004_CDB2├─5943 ora_q007_CDB1├─6175 ora_q00d_CDB2├─6188 ora_q00j_CDB2├─6197 ora_cjq0_CDB2├─6556 ora_cl00_CDB1├─6559 ora_w005_CDB1├─6607 ora_m001_CDB2├─6609 ora_m002_CDB2├─6611 ora_m003_CDB2├─6639 ora_m004_CDB2├─6681 ora_cl00_CDB2├─9786 ora_w006_CDB1├─9791 ora_w007_CDB1├─9892 ora_w005_CDB2├─9929 ora_w006_CDB2└─9934 ora_w007_CDB2
[CDB1:oracle@dbhol:~]$ systemctl status oracle-db-listener
● oracle-db-listener.service - The Oracle DB Listeners ServiceLoaded: loaded (/etc/systemd/system/oracle-db-listener.service; enabled; vendor preset: disabled)Active: active (running) since Mon 2021-12-13 08:37:54 GMT; 35min agoProcess: 3108 ExecStart=/bin/bash -c /home/oracle/scripts/start-all-listeners.sh (code=exited, status=0/SUCCESS)Main PID: 3189 (tnslsnr)Tasks: 2Memory: 23.3MCGroup: /system.slice/oracle-db-listener.service└─3189 /opt/oracle/product/19c/dbhome_1/bin/tnslsnr LISTCDB2 -inherit

从以上输出可知,目前有2个CDB:CDB1和CDB2。两个监听:LISTENER(1521端口) 和 LISTCDB2(1522端口) 。
从以下输出可知。CDB1用的LISTENER,CDB2用的LISTCDB2 :

[CDB2:oracle@dbhol:~]$ lsnrctl statusLSNRCTL for Linux: Version 19.0.0.0.0 - Production on 13-DEC-2021 09:16:23Copyright (c) 1991, 2021, Oracle.  All rights reserved.Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=dbhol.livelabs.oraclevcn.com)(PORT=1521)))
STATUS of the LISTENER
------------------------
Alias                     LISTENER
Version                   TNSLSNR for Linux: Version 19.0.0.0.0 - Production
Start Date                13-DEC-2021 08:37:53
Uptime                    0 days 0 hr. 38 min. 30 sec
Trace Level               off
Security                  ON: Local OS Authentication
SNMP                      OFF
Listener Parameter File   /opt/oracle/product/19c/dbhome_1/network/admin/listener.ora
Listener Log File         /opt/oracle/diag/tnslsnr/dbhol/listener/alert/log.xml
Listening Endpoints Summary...(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=dbhol.livelabs.oraclevcn.com)(PORT=1521)))(DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC1521)))(DESCRIPTION=(ADDRESS=(PROTOCOL=tcps)(HOST=dbhol.livelabs.oraclevcn.com)(PORT=5501))(Security=(my_wallet_directory=/opt/oracle/admin/CDB1/xdb_wallet))(Presentation=HTTP)(Session=RAW))
Services Summary...
Service "CDB1" has 1 instance(s).Instance "CDB1", status READY, has 1 handler(s) for this service...
Service "CDB1XDB" has 1 instance(s).Instance "CDB1", status READY, has 1 handler(s) for this service...
Service "cd8d29dc40fd7370e0533800000ab923" has 1 instance(s).Instance "CDB1", status READY, has 1 handler(s) for this service...
Service "pdb1" has 1 instance(s).Instance "CDB1", status READY, has 1 handler(s) for this service...
The command completed successfully[CDB2:oracle@dbhol:~]$ lsnrctl status LISTCDB2LSNRCTL for Linux: Version 19.0.0.0.0 - Production on 13-DEC-2021 09:19:54Copyright (c) 1991, 2021, Oracle.  All rights reserved.Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=dbhol.livelabs.oraclevcn.com)(PORT=1522)))
STATUS of the LISTENER
------------------------
Alias                     LISTCDB2
Version                   TNSLSNR for Linux: Version 19.0.0.0.0 - Production
Start Date                13-DEC-2021 08:37:53
Uptime                    0 days 0 hr. 42 min. 1 sec
Trace Level               off
Security                  ON: Local OS Authentication
SNMP                      OFF
Listener Parameter File   /opt/oracle/product/19c/dbhome_1/network/admin/listener.ora
Listener Log File         /opt/oracle/diag/tnslsnr/dbhol/listcdb2/alert/log.xml
Listening Endpoints Summary...(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=dbhol.livelabs.oraclevcn.com)(PORT=1522)))(DESCRIPTION=(ADDRESS=(PROTOCOL=tcps)(HOST=dbhol.livelabs.oraclevcn.com)(PORT=5502))(Security=(my_wallet_directory=/opt/oracle/admin/CDB2/xdb_wallet))(Presentation=HTTP)(Session=RAW))
Services Summary...
Service "CDB2" has 1 instance(s).Instance "CDB2", status READY, has 1 handler(s) for this service...
Service "CDB2XDB" has 1 instance(s).Instance "CDB2", status READY, has 1 handler(s) for this service...
Service "cd8d71a2721f1aace0533800000a39bd" has 1 instance(s).Instance "CDB2", status READY, has 1 handler(s) for this service...
Service "pdb2" has 1 instance(s).Instance "CDB2", status READY, has 1 handler(s) for this service...
The command completed successfully

如果监听和数据库状态不对,可以用以下脚本重置:

sudo systemctl restart oracle-database
sudo systemctl restart oracle-db-listener

为多租户用例初始化数据库

下载脚本:

cd ~
wget -O labs-novnc.zip https://objectstorage.us-ashburn-1.oraclecloud.com/p/DI8FDu8opoqAK7MoplCLgwUiVsf8uyNNbcLkaytAdJyGSMmgn0Jw14OMtG3vNLI-/n/c4u04/b/labfiles/o/labs-novnc.zip
unzip -qo labs-novnc.zip
rm -f labs-novnc.zip
cd labs/multitenant
chmod +x *.sh

Lab 3: Clone, Plug and Drop

Task 1: Log in and create PDB

cd /home/oracle/labs/multitenant
# 设置ORACLE_SID: CDB1
# 设置ORACLE_HOME: /opt/oracle/product/19c/dbhome_1
. ~/.set-env-db.sh CDB1
sql sys/Ora_DB4U@localhost:1521/cdb1 as sysdba
set sqlformat ANSICONSOLE

以上.set-env-db.sh脚本,从oratab中获取SID,然后设置ORACLE_HOME。oratab位置可能有两处:

if [ -f /etc/oratab ]; thenOTAB=/etc/oratab
elif [ -f /var/opt/oracle/oratab ]; thenOTAB=/var/opt/oracle/oratab
elseecho 'oratab file not found.'exit
fi

下面这个脚本可以显示当前所连数据库的用户:

select'DB Name: '  ||Sys_Context('Userenv', 'DB_Name')||' / CDB?: '     ||casewhen Sys_Context('Userenv', 'CDB_Name') is not null then 'YES'else  'NO'end||' / Auth-ID: '   ||Sys_Context('Userenv', 'Authenticated_Identity')||' / Sessn-User: '||Sys_Context('Userenv', 'Session_User')||' / Container: ' ||Nvl(Sys_Context('Userenv', 'Con_Name'), 'n/a')"Who am I?"from Dual.save whoami.sql

以上脚本中,.命令的作用是把输入存入buffer,但不执行,效果和空行相同。后续save命令将buffer内容存为文件。和buffer相关SQL Plus命令包括list,edit,save,input。

SYS_CONTEXT函数的帮助见这里,对于开发者尤为有用。

看一下执行效果:

SQL> @whoami
Who am I?
DB Name: CDB1 / CDB?: YES / Auth-ID: SYS / Sessn-User: SYS / Container: CDB$ROOT

创建可插拔数据库PDB2:

SQL> show user
USER is "SYS"SQL> show pdbsCON_ID CON_NAME   OPEN MODE    RESTRICTED2 PDB$SEED   READ ONLY    NO3 PDB1       READ WRITE   NO-- pdb_admin是local admin user
SQL> create pluggable database PDB2 admin user pdb_admin identified by Ora_DB4U;
Pluggable database created.-- 初始克隆的PDB是mount状态
SQL> alter pluggable database PDB2 open;
Pluggable database altered.SQL> show pdbsCON_ID CON_NAME   OPEN MODE    RESTRICTED2 PDB$SEED   READ ONLY    NO3 PDB1       READ WRITE   NO4 PDB2       READ WRITE   NOSQL> alter session set container = PDB2;
Session altered.SQL> grant sysdba to pdb_admin;
Grant succeeded.-- 由pdb$seed克隆而来,因此最初没有users表空间
SQL> create tablespace users datafile size 20M autoextend on next 1M maxsize unlimited segment space management auto;
Tablespace created.SQL> alter database default tablespace Users;
Database altered.SQL> grant create table, unlimited tablespace to pdb_admin;
Grant succeeded.

在pdb2中创建测试表:

SQL> connect pdb_admin/Ora_DB4U@localhost:1521/pdb2
Connected.SQL> create table my_tab(my_col number);
Table created.SQL> insert into my_tab values (1);
1 row created.SQL> commit;
Commit complete.

切换到CDB根并显示所有的表空间:

connect sys/Ora_DB4U@localhost:1521/cdb1 as sysdbawith Containers as (select PDB_ID Con_ID, PDB_Name Con_Name from DBA_PDBsunionselect 1 Con_ID, 'CDB$ROOT' Con_Name from Dual)
selectCon_ID,Con_Name "Con_Name",Tablespace_Name "T'space_Name",File_Name "File_Name"
from CDB_Data_Files inner join Containers using (Con_ID)
union
selectCon_ID,Con_Name "Con_Name",Tablespace_Name "T'space_Name",File_Name "File_Name"
from CDB_Temp_Files inner join Containers using (Con_ID)
order by 1, 3
/

这个SQL首先使用with子句创建了CTE(Common Table Expression),CTE中的union兼顾了PDB和CDB根。然后在之后的SELECT语句中,分别查询了CDB_Data_Files和CDB_Temp_Files,并将结果集合并。然后,inner join是最常见的联接类型。 只会从一个表中返回与另一个表中存在匹配行的行。

输出如下:

  CON_ID Con_Name   T'space_Name   File_Name1 CDB$ROOT   SYSAUX         /opt/oracle/oradata/CDB1/sysaux01.dbf1 CDB$ROOT   SYSTEM         /opt/oracle/oradata/CDB1/system01.dbf1 CDB$ROOT   TEMP           /opt/oracle/oradata/CDB1/temp01.dbf1 CDB$ROOT   UNDOTBS1       /opt/oracle/oradata/CDB1/undotbs01.dbf1 CDB$ROOT   USERS          /opt/oracle/oradata/CDB1/users01.dbf3 PDB1       SYSAUX         /opt/oracle/oradata/CDB1/PDB1/sysaux01.dbf3 PDB1       SYSTEM         /opt/oracle/oradata/CDB1/PDB1/system01.dbf3 PDB1       TEMP           /opt/oracle/oradata/CDB1/PDB1/temp01.dbf3 PDB1       UNDOTBS1       /opt/oracle/oradata/CDB1/PDB1/undotbs01.dbf3 PDB1       USERS          /opt/oracle/oradata/CDB1/PDB1/users01.dbf4 PDB2       SYSAUX         /opt/oracle/oradata/CDB1/D311F4F4FC433460E053C000000ABBB1/datafile/o1_mf_sysaux_jvhw5tmm_.dbf4 PDB2       SYSTEM         /opt/oracle/oradata/CDB1/D311F4F4FC433460E053C000000ABBB1/datafile/o1_mf_system_jvhw5tmb_.dbf4 PDB2       TEMP           /opt/oracle/oradata/CDB1/D311F4F4FC433460E053C000000ABBB1/datafile/o1_mf_temp_jvhw5tmn_.dbf4 PDB2       UNDOTBS1       /opt/oracle/oradata/CDB1/D311F4F4FC433460E053C000000ABBB1/datafile/o1_mf_undotbs1_jvhw5tmm_.dbf4 PDB2       USERS          /opt/oracle/oradata/CDB1/D311F4F4FC433460E053C000000ABBB1/datafile/o1_mf_users_jvhw7gfy_.dbf15 rows selected.

Task 2: Clone a PDB

SQL> connect sys/Ora_DB4U@localhost:1521/cdb1 as sysdba
Connected.-- 普通的克隆要求源PDB是只读的,但实际上此处也可以热克隆
SQL> alter pluggable database PDB2 open read only force;
Pluggable database altered.SQL> show pdbsCON_ID CON_NAME   OPEN MODE    RESTRICTED2 PDB$SEED   READ ONLY    NO3 PDB1       READ WRITE   NO4 PDB2       READ ONLY    NOSQL> create pluggable database PDB3 from PDB2;
Pluggable database created.SQL> alter pluggable database PDB3 open force;
Pluggable database altered.SQL> show pdbsCON_ID CON_NAME   OPEN MODE    RESTRICTED2 PDB$SEED   READ ONLY    NO3 PDB1       READ WRITE   NO4 PDB2       READ ONLY    NO5 PDB3       READ WRITE   NOSQL> alter pluggable database PDB2 open read write force;
Pluggable database altered.SQL> show pdbsCON_ID CON_NAME   OPEN MODE    RESTRICTED2 PDB$SEED   READ ONLY    NO3 PDB1       READ WRITE   NO4 PDB2       READ WRITE   NO5 PDB3       READ WRITE   NO

注意以上代码段中的alter pluggable database open .... force。如果不指定force,则PDB要求处于mount状态。如果PDB不是mount状态,则报错如下:

ERROR at line 1:
ORA-65019: pluggable database PDB2 already open

以下确认测试表被克隆:

SQL> connect pdb_admin/Ora_DB4U@localhost:1521/pdb2
Connected.
SQL> select * from my_tab;MY_COL1SQL> connect pdb_admin/Ora_DB4U@localhost:1521/pdb3
Connected.
SQL> select * from my_tab;MY_COL1

Task 3: Unplug a PDB

本节演示如何从容器数据库 (CDB) 中拔出 PDB 并将 PDB 元数据保存到 XML文件中。

SQL> connect sys/Ora_DB4U@localhost:1521/cdb1 as sysdba
Connected.
SQL> show pdbsCON_ID CON_NAME   OPEN MODE    RESTRICTED2 PDB$SEED   READ ONLY    NO3 PDB1       READ WRITE   NO4 PDB2       READ ONLY    NO5 PDB3       READ WRITE   NO-- unplug前必须关闭数据库
SQL> alter pluggable database PDB3 close immediate;
Pluggable database altered.SQL> alter pluggable database PDB3 unplug into '/opt/oracle/oradata/CDB1/pdb3.xml';
Pluggable database altered.SQL> show pdbsCON_ID CON_NAME   OPEN MODE    RESTRICTED2 PDB$SEED   READ ONLY    NO3 PDB1       READ WRITE   NO4 PDB2       READ ONLY    NO5 PDB3       MOUNTED-- 将PDB3从CDB中删除,但其数据文件仍在(keep datafiles)
SQL> drop pluggable database PDB3 keep datafiles;
Pluggable database dropped.SQL> show pdbsCON_ID CON_NAME   OPEN MODE    RESTRICTED2 PDB$SEED   READ ONLY    NO3 PDB1       READ WRITE   NO4 PDB2       READ ONLY    NO

查看XML文件:

SQL> host cat /opt/oracle/oradata/CDB1/pdb3.xml
<?xml version="1.0" encoding="UTF-8"?>
<PDB><xmlversion>1</xmlversion><pdbname>PDB3</pdbname><cid>5</cid><byteorder>1</byteorder><vsn>318767104</vsn><vsns><vsnnum>19.0.0.0.0</vsnnum><cdbcompt>19.0.0.0.0</cdbcompt><pdbcompt>19.0.0.0.0</pdbcompt><vsnlibnum>0.0.0.0.24</vsnlibnum><vsnsql>24</vsnsql><vsnbsv>8.0.0.0.0</vsnbsv></vsns><dbid>1895726733</dbid><ncdb2pdb>0</ncdb2pdb><cdbid>1058798813</cdbid><guid>D3125F5FE21B66E1E053C000000AE230</guid><uscnbas>4249686</uscnbas><uscnwrp>0</uscnwrp><undoscn>280</undoscn><rdba>4194824</rdba><tablespace><name>SYSTEM</name><type>0</type><tsn>0</tsn><status>1</status><issft>0</issft><isnft>0</isnft><encts>0</encts><flags>0</flags><bmunitsize>8</bmunitsize><file><path>/opt/oracle/oradata/CDB1/D3125F5FE21B66E1E053C000000AE230/datafile/o1_mf_system_jvhxxvhj_.dbf</path><afn>17</afn><rfn>1</rfn><createscnbas>4247653</createscnbas><createscnwrp>0</createscnwrp><status>1</status><fileblocks>42240</fileblocks><blocksize>8192</blocksize><vsn>318767104</vsn><fdbid>1895726733</fdbid><fcpsb>4249677</fcpsb><fcpsw>0</fcpsw><frlsb>1920977</frlsb><frlsw>0</frlsw><frlt>1085081375</frlt><autoext>1</autoext><maxsize>4194302</maxsize><incsize>1280</incsize><plugscn>0</plugscn><plugafn>0</plugafn><plugdbid>0</plugdbid><dfflags>1</dfflags></file></tablespace><tablespace><name>SYSAUX</name><type>0</type><tsn>1</tsn><status>1</status><issft>0</issft><isnft>0</isnft><encts>0</encts><flags>0</flags><bmunitsize>8</bmunitsize><file><path>/opt/oracle/oradata/CDB1/D3125F5FE21B66E1E053C000000AE230/datafile/o1_mf_sysaux_jvhxxvhk_.dbf</path><afn>18</afn><rfn>4</rfn><createscnbas>4247658</createscnbas><createscnwrp>0</createscnwrp><status>1</status><fileblocks>60160</fileblocks><blocksize>8192</blocksize><vsn>318767104</vsn><fdbid>1895726733</fdbid><fcpsb>4249677</fcpsb><fcpsw>0</fcpsw><frlsb>1920977</frlsb><frlsw>0</frlsw><frlt>1085081375</frlt><autoext>1</autoext><maxsize>4194302</maxsize><incsize>1280</incsize><plugscn>0</plugscn><plugafn>0</plugafn><plugdbid>0</plugdbid><dfflags>1</dfflags></file></tablespace><tablespace><name>UNDOTBS1</name><type>2</type><tsn>2</tsn><status>1</status><issft>0</issft><isnft>0</isnft><encts>0</encts><flags>0</flags><bmunitsize>8</bmunitsize><file><path>/opt/oracle/oradata/CDB1/D3125F5FE21B66E1E053C000000AE230/datafile/o1_mf_undotbs1_jvhxxvhk_.dbf</path><afn>19</afn><rfn>9</rfn><createscnbas>4247661</createscnbas><createscnwrp>0</createscnwrp><status>1</status><fileblocks>27520</fileblocks><blocksize>8192</blocksize><vsn>318767104</vsn><fdbid>1895726733</fdbid><fcpsb>4249677</fcpsb><fcpsw>0</fcpsw><frlsb>1920977</frlsb><frlsw>0</frlsw><frlt>1085081375</frlt><autoext>1</autoext><maxsize>4194302</maxsize><incsize>640</incsize><plugscn>0</plugscn><plugafn>0</plugafn><plugdbid>0</plugdbid><dfflags>1</dfflags></file></tablespace><tablespace><name>TEMP</name><type>1</type><tsn>3</tsn><status>1</status><issft>0</issft><isnft>0</isnft><encts>0</encts><flags>0</flags><bmunitsize>128</bmunitsize><file><path>/opt/oracle/oradata/CDB1/D3125F5FE21B66E1E053C000000AE230/datafile/o1_mf_temp_jvhxxvhl_.dbf</path><afn>5</afn><rfn>1</rfn><createscnbas>4247654</createscnbas><createscnwrp>0</createscnwrp><status>1</status><fileblocks>8320</fileblocks><blocksize>8192</blocksize><vsn>318767104</vsn><autoext>1</autoext><maxsize>4194302</maxsize><incsize>80</incsize><plugscn>0</plugscn><plugafn>0</plugafn><plugdbid>0</plugdbid><dfflags>1</dfflags></file></tablespace><tablespace><name>USERS</name><type>0</type><tsn>5</tsn><status>1</status><issft>0</issft><isnft>0</isnft><encts>0</encts><flags>0</flags><bmunitsize>8</bmunitsize><file><path>/opt/oracle/oradata/CDB1/D3125F5FE21B66E1E053C000000AE230/datafile/o1_mf_users_jvhxxvhl_.dbf</path><afn>20</afn><rfn>16</rfn><createscnbas>4247666</createscnbas><createscnwrp>0</createscnwrp><status>1</status><fileblocks>2560</fileblocks><blocksize>8192</blocksize><vsn>318767104</vsn><fdbid>1895726733</fdbid><fcpsb>4249677</fcpsb><fcpsw>0</fcpsw><frlsb>1920977</frlsb><frlsw>0</frlsw><frlt>1085081375</frlt><autoext>1</autoext><maxsize>4194302</maxsize><incsize>128</incsize><plugscn>0</plugscn><plugafn>0</plugafn><plugdbid>0</plugdbid><dfflags>1</dfflags></file></tablespace><recover>0</recover><optional><ncdb2pdb>0</ncdb2pdb><csid>873</csid><ncsid>2000</ncsid><options><option>APS=19.0.0.0.0</option><option>CATALOG=19.0.0.0.0</option><option>CATJAVA=19.0.0.0.0</option><option>CATPROC=19.0.0.0.0</option><option>CONTEXT=19.0.0.0.0</option><option>DV=19.0.0.0.0</option><option>JAVAVM=19.0.0.0.0</option><option>OLS=19.0.0.0.0</option><option>ORDIM=19.0.0.0.0</option><option>OWM=19.0.0.0.0</option><option>SDO=19.0.0.0.0</option><option>XDB=19.0.0.0.0</option><option>XML=19.0.0.0.0</option><option>XOQ=19.0.0.0.0</option></options><olsoid>0</olsoid><dv>0</dv><APEX>NULL</APEX><parameters><parameter>processes=320</parameter><parameter>sga_max_size=3221225472</parameter><parameter>nls_language='AMERICAN'</parameter><parameter>nls_territory='AMERICA'</parameter><parameter>db_block_size=8192</parameter><parameter>compatible='19.0.0'</parameter><parameter>open_cursors=300</parameter><parameter>pga_aggregate_target=3310354432</parameter><parameter>enable_pluggable_database=TRUE</parameter></parameters><sqlpatches><sqlpatch>19.11.0.0.0 Release_Update 2104130040 (RU): APPLY SUCCESS</sqlpatch><sqlpatch>Interim patch 32399816/24099425 (OJVM RELEASE UPDATE: 19.11.0.0.210420 (32399816)): APPLY SUCCESS</sqlpatch></sqlpatches><tzvers><tzver>primary version:32</tzver><tzver>secondary version:0</tzver></tzvers><walletkey>0</walletkey><services/><opatches><opatch>32545013</opatch><opatch>29585399</opatch></opatches><hasclob>1</hasclob><awr><loadprofile>CPU used by this session=27.946360</loadprofile><loadprofile>DB time=44.249076</loadprofile><loadprofile>db block changes=2615.587474</loadprofile><loadprofile>execute count=1203.313948</loadprofile><loadprofile>logons cumulative=1.261745</loadprofile><loadprofile>parse count (hard)=63.016489</loadprofile><loadprofile>parse count (total)=824.034300</loadprofile><loadprofile>physical reads=109.988929</loadprofile><loadprofile>physical writes=34.585917</loadprofile><loadprofile>redo size=464588.416887</loadprofile><loadprofile>session logical reads=7620.112571</loadprofile><loadprofile>user calls=40.315157</loadprofile><loadprofile>user commits=8.739462</loadprofile><loadprofile>user logons cumulative=0.001984</loadprofile><loadprofile>user rollbacks=0.047312</loadprofile></awr><hardvsnchk>0</hardvsnchk><localundo>1</localundo><apps/><dbedition>8</dbedition><dvopsctl>2</dvopsctl><clnupsrcpal>1</clnupsrcpal></optional>
</PDB>

Task 4: Plug in a PDB

本实验开始涉及另一个CDB:CDB2。

SQL> connect sys/Ora_DB4U@localhost:1522/cdb2 as sysdba
Connected.SQL> @whoami
Who am I?
DB Name: CDB2 / CDB?: YES / Auth-ID: SYS / Sessn-User: SYS / Container: CDB$ROOTSQL> show pdbsCON_ID CON_NAME   OPEN MODE    RESTRICTED2 PDB$SEED   READ ONLY    NO3 PDB2       READ WRITE   NO

检查PDB3和CDB2的兼容性。无报错,表示兼容:

SQL>
beginif notSys.DBMS_PDB.Check_Plug_Compatibility('/opt/oracle/oradata/CDB1/pdb3.xml')thenRaise_Application_Error(-20000, 'Incompatible');end if;
end;
/PL/SQL procedure successfully completed.

使用XML文件插入PDB:

-- move表示将数据文件从CDB1移动到CDB2中的位置
SQL> create pluggable database PDB3 using '/opt/oracle/oradata/CDB1/pdb3.xml' move;
Pluggable database created.SQL> show pdbsCON_ID CON_NAME   OPEN MODE    RESTRICTED2 PDB$SEED   READ ONLY    NO3 PDB2       READ WRITE   NO4 PDB3       MOUNTEDSQL> alter pluggable database PDB3 open;
Pluggable database altered.SQL> show pdbsCON_ID CON_NAME   OPEN MODE    RESTRICTED2 PDB$SEED   READ ONLY    NO3 PDB2       READ WRITE   NO4 PDB3       READ WRITE   NO

此时数据文件位置如下:

  CON_ID Con_Name   T'space_Name   File_Name1 CDB$ROOT   SYSAUX         /opt/oracle/oradata/CDB2/sysaux01.dbf1 CDB$ROOT   SYSTEM         /opt/oracle/oradata/CDB2/system01.dbf1 CDB$ROOT   TEMP           /opt/oracle/oradata/CDB2/temp01.dbf1 CDB$ROOT   UNDOTBS1       /opt/oracle/oradata/CDB2/undotbs01.dbf1 CDB$ROOT   USERS          /opt/oracle/oradata/CDB2/users01.dbf3 PDB2       SYSAUX         /opt/oracle/oradata/CDB2/PDB2/sysaux01.dbf3 PDB2       SYSTEM         /opt/oracle/oradata/CDB2/PDB2/system01.dbf3 PDB2       TEMP           /opt/oracle/oradata/CDB2/PDB2/temp01.dbf3 PDB2       UNDOTBS1       /opt/oracle/oradata/CDB2/PDB2/undotbs01.dbf3 PDB2       USERS          /opt/oracle/oradata/CDB2/PDB2/users01.dbf4 PDB3       SYSAUX         /opt/oracle/oradata/CDB2/D3125F5FE21B66E1E053C000000AE230/datafile/o1_mf_sysaux_jvhyx07p_.dbf4 PDB3       SYSTEM         /opt/oracle/oradata/CDB2/D3125F5FE21B66E1E053C000000AE230/datafile/o1_mf_system_jvhyx07c_.dbf4 PDB3       TEMP           /opt/oracle/oradata/CDB2/D3125F5FE21B66E1E053C000000AE230/datafile/o1_mf_temp_jvhyx07r_.dbf4 PDB3       UNDOTBS1       /opt/oracle/oradata/CDB2/D3125F5FE21B66E1E053C000000AE230/datafile/o1_mf_undotbs1_jvhyx07q_.dbf4 PDB3       USERS          /opt/oracle/oradata/CDB2/D3125F5FE21B66E1E053C000000AE230/datafile/o1_mf_users_jvhyx07r_.dbf15 rows selected.

确认测试表还在:

SQL> connect pdb_admin/Ora_DB4U@localhost:1522/pdb3
Connected.SQL> select * from my_tab;MY_COL1

Task 5: Drop a PDB

SQL> connect sys/Ora_DB4U@localhost:1522/cdb2 as sysdba
Connected.SQL> show pdbsCON_ID CON_NAME   OPEN MODE    RESTRICTED2 PDB$SEED   READ ONLY    NO3 PDB2       READ WRITE   NO4 PDB3       READ WRITE   NOSQL> alter pluggable database PDB3 close immediate;
Pluggable database altered.-- including datafiles表示将数据文件也删除了
SQL> drop pluggable database PDB3 including datafiles;
Pluggable database dropped.SQL> show pdbsCON_ID CON_NAME   OPEN MODE    RESTRICTED2 PDB$SEED   READ ONLY    NO3 PDB2       READ WRITE   NO

Task 6: Clone an unplugged PDB

首先在CDB1中制造由PDB2克隆黄金副本PDB:GOLDPDB,然后拔出并保留数据文件,

SQL> connect sys/Ora_DB4U@localhost:1521/cdb1 as sysdba
Connected.SQL> alter pluggable database PDB2 open read only force;
Pluggable database altered.SQL> show pdbsCON_ID CON_NAME   OPEN MODE    RESTRICTED2 PDB$SEED   READ ONLY    NO3 PDB1       READ WRITE   NO4 PDB2       READ ONLY    NOSQL> create pluggable database GOLDPDB from PDB2;
Pluggable database created.SQL> alter pluggable database GOLDPDB open force;
Pluggable database altered.SQL> show pdbsCON_ID CON_NAME   OPEN MODE    RESTRICTED2 PDB$SEED   READ ONLY    NO3 PDB1       READ WRITE   NO4 PDB2       READ ONLY    NO5 GOLDPDB    READ WRITE   NOSQL> alter pluggable database PDB2 open read write force;
Pluggable database altered.SQL> show pdbsCON_ID CON_NAME   OPEN MODE    RESTRICTED2 PDB$SEED   READ ONLY    NO3 PDB1       READ WRITE   NO4 PDB2       READ WRITE   NO5 GOLDPDB    READ WRITE   NOSQL> alter pluggable database GOLDPDB close immediate;
Pluggable database altered.SQL> alter pluggable database GOLDPDB unplug into '/opt/oracle/oradata/CDB1/goldpdb.xml';
Pluggable database altered.SQL> show pdbsCON_ID CON_NAME   OPEN MODE    RESTRICTED2 PDB$SEED   READ ONLY    NO3 PDB1       READ WRITE   NO4 PDB2       READ WRITE   NO5 GOLDPDB    MOUNTED-- 保留数据文件
SQL> drop pluggable database GOLDPDB keep datafiles;
Pluggable database dropped.SQL> show pdbsCON_ID CON_NAME   OPEN MODE    RESTRICTED2 PDB$SEED   READ ONLY    NO3 PDB1       READ WRITE   NO4 PDB2       READ WRITE   NO

然后在CDB2中,直接由XML文件克隆PDB:

SQL> connect sys/Ora_DB4U@localhost:1522/cdb2 as sysdba
Connected.-- 验证PDB与CDB的兼容性
SQL>
beginif notSys.DBMS_PDB.Check_Plug_Compatibility
('/opt/oracle/oradata/CDB1/goldpdb.xml')thenRaise_Application_Error(-20000, 'Incompatible');end if;
end;
/PL/SQL procedure successfully completed.SQL>
create pluggable database COPYPDB1 as clone
using '/opt/oracle/oradata/CDB1/goldpdb.xml'
storage (maxsize unlimited max_shared_temp_size unlimited)
copy;
Pluggable database created.-- 此语法属于create_pdb_from_xml子句,storage行无必要,因其指定的就是默认值。
-- copy选项外,还有move和nocopy(留在原处)
SQL>
create pluggable database COPYPDB2 as clone
using '/opt/oracle/oradata/CDB1/goldpdb.xml'
storage (maxsize unlimited max_shared_temp_size unlimited)
copy;SQL> show pdbsCON_ID CON_NAME   OPEN MODE    RESTRICTED2 PDB$SEED   READ ONLY    NO3 PDB2       READ WRITE   NO4 COPYPDB1   MOUNTED5 COPYPDB2   MOUNTEDSQL> alter pluggable database all open;
Pluggable database altered.SQL> show pdbsCON_ID CON_NAME   OPEN MODE    RESTRICTED2 PDB$SEED   READ ONLY    NO3 PDB2       READ WRITE   NO4 COPYPDB1   READ WRITE   NO5 COPYPDB2   READ WRITE   NO-- 由于源自同一PDB,因此GUID类似,但不相同
SQL> select PDB_Name "PDB Name", GUIDfrom DBA_PDBsorder by Creation_Scn/
PDB Name   GUID
PDB$SEED   CD8D4DDD8CCB05E1E0533800000A858C
PDB2       CD8D71A2721F1AACE0533800000A39BD
COPYPDB1   D312CACA2B480DA9E053C000000A95A5
COPYPDB2   D312CACA2B4A0DA9E053C000000A95A5

Task 7: PDB hot clones

这是12.2的新特性,请在此网站搜索Hot Clone。

首先在CDB1中操作:

SQL> connect sys/Ora_DB4U@localhost:1521/cdb1 as sysdba
Connected.SQL> create pluggable database oe admin user soe identified by soe roles=(dba);
Pluggable database created.SQL> alter pluggable database oe open;
Pluggable database altered.SQL> show pdbsCON_ID CON_NAME   OPEN MODE    RESTRICTED2 PDB$SEED   READ ONLY    NO3 PDB1       READ WRITE   NO4 PDB2       READ WRITE   NO5 OE         READ WRITE   NOSQL> alter session set container = oe;
Session altered.SQL> grant create session, create table to soe;
Grant succeeded.-- bigfile表空间类型是相对于传统的smallfile而言,只有1个数据文件,可以简化管理。
SQL> create bigfile tablespace users;
Tablespace created.SQL> alter user soe quota unlimited on users;
User altered.SQL> alter user soe default tablespace users;
User altered.

上一段代码中,创建PDB有一个子句roles=(dba),那后续为什么又给soe用户授权呢?看以下的SQL:

-- DBA是角色,而且是common role
SQL> select * from dba_roles where role='DBA';
ROLE     ROLE_ID PASSWORD_REQUIRED   AUTHENTICATION_TYPE   COMMON   ORACLE_MAINTAINED   INHERITED   IMPLICIT   EXTERNAL_NAME
DBA            4 NO                  NONE                  YES      Y                   YES         NO-- PDB_DBA也是common role
SQL> select * from dba_roles where role='PDB_DBA';
ROLE        ROLE_ID PASSWORD_REQUIRED   AUTHENTICATION_TYPE   COMMON   ORACLE_MAINTAINED   INHERITED   IMPLICIT   EXTERNAL_NAME
PDB_DBA           5 NO                  NONE                  YES      Y                   YES         NO-- PDB_DBA被赋予了DBA role
SQL> SELECT * FROM DBA_ROLE_PRIVS where grantee='PDB_DBA';
GRANTEE   GRANTED_ROLE   ADMIN_OPTION   DELEGATE_OPTION   DEFAULT_ROLE   COMMON   INHERITED
PDB_DBA   DBA            NO             NO                YES            NO       NO-- DBA role被赋予的角色
SQL> select * from role_role_privs  where role = 'DBA' order by 1;
ROLE   GRANTED_ROLE                 ADMIN_OPTION   COMMON   INHERITED
DBA    EXECUTE_CATALOG_ROLE         NO             YES      YES
DBA    DATAPUMP_IMP_FULL_DATABASE   NO             YES      YES
DBA    SCHEDULER_ADMIN              NO             YES      YES
DBA    XDBADMIN                     NO             YES      YES
DBA    OLAP_DBA                     NO             YES      YES
DBA    CAPTURE_ADMIN                NO             YES      YES
DBA    SELECT_CATALOG_ROLE          NO             YES      YES
DBA    DATAPUMP_EXP_FULL_DATABASE   NO             YES      YES
DBA    GATHER_SYSTEM_STATISTICS     NO             YES      YES
DBA    WM_ADMIN_ROLE                NO             YES      YES
DBA    EXP_FULL_DATABASE            NO             YES      YES
DBA    OPTIMIZER_PROCESSING_RATE    NO             YES      YES
DBA    EM_EXPRESS_ALL               NO             YES      YES
DBA    IMP_FULL_DATABASE            NO             YES      YES
DBA    XDB_SET_INVOKER              NO             YES      YES
DBA    JAVA_ADMIN                   NO             YES      YES
DBA    OLAP_XS_ADMIN                NO             YES      YES17 rows selected.-- DBA role的权限,非常多
SQL> select * from role_sys_privs where ROLE = 'DBA' order by 1;
ROLE   PRIVILEGE                            ADMIN_OPTION   COMMON   INHERITED
DBA    CREATE ANY HIERARCHY                 NO             YES      YES
DBA    ALTER ANY ATTRIBUTE DIMENSION        NO             YES      YES
DBA    CREATE ANY ATTRIBUTE DIMENSION       NO             YES      YES
DBA    CREATE ATTRIBUTE DIMENSION           NO             YES      YES
...
DBA    CREATE ANY TABLE                     NO             YES      YES
DBA    MANAGE TABLESPACE                    NO             YES      YES235 rows selected.-- soe用户实际并没有被赋予任何角色
SQL> select * from USER_ROLE_PRIVS where username = 'SOE';
no rows selected

根据文档,ROLES=(DBA)表示将DBA角色赋予角色PDB_DBA,这语句颇具迷惑性,虽然admin user是soe,但soe并没有赋予任何角色。除非:

SQL> grant pdb_dba to soe;

role相关系统表参考这里。

创建测试表:

SQL> connect soe/soe@localhost:1521/oe
Connected.
SQL>
CREATE TABLE sale_orders
(ORDER_ID      number,
ORDER_DATE    date,
CUSTOMER_ID   number);Table created.

在另一终端启动测试脚本,持续向表中写数据。让其一致运行,因为下一个实验还需要:

cd /home/oracle/labs/multitenant
./write-load.sh

然后在CDB2中将PDB oe克隆为oe_dev。

SQL> connect sys/Ora_DB4U@localhost:1522/cdb2 as sysdba
Connected.-- 通过Database Link热克隆,源PDB为可读写状态
SQL> create pluggable database oe_dev from oe@cdb1_link;
Pluggable database created.SQL> alter pluggable database oe_dev open;
Pluggable database altered.-- 1522表示是CDB2
SQL> connect soe/soe@localhost:1522/oe_dev
Connected.SQL> select count(*) from sale_orders;COUNT(*)230-- 1521表示是CDB1
SQL> connect soe/soe@localhost:1521/oe
Connected.-- oe中的输出大于oe_dev中的输出,说明oe_dev是oe的时间点快照
SQL> select count(*) from sale_orders;COUNT(*)580SQL> connect sys/Ora_DB4U@localhost:1522/cdb2 as sysdba
Connected.
SQL> alter pluggable database oe_dev close;Pluggable database altered.SQL> drop pluggable database oe_dev including datafiles;
Pluggable database dropped.

研究下脚本write-load.sh:

$ cat write-load.sh
#!/bin/sh
#
ORACLE_SID=CDB1
ORAENV_ASK=NO
. oraenv#
echo ""
echo "  NOTE:"
echo "  To break out of this batch"
echo "  job, please issue CTL-C "
echo ""
echo "...sleeping 5 seconds"
echo ""
sleep 5sqlplus -S /nolog << EOF@truncate_sale_orders.sql
EOFc=1
while [ $c -le 1000 ]
dosqlplus -S /nolog  << EOF@batch-orders.sqlcommit;@count-sales.sql@scn.sql@dbname.sql
EOF
sleep 1
(( c++))
done

把这个脚本展开,大致是以下的意思:

-- 清空表
truncate table sale_orders;-- 插入数据
insert allinto sale_orders (ORDER_ID, ORDER_DATE, CUSTOMER_ID) VALUES (3041,'10-MAY-15', 13287)into sale_orders (ORDER_ID, ORDER_DATE, CUSTOMER_ID) VALUES (3041,'10-MAY-15', 13287)into sale_orders (ORDER_ID, ORDER_DATE, CUSTOMER_ID) VALUES (3041,'10-MAY-15', 13287)into sale_orders (ORDER_ID, ORDER_DATE, CUSTOMER_ID) VALUES (3041,'10-MAY-15', 13287)into sale_orders (ORDER_ID, ORDER_DATE, CUSTOMER_ID) VALUES (3041,'10-MAY-15', 13287)into sale_orders (ORDER_ID, ORDER_DATE, CUSTOMER_ID) VALUES (3041,'10-MAY-15', 13287)into sale_orders (ORDER_ID, ORDER_DATE, CUSTOMER_ID) VALUES (3041,'10-MAY-15', 13287)into sale_orders (ORDER_ID, ORDER_DATE, CUSTOMER_ID) VALUES (3035,'10-MAY-15', 13287)into sale_orders (ORDER_ID, ORDER_DATE, CUSTOMER_ID) VALUES (3041,'10-MAY-15', 13287)into sale_orders (ORDER_ID, ORDER_DATE, CUSTOMER_ID) VALUES (3041,'10-MAY-15', 13287)
select 1 from dual;-- 显示行数
select count(*) from sale_orders;-- 显示数据库SCN和当前时间
select current_scn, to_char(sysdate, 'YYYYMMDD-HH12MISS') time from v$database;-- 显示数据库名
select name from v$database;-- 休眠1秒,回到插入数据那一步

Task 8: PDB refresh

连到CDB2,由CDB1中的PDB oe创建可刷新的PDB oe_refresh:

SQL> connect sys/Ora_DB4U@localhost:1522/cdb2 as sysdba
Connected.-- 手工刷新模式
SQL> create pluggable database oe_refresh from oe@cdb1_link refresh mode manual;
Pluggable database created.SQL> alter pluggable database oe_refresh open read only;
Pluggable database altered.SQL> show pdbsCON_ID CON_NAME     OPEN MODE    RESTRICTED2 PDB$SEED     READ ONLY    NO3 PDB2         READ WRITE   NO4 COPYPDB1     READ WRITE   NO5 COPYPDB2     READ WRITE   NO6 OE_REFRESH   READ ONLY    NOSQL> conn soe/soe@localhost:1522/oe_refresh
Connected.-- 刷新前的计数
SQL> select count(*) from sale_orders;COUNT(*)4710-- 在PDB oe_refresh中手工刷新
SQL> conn sys/Ora_DB4U@localhost:1522/oe_refresh as sysdba
Connected.SQL> alter pluggable database oe_refresh close;
Pluggable database altered.SQL> alter session set container=oe_refresh;
Session altered.SQL> alter pluggable database oe_refresh refresh;
Pluggable database altered.SQL> alter pluggable database oe_refresh open read only;
Pluggable database altered.SQL> conn soe/soe@localhost:1522/oe_refresh
Connected.-- 刷新后的计数
SQL> select count(*) from sale_orders;COUNT(*)5040

注意,可刷新PDB只能处于mount或只读状态(如此才能刷新),不能设置为读写状态,除非将refresh mode置为none。

SQL> connect sys/Ora_DB4U@localhost:1522/cdb2 as sysdba
Connected.SQL> show pdbsCON_ID CON_NAME     OPEN MODE    RESTRICTED2 PDB$SEED     READ ONLY    NO3 PDB2         READ WRITE   NO4 COPYPDB1     READ WRITE   NO5 COPYPDB2     READ WRITE   NO6 OE_REFRESH   READ ONLY    NOSQL> alter pluggable database oe_refresh open read write;alter pluggable database oe_refresh open read write*
ERROR at line 1:
ORA-65341: cannot open pluggable database in read/write modeSQL> alter pluggable database oe_refresh refresh mode none;
Pluggable database altered.SQL> alter pluggable database oe_refresh open read write;
Pluggable database altered.

这里有个有趣的现象,就是oe_refresh在可刷新状态时,只能看到TEMP表空间,而在取消刷新状态,变为可读写后,就可以看到所有数据文件了:

  CON_ID Con_Name     T'space_Name   File_Name1 CDB$ROOT     SYSAUX         /opt/oracle/oradata/CDB2/sysaux01.dbf1 CDB$ROOT     SYSTEM         /opt/oracle/oradata/CDB2/system01.dbf1 CDB$ROOT     TEMP           /opt/oracle/oradata/CDB2/temp01.dbf1 CDB$ROOT     UNDOTBS1       /opt/oracle/oradata/CDB2/undotbs01.dbf1 CDB$ROOT     USERS          /opt/oracle/oradata/CDB2/users01.dbf3 PDB2         SYSAUX         /opt/oracle/oradata/CDB2/PDB2/sysaux01.dbf3 PDB2         SYSTEM         /opt/oracle/oradata/CDB2/PDB2/system01.dbf3 PDB2         TEMP           /opt/oracle/oradata/CDB2/PDB2/temp01.dbf3 PDB2         UNDOTBS1       /opt/oracle/oradata/CDB2/PDB2/undotbs01.dbf3 PDB2         USERS          /opt/oracle/oradata/CDB2/PDB2/users01.dbf7 OE_REFRESH   SYSAUX         /opt/oracle/oradata/CDB2/D315C60F6FBB5032E053C000000A3D63/datafile/o1_mf_sysaux_jvjd63d4_.dbf7 OE_REFRESH   SYSTEM         /opt/oracle/oradata/CDB2/D315C60F6FBB5032E053C000000A3D63/datafile/o1_mf_system_jvjd63d2_.dbf7 OE_REFRESH   TEMP           /opt/oracle/oradata/CDB2/D315C60F6FBB5032E053C000000A3D63/datafile/o1_mf_temp_jvjd63d5_.dbf7 OE_REFRESH   UNDOTBS1       /opt/oracle/oradata/CDB2/D315C60F6FBB5032E053C000000A3D63/datafile/o1_mf_undotbs1_jvjd63d5_.dbf7 OE_REFRESH   USERS          /opt/oracle/oradata/CDB2/D315C60F6FBB5032E053C000000A3D63/datafile/o1_mf_users_jvjd63d6_.dbf

还有,如果取消刷新模式后,如果需要再启用刷新模式,就只有重新建立可刷新PDB了。

SQL> alter pluggable database oe_refresh refresh mode manual;alter pluggable database oe_refresh refresh mode manual*
ERROR at line 1:
ORA-65261: pluggable database OE_REFRESH not enabled for refresh

Task 9: PDB snapshot COPY

先来看概念。快照副本减少了创建克隆所需的时间(这点在创建测试环境时尤为重要)并节省空间。 可以在任何文件系统中创建快照副本,例如用于本地磁盘的 ext3、ext4、ntfs。 它还支持 NFS、ZFS、ACFS 和 Oracle Exadata 上的ASM 稀疏磁盘组。

在此实验的Linux环境下,需要满足以下条件:

  • CLONEDB初始化参数设置为TRUE
  • 源PDB只读(此处使用了上一个实验中的可刷新PDB)

连接到CDB2,修改参数CLONEDB,重启数据库使其生效:

SQL> connect sys/Ora_DB4U@localhost:1522/cdb2 as sysdba
Connected.SQL> @whoami
Who am I?
DB Name: CDB2 / CDB?: YES / Auth-ID: SYS / Sessn-User: SYS / Container: CDB$ROOTSQL> show pdbsCON_ID CON_NAME     OPEN MODE    RESTRICTED2 PDB$SEED     READ ONLY    NO3 PDB2         READ WRITE   NO4 COPYPDB1     READ WRITE   NO5 COPYPDB2     READ WRITE   NO6 OE_REFRESH   READ ONLY    NOSQL> show parameter CLONEDB
NAME        TYPE    VALUE
----------- ------- -----
clonedb     boolean FALSE
clonedb_dir stringSQL> alter system set CLONEDB = TRUE scope = spfile;
System altered.SQL> shutdown immediate
Database closed.
Database dismounted.
ORACLE instance shut down.SQL> startup
ORACLE instance started.Total System Global Area 3221223184 bytes
Fixed Size                  9139984 bytes
Variable Size             905969664 bytes
Database Buffers         2298478592 bytes
Redo Buffers                7634944 bytes
Database mounted.
Database opened.SQL> show parameter CLONEDBNAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
clonedb                              boolean     TRUE
clonedb_dir                          string

创建snapshot copy PDB OE_SNAP:

SQL> show pdbsCON_ID CON_NAME     OPEN MODE    RESTRICTED2 PDB$SEED     READ ONLY    NO3 PDB2         READ WRITE   NO4 COPYPDB1     MOUNTED5 COPYPDB2     MOUNTED6 OE_REFRESH   MOUNTEDSQL> alter pluggable database OE_REFRESH open read only force;
Pluggable database altered.SQL> create pluggable database OE_SNAP from OE_REFRESH snapshot copy;
Pluggable database created.SQL> show pdbsCON_ID CON_NAME     OPEN MODE    RESTRICTED2 PDB$SEED     READ ONLY    NO3 PDB2         READ WRITE   NO4 COPYPDB1     MOUNTED5 COPYPDB2     MOUNTED6 OE_REFRESH   READ ONLY    NO7 OE_SNAP      MOUNTEDSQL> alter pluggable database OE_SNAP open;Pluggable database altered.SQL> show pdbsCON_ID CON_NAME     OPEN MODE    RESTRICTED2 PDB$SEED     READ ONLY    NO3 PDB2         READ WRITE   NO4 COPYPDB1     MOUNTED5 COPYPDB2     MOUNTED6 OE_REFRESH   READ ONLY    NO7 OE_SNAP      READ WRITE   NO

snapshot copy pdb是可读写的,但其依赖的源库只能是只读状态,无论其是可刷新的PDB还是普通PDB。但

SQL> connect soe/soe@localhost:1522/oe_snap
Connected.
SQL> select count(*) from sale_orders;COUNT(*)5040SQL> insert into sale_orders VALUES (1, SYSDATE, 30);1 row created.SQL> commit;Commit complete.SQL> select count(*) from sale_orders;COUNT(*)5041

此处还必须说明一点,在创建snapshot copy PDB时,源PDB的数据文件权限会被修改成只读:

SQL> !ls -l /opt/oracle/oradata/CDB2/D3162D35EC8F2976E053C000000A7B1C/datafile/*.dbf
-rw-r-----. 1 oracle oinstall 513810432 Dec 14 06:22 /opt/oracle/oradata/CDB2/D3162D35EC8F2976E053C000000A7B1C/datafile/o1_mf_sysaux_jvjfw5xx_.dbf
-rw-r-----. 1 oracle oinstall 356524032 Dec 14 06:22 /opt/oracle/oradata/CDB2/D3162D35EC8F2976E053C000000A7B1C/datafile/o1_mf_system_jvjfw5xv_.dbf
-rw-r-----. 1 oracle oinstall  68165632 Dec 14 06:19 /opt/oracle/oradata/CDB2/D3162D35EC8F2976E053C000000A7B1C/datafile/o1_mf_temp_jvjfw5xy_.dbf
-rw-r-----. 1 oracle oinstall 225452032 Dec 14 06:22 /opt/oracle/oradata/CDB2/D3162D35EC8F2976E053C000000A7B1C/datafile/o1_mf_undotbs1_jvjfw5xx_.dbf
-rw-r-----. 1 oracle oinstall 104865792 Dec 14 06:22 /opt/oracle/oradata/CDB2/D3162D35EC8F2976E053C000000A7B1C/datafile/o1_mf_users_jvjfw5xy_.dbfSQL> create pluggable database OE_SNAP from OE_REFRESH snapshot copy;Pluggable database created.SQL> !ls -l /opt/oracle/oradata/CDB2/D3162D35EC8F2976E053C000000A7B1C/datafile/*.dbf
-r--r-----. 1 oracle oinstall 513810432 Dec 14 06:22 /opt/oracle/oradata/CDB2/D3162D35EC8F2976E053C000000A7B1C/datafile/o1_mf_sysaux_jvjfw5xx_.dbf
-r--r-----. 1 oracle oinstall 356524032 Dec 14 06:22 /opt/oracle/oradata/CDB2/D3162D35EC8F2976E053C000000A7B1C/datafile/o1_mf_system_jvjfw5xv_.dbf
-rw-r-----. 1 oracle oinstall  68165632 Dec 14 06:19 /opt/oracle/oradata/CDB2/D3162D35EC8F2976E053C000000A7B1C/datafile/o1_mf_temp_jvjfw5xy_.dbf
-r--r-----. 1 oracle oinstall 225452032 Dec 14 06:22 /opt/oracle/oradata/CDB2/D3162D35EC8F2976E053C000000A7B1C/datafile/o1_mf_undotbs1_jvjfw5xx_.dbf
-r--r-----. 1 oracle oinstall 104865792 Dec 14 06:22 /opt/oracle/oradata/CDB2/D3162D35EC8F2976E053C000000A7B1C/datafile/o1_mf_users_jvjfw5xy_.dbf

要恢复读写权限,除了要没有关联它的PDB外,还需要调用下面的过程。详见How To Safely Revert Back Datafile Permissions For Source PDB After Removing All Snapshot Clones (Doc ID 2627975.1):

SQL> exec dbms_dnfs.restore_datafile_permissions('oe_refresh');PL/SQL procedure successfully completed.SQL> !ls -l /opt/oracle/oradata/CDB2/D3162D35EC8F2976E053C000000A7B1C/datafile/*.dbf
-rw-rw--w-. 1 oracle oinstall 513810432 Dec 14 06:22 /opt/oracle/oradata/CDB2/D3162D35EC8F2976E053C000000A7B1C/datafile/o1_mf_sysaux_jvjfw5xx_.dbf
-rw-rw--w-. 1 oracle oinstall 356524032 Dec 14 06:22 /opt/oracle/oradata/CDB2/D3162D35EC8F2976E053C000000A7B1C/datafile/o1_mf_system_jvjfw5xv_.dbf
-rw-r-----. 1 oracle oinstall  68165632 Dec 14 06:19 /opt/oracle/oradata/CDB2/D3162D35EC8F2976E053C000000A7B1C/datafile/o1_mf_temp_jvjfw5xy_.dbf
-rw-rw--w-. 1 oracle oinstall 225452032 Dec 14 06:22 /opt/oracle/oradata/CDB2/D3162D35EC8F2976E053C000000A7B1C/datafile/o1_mf_undotbs1_jvjfw5xx_.dbf
-rw-rw--w-. 1 oracle oinstall 104865792 Dec 14 06:22 /opt/oracle/oradata/CDB2/D3162D35EC8F2976E053C000000A7B1C/datafile/o1_mf_users_jvjfw5xy_.dbf

生成并执行操作系统命令:

SQL> connect sys/Ora_DB4U@//localhost:1522/cdb2 as sysdba
Connected.SQL> show pdbsCON_ID CON_NAME     OPEN MODE    RESTRICTED2 PDB$SEED     READ ONLY    NO3 PDB2         READ WRITE   NO4 COPYPDB1     MOUNTED5 COPYPDB2     MOUNTED6 OE_REFRESH   READ ONLY    NO7 OE_SNAP      READ WRITE   NOSQL>
select distinct 'host du -h '||SUBSTR(NAME,1,INSTR(NAME,'datafile')+8 ) du_outputfrom v$datafile  where con_id in(select con_id from v$pdbs where name in ('OE_REFRESH','OE_SNAP'));
DU_OUTPUT
host du -h /opt/oracle/oradata/CDB2/D313D9691F81065CE053C000000A6591/datafile/
host du -h /opt/oracle/oradata/CDB2/D31433141B804056E053C000000AA220/datafile/SQL> host du -h /opt/oracle/oradata/CDB2/D313D9691F81065CE053C000000A6591/datafile/
1.1G    /opt/oracle/oradata/CDB2/D313D9691F81065CE053C000000A6591/datafile/SQL> host du -h /opt/oracle/oradata/CDB2/D31433141B804056E053C000000AA220/datafile/
2.0M    /opt/oracle/oradata/CDB2/D31433141B804056E053C000000AA220/datafile/

清理环境:

SQL> connect sys/Ora_DB4U@localhost:1522/cdb2 as sysdba
Connected.SQL> show pdbsCON_ID CON_NAME                       OPEN MODE  RESTRICTED
---------- ------------------------------ ---------- ----------2 PDB$SEED                       READ ONLY  NO3 PDB2                           READ WRITE NO4 COPYPDB1                       MOUNTED5 COPYPDB2                       MOUNTED6 OE_REFRESH                     MOUNTED7 OE_SNAP                        READ WRITE NOSQL> alter pluggable database oe_snap close;
Pluggable database altered.SQL> drop pluggable database oe_snap including datafiles;
Pluggable database dropped.SQL> alter pluggable database oe_refresh close;SQL> drop pluggable database oe_refresh including datafiles;
Pluggable database dropped.SQL> show pdbsCON_ID CON_NAME   OPEN MODE    RESTRICTED2 PDB$SEED   READ ONLY    NO3 PDB2       READ WRITE   NO4 COPYPDB1   MOUNTED5 COPYPDB2   MOUNTED

Task 10: PDB relocation

确保写负载还在运行:

cd /home/oracle/labs/multitenant
./write-load.sh

执行PDB relocation。为了保证客户端的业务连续,对监听有一些要求。

-- 连接到CDB2
SQL> conn sys/Ora_DB4U@localhost:1522/cdb2 as sysdba
Connected.-- 将监听改为与CDB1一样
SQL> alter system set local_listener='LISTENER_CDB1' scope=both;
System altered.-- 重新连接到CDB2(新的端口1521)
SQL> conn sys/Ora_DB4U@localhost:1521/cdb2 as sysdba;
Connected.-- 执行PDB relocate
SQL> create pluggable database oe from oe@cdb1_link relocate;
Pluggable database created.SQL> alter pluggable database oe open;
Pluggable database altered.-- 其中有PDB:OE
SQL> show pdbsCON_ID CON_NAME                       OPEN MODE  RESTRICTED
---------- ------------------------------ ---------- ----------2 PDB$SEED                       READ ONLY  NO3 PDB2                           READ WRITE NO4 COPYPDB1                       MOUNTED5 COPYPDB2                       MOUNTED6 OE                             READ WRITE NO-- 连接到CDB1
SQL> conn sys/Ora_DB4U@localhost:1521/cdb1 as sysdba
Connected.-- 其中OE不存在,说明relocate成功了。而且write-load.sh程序运行也会失败,因为连接的数据库不存在了。
SQL> show pdbsCON_ID CON_NAME                       OPEN MODE  RESTRICTED
---------- ------------------------------ ---------- ----------2 PDB$SEED                       READ ONLY  NO3 PDB1                           READ WRITE NO4 PDB2                           READ WRITE NO

实验结束,将CDB2的监听恢复:

SQL> conn sys/Ora_DB4U@localhost:1521/cdb2 as sysdba
Connected.SQL> alter system set local_listener='LISTENER_CDB2' scope=both;
System altered.

原文是这么说的:

One important note: either both container databases need to be using the same listener in order for sessions to keep connecting, or local and remote listeners need to be set up correctly.

本实验采用的是第一种方式。

Task 11: Lab cleanup

exit
~/labs/multitenant/resetCDB.sh

Oracle LiveLabs实验: Pluggables, Clones and Containers: Oracle Multitenant Fundamentals Workshop相关推荐

  1. Oracle LiveLabs实验:Manage and Monitor Autonomous Database

    概述 本研讨会中的实验将引导您完成开始使用 Oracle 自治数据库的所有步骤. 首先,您将创建一个 Oracle 自治数据库实例. 然后,您将练习使用自治数据库工具和 API 从不同位置以不同格式加 ...

  2. Oracle Livelabs实验: Setting Up Active Data Guard For On-Premises

    本文是Oracle LiveLabs实验:Setting Up Active Data Guard For On-Premises 的过程记录. 实验步骤请参考这里. 因为是利用你自己的OCI云环境搭 ...

  3. Oracle LiveLabs实验:DB Security - Oracle Label Security (OLS)

    概述 此实验申请地址在这里,时间为30分钟. 本实验也是DB Security Advanced研讨会的的第7个实验,即Lab 7. 实验帮助在这里. 本实验使了Oracle数据库19.13及Orac ...

  4. Oracle LiveLabs实验:DB Security - Key Vault

    概述 此实验关于Oracle Key Vault. 此实验申请地址在这里,时间为55分钟. 实验帮助在这里. 实验生成需要15分钟左右,最终会生成2个虚机,以下为我的专属配置: 129.146.74. ...

  5. Oracle LiveLabs实验:Configure network environment for Oracle Database 21c

    概述 此实验申请地址在这里. 实验帮助在这里. 此实验预估完成时间65分钟. 这个实验其实并不需要特别的实验环境,任意找一个安装好的数据库都行. 简介 本研讨会重点介绍 Oracle Database ...

  6. Oracle LiveLabs实验:DB Security - Native Network Encryption (NNE)

    概述 此实验申请地址在这里,时间为2小时. 实验帮助在这里. 本实验使用的数据库为19c. 简介 在此小型实验中,您将学习如何使用 Oracle 本地网络加密 (NNE - Native Networ ...

  7. Oracle LiveLabs实验:DB Security - Audit Vault and DB Firewall

    概述 此实验关于Oracle AVDF(Audit Vault and DB Firewall). 此实验申请地址在这里,时间为150分钟. 实验帮助在这里. 本实验使用的AVDF版本为Oracle ...

  8. Oracle LiveLabs实验:Load and Analyze Your Data with Autonomous Database

    概述 本研讨会中的实验将引导您完成开始使用 Oracle 自治数据库的所有步骤. 首先,您将创建一个 Oracle 自治数据库实例. 然后,您将练习使用自治数据库工具和 API 从不同位置以不同格式加 ...

  9. Oracle LiveLabs DB Security (数据库安全)实验汇总

    在Oracle LiveLabs中,和数据库安全相关的实验分为2个系列,共12个实验. Oracle数据库安全架构如下图: 这些实验涉及了Oracle安全相关的特性,企业版选件,独立产品和服务. 关于 ...

最新文章

  1. 项目的简单总结一 -- 关于对贝塞尔和shapelayer结合使用的动画特效
  2. 霍夫斯特拉大学计算机科学专业排名,美国霍夫斯特拉大学最新排名
  3. oracle 之 COMMENT
  4. zabbix3.4配置钉钉机器人报警
  5. GARFIELD@05-02-2005
  6. sql 左侧要固定最近一周的周四 怎么写_数据与IT人怎么提高公司地位,避免被业务当工具人?...
  7. 经典网络DenseNet介绍
  8. power query时间函数(思维导图)
  9. java注册功能实现
  10. (附源码)spring boot智能服药提醒app 毕业设计 102151
  11. 获取窗口 history数量_带你走进JavaScript世界系列——history 对象
  12. 知物由学 | 一文读懂Android资源文件保护
  13. 使用ajax和window.history.pushState无刷新改变页面内容和地址栏URL
  14. 广东计算机二级考试大纲,全国计算机等级考试大纲(二级)
  15. SQLPLUS登录以及切换Oracle数据库实例和用户
  16. 【报名】RT-Thread师资培训,苏州大学王宜怀教授主讲!
  17. 我的世界神秘时代安卓java版_我的世界神秘时代4
  18. Excel使用技巧总结二
  19. mysql select 反选_checkbox的全选与反选
  20. 网站通过API调用GG地图.

热门文章

  1. 用java实现耀辉三角
  2. php里 没temp文档 如何创建temp文档 win7,Win7更改Temp文件夹存储位置的操作方法
  3. 图文并茂详细教程之——用pixhawk飞控组装一台S500四轴无人机(中)(苍穹四轴)
  4. 二十世纪九十年代,可以简化为1990年代
  5. 全局变量和全局静态变量
  6. 【解决】无线网卡windows仍在设置此设备的类配置,代码56
  7. php第三方支付系统--支付流程--及代码
  8. Jolla 超额完成开源平板电脑众筹
  9. 中国厉害的黑客组织?别说只知道红客联盟,知道“他们”才厉害
  10. Mycat JVM appears hung: Timed out waiting for signal from JVM.