Blog 
Hilfe, wo bin ich? CDB oder PDB … und welche DB überhaupt?

Von Problemen in der Oracle 12c Multitenant Datenbank

Früher war doch alles einfacher, oder? Bis jetzt hat sich wohl der ein oder andere an seine Datenbank angemeldet und im Zweifel über eine Abfrage der v$instance oder der v$database mal schnell gegen gecheckt ob er auch richtig gelandet ist. Seit 12c ist das aber leider nicht mehr so eindeutig. Inzwischen gibt es die Multitenant Option und verbinde ich mich mit einer Pluggable Database, bekomme ich mit meinen althergebrachten Views vielleicht nicht das gewünschte Ergebnis.

Aber warum ist das so ein Problem?

In einer Multitenant Umgebung kann man sich nicht nur direkt anmelden, sondern auch durch ein ALTER SESSION zwischen den verschiedenen Pluggable Datenbanken und dem Root Container hin und her springen. Arbeitet man mit mehreren Sessions und verschiedenen Fenstern, kann man schonmal den Überblick verlieren. Auch für das Scripting kann es hilfreich sein, Änderungen auch auf die richtige PDB anzuwenden und nicht versehentlich auf den Root Container.

Im folgenden Beispiel habe ich eine einfache 12c Multitenant Datenbank mit der CDB, also dem ROOT Container und einer angeschlossenen Pluggable Database (PDB).

CDB = SJW12C01 und PDB = SJWPDB01

Unsere v$instance ist in Sachen PDB leider nicht mehr so hilfreich, auch wenn das Ergebnis vollkommen korrekt ist:

CDB

sqlplus system@SJW12C01

SQL> select instance_name, con_id, version from v$instance;

INSTANCE_NAME        CON_ID VERSION
---------------- ---------- -----------------
sjw12c01                  0 12.1.0.2.0

PDB

sqlplus system@SJWPDB01

SQL> select instance_name, con_id, version from v$instance;

INSTANCE_NAME        CON_ID VERSION
---------------- ---------- -----------------
sjw12c01                  0 12.1.0.2.0 

Leider das gleiche Bild mit der v$database Abfrage:

CDB

sqlplus system@SJW12C01

SQL> select name, con_id, db_unique_name from v$database;

NAME          CON_ID DB_UNIQUE_NAME
--------- ---------- ------------------------------
SJW12C01           0 SJW12C01

PDB

sqlplus system@SJWPDB01

SQL> select name, con_id, db_unique_name from v$database;

NAME          CON_ID DB_UNIQUE_NAME
--------- ---------- ------------------------------
SJW12C01           0 SJW12C01

Mit der v$pdbs haben wir eine erste Möglichkeit Abhilfe zu schaffen. Ähnliche Ergebnisse liefert auch ein select * from cdb_pdbs;. Nachfolgend springen wir mit alter session set container von der CDB zur PDB und wieder zurück:

CDB > PDB > CDB

sqlplus system@SJW12C01

SQL> select dbid, con_id, name from v$pdbs;

      DBID     CON_ID NAME
---------- ---------- ------------------------------
4043975488          2 PDB$SEED
4185832567          3 SJWPDB01

SQL> alter session set container = SJWPDB01;

Session wurde geõndert.

SQL> select dbid, con_id, name from v$pdbs;

      DBID     CON_ID NAME
---------- ---------- ------------------------------
4185832567          3 SJWPDB01

SQL> alter session set container = CDB$ROOT;

Session wurde geõndert.

SQL> select dbid, con_id, name from v$pdbs;

      DBID     CON_ID NAME
---------- ---------- ------------------------------
4043975488          2 PDB$SEED
4185832567          3 SJWPDB01

Wie man sieht, erhält man in der Container Datenbank Infos über die PDB$SEED. Die SEED Datenbank dient in der Multitenant Datenbank als Vorlage für die Erstellung neuer PDB’s. In einer PDB dagegen bekommt man in jedem Fall nur eine, die eigene PDB angezeigt.

Aber es geht noch besser über USERENV aus der SYS_CONTEXT Funktion heraus:

CDB

sqlplus system@SJW12C01

SQL> select sys_context('USERENV','CON_NAME') CON_NAME,
            sys_context('USERENV','CON_ID') CON_ID,
            sys_context('USERENV','DB_NAME') DB_NAME from DUAL;

CON_NAME   CON_ID     DB_NAME
---------- ---------- ----------
CDB$ROOT   1          SJW12C01

PDB

sqlplus system@SJWPDB01

SQL> select sys_context('USERENV','CON_NAME') CON_NAME,
            sys_context('USERENV','CON_ID') CON_ID,
            sys_context('USERENV','DB_NAME') DB_NAME from DUAL;

CON_NAME   CON_ID     DB_NAME
---------- ---------- ----------
SJWPDB01   3          SJW12C01

Aufgepasst bei DB_NAME. Hier wird immer der Name der (Root) Container Datenbank zurück gegeben. Die CON_ID ist sicherlich auch schon aufgefallen. Hier nicht irritieren lassen CON_ID 0 steht für die Gesamtheit der Multitenant Datenbank und 1 ist für den Root Container reserviert. CON_ID 2 ist immer die PDB$SEED. Alles ab CON_ID 3 sind Pluggable Databases.

Mit diesem Wissen und etwas DECODE erhält man immer den aktuellen Datenbanknamen und ob man sich auf der CDB oder einer PDB befindet:

CDB

sqlplus system@SJW12C01

SQL> select decode(sys_context('USERENV', 'CON_NAME'),'CDB$ROOT',sys_context('USERENV', 'DB_NAME'),sys_context('USERENV', 'CON_NAME')) DB_NAME, 
            decode(sys_context('USERENV','CON_ID'),1,'CDB','PDB') TYPE from DUAL;

DB_NAME    TYPE
---------- ----
SJW12C01   CDB

PDB

sqlplus system@SJWPDB01

SQL> select decode(sys_context('USERENV', 'CON_NAME'),'CDB$ROOT',sys_context('USERENV', 'DB_NAME'),sys_context('USERENV', 'CON_NAME')) DB_NAME,
            decode(sys_context('USERENV','CON_ID'),1,'CDB','PDB') TYPE from DUAL;

DB_NAME    TYPE
---------- ----
SJWPDB01   PDB

Schneller und einfacher geht es noch mit SQL Plus (leider nur hier), mittels SHOW CON_ID, SHOW CON_NAME. SHOW PDBS dagegen funktioniert nur als SYSDBA. Achten Sie in diesem Beispiel auch auf den connect / as sysdba – durch die Neuanmeldung wechselt die Umgebung von PDB auf CDB. Man sollte sich vom Parameter db_name nicht irritieren lassen.:

CDB > PDB > CDB > PDB

sqlplus system@SJW12C01

SQL> show parameter db_name

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
db_name                              string      SJW12C01

SQL> show con_id

CON_ID
------------------------------
1

SQL> show con_name

CON_NAME
------------------------------
CDB$ROOT

SQL> alter session set container = SJWPDB01;

Session wurde geõndert.

SQL> show parameter db_name

NAME                                 TYPE        VALUE

------------------------------------ ----------- ------------------------------

db_name                              string      SJW12C01

SQL> show con_id

CON_ID
------------------------------
3

SQL> show con_name

CON_NAME
------------------------------
SJWPDB01

SQL> conn / as sysdba

Connect durchgef³hrt.

SQL> show pdbs

    CON_ID CON_NAME                       OPEN MODE  RESTRICTED
---------- ------------------------------ ---------- ----------
         2 PDB$SEED                       READ ONLY  NO
         3 SJWPDB01                       READ WRITE NO

SQL> show con_name

CON_NAME
------------------------------
CDB$ROOT

SQL> show con_id

CON_ID
------------------------------
1

SQL> alter session set container = SJWPDB01;

Session wurde geõndert.

SQL> show pdbs

    CON_ID CON_NAME                       OPEN MODE  RESTRICTED
---------- ------------------------------ ---------- ----------
         3 SJWPDB01                       READ WRITE NO

Hinweis

Seit der Version 12.2 wird bei der Ausgabe von sys_context(‚USERENV‘,’DB_NAME‘) in der CDB$ROOT der Name der Datenbank ausgegeben, innerhalb einer PDB aber der Name der PDB.

5 Kommentare zu “Hilfe, wo bin ich? CDB oder PDB … und welche DB überhaupt?

Habe soeben die 18c XE installiert und war verzweifelt, weil nichts aus dem von mir gewählten Tutorial klappen wollte.
Jetzt habe ich verstanden, wie das mit der CDB und PDB läuft.
Super Erklärung. Danke.

habe im $ORACLE_HOME/sqlplus/admin/glogin.sql eine Promptänderung eingetragen. Da weiss ich immer , wo ich gerade bin.
Eintrag: set sqlprompt „_user’@‘ _connect_identifier>“
Ergebnis sqlplus sys/xxxxxxxxx@cdb1:
SYS@ cdb1>conn sys/xxxxxxxxxx@pdb11
SYS@ pdb11>

hinter die connect anweisungen sollte schon noch ein “ as sysdba“ stehen.

Hallo Horst,
sorry aber ich sehe nicht, wo der Connect fehlerhaft sein sollte. Da in den meisten Fällen der User „SYSTEM“ genommen wurde, ist hier kein „as sysdba“ notwendig bzw. in der Regel auch gar nicht möglich.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Was kann CarajanDB für Sie tun?