Die Multitenant-Architektur umschreibt eine mandantenfähige Datenbank, die ihren Memory, die Hintergrundprozesse usw. einer oder mehreren Pluggable Databases zur Verfügung stellt.
In den Pluggable Databases liegen abgekapselt die Applikationsdaten, so können sich z. B. eine Entwicklungs-, eine Test- und eine Integrations-PDB die SGA usw. einer CDB teilen.
Durch Einsatz dieser Architektur kann eine Konsolidierung von Datenbanken erfolgen. Doch sowohl Konsolidierung als auch Mandantenfähigkeit ließen sich auch in der alten Archietektur mit geringem Aufwand realisieren. Über die Sinnhaftigkeit bzw. den Overhead beim Einsatz einer einzelnen Datenbank kann man allerdings streiten.
Non-CDB: eine herkömmlich angelegte Datenbank (ohne Einsatz von Multitenant ab Version 12)
Container Datenbank (CDB): Container Datenbank in die eine oder mehrere Pluggable Databases eingeklinkt werden können. Die Container Datenbank stellt den PDBs den Memory (SGA), die Hintergrundprozesse, Kontrolldatei(en) und die Redolog-Dateien zur Verfügung.
Pluggable Database (PDB): In der Pluggable Database liegt mehr oder weniger nur noch der Applikationsteil der Datenbank, sprich Applikationsuser und Tablespaces mit Applikationsdaten.
In den folgenden Beispielen heißt die CDB : CDBA mit den RAC Instanzen CDBA1 und CDBA2
In der CDBA liegen die beiden die PDBs PDBEINS und PDBZWEI. Bei den PDBs gibt es im RAC keinen eigenen Instanznamen. Unter Linux werden die Umgebungsvariablen ORACLE_SID=CDBA1 (erste RAC Instanz) sowie das ORACLE_HOME gesetzt und sqlplus aufgerufen:
An die CDB kann man sich analog einer non-CDB z. B. mit „sqlplus / as sysdba“ anmelden.
Nachdem die erste PDB mit dem DBCA oder per Skript angelegt oder eine non-CDB z. B. mit dem Autoupgrade-Tool in eine PDB umgewandelt wurde, ist die Frage welche PDBs laufen in der CDB und wie melde ich mich dort an.
Für die Abfrage von Multitenant Informationen gibt es diverse CDB_* (Erweiterung der DBA-Views um die CON_ID) ein paar PDB_* Views, sowie V_$PDBS bzw. GV$PDBS.
Hier zunächst die Anzeige der eingerichteten PDBs samt Status:
[]$ . CDBA1
ORACLE_SID: CDBA1
ORACLE_HOME: /u01/app/oracle/product/19.0.0.0/dbhome_1
[CDBA1]$ sqlplus / as sysdba
SQL> show pdbs
CON_ID CON_NAME OPEN MODE RESTRICTED
---------- ------------------------------ ---------- ----------
2 PDB$SEED READ ONLY NO
3 PDBEINS MOUNTED
4 PDBZWEI MOUNTED
SQL> select INST_ID, CON_ID, NAME, OPEN_MODE from gv$pdbs order by 2,1;
INST_ID CON_ID NAME OPEN_MODE
---------- ---------- ------------------------------ ----------
1 2 PDB$SEED READ ONLY
2 2 PDB$SEED READ ONLY
1 3 PDBEINS MOUNTED
2 3 PDBEINS MOUNTED
1 4 PDBZWEI MOUNTED
2 4 PDBZWEI MOUNTED
6 rows selected.
Wie wir sehen können, sind sowohl PDBEINS als auch PDBZWEI nach der Erstellung nicht geöffnet. Die Oracle interne PDB PDB$SEED ist normalerweise nur lesend geöffnet.
Im Folgenden wird aufgezeigt, wie man eine PDB öffnet, bzw. wie man im RAC-Umfeld eine PDB auf einer oder allen Instanzen öffnet:
SQL> -- oeffnen der PDB in der aktuellen Instanz (CDBA1):
SQL> alter pluggable database PDBEINS open;
Pluggable database altered.
SQL> select INST_ID, CON_ID, NAME, OPEN_MODE from gv$pdbs order by 2,1;
INST_ID CON_ID NAME OPEN_MODE
---------- ---------- ------------------------------ ----------
1 2 PDB$SEED READ ONLY
2 2 PDB$SEED READ ONLY
1 3 PDBEINS READ WRITE
2 3 PDBEINS MOUNTED
1 4 PDBZWEI MOUNTED
2 4 PDBZWEI MOUNTED
6 rows selected.
SQL> -- oeffnen der PDB in einer bestimmten Instanz (CDBA2):
SQL> alter pluggable database PDBZWEI open instances=('CDBA2');
SQL> -- oeffnen der PDB in allen Instanzen:
SQL> alter pluggable database PDBZWEI open instances=all;
Pluggable database altered.
SQL> select INST_ID, CON_ID, NAME, OPEN_MODE from gv$pdbs order by 2,1;
INST_ID CON_ID NAME OPEN_MODE
---------- ---------- ------------------------------ ----------
1 2 PDB$SEED READ ONLY
2 2 PDB$SEED READ ONLY
1 3 PDBEINS READ WRITE
2 3 PDBEINS MOUNTED
1 4 PDBZWEI READ WRITE
2 4 PDBZWEI READ WRITE
6 rows selected.
Nach einem Restart der Datenbank ist im Gegensatz zur CDB die PDB jedoch immer noch geschlossen (bzw. im MOUNTED Status). Ausnahme, eine Grid Infrastructure Umgebung incl. einem Service für die PDB ist eingerichtet (siehe weiter unten). Ändern lässt sich dies über den „save state":
[CDBA1]$ srvctl stop database -d cdba
[CDBA1]$ srvctl start database -d cdba
[CDBA1]$ sqlplus / as sysdba
SQL> select INST_ID, CON_ID, NAME, OPEN_MODE from gv$pdbs order by 2,1;
INST_ID CON_ID NAME OPEN_MODE
---------- ---------- ------------------------------ ----------
1 2 PDB$SEED READ ONLY
2 2 PDB$SEED READ ONLY
1 3 PDBEINS MOUNTED
2 3 PDBEINS MOUNTED
1 4 PDBZWEI MOUNTED
2 4 PDBZWEI MOUNTED
6 rows selected.
SQL> alter pluggable database PDBEINS OPEN;
Pluggable database altered.
SQL> -- Sichern des „Open“ Status:
SQL> alter pluggable database PDBEINS save state;
Pluggable database altered.
SQL> -- Abfrage des „save state“
SQL> select CON_NAME, INSTANCE_NAME, STATE from dba_pdb_saved_states;
CON_NAME INSTANCE_NAME STATE
------------------------------ ------------------------------ --------------
PDBEINS CDBA1 OPEN
SQL> -- Auch wenn jetzt der save state für alle Instanzen gesetzt wird,
SQL> -- wird dies nicht vermerkt, da die PDBEINS auf CDBA2 nicht geoeffnet ist:
SQL> alter pluggable database PDBEINS save state instances=all;
Pluggable database altered.
SQL> select CON_NAME, INSTANCE_NAME, STATE from dba_pdb_saved_states;
CON_NAME INSTANCE_NAME STATE
------------------------------ ------------------------------ --------------
PDBEINS CDBA1 OPEN
SQL> -- oeffnet man alle Instanzen,
SQL> alter pluggable database PDBZWEI open instances=all;
Pluggable database altered.
SQL> select INST_ID, CON_ID, NAME, OPEN_MODE from gv$pdbs order by 2,1;
INST_ID CON_ID NAME OPEN_MODE
---------- ---------- ------------------------------ ----------
1 2 PDB$SEED READ ONLY
2 2 PDB$SEED READ ONLY
1 3 PDBEINS READ WRITE
2 3 PDBEINS MOUNTED
1 4 PDBZWEI READ WRITE
2 4 PDBZWEI READ WRITE
6 rows selected.
SQL> -- und setzt den „save state“ nur für eine Instanz, so wird nach dem
SQL> -- reboot ebenfalls nur auf einer Instanz die PDBZWEI geoeffnet:
SQL> alter pluggable database PDBZWEI save state instances=('CDBA2');
Pluggable database altered.
SQL> select CON_NAME, INSTANCE_NAME, STATE from dba_pdb_saved_states;
CON_NAME INSTANCE_NAME STATE
------------------------------ ------------------------------ --------------
PDBEINS CDBA1 OPEN
PDBZWEI CDBA2 OPEN
SQL> exit
[CDBA1]$ srvctl stop database -d CDBA
[CDBA1]$ srvctl start database -d CDBA
[CDBA1]$ sqlplus / as sysdba
SQL> -- jetzt sind die PDBs auf je einer Instanz geoeffnet
SQL> select INST_ID, CON_ID, NAME, OPEN_MODE from gv$pdbs order by 2,1;
INST_ID CON_ID NAME OPEN_MODE
---------- ---------- ------------------------------ ----------
1 2 PDB$SEED READ ONLY
2 2 PDB$SEED READ ONLY
1 3 PDBEINS READ WRITE
2 3 PDBEINS MOUNTED
1 4 PDBZWEI MOUNTED
2 4 PDBZWEI READ WRITE
6 rows selected.
SQL> select CON_NAME, INSTANCE_NAME, STATE from dba_pdb_saved_states;
CON_NAME INSTANCE_NAME STATE
------------------------------ ------------------------------ --------------
PDBZWEI CDBA2 OPEN
PDBEINS CDBA1 OPEN
Wie wir gesehen haben, muss die PDB geöffnet sein, wenn der „save state“ gesetzt wird, damit die PDB nach einem Restart der CDB automatisch mitgestartet wird.
Ein Zurücknehmen des „save state“ Status kann auf zwei Arten erfolgen, entweder man stoppt die PDB und sichert den „save state“ oder man löscht den Eintrag mit „discard“:
SQL> select INST_ID, CON_ID, NAME, OPEN_MODE from gv$pdbs order by 2,1;
INST_ID CON_ID NAME OPEN_MODE
---------- ---------- ------------------------------ ----------
1 2 PDB$SEED READ ONLY
2 2 PDB$SEED READ ONLY
1 3 PDBEINS READ WRITE
2 3 PDBEINS MOUNTED
1 4 PDBZWEI MOUNTED
2 4 PDBZWEI READ WRITE
6 rows selected.
SQL> alter pluggable database PDBEINS close instances=all;
Pluggable database altered.
SQL> select INST_ID, CON_ID, NAME, OPEN_MODE from gv$pdbs order by 2,1;
INST_ID CON_ID NAME OPEN_MODE
---------- ---------- ------------------------------ ----------
1 2 PDB$SEED READ ONLY
2 2 PDB$SEED READ ONLY
1 3 PDBEINS MOUNTED
2 3 PDBEINS MOUNTED
1 4 PDBZWEI MOUNTED
2 4 PDBZWEI READ WRITE
6 rows selected.
SQL> select CON_NAME, INSTANCE_NAME, STATE from dba_pdb_saved_states;
CON_NAME INSTANCE_NAME STATE
------------------------------ ------------------------------ ----
PDBZWEI CDBA2 OPEN
PDBEINS CDBA1 OPEN
SQL> alter pluggable database PDBEINS save state instances=all;
Pluggable database altered.
SQL> select CON_NAME, INSTANCE_NAME, STATE from dba_pdb_saved_states;
CON_NAME INSTANCE_NAME STATE
------------------------------ ------------------------------ --------------
PDBZWEI CDBA2 OPEN
SQL> alter pluggable database PDBZWEI discard state;
Pluggable database altered.
SQL> select INST_ID, CON_ID, NAME, OPEN_MODE from gv$pdbs order by 2,1;
INST_ID CON_ID NAME OPEN_MODE
---------- ---------- ------------------------------ ----------
1 2 PDB$SEED READ ONLY
2 2 PDB$SEED READ ONLY
1 3 PDBEINS MOUNTED
2 3 PDBEINS MOUNTED
1 4 PDBZWEI MOUNTED
2 4 PDBZWEI READ WRITE
6 rows selected.
SQL> --Ein discard in der akt. Instanz bewirkt in diesem Falle nichts, da für die PDBZWEI
SQL> --für die zweite Instanz ein „save state“ gesetzt ist.
SQL> select CON_NAME, INSTANCE_NAME, STATE from dba_pdb_saved_states;
CON_NAME INSTANCE_NAME STATE
------------------------------ ------------------------------ --------------
PDBZWEI CDBA2 OPEN
SQL> alter pluggable database PDBZWEI discard state instances=all;
Pluggable database altered.
SQL> select CON_NAME, INSTANCE_NAME, STATE from dba_pdb_saved_states;
no rows selected
SQL> quit
Nach einem Restart der CDB werden die PDBs dann nicht mehr mit gestartet:
[CDBA1]$ srvctl stop database -d CDBA
[CDBA1]$ srvctl start database -d CDBA
SQL> select INST_ID, CON_ID, NAME, OPEN_MODE from gv$pdbs order by 2,1;
INST_ID CON_ID NAME OPEN_MODE
---------- ---------- ------------------------------ ----------
1 2 PDB$SEED READ ONLY
2 2 PDB$SEED READ ONLY
1 3 PDBEINS MOUNTED
2 3 PDBEINS MOUNTED
1 4 PDBZWEI MOUNTED
2 4 PDBZWEI MOUNTED
6 rows selected.
SQL> quit
Nutzt man einen Service der über die Grid Infrastructure angelegt und gestartet wird, so werden die „save state“ Einträge zum Starten der PDB übersteuert und sind hinfällig:
[CDBA1]$ srvctl enable service -d CDBA -s client_pdbeins
[CDBA1]$ srvctl start service -d CDBA -s client_pdbeins
SQL> select INST_ID, CON_ID, NAME, OPEN_MODE from gv$pdbs order by 2,1
INST_ID CON_ID NAME OPEN_MODE
---------- ---------- ------------------------------ ----------
1 2 PDB$SEED READ ONLY
2 2 PDB$SEED READ ONLY
1 3 PDBEINS READ WRITE
2 3 PDBEINS READ WRITE
1 4PDBZWEI MOUNTED
2 4 PDBZWEI MOUNTED
6 rows selected.
SQL> select CON_NAME, INSTANCE_NAME, STATE from dba_pdb_saved_states;
no rows selected
SQL> quit
[CDBA1]$ crsctl status res -t | grep -A2 pdb
ora.cdba.client_pdbeins.svc
1 ONLINE ONLINE tl19hawe03 STABLE
2 ONLINE ONLINE tl19hawe04 STABLE
ora.cdba.client_pdbzwei.svc
1 OFFLINE OFFLINE STABLE
2 OFFLINE OFFLINE STABLE
Achtung!
Beim Stoppen des Service wird die PDB nicht mit gestoppt. Startet man die PDB über SQL-Plus, so wird der Grid Infrastructure Service nicht mit gestartet.
[CDBA1]$ srvctl stop service -d CDBA -s client_pdbeins
[CDBA1]$ srvctl enable service -d CDBA -s client_pdbzwei
[CDBA1]$ crsctl status res -t | grep -A2 pdb
ora.cdba.client_pdbeins.svc
1 OFFLINE OFFLINE STABLE
2 OFFLINE OFFLINE STABLE
ora.cdba.client_pdbzwei.svc
1 ONLINE OFFLINE tl19hawe03 STARTING
2 ONLINE OFFLINE tl19hawe04 STARTING
SQL> select INST_ID, CON_ID, NAME, OPEN_MODE from gv$pdbs order by 2,1
INST_ID CON_ID NAME OPEN_MODE
---------- ---------- ------------------------------ ----------
1 2 PDB$SEED READ ONLY
2 2 PDB$SEED READ ONLY
1 3 PDBEINS READ WRITE
2 3 PDBEINS READ WRITE
1 4 PDBZWEI MOUNTED
2 4 PDBZWEI MOUNTED
6 rows selected.
SQL> alter pluggable database PDBZWEI OPEN instances=all;
SQL> select INST_ID, CON_ID, NAME, OPEN_MODE from gv$pdbs order by 2,1
INST_ID CON_ID NAME OPEN_MODE
---------- ---------- ------------------------------ ----------
1 2 PDB$SEED READ ONLY
2 2 PDB$SEED READ ONLY
1 3 PDBEINS READ WRITE
2 3 PDBEINS READ WRITE
1 4 PDBZWEI READ WRITE
2 4 PDBZWEI READ WRITE
6 rows selected.
[CDBA1]$ crsctl status res -t | grep -A2 pdb
ora.cdba.client_pdbeins.svc
1 OFFLINE OFFLINE STABLE
2 OFFLINE OFFLINE STABLE
ora.cdba.client_pdbzwei.svc
1 ONLINE OFFLINE tl19hawe03 STARTING
2 ONLINE OFFLINE tl19hawe04 STARTING
Meine Empfehlung:
Den „Save State“ immer für alle Instanzen setzen.
Den „Save State“ auch setzen, wenn ein Service für die PDBs angelegt wird.
Starten einer PDB durch Starten des Service.
Stoppen einer PDB in SQL-Plus mit: alter pluggable database … CLOSE …
Sofern man mit „sysdba“ Rechten angemeldet ist, kann ein Wechsel zwischen CDB und PDB über „alter session set container=…“ erfolgen:
[CDBA1]$ sqlplus / as sysdba
SQL> show pdbs
CON_ID CON_NAME OPEN MODE RESTRICTED
---------- ------------------------------ ---------- ----------
2 PDB$SEED READ ONLY NO
3 PDBEINS READ WRITE NO
4 PDBZWEI MOUNTED
SQL> col USER_NAME form a20
col CDB_NAME form a20
col CONTAINER form a20
col SERVICE_NAME form a30
select sys_context ('USERENV','SESSION_USER') USER_NAME,
sys_context ('USERENV','CDB_NAME') CDB_NAME,
sys_context ('USERENV','CON_NAME') CONTAINER,
sys_context ('USERENV','SERVICE_NAME') SERVICE_NAME from dual;
USER_NAME CDB_NAME CONTAINER SERVICE_NAME
-------------------- -------------------- -------------------- --------------------
SYS CDBA CDB$ROOT SYS$USERS
SQL> alter session set container=PDBZWEI;
SQL> select sys_context ('USERENV','SESSION_USER') USER_NAME,
sys_context ('USERENV','CDB_NAME') CDB_NAME,
sys_context ('USERENV','CON_NAME') CONTAINER,
sys_context ('USERENV','SERVICE_NAME') SERVICE_NAME from dual;
USER_NAME CDB_NAME CONTAINER SERVICE_NAME
-------------------- -------------------- -------------------- --------------------
SYS CDBA PDBZWEI SYS$USERS
SQL> show pdbs
CON_ID CON_NAME OPEN MODE RESTRICTED
---------- ------------------------------ ---------- ----------
4 PDBZWEI MOUNTED
SQL> alter session set container=CDB$ROOT;
USER_NAME CDB_NAME CONTAINER SERVICE_NAME
-------------------- -------------------- -------------------- --------------------
SYS CDBA CDB$ROOT SYS$USERS
SQL> show pdbs
CON_ID CON_NAME OPEN MODE RESTRICTED
---------- ------------------------------ ---------- ----------
2 PDB$SEED READ ONLY NO
3 PDBEINS READ WRITE NO
4 PDBZWEI MOUNTED
SQL>
Alle Benutzer ohne „sysdba“ Rechte haben nur die Möglichkeit sich über eine SQL-Net Verbindung mit der PDB zu verbinden. Dazu wird pro PDB ein TNS-Alias in der tnsnames.ora angelegt:
[CDBA1]$ cat tnsnames.ora
. . .
PDBEINS_CON =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = tcp)(HOST = rac19c-scan.muniqsoft.de)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = client_pdbeins)
)
)
. . .
[CDBA1]$ sqlplus system@PDBEINS_CON
Enter password:
Connected.
select sys_context ('USERENV','SESSION_USER') USER_NAME,
sys_context ('USERENV','CDB_NAME') CDB_NAME,
sys_context ('USERENV','CON_NAME') CONTAINER,
sys_context ('USERENV','SERVICE_NAME') SERVICE_NAME from dual;
USER_NAME CDB_NAME CONTAINER SERVICE_NAME
-------------------- -------------------- -------------------- -----------------
SYSTEM CDBA PDBEINS client_pdbeins
SQL> create user test identified by manager;
User created.
SQL> grant connect to test;
Grant succeeded.
SQL> connect test/manager;
ERROR:
ORA-01017: invalid username/password; logon denied
SQL> connect test/manager@PDBEINS_CON
Connected.
USER_NAME CDB_NAME CONTAINER SERVICE_NAME
-------------------- -------------------- -------------------- ------------------
TEST CDBA PDBEINS client_pdbeins
Achtung!
Bei einer direkten Anmeldung in SQL-Plus als nicht „sysdba“ Benutzer an einer CDB/PDB ohne SQL-Net erhält man einen ORA-01017 Fehler
Oracle bietet ab der Version 18 bzw. 19 incl. April 2019 RU mit der undokumentierten Umgebungs-variablen ORACLE_PDB_SID und dem Trigger DBMS_SET_PDB auch die Möglichkeit als Benutzer mit sysdba Rechten sich „direkt“ an einer PDB anzumelden, siehe unter anderem Blog von Mike Dietrich:
https://mikedietrichde.com/2020/05/07/can-you-connect-as-sysdba-without-password-into-a-pdb-directly
https://mikedietrichde.com/2020/07/13/pitfalls-connect-to-a-pdb-directly-with-oracle_pdb_sid/
und der Oracle Support Artikel:
Performing bequeath direct connections to PDB as SYS and SYSTEM (Doc ID 2728684.1)
Dies ist jedoch mit Vorsicht zu genießen, da der von Oracle ausgelieferte Trigger derzeit keinerlei Exception Handling bietet. Sprich gibt es keine PDB mit dem Namen, der über die Variable gesetzt wird, so kann der Trigger kein „alter session set container = …“ durchführen und man landet in der CDB statt der gewünschten PDB.
Dies kann aber mit zwei/drei „Kniffen“ so gut wie vermieden werden:
Beispiel Skript zum Setzen der Umgebung für PDBEINS:
cat /home/oracle/PDBEINS
# set Environment for PDB : PDBEINS
export ORACLE_DBNAME="PDBEINS"
export ORACLE_SID="CDBA1"
# new variable to set environment for PDB
export ORACLE_PDB_SID="PDBEINS"
export ORACLE_BASE=/u01/app/oracle
export ORACLE_HOME=/u01/app/oracle/product/19.0.0.0/dbhome_1
# Set ORACLE_PATH to location of login.sql script
export ORACLE_PATH=${ORACLE_BASE}/sql
export PATH=${ORACLE_HOME}/bin:${PATH}
export PS1='[${ORACLE_PDB_SID:-${ORACLE_SID} }]\$ '
echo "ORACLE_DBNAME: ${ORACLE_DBNAME}"
echo "ORACLE_SID: ${ORACLE_SID}"
echo "ORACLE_PDB_SID: ${ORACLE_PDB_SID}"
echo "ORACLE_HOME: ${ORACLE_HOME}"
Bei allen nicht PDB-Skripten wird dann ORACLE_PDB_SID="" gesetzt!
Beispiel für ein login.sql Skript:
set serveroutput on format WRAPPED size 1000000
set trimspool on
set long 5000
set linesize 100
set feedback off
declare
v_prompt VARCHAR2(40);
v_user_name VARCHAR2(20);
v_db_name VARCHAR2(9);
v_db_unique_name VARCHAR2(30);
v_container VARCHAR2(30);
v_cdb VARCHAR2(3);
v_cdb_pdb VARCHAR2(3);
v_cdb_name VARCHAR2(30);
v_con_id NUMBER;
v_instance VARCHAR2(30);
v_host VARCHAR2(30);
v_service VARCHAR2(30);
begin
-- get infos via sys_context
v_user_name:=substr(sys_context ('USERENV','SESSION_USER'),1,20);
v_db_name:=sys_context ('USERENV','DB_NAME');
v_db_unique_name:=sys_context ('USERENV','DB_UNIQUE_NAME');
v_con_id:=sys_context ('USERENV','CON_ID');
v_cdb_name:=sys_context ('USERENV','CDB_NAME');
v_container:=sys_context ('USERENV','CON_NAME');
v_instance:=sys_context ('USERENV','INSTANCE_NAME');
v_host:=sys_context ('USERENV','HOST');
v_service:=sys_context ('USERENV','SERVICE_NAME');
if nvl(v_con_id,0)=0 then
v_cdb_pdb:='';
elsif v_con_id=1 then
v_cdb_pdb:='CDB';
else
v_cdb_pdb:='PDB';
end if;
-- display the information
dbms_output.put_line(chr(13) || rpad (' #', 84, '#'));
if v_cdb_pdb is not null then
dbms_output.put_line(' # ' || rpad ('Container: '||v_container,37,' ')
|| ' # ' || rpad ('CDB/PDB: ' || v_cdb_pdb,37,' ') || ' #') ;
dbms_output.put_line(' # ' || rpad ('CDB-Name: '||v_cdb_name,37,' ')
|| ' # ' || rpad ('DB-Uniq-Name: ' || v_db_unique_name,37,' ') || ' #') ;
else
dbms_output.put_line(' # ' || rpad ('DB-Name: '||v_db_name,37,' ')
|| ' # ' || rpad ('DB-Uniq-Name: ' || v_db_unique_name,37,' ') || ' #') ;
end if;
dbms_output.put_line(' # ' || rpad ('Host: '||v_host,37,' ')
|| ' # ' || rpad ('Service: ' || v_service,37,' ') || ' #') ;
dbms_output.put_line(rpad (' #', 84, '#') || (chr(13));
exception
WHEN OTHERS THEN
dbms_output.put_line( 'when others' || sqlerrm);
end;
/
set termout off
-- setting the prompt depending on CDB/PDB Type
define gprompt='SQL>'
column global_prompt new_value gprompt
select decode (nvl(sys_context ('USERENV','CON_ID'),0)
, '0', substr(sys_context ('USERENV','SESSION_USER'),1,20)
||'@'||sys_context ('USERENV','INSTANCE_NAME')
, '1', 'CDB:'||substr(sys_context ('USERENV','SESSION_USER'),1,20)
||'@'||sys_context ('USERENV','INSTANCE_NAME')
||':'||sys_context ('USERENV','CON_NAME')
, 'PDB:'||substr(sys_context ('USERENV','SESSION_USER'),1,20)
||'@'||sys_context ('USERENV','CON_NAME')) global_prompt
from dual;
set sqlprompt '&gprompt> '
set termout on
undefine gprompt
column global_prompt clear
Mit obigen Skripten setzen wir die Umgebung einmal für die PDB PDBEINS und einmal für die CDB-Datenbank CDBA und rufen sqlplus auf:
[]$ . PDBEINS
ORACLE_DBNAME: PDBEINS
ORACLE_SID: CDBA1
ORACLE_PDB_SID: PDBEINS
ORACLE_HOME: /u01/app/oracle/product/19.0.0.0/dbhome_1
[PDBEINS]$ sqlplus / as sysdba
#################################################################################
# Container: PDBEINS # CDB/PDB: PDB #
# CDB-Name: CDBA # DB-Uniq-Name: CDBA #
# Host: racnode1.muniqsoft.de # Service: client_pdbeins #
#################################################################################
PDB:SYS@PDBEINS>
PDB:SYS@PDBEINS> quit
[PDBEINS]$ . CDBA1
ORACLE_DBNAME: CDBA
ORACLE_SID: CDBA1
ORACLE_PDB_SID:
ORACLE_HOME: /u01/app/oracle/product/19.0.0.0/dbhome_1
[CDBA1]$ sqlplus / as sysdba
#################################################################################
# Container: CDB$ROOT # CDB/PDB: CDB #
# CDB-Name: CDBA # DB-Uniq-Name: CDBA #
# Host: racnode1.muniqsoft.de # Service: SYS$USERS #
#################################################################################
CDB:SYS@CDBA1:CDB$ROOT>
Achtung!
Bei einem Wechsel des Kontextes mit „alter session set container=…“ innerhalb von SQL-Plus wird login.sql nicht automatisch aufgerufen und somit bleibt dabei der Prompt unverändert. Um den Prompt anzupassen, muss das login.sql von Hand aufrufen werden. Alternativ meldet man sich ohne Setzen des Containers mit Hilfe eines TNS-Alias gleich an der richtigen PDB an, dann wird automatisch das login.sql Skript ausgeführt.
CDB:SYS@CDBA1:CDB$ROOT> alter session set container=PDBZWEI;
Session altered.
CDB:SYS@CDBA1:CDB$ROOT> @login.sql
#################################################################################
# Container: PDBZWEI # CDB/PDB: PDB #
# CDB-Name: CDBA # DB-Uniq-Name: CDBA #
# Host: racnode1.muniqsoft.de # Service: client_pdbzwei #
#################################################################################
PDB:SYS@PDBZWEI>
PDB:SYS@PDBZWEI> connect system/manager@PDBEINS_CON
Connected.
#################################################################################
# Container: PDBEINS # CDB/PDB: PDB #
# CDB-Name: CDBA # DB-Uniq-Name: CDBA #
# Host: racnode1.muniqsoft.de # Service: client_pdbeins #
#################################################################################
PDB:SYSTEM@PDBEINS>
Der Architekturwandel bei Oracle ist leider unumgänglich. Somit müssen im täglichen Ablauf, in vorhandenem Scripting und Monitoring teils erhebliche Aufwände betrieben werden, um weiterhin einen reibungslosen Ablauf zu gewährleisten.
To be continued.
Oracle Dokumentation z. B.:
Blog von Mike Dietrich
In unserer Know-How Datenbank finden Sie mehr als 300 ausführliche Beiträge zu den
Oracle-Themen wie DBA, SQL, PL/SQL, APEX und vielem mehr.
Hier erhalten Sie Antworten auf Ihre Fragen.