spfile im Single-Instance-System: ein Parameter, mehrere Einträge

7. Februar 2021 Aus Von Markus Flechtner

Vor einiger Zeit erreichte mich eine Anfrage eines Kunden: er hätte in einem SPFILE für eine Single-Instance-Datenbank für einen Parameter mehrere Einträge. Was ist da passiert?

Im SPFILE stellt sich diese Szenario wie folgt dar:

DEMODB@> select sid,name,value from v$spparameter where name='optimizer_index_cost_adj'
  2  ;

SID       NAME                 VALUE
---------- ------------------------------ ------------------------------
*          optimizer_index_cost_adj   100
DEMODB    optimizer_index_cost_adj     110
2 rows selected.

Die Einträge mit der SID werden normalerweise nur im RAC gebraucht und es gilt der Grundsatz:

Wenn es einen instanzspezfischen Parameter gibt, dann hat der Vorrag vor einem allgemeingültigen Eintrag (mit “*”)
Man kann dann also in einem größeren RAC z.B. eine Standard-SGA-Größe festlegen und für einzelne Instanzen eine größere SGA.

Einige Parameter müssen im RAC auch instanzspezfisch sein (z.B. INSTANCE_NUMBER, THREAD), andere müssen für alle Instanzen im RAC identisch sein (z.B. DB_BLOCK_SIZE, DB_NAME).

Die bekannten Befehle um die Parameter zu setzen, sind:

REM Allgemeingültig:
ALTER SYSTEM SET. .... SID='*'*;


REM Instanzspezfisch
ALTER SYSTEM SET. .... SID='<SID>';

 

Wie kann es also auf einem Single-Instanz-System passieren, dass es für einen Parameter zwei Einträge im SPFILE gibt?

Der normale ALTER SYSTEM-Befehl (ohne SID=) setzt immer “*” als Geltungsbereich.

Beispiel:

DEMODB@> alter system set optimizer_index_cost_adj=100 scope=both;
System altered.

DEMODB@> select sid,name,value from v$spparameter where name='optimizer_index_cost_adj';

SID NAME VALUE
---------- ------------------------------ ------------------------------
* optimizer_index_cost_adj 100
1 row selected.

Aber auch im Single-Instance-System kann man mit “SID=..” arbeiten:

DEMODB@> alter system set optimizer_index_cost_adj=110 scope=both sid='DEMODB';
System altered.

DEMODB@> select sid,name,value from v$spparameter where name='optimizer_index_cost_adj'
  2  ;

SID       NAME                 VALUE
---------- ------------------------------ ------------------------------
*          optimizer_index_cost_adj   100
DEMODB    optimizer_index_cost_adj     110
2 rows selected.

Wir haben also zwei Einträge zum gleichen Parameter.

Und beim nächsten Startup wird der instanzspezifische Wert genommen:

DEMODB@> startup force;
ORACLE instance started.

Total System Global Area 2147481656 bytes
Fixed Size          8898616 bytes
Variable Size           704643072 bytes
Database Buffers 1426063360 bytes
Redo Buffers              7876608 bytes
Database mounted.
Database opened.

DEMODB@> show parameter optimizer_index_cost_adj

NAME                      TYPE  VALUE
------------------------------------ ----------- ------------------------------
optimizer_index_cost_adj        integer    110

Im Single-Instanz-System wird eine solche Konfiguration oftmals nicht entdeckt und man wundert sich, warum ein Parameter einen Wert hat der nicht dem mit “ALTER SYSTEM” eingestellten Wert entspricht

Daher ist mein Tipp, das spfile zu bereinigen, d.h.:

  1. Den “*”-Wert auf den “richtigen” Wert setzen.
  2. Die instanzspezifische Zeile löschen.

In obigem Beispiel also:

ALTER SYSTEM SET optimizer_index_cost_adj=110 scope=both;
alter system reset optimizer_index_cost_adj scope=spfile sid='DEMODB';

DEMODB@> select sid,name,value from v$spparameter where name='optimizer_index_cost_adj' ;

SID     NAME                 VALUE
---------- ------------------------------ ------------------------------
*       optimizer_index_cost_adj   110
1 row selected.

 

Wie kann man sein spfile prüfen und so eine Konfiguration erkennen?

Über

select name,min(value),max(value) from v$spparameter group by name having count(*) >1;

kann man rausfinden, ob es Parameter gibt, die mehrfach im spfile eingetragen sind (und dann ggf. aufräumen).
Achtung: der Parameter “control_files” hat pro Controlfile eine Zeile und taucht daher auch in der o.a. Abfrage auf.

Um bei der Kontrolle eines Parameters nur die gültige Zeile abzufragen, könnte man – ab 12c – mit “fetch next 1 rows only” arbeiten:

DEMODB> select sid,name,value from v$spparameter where name='optimizer_index_cost_adj' order by sid desc fetch next 1 rows only;

SID     NAME                 VALUE
---------- ------------------------------ ------------------------------
DEMODB    optimizer_index_cost_adj     110

Um eine Übersicht für alle Parameter anzuzeigen, die – falls vorhanden – nur den instanzspezfischen Wert anzeigt (und den “*”-Wert unterdrückt),
fällt mir erstmal folgendes SQL ein (es gibt sicher auch elegantere Varianten):

select p1.sid,p1.name,p1.value from v$spparameter p1 where p1.sid=(select instance_name from v$instance)
union
select p2.sid,p2.name,p2.value from v$spparameter p2 where p2.sid='*' and not exists (select 1 from v$spparameter p3 where p3.name=p2.name and p3.sid<>p2.sid)
order by 2;

Amazon-Partner-Link: