Parameterverwaltung in CDBs und PDBs
Auch knapp acht Jahre nachdem Oracle mit der Version 12c die Container-Datenbank-Architektur veröffentlicht hat, ist diese Architektur immer noch nicht bei allen Kunden „angekommen“ und sorgt immer wieder für Fragen. Zum Beispiel auch zu dem Thema, wie Parameter in Container-Datenbanken definiert werden und wo die definierten Werte gespeichert werden.
Es gilt – wie bei der klassischen Datenbank („Non-CDB“):
- Es gibt eine Instanz mit einer Menge von Prozessen (PMON, SMON, DWB0, LGWR etc.) und einer SGA (Shared Pool, Buffer Cache, Log Buffer etc.)
- Es gibt ein spfile in dem die Instanz-Parameter gespeichert sind.
Die Parameter, die im spfile abgelegt sind, werden beim Start der Instanz ausgelesen und sind die Einstellungen für den Root-Container (CDB$ROOT). Änderungen der Parameter erfolgen, auch das ist nichts Neues, mit dem altbekannten „ALTER SYSTEM“-Befehl und werden auch in das spfile geschrieben
CDB$ROOT > alter system set optimizer_index_cost_adj=105 scope=spfile; System altered. CDB$ROOT > !strings /u00/app/oracle/dbs/spfileTVDCDB1.ora |grep -i optimizer_index_cost_adj *.optimizer_index_cost_adj=105
Kurz gesagt: für den Root-Container CDB$ROOT ändert sich nichts. Wie sieht das nun bei den PDBs aus?
Hier gilt, dass – wenn nichts anderes auf PDB-Ebene definiert ist – die Parametereinstellungen aus dem Root-Container übernommen werden. Ein Teil der Parameter kann aber auf PDB-Ebene geändert werden. Diese Parameter enthalten in der Spalte ISPDB_MODIFIABLE in V$SYSTEM_PARAMETER den Wert ‚TRUE‘.
CDB$ROOT > select distinct name from v$system_parameter 2 where ispdb_modifiable='TRUE' order by name; NAME ------------------------------------------------------------ adg_account_info_tracking allow_rowid_column_type approx_for_aggregation approx_for_count_distinct approx_for_percentile […] undo_retention undo_tablespace unified_audit_systemlog workarea_size_policy xml_db_events 196 rows selected.
Um einen derartigen Parameter in einer PDB zu ändern, muss man zuerst in die PDB wechseln:
CDB$ROOT> alter session set container=pdb01; Session altered.
Die Änderung eines Parameters erfolgt dann wieder mit dem bekannten Befehl „ALTER SYSTEM“:
CDB$ROOT@TVDCDB1> alter system set optimizer_index_cost_adj=110 scope=both; System altered.
Allerdings wird der geänderte Parameter dann nicht im spfile gespeichert, wie folgender Befehl zeigt:
PDB01> !strings /u00/app/oracle/dbs/spfileTVDCDB1.ora |grep -i optimizer_index_cost_adj *.optimizer_index_cost_adj=105
Wo ist der geänderte Wert dann zu finden?
Um diese Frage zu beantworten, müssen wir wieder zurück in den Root-Container gehen.
PDB01> alter session set container=CDB$ROOT; Session altered.
Dort gibt es die Tabelle PDB_SPFILE$, in der Oracle die auf PDB-Ebene geänderten Parameter ablegt:
CDB$ROOT@TVDCDB1> desc pdb_spfile$ Name Null? Type ------------------------------- -------- ---------------------------- DB_UNIQ_NAME NOT NULL VARCHAR2(30) PDB_UID NOT NULL NUMBER SID NOT NULL VARCHAR2(80) NAME NOT NULL VARCHAR2(80) VALUE$ VARCHAR2(4000) COMMENT$ VARCHAR2(255) SPARE1 NUMBER SPARE2 NUMBER SPARE3 VARCHAR2(128) COLUMN pdb_name FORMAT a10 COLUMN name FORMAT a30 COLUMN value$ FORMAT a25 SELECT a.pdb_name, b.name, b.value$ FROM cdb_pdbs a, pdb_spfile$ b WHERE a.con_uid = b.pdb_uid AND b.spare2 <> 1 AND a.pdb_name = 'PDB01' ORDER BY a.pdb_name, b.name; PDB_NAME NAME VALUE$ ---------- --------------------------- ------------------------- PDB01 optimizer_index_cost_adj 110 1 row selected.
Bei der PDB_SPFILE$ gibt es allerdings einige Dinge zu beachten:
- Wenn man PDB_SPFILE$ in einer PDB abfragt, dann ist sie leer.
- Wenn man einen Parameter auf PDB Ebene löscht („ALTER SYSTEM RESET ..“), dann wird die zugehörige Zeile in PDB_SPFILE$ nicht gelöscht. Stattdessen wird die Spalte SPARE2 mit dem Wert 1 gefüllt:
CDB$ROOT > select b.name,b.value$,b.spare2 2 from cdb_pdbs a,pdb_spfile$ b 3 where a.con_uid=b.pdb_uid and a.pdb_name='PDB01' 4 and b.name='optimizer_index_cost_adj'; NAME VALUE$ SPARE2 ------------------------------ ------------------------- ---------- optimizer_index_cost_adj 110 0 1 row selected. CDB$ROOT> alter session set container=PDB01; Session altered. PDB01> alter system reset optimizer_index_cost_adj scope=both; System altered. PDB01> alter session set container=CDB$ROOT; Session altered. CDB$ROOT> select b.name,b.value$,b.spare2 2 from cdb_pdbs a,pdb_spfile$ b 3 where a.con_uid=b.pdb_uid and a.pdb_name='PDB01' 4 and b.name='optimizer_index_cost_adj'; NAME VALUE$ SPARE2 ------------------------------ ------------------------- ---------- optimizer_index_cost_adj 110 1 1 row selected.
Für die Abfrage der gültigen Einträge in PDB_SPFILE$ sollte man daher immer die WHERE-Bedingung „where spare2<>1“ ergänzen.
Wie zeigen sich die Parameter nun in den diversen V$-Views?
Starten wir mit dem Root-Container:
CDB$ROOT > show con_name CON_NAME ------------------------------ CDB$ROOT
Im spfile steht der Wert, den wir oben geändert haben:
CDB$ROOT1> select con_id,name,value from v$spparameter where name='optimizer_index_cost_adj'; CON_ID NAME VALUE ---------- ------------------------------ ---------- 1 optimizer_index_cost_adj 105
Da der Wert nur im spfile eingetragen ist („SCOPE=SPFILE“) und nicht für die laufende Instanz geändert wurde, gilt für die laufende Session (V$PARAMETER) und die laufende Instanz (V$SYSTEM_PARAMETER) noch der Ursprungswert:
CDB$ROOT> select con_id,name,value from v$parameter where name='optimizer_index_cost_adj'; CON_ID NAME VALUE ---------- ------------------------------ ---------- 1 optimizer_index_cost_adj 100 1 row selected. CDB$ROOT> select con_id,name,value from v$system_parameter where name='optimizer_index_cost_adj'; CON_ID NAME VALUE ---------- ------------------------------ ---------- 0 optimizer_index_cost_adj 100 1 row selected.
Wie sieht es nun in der PDB aus?
CDB$ROOT@TVDCDB1> alter session set container=PDB01; Session altered.
Auch hier gilt für die Session der originale Wert:
PDB01> select con_id,name,value from v$parameter where name='optimizer_index_cost_adj'; CON_ID NAME VALUE ---------- ------------------------------ ---------- 1 optimizer_index_cost_adj 100
Die Abfrage auf v$spparameter zeigt ein interessantes Ergebnis:
PDB01> select con_id,name,value from v$spparameter where name='optimizer_index_cost_adj'; CON_ID NAME VALUE ---------- ------------------------------ ---------- 7 optimizer_index_cost_adj 1 row selected.
Der Eintrag ist leer, da es nur einen inaktiven Eintrag in PDB_SPFILE$ gibt („spare2=1“), denn die Parameteränderung, die wir oben gemacht hatten, hatten wir ja mit „ALTER SYSTEM RESET“ wieder rückgängig gemacht.
Jetzt ändern wir den Wert nochmal in der PDB, diesmal für das „spfile“ und die laufende Instanz:
PDB01> alter system set optimizer_index_cost_adj=101 scope=both; System altered.
Und natürlich sind diese Änderungen in den V$-Views sichtbar:
PDB01> select con_id,name,value from v$system_parameter where name='optimizer_index_cost_adj'; CON_ID NAME VALUE ---------- ------------------------------ ---------- 7 optimizer_index_cost_adj 101 1 row selected. PDB01> select con_id,name,value from v$parameter where name='optimizer_index_cost_adj'; CON_ID NAME VALUE ---------- ------------------------------ ---------- 7 optimizer_index_cost_adj 101 1 row selected. PDB01> select con_id,name,value from v$spparameter where name='optimizer_index_cost_adj'; CON_ID NAME VALUE ---------- ------------------------------ ---------- 7 optimizer_index_cost_adj 101 1 row selected.
Eine interessante Änderung ergibt sich jetzt im Root-Container, wenn wir v$system_parameter abfragen:
PDB01> alter session set container=CDB$ROOT; Session altered. CDB$ROOT> select con_id,name,value from v$system_parameter where name='optimizer_index_cost_adj'; CON_ID NAME VALUE ---------- ------------------------------ ---------- 0 optimizer_index_cost_adj 100 7 optimizer_index_cost_adj 101 2 rows selected.
Über die v$system_parameter können wir also unterschiedliche Parameter in CDB$ROOT bzw. den PDBs einfach ermitteln.
Abschließend noch ein paar Worte zum Real Application Cluster (RAC):
Auch hier ändert sich nichts (unabhängig davon, ob man sich in CDB$ROOT oder in einer PDB befindet):
- „ALTER SYSTEM .. SCOPE=SPFILE“ ändert einen Wert für alle Instanzen.
- „ALTER SYSTEM .. SCOPE=SPFILE SID=‘..'“ ändert einen Wert für eine Instanz
Da ich aber schon einmal einen Kunden hatte, der im RAC für die SID den Namen der PDB angegeben hatte – und der sich dann gewundert hat, dass die Änderung nicht erfolgreich war – sei dieser kurze Hinweis gestattet: Wenn man instanzspezifische Parameter für eine PDB setzen will, dann muss man – wie üblich bei „SID“ die Instanz angeben und nicht den PDB-Namen.
Data Dictionary Tabellen
- PDB_SPFILE$
V$-Views:
- v$spparameter (Einträge im spfile)
- v$parameter (aktuell gültige Einstellungen in einer Session)
- v$system_parameter (aktuell gültige Einstellungen für die Instanz)
MOS-Notes
- Initialization parameters in a Multitenant database – Facts and additional information (Doc ID 2101596.1)
- Initialization parameters in a Multitenant database – FAQ and Examples (Doc ID 2101638.1)
- Alter Session And System Parameter In Both CDB and PDB (Doc ID 2673509.1)
- Bug 24423308 – SV12.2DBSA: ALTER SYSTEM RESET DOESN’T UPDATE PARAM VALUE IN PDB_SPFILE$@ROOT
Amazon Partner Link: