corner image
home ·Howto Oracle SQL / Administration


letzte Änderung:
TCP-States
Netzwerk
Links
Australien
Wertpapiere

Howto Oracle SQL / Administration

Claus Ebert

Version 1.10

Was macht man mit Oracle ? (Blödsinn, was denn sonst), und wie macht man das ? (zum Thema Blödsinn darf sich jeder seinen Teil denken)

1.SQL*Plus

2.Verwaltung von Sessions

3.Monitoring

4.Speicher / Plattenplatz Verwalten

5.Troubleshooting

6.Export / Import

7.Hostname IP-Auflösung innerhalb der Datenbank

8.Nette und Nützliche SQL's

9.Sonstiges


1. SQL*Plus

Einfaches und sehr mächtiges Kommandozeilen-Tool.

1.1 SET-Parameter

In der Default-Configuration macht das Arbeiten mit SQL*Plus keinen Spass, aber mit einigen SET Anweisungen kann man den Output in eine lesbarere Form bringen

  • SET NEWPAGE 0
    Anzahl der Leerzeilen am Seitenanfang.
  • SET ECHO OFF
    Unterdrückt die nochmalige Ausgabe des SQL Kommandos.
  • SET FEEDBACK OFF
    Unterdrückt die Ausgabe von: X rows selected.
  • SET HEADING OFF
    Unterdrückt die Ausgabe der Überschriften.
  • SET LINESIZE 120
    Setzt die Zeilenbreite auf 120 Zeichen. Falls die Ausgabe mit SPOOL in eine Datei geschrieben wird, dann werden IMMER 120 Zeichen pro Zeile ausgegeben. (mit Leerzeichen aufgefüllt).
    Wenn die auszugebende Zeile allerdings länger ist wird ab der 120en Zeichen umgebrochen (unschön).
    Dieses Dilemma kann man (zumindest unter Unix) dadurch umgehen, das man LINESIZE auf einen sehr großen Wert setzt und SPOOL nicht verwendet, sondern die Ausgabein eine Datei umleitet. Die Shell übernimmt dan das Entfernen der Leerzeichen für einen.
    z.B:
    sqlplus @abfrage.sql > ausgabedatei.txt
  • SET PAGESIZE 0
    Setzt die Anzahl der Zeilen, die auf eine Seite kommen.
    0 unterdrückt alle Format-Optionen die eine Seite betreffen (HEADING, NEWPAGE ...)
  • SET AUTOTRACE ON
    Schaltet die Autotrace-Funktionalität von SQL*Plus ein.
  • SET TIMING ON
        Die Ausführungszeit jedes SQL's wird mit ausgegeben.
top

1.2 Setzen des Prompts

sogar das Prompt von SQL*Plus kann man anpassen (wenn man einen etwas längeren Login in kauf nimmt).

Immer wenn SQL*Plus gestartet wird, verarbeitet es die Datei

$ORACLE_HOME/sqlplus/admin/glogin.sql

dann suchte SQL*Plus die Datei login.sql in dem Verzeichnis, von wo aus SQL*PLus gestartet wurde und danach in in dem Verzeichnis auf dem die Environment-Variable SQLPATH zeigt, und führ Sie aus.

Die Einstellungen der Datei login.sql überschreiben die Einstellungen, die in der Datei glogin.sql vorgenommen wurden.
In diese beiden Dateien können alle oben genannten SET-Parameter angegeben werden.

Soviel zur Theorie, jetzt die Praxis:

ALTER SESSION SET NLS_DATE_FORMAT='DD.MM.YYYY HH24:MI:SS";
Stellt das deutsche Datumsformat ein (oder jedes beliebige andere)

DEFINE_EDITOR='dtpad'
Setzt den Standard Editor (der bei 'edit' verwendet wird)

SET TERMOUT OFF
COLUMN NEW_PROMPT NEW_VALUE PROMPTIN
select name||'_'||user NEW_PROMPT from v$database;
SET SQLPROMPT "&&PROMPTIN>"
SET TERMOUT ON
Setzt das Standard-Prompt um.

top

1.3 SQL*Plus als Ersatz für svrmgrl

Seit Version 9 gibt es das Tool svrmgrl nicht mehr

Als Ersatz für svrmgrl sollte mann jetzt SQL*Plus verwenden:
sqlplus '/ as sysdba'

top

1.4 Mit SQL*Plus Select Ergebnisse in Unix-Variablen übertragen

Das erste Beispiel kann den Wert eine Datenbank-Spalte direkt in eine Unix-Variable lesen:
#!/bin/sh
VALUE=`sqlplus -silent user/password@instance <<END
set pagesize 0 feedback off verify off heading off echo off
select max(c1) from t1;
exit;
END`
if [ -z "$VALUE" ]; then
  echo "No rows returned from database"
  exit 0
else
  echo $VALUE
fi

Das zweite Beispiel benutzt den SQL*Plus EXIT status code (kann daher nur Interger-Werte liefern):
#!/bin/ksh
sqlplus -s >junk1 /nolog <<EOF
connect user/password@instance
column num_rows new_value num_rows format 9999
select count(*) num_rows
  from table_name;
exit num_rows
EOF
echo "Number of rows are: $?"

Im dritten Beispiel werden gleich mehrere Varibalen gefüllt:
sqlplus  -s /nolog |&     # Open a pipe to SQL*Plus

print -p -- 'connect user/password@instance'
print -p -- 'set feed off pause off pages 0 head off veri off line 500'
print -p -- 'set term off time off'
print -p -- "set sqlprompt ''"

print -p -- "select sysdate from dual;"
read  -p SYSDATE

print -p -- "select user from dual;"
read  -p USER

print -p -- "select global_name from global_name;"
read  -p GLOBAL_NAME

print -p -- exit

echo SYSDATE:     $SYSDATE
echo USER:        $USER
echo GLOBAL_NAME: $GLOBAL_NAME

top

1.5 Unix-Variablen in einem SQL verwenden

Dies ist ein kleines Beispiel wie man Unix-Variablen mit Hilfe von SQL*Plus in einem SQL-Script verwenden kann:
#!/bin/ksh
CONNECT=user/pass@instance
DBLINKUSER=linkuser
DBLINKPWD=linkpwd
DBLINKINSTANCE=linkinstance

sqlplus -s $CONNECT << _EOF_
  SET NEWPAGE 0
  SET SPACE 0
  SET ECHO ON
  SET FEEDBACK ON
  SET HEADING OFF
  SET LINESIZE 120
  SET PAGESIZE 0

  whenever sqlerror exit 1
  whenever oserror exit 2

  create database link eqty connect to ${DBLINKUSER}
      identified by ${DBLINKPWD} using '${DBLINKINSTANCE}' ;
  exit 0
_EOF_
 RC=$?;
 eqty_echo "createDBLink with rc=$RC" 

top

2. Verwaltung von Sessions

Die Datenbank hätte keinerlei Probleme, wenn es nicht User (Programme) gäbe, die sich über Sessions an die Datenbank connecten und SQL-Anfragen stellen würden.

2.1 Session identifizieren

Oracle Sessions kann man nur Administrieren wenn man die richtige Session identifizieren kann. Wie man Sessions findet, und wie man an deren SID und #Serial kommt, beschreibe ich hier.

Um die SID und die SERIAL# der Session herausbekommen führen wir als DBA (SYSTEM) folgends SQL-Statement aus:

SET PAGES 20
COL SID FORM 9990
COL #SERIAL FORM 99990
COL USERNAME FORM A10
COL OSUSER FORM A10
COL PROCESS FORM A9
COL MACHINE FORM A10
COL STATUS FORM A8
SELECT SID, SERIAL#, USER#, USERNAME, OSUSER, PROCESS, MACHINE, STATUS
  FROM V$SESSION;

Wir erhalten dann eine Liste aller vorhandenen Sessions z.B:

  SID    SERIAL#      USER# USERNAME   OSUSER     PROCESS   MACHINE    STATUS
------ --------- ---------- ---------- ---------- --------- ---------- --------
   64      15810         19 PTS        root       52388     sdev3      ACTIVE
   65       8953         19 PTS        root       36190     sdev3      ACTIVE

Das Beispiel zeigt uns, das die Session mit der SID 65 von root auf dem Computer sdev3 mit dem DB-User PTS stammt. 36190 ist die Prozess ID auf dem Client (mit ps -ef unter UNIX, oder unter Windows im Taskmanager zu erfahren). Mit diesen Informationen sollte die gewünschte Session leicht zu finden sein.

Die Bedeutung der einzelnen Spalten:

  • USER# Ist die eindeutige Nummer des Oracle-Users
  • USERNAME Ist der Oracle-User mit dem die Session in der Datenbank angemeldet ist.
  • OSUSER Betriebsystem-User mit der der Client im Betriebsystem des Clientrechners angemeldet ist.
  • PROCESS Prozessnummer auf dem Client-Rechner.
  • MACHINE Hostname des Client-Rechners.
  • STATUS
    • ACTIVE führt gerade SQL's aus.
    • INACTIVE Connected, aber nicht aktiv.
    • KILLED Session gekillt, aber noch nicht aus der Liste entfernt.
    • CACHED zwischengespeichert.
    • SNIPED inaktv, wartet auf den Client.
top

2.2 Trace in einem Programm / Script anschalten

Mit einem Datenbank-Trace werden alle SQL-Statements mitgeschrieben, die innerhalb der SQL-Session (Connect) an die Datenbank abgesetzt werden. Es werden auch die Ausführungszeiten und Ausführungspläne gespeichert.
Damit ist es möglich langsame SQL-Statements aufzuspüren.

In einem Programm (Pro*C, OCI, Perl, ODBC, SQL*Plus usw...) kann das Tracing durch das SQL-Statement
ALTER SESSION SET SQL_TRACE=TRUE;
eingeschaltet werden.

top

2.3 Trace zu einer Client Session anschalten

In vielen Fällen kann das Programm nicht geändert werden, so das die vorher beschriebene Methode nicht Angewand werden kann. Das soll uns aber nicht weiter stören, denn Oracle bietet auch hierfür einen Mechanismus an:

Zuerst müssen wir die SID und die SERIAL der zu überwachenden Session herausbekommen.

siehe dazu [Session identifizieren]

Folgende Statement schaltet das Trace für die SID ( 65 ) und die SERIAL# ( 8953 an:
EXECUTE DBMS_SYSTEM.SET_SQL_TRACE_IN_SESSION(65,8953,TRUE);

mit:
EXECUTE DBMS_SYSTEM.SET_SQL_TRACE_IN_SESSION(65,8953,FALSE);
schalten wir das trace wieder aus.

top

2.4 Session beenden (Killen)

Um eine laufende Session zu beenden benötigt man (wie auch beim Trace) die SID und die SERIAL# der Session.
siehe dazu [Session identifizieren]
Nehmen wir an, das die SID ( 82 ) und die SERIAL# ( 1012 ) sind. Diese Session kann nun mit dem SQL-Befehl:
ALTER SYSTEM KILL SESSION '82,1012';
gnadenlos beendet werden. Es kann sein, das sie weiterhin in der Session-Liste vorhanden ist.
Dann sollte sie aber den Status KILLED haben. Diese KILLED Sessions werden, wenn das Rollback gelaufen ist, vom PMON-Prozesses entfernt.

top

2.5 Welcher Client-Prozess gehört zu welchen Server-Prozess

Manchmal hat man einen Server-Prozess der den ganzen Rechner lahmlegt. Aber welcher Client hängt an dem Prozess ?

Um herauszubekommen welcher Client Prozess zu welchem Server-Prozess gehört brauchen wir zuerst einmal die Prozessnummer ( PID ) des Clients:
Unter Unix/Linux mit:
ps -ef | grep  prozessname
oder unter Windows findet man die Prozessnummer im Taskmanager.
Um die Server PID zu der Client PID zu bekommen führen wir nun folgendes SQL aus:
SET LINESIZE 250
SET PAGESIZE 100
SELECT S.SID,S.SADDR,P.SPID SPID,S.USERNAME,S.OSUSER,
       S.PROCESS,S.SERVER,S.LOGON_TIME,S.PROGRAM 
FROM V$SESSION S,V$PROCESS P 
WHERE S.PADDR=P.ADDR ORDER BY PROCESS;
In der Liste, die wir zurückbekommen sehen wir die Client-Prozessnummer in der Spalte PROCESS, die dazu gehörige Server-Prozessnummer wird in der Spalte SPID angezeigt.

top

3. Monitoring

3.1 Datenbank-Locks ermitteln (als Baumstruktur)

Da auch Oracle das Problem mit den Blocking Locks erkannt hat, bietet Oracle einige interresante Views Locks aufzuspüren

Die drei Views DBA_LOCKS, DBA_BLOCKERS und DBA_WAITERS erleichtern einem die Suche nach der Ursache des Blocking-Locks ganz erheblich.
Falls diese Views nicht vorhanden sind, hier findet sich eine Beschreibung wie man Sie erzeugt.
Im gleichen Verzeichnis, wie das Create-Script der drei Views befindet sich auch die Datei utllockt.sql die alle aktuellen Locks als Baumstruktur darstellt.
Das Script ist ganz nett, hat aber (bei mir) die Baumstruktur nicht so richtig dargestellt.

Aus diesem Grund habe ich das Select am Ende dieses Scripts umgebaut (wenn es funktioniert ... braucht man nichts ändern):

set heading off
set echo off
set newpage 0
set linesize 120
set pagesize 0
select 'Waiting Session     |    Lock Type   |  Req Mode   |'||
       '  Held Mode  |  LockID 1 | LockId 2' from dual;
select '---------------------------------------------------'||
       '-------------------------------------' from dual;
select  rpad(lpad(waiting_session,3*(level),' '),20)||'|'||
       lpad(lock_type,15)||' '||'|'||
       lpad(nvl(mode_requested,' '),12)||' '||'|'||
       lpad(nvl(mode_held,' '),12)||' '||'|'||
       lpad(nvl(lock_id1,' '),10)||' '||'|'||
       lpad(nvl(lock_id2,' '),10)
 from lock_holders
connect by  prior waiting_session = holding_session
  start with holding_session is null;

set feedback on
set echo on
set heading on

Der Output dieses Select ist (meines erachtens) das, was Oracle eigendlich ausgeben wollte.
z.B:

Wainting Session    |    Lock Type   |  Req Mode   |  Held Mode  |
-------------------------------------------------------------------
  8                 |           None |             |             |
    11              |    Transaction |   Exclusive |   Exclusive |

Im obigen Beispiel Blockt die Session 8 die Session 11 . Um die Session (Den Urheber zu idetifizieren können wir jetzt die Session suchen ( siehe Session idetifizieren oder nachsehen, welches Datenbank-Objekt (Tabelle) betroffen ist. (
siehe gelockte Objekte auflisten ).

Wenn die Views nicht installiert werden sollen (können) kann mann folgendes SQL verwenden:

set echo off
set pagesize 60
Column SID         FORMAT 999 heading "Sess|ID "
COLUMN OBJECT_NAME FORMAT A17 heading "OBJ NAME or|TRANS_ID" Trunc
COLUMN OSUSER      FORMAT A10 heading "Op Sys|User ID"
COLUMN USERNAME    FORMAT A8
COLUMN TERMINAL    FORMAT A8  trunc
COLUMN CTIME   FORMAT 9999990 heading Sec.
select B.SID, C.USERNAME, C.OSUSER, C.TERMINAL,
       DECODE(B.ID2, 0, A.OBJECT_NAME,
            'Trans-'||to_char(B.ID1)) OBJECT_NAME,
       B.TYPE,
       DECODE(B.LMODE,0,'--Waiting--',
                      1,'Null',
                      2,'Row Share',
                      3,'Row Excl',
                      4,'Share',
                      5,'Sha Row Exc',
                      6,'Exclusive',
                      'Other') "Lock Mode",
       DECODE(B.REQUEST,0,' ',
                      1,'Null',
                      2,'Row Share',
                      3,'Row Excl',
                      4,'Share',
                      5,'Sha Row Exc',
                      6,'Exclusive',
                     'Other') "Req Mode",
       B.CTIME
  from DBA_OBJECTS A, V$LOCK B, V$SESSION C
 where A.OBJECT_ID(+) = B.ID1
   and B.SID = C.SID
   and C.USERNAME is not null
 order by B.SID, B.ID2;

Als Ergebnis erhalten wir folgende Tabelle:

Sess          Op Sys              OBJ NAME or
 ID  Username User ID    Term     TRANS_ID          TYPE Lock Mode   Req Mode
---- -------- ---------- -------- ----------------- ---- ----------- -----------
   8 CHOC     ebertkl    DBFFM510 CCH_PERSON_CACHE  TM   Row Excl
   8          ebertkl             KRN_PERSON        TM   Row Excl
   8          ebertkl             Trans-851976      TX   Exclusive
  11          oracle     pts/0    KRN_PERSON        TM   Row Excl
  11          oracle              Trans-851976      TX   --Waiting-- Exclusive

Im obigen Beispiel sieht man, das Session 11 waiting ist, also auf ein Lock wartet. Die gleiche Transaktions-id Trans-851976 hat Session 8. Daher wartet Session 11 auf Session 8.

top

3.2 Gelockte Objekte auflisten

Dieses Script listet die aktuellen Locks der Datenbank, das gelockte Objekt und den User auf.

SET PAGES 20
SET LINESIZE 120
COL USERNAME FORM A10
COL SID FORM 9990
COL TYPE FORM A4
COL LMODE FORM 990
COL REQUEST FORM 990
COL OBJNAME FORM A15 HEADING "OBJECT NAME"
COL OBJID FORM 9999990 HEADING "OBJECT ID"

SELECT SN.USERNAME, M.SID, M.TYPE,
  DECODE(M.LMODE
    , 0, 'NONE'
    , 1, 'NULL'
    , 2, 'ROW SHARE'
    , 3, 'ROW EXCL.'
    , 4, 'SHARE'
    , 5, 'S/ROW EXCL.'
    , 6, 'EXCLUSIVE'
    , LMODE, LTRIM(TO_CHAR(LMODE,'990'))) LMODE,
  DECODE(M.REQUEST
    , 0, 'NONE'
    , 1, 'NULL'
    , 2, 'ROW SHARE'
    , 3, 'ROW EXCL.'
    , 4, 'SHARE'
    , 5, 'S/ROW EXCL.'
    , 6, 'EXCLUSIVE'
    , REQUEST, LTRIM(TO_CHAR(REQUEST,'990'))) REQUEST,
  DECODE(M.BLOCK
    , 0, 'not Blocking'
    , 1, 'Blocking'
    , M.BLOCK, LTRIM(TO_CHAR(M.BLOCK,'990'))) BLOCK,
 OBJ1.OBJECT_NAME OBJNAME, OBJ1.OBJECT_ID OBJID, 
 OBJ2.OBJECT_NAME OBJNAME, OBJ2.OBJECT_ID OBJID
FROM V$SESSION SN, V$LOCK M, DBA_OBJECTS OBJ1, DBA_OBJECTS OBJ2
WHERE SN.SID = M.SID
AND M.ID1 = OBJ1.OBJECT_ID (+)
AND M.ID2 = OBJ2.OBJECT_ID (+)
   AND LMODE != 4
ORDER BY ID1,ID2, M.REQUEST
/

Das Ergebnis sieht dann folgendermaßen aus

USERNAME  SID TYPE LMODE       REQUEST   BLOCK        OBJECT NAME     OBJECT ID
CHOC        8 TM   ROW EXCL.   NONE      not Blocking CCH_PERSON_CACHE    31964
CHOC        8 TM   ROW EXCL.   NONE      not Blocking KRN_PERSON          32065
CHOC       11 TM   ROW EXCL.   NONE      not Blocking KRN_PERSON          32065
CHOC        8 TX   EXCLUSIVE   NONE      Blocking
CHOC       11 TX   NONE        EXCLUSIVE not Blocking

Da wir schon wissen welche die wartende Session ist (siehe Datenbank-Locks ermitteln [Session 11] ) interresiert uns vor allen, welche Objekte betroffen sind.
Im obigen Beispiel ist das die Tabelle KRN_PERSON .
Aber welche Spalte ???. Dies wird im Kapitel (Ermitteln der Spalte, die gelockt ist) beschrieben.

top

3.3 Ermitteln der Spalte, die gelockt ist.

Hier ermitteln wir an Hand der bereits gefundenen OBJECT_ID die Spalte, die gelockt ist.

Um die Spalte zu ermitteln, auf welche die wartende Session zufreifen will benötigen wir die SID, den Tabellennamen und deren Object_ID.
Um die Spalte zu ermittel gehen wir nun folgendermaßen vor:
Zuerst stellen wir sicher, das die OBJECT_ID auch die gewünschte Tabelle ist.

SELECT OBJECT_TYPE||' '||OWNER||
      ' '|| OBJECT_NAME OBJECT
  FROM DBA_OBJECTS
  WHERE OBJECT_ID=32065;

Liefert uns folgendes Ergebnis:

OBJECT
-----------------------------------------
TABLE CHOC KRN_PERSON

OK. die Objekt_Id 32065 entsprichet der Tabelle KRN_PERSON.
Jetzt holen wir uns noch die nötigen Informationen um die Spalte zu ermitteln:

SELECT SID, ROW_WAIT_OBJ#,ROW_WAIT_FILE#,
       ROW_WAIT_BLOCK#,ROW_WAIT_ROW# 
FROM V$SESSION WHERE SID =11;

  SID ROW_WAIT_OBJ# ROW_WAIT_FILE# ROW_WAIT_BLOCK# ROW_WAIT_ROW#
----- ------------- -------------- --------------- -------------
   11         32065              7            6992             0

Um die ROW_ID zu erzeugen benötigen wir die Object_Id ROW_WAIT_OBJ# (32065) die FileNo ROW_WAIT_FILE# (7) die BlockNo ROW_WAIT_BLOCK# (6992) und die FileBlockNo ROW_WAIT_ROW# (0) Die gelockte Zeile kann jetzt mit folgendem SQL ermittelt werden:

SELECT * 
 FROM KRN_PERSON
WHERE rowid = DBMS_ROWID.ROWID_CREATE(1, 32065, 7, 6992, 0);

Der Erste Parameter der Funktion DBMS_ROWID.ROWID_CREATE ist der Typ der ROWID (1 = extended ROWID).
So.... jetzt wissen wir welche Spalte gelockt ist.

top

3.4 Bei welchen Objekten ist das Next-Extend kleiner als das größte freie Verfügbare

Dieses SQL zeigt alle Datenbankobjekte an, bei denen eine Erweiterung um den im NEXTEXTEND angegebenen Wert fehlschlagen wird.

SET LINESIZE 200
select b.tablespace_name "Tablespace",
       b.segment_type "Type",
       substr(ext.owner||'.'||ext.segment_name,1,50) "Object Name",
       To_Char(decode(freespace.Extent_Management,'DICTIONARY',
                     decode(b.extents,1,b.next_extent, ext.bytes *
                            (1+b.pct_increase/100)),'LOCAL',
                     decode(freespace.Allocation_Type,'UNIFORM',
                            freespace.INITIAL_EXTENT,'SYSTEM',ext.bytes)
             )/1024,'9,999,999,999') "Required Extent(KB)",
       to_char(freespace.largest/1024,'9,999,999,999') "MaxAvail (KB)"
 from dba_segments b, dba_extents ext,
      (select B.tablespace_name, B.Extent_Management, B.Allocation_Type,
            B.INITIAL_EXTENT, B.NEXT_EXTENT, max(A.bytes) largest
         from dba_free_space A, dba_tablespaces B
        Where B.Tablespace_Name = A.Tablespace_Name
          And B.Status='ONLINE'
        group by B.tablespace_name, B.Extent_Management, B.Allocation_Type,
                  B.INITIAL_EXTENT, B.NEXT_EXTENT
      ) freespace
where
  b.owner=ext.owner and
  b.segment_type=ext.segment_type and
  b.segment_name=ext.segment_name and
  b.tablespace_name= ext.tablespace_name and
  (b.extents-1) =ext.extent_id and
  b.tablespace_name = freespace.tablespace_name and
  decode(freespace.Extent_Management,'DICTIONARY',
         decode(b.extents,1,(b.next_extent),ext.bytes*(1+b.pct_increase/100))
         ,'LOCAL',decode(freespace.Allocation_Type,'UNIFORM',
         freespace.INITIAL_EXTENT,'SYSTEM',ext.bytes)
        ) > freespace.largest
order by b.Tablespace_Name,b.Segment_Type,b.Segment_Name
/

top

3.5 Wieviel Platz verbraucht die Datenbank

Dieses SQL summiert den Platz auf, der von der Datenbank beansprucht wird. Es Zeigt NICHT an wieviel davon belegt ist.

SELECT
  (SELECT SUM(BYTES/1048576) FROM DBA_DATA_FILES) "Data MB",
  (SELECT NVL(SUM(BYTES/1048576),0) FROM DBA_TEMP_FILES) "Temp MB",
  (SELECT SUM(BYTES/1048576)*MAX(MEMBERS) FROM V$LOG) "Redo MB",
  (SELECT SUM(BYTES/1048576) FROM DBA_DATA_FILES) +
  (SELECT NVL(SUM(BYTES/1048576),0) FROM DBA_TEMP_FILES) +
  (SELECT SUM(BYTES/1048576)*MAX(MEMBERS) FROM V$LOG) "Total MB"
FROM DUAL;

top

3.6 Wieviel Platz benötigen die einzelnen Tabellen

Dieses SQL zeigt den Platzverbrauch aller Tabellen des Schemas in Megabyte an. Ist nett wenn man zu wenig Plattenplatz hat (und wer hat das nicht).
Es wird hier NICHT angezeigt, wieviel Platz die Tabelle wirklich benötigt. Es wird nur angezeigt wiviel Platz für die Tabelle allokiert (reserviert) ist.

Wenn mann wissen will, ob in einer Tabelle (oder in einem Index) viel "Luft" ist, kann man dies
hier erfahren.

SELECT 
  a.table_name,
  a.tablespace_name,
  to_char(ROUND(SUM (b.bytes) / 1024 / 1024 , 3),'999999990D0000') MegaBytes
 FROM user_tables a,
      user_extents b
WHERE a.table_name = b.segment_name
  AND a.tablespace_name = b.tablespace_name
GROUP BY a.tablespace_name, a.table_name
ORDER BY megabytes DESC, table_name ASC;

top

3.7 Wieviel Platz benötigen Tabellen und Indizes wirklich ?

Diese Frage ist leider nicht so einfach zu beantworten. Eine möglichkeit bietet uns das Oracle-Package DBMS_SPACE das bei einer Standard-Installation eigendlich vorhanden sein sollte.
Ich habe ein kleines SQL geschrieben, das die Informationen übersichtlich in Tabellenform ausgibt:
unused_space.sql

Das SQL fragt nach den Starten ab, welcher Typ von Segment ausgegeben werden soll (I=Index und t=Tabelle).
außerdem will es wissen, in welchem Tablespace es suchen soll.

Die einzelnen Spalten haben folgende Bedeutung:
Der Einfachheit halber beziehe ich mich in der Beschreibung auf den Typ "TABELLE".

  • Table Name oder Index Name
    Na ja. .. der Name des Indexes oder der Tabelle
  • Total Blocks
    Anzahl der Blöcke, die für diese Tabelle reserviert sind.
  • Total Bytes
    Anzahl der Bytes, die für diese Tabelle reserviert sind.
  • Unused Blocks
    Anzahl der Blöcke, die noch nicht verwendet sind. Diese Blöcke können mit
    ALTER [ TABLE | INDEX | CLUSTER ] segment_name DEALLOCATE UNUSED;
    wieder Freigegeben werden.
  • Unused Bytes
    Anzahl der Bytes, die noch nicht verwendet sind. siehe auch Unused Blocks .
  • Used Blocks
    Anzahl der Blöcke, die für diese Tabelle reserviert sind, und die NICHT wieder freigegeben werden können.
    Diese Blöcke können Daten enthalten, müssen aber nicht.
    Sie befinden sich nur unter der High Watermark , was nur bedeutet, das eine deallokation nicht möglich ist.
  • Used Bytes
    siehe Used Blocks jedoch in Bytes. Dies ist nur die Anzahl der
    Used Blocks multipliziert mit der Blockgröße in Bytes.
    Dies sagt leider nichts über den wirkliche Platzbedarf der Tabelle aus. Dazu müsste man die Füllstande aller Used Blocks zusammenaddieren.
  • Used KBytes
    siehe Used Bytes jedoch in Kilo-Bytes
  • Used MBytes
    siehe Used Bytes jedoch in Mega-Bytes
  • ext File ID
    ID des letzten Extents's das Daten enthält.
  • ext Block ID
    ID des letzten Block's in letzten Extent,der Daten enthält.
  • Last Block

top

3.8 Reservieren Speicher freigeben

Mit dem Statement
ALTER [ TABLE | INDEX | CLUSTER ] segment_name DEALLOCATE UNUSED;
kann man den freien Speicher oberhalb der High-Water-Mark wieder freigeben, solange der INITIAL-EXTENDT und MINEXTEND erhalten bleiben.

Wenn der optionale Parameter KEEP mit angegeben wurde, wird vesucht, den Speicher des Segmenmts auf den angegeben Wert zu reduzieren. Dabei werden INITIAL-EXTENT und MAXEXTENT angepasst.
z.B:
ALTER TABLE HIST_POSITION DEALLOCATE UNUSED KEEP 2000K;

top

4. Speicher / Plattenplatz Verwalten

4.1 Indexe Regenerieren / Verschieben

Wie kann man Indexe regenerieren (oder wichtiger ... die Storage-Parameter online ändern)

Prinzipiell bin ich dagegen, Indexe auf verdacht zu reorganisieren, siehe Fragmentierung ,aber dies ist eine wunderbare Methode die Indexe in ein anderes Tablespace zu verschieben.

Um z.B. alle Indexe eines Owners in ein anderes Tablespace zu verschieben führt man das folgende SQL aus (nicht ohne das man vorher das SQL den eigenen Bedürfnissen angepasst hat).

create_index_regenerate_move.sql

Diese SQL generiert eine Datei mit des SQL's fü alle Indexe des Owners mit Namen index_regenerate.sql in aktuellen Verzeichnis.
Durch das ausführen dieser SQL-Datei werden alle Indexe des Owners regeneriert (verschoben)

top

4.2 Tabellen in ein anderes Tablespace verschieben

Prinzipiell funktioniert das verschieben von Tabellen ähnlich wie das Verschieben der Indexe
Zuerst generiert man sich das passende SQL-File (z.B mit create_table_move.sql ) was einem eine Datei mit den SQL's für alle Tabellen des Owners erzeugt ( table_move.sql ) und führt dieses SQL danach aus.

Auf hier gilt wieder das in Oracle Fragmentierung gesagte.

top

5. Troubleshooting

5.1 Gelöschtes Datafile entfernen

Falls aus Versehen ein Datafile gelöscht wurde

Dies zeigt leider nur die Möglichkeit die Datenbank wieder starten zu können,

Durch diese vorgehensweisen können ALLE Daten in der Datenbank gelöscht werden. Dies solle auf keinen Fall in einer Produktiven Umgebung angewand werden.

  • Login mit svrmgrl (oder sqlplus '/ as sysdba' )
  • shutdown abort;
  • startup mount;
  • alter database datafile '/ora8/.dbf' offline drop;
  • alter database open;

Alternativ kann am auch folgendes probieren

  • Login mit svrmgrl (oder sqlplus '/ as sysdba' )
  • shutdown abort;
  • startup mount;
  • Lesen des Pfades und der Dateigröße:
    select df.file#, df.status, df.enabled, df.create_bytes, df.name 
    rom v$recover_file rf, v$datafile df 
    where rf.file#=df.file# and rf.error = "FILE NOT FILE"
    Pfad/Dateiname und die Dateigröße notieren!
  • Erzeuge das neue datafile:
    alter database create datafile '/path/filename.dbf' as '/path/filename.dbf' size xxx reuse;
    Der Pfad/Dateiname und Dateigröße müssen die gleichen sein wie sie oben ermittelt wurden.
  • alter database datafile '/path/filename.dbf' online;
  • recover database
  • alter database open
top

6. Export / Import

Export oder Import der Datenbank

6.1 Wie benutzt man die Export- Import-Programme

Die imp und exp Programme befinden sich normalerweise im Verweichnis $ORACLE_HOME/bin
Sie können interaktiv verwendet werden (einfach exp eintippen), über Kommandozeilenparameter gesteuert werden oder mit einer Steuerdatei arbeiten.
Ein exp help=yes oder ein imp help=yes listen alle verfügbaren Parameter auf.

hier folgen einige Beispiele:
exp scott/tiger file=emp.dmp log=emp.log tables=emp rows=yes indexes=no
exp scott/tiger file=emp.dmp tables=(emp,dept)

imp scott/tiger file=emp.dmp full=yes
imp scott/tiger file=emp.dmp fromuser=scott touser=scott tables=dept

exp userid=scott/tiger@orcl parfile=export.txt

... wobei die Datei export.txt folgende Parameter enthält:
     BUFFER=100000
     FILE=account.dmp
     FULL=n
     OWNER=scott
     GRANTS=y
     COMPRESS=y

Für alle, die Kommandozeilentools nich mögen, bietet der Schema Manager ein Grafisches Frontend (Wird mit dem Oracle Enterprise Manager ausgeliefert). ausgeliefert).

top

6.2 Teile einer Tabelle exportieren

Seit Oracle 8i kennt exp den Parameter QUERY mit dem man einen Teil einer Tabelle exportieren kann.

 exp scott/tiger tables=emp query=\"where deptno=10\"

top

6.3 Wie importiert man in andere Tablespaces

Beim import kann man leider nicht das Ziel-Tablespace angeben, in dem die Tabellen erstellt werden sollen. Import versucht immer die Objekte in dem Tablespace zu erstellen,aus dem sie exportiert wurden.

Durch folgende Forgehensweisen ist es jedoch möglich das Tablespace vorzugeben, in das die Tabellen (oder alle anderen Datenbankobjekte) importiert werden sollen:

  • Das anlegen der Tabllen im richtigen Tablespace VOR dem Import
    • Importieren des dump-files mit dem Parameter INDEXFILE=
      Dadurch wird nichts importiert, sondern nur eine Datei erzeugt, in der für alle Objekte des dump-files CREATE-Statements der geschrieben werden.
    • Bearbeiten des Indexfiles (Das korrekte Tablespace bei den CREATE TABLE Statements) und entfernen der auskommentierung.
    • Erstellen der gewünschten Objekte (Tabellen) mit den bearbeiteten Statements.
    • Starten des Imports mit dem Parameter IGNORE=Y
      Dadurch werden alle Fehler beim Erstellen der Datenbankobjekte ignoriert (Wir haben unsere Tabellen ja schon abgelegt)
  • Ändern des default-Tablespaces fü den user
    • Entferne das UNLIMITED TABLESPACE privilege fü den user
      REVOKE UNLIMITED TABLESPACE FROM USER
    • Entferne die Quota des Users vom dem Tablespace aus dem die Tabellen exportiert wurden
    • Ändere das default tablespace des users auf das Ziel-Tablespace
    • Importiere das dump-file
top

6.4 Müssen Tabellen vor dem Import geleert werden

Einfache Antwot: JA

Der import hängt einfach die Datan an die bestehenden Daten der Tabelle an. Das kann manchmal hilfreich sein wenn man zwei Datenquellen zusammenführen will.

Falls man aber einen Export zurückspielen will, sollte man vorher alle Tabelle leeren z.B:
TRUNCATE TABLE TABELLENNAME;
oder gleich den kompletten Owner (user) der Tabelle(n) löschen:
DROP USER TABLEOWNER CASCADE;

Besonders bei Sequenzen sollte man aufpassen, da sonst leicht die ganze Numerierung durcheinander kommt.

top

6.5 Import / Export zwischen verschiedenen Oracle-Versionen

Das import-tool ist normalerweise aufwärtskomatibel, d.H. ein mit Version 8 erstellte DUMP-Datei kann mit einem Version 9 import importiert werden.
Dies ist auch ein guter Weg um ein Datenbank-Upgrade durchzuführen.

Hinweis
Bei mit ist der Import immer abgestürzt, als ich einen Version 8 export in meine 9i (10g) Datenbank importieren wollte.
Laut Oracle hat der Import probleme mit den Statistik-Informationen. Da diese sowieso in den neuen Datenbank mit ANALYZE erst erstellt werden sollten habe ich mit dem Parameter STATISTIC=N den import der Statistiken unterdrückt, und siehe da, alles hat klaglos funktioniert.

Prinzipiell ist es auch möglich einen Version 8 Export aus einer 9i Datenbank zu erstellen:
Dazu benötigt mann irgendwo einen Rechner mit einem Version 8 Client und man muß die kompatibilitäts-Scripte in der Datenbank laufen lassen. Diese liegen (auf den Datenbank-Rechner) unter
$ORACLE_HOME/rdbms/admin/catexpX.sql
wobei das X die Oracle-Version wiederspiegelt.

Man kann dann mit der alten exp-Version aus der neuen Datenbank ein Export erstellen (meistens)

top

6.6 Export auf mehrere Dateien verteilen

Seit Version 8i ist es möglich den Export auf mehrere Dateien zu verteilen.
Dadurch ist kann man große exporte auf mehrere Dateien zu verteilen ohne das die Grenzen des Betriebssystems erreicht werden (z.B. 2 Gigabyte).
Dazu muß man nur dem FILE-Parameter mehrere Dateien mitgeben und mit FILESIZE die maximale größe einer Datei angeben.

z.B:
exp SCOTT/TIGER FILE=D:\F1.dmp,E:\F2.dmp FILESIZE=10m LOG=scott.log

beim Importieren muß man dann nur den gleichen FILE-Parameter wie beim Exportieren verwenden.

Falls man mit einem Export arbeiten muß, der diese Parameter noch nicht bietet kann man sich mit folgenden Script helfen (2G-Files):

cd /tmp/data
rm exp.dmp
mknod exp.dmp p       # mkfifo on certain Unix flavours
split -b2047m </tmp/data/exp.dmp &
exp scott/tiger file=/tmp/data/exp.dmp record=n tables=tableX

cd /tmp/data
rm exp.dmp
mknod exp.dmp p
cat xaa xab xac xad > /tmp/data/exp.dmp &
imp scott/tiger file=/tmp/data/exp.dmp commit=y tables=tableX

Das obige Verfahren kann prinzipiell für Import, Export und Loader Operationen verwendet werden.

top

6.7 Export ohne Zwischendatei online komprimieren

Das Tool exp von Oracle kann eine komplette Datenbank sichern, aber die Ausgabedatei nicht komprimieren.

Die Online-Komprimierung können wir uns aber einfach mit dem Bordmitteln von Unix zusammenbasteln (in meinem Fall AIX)
Dazu verwenden wir ein Spezialfile (Pipe) das immer nur eine begrenzte Menge an Daten von einem Programm aufnehmen, und an ein anderes Programm abgeben kann.

Zuerst löschem wir die Pipe (da es nicht Funktioniert, falls eine alte noch vorhanden ist):
rm -f  expdat.dmp

Danach erstellen wir uns die neue Pipe.
mknod exp.dmp p       # mkfifo on certain Unix flavours
Jetzt starten wir compress, das alle Daten aus der Pipe saugt und komprimiert:
compress < expdat.dmp > expdat.dmp.Z & 
Das gleiche kann man natürlich auch mit gzip machen:
gzip < expdat.dmp > expdat.dmp.gz &
oder bit bzip2
bzip2 < expdat.dmp > expdat.dmp.bz2 &

Wir warten sicherheitshalber noch 5 Sekunden
sleep 5

Dann starten wir den Export mit der pipe als Ausgabedatei
exp scott/tiger file=expdat.dmp

Wir sind fertig, also weg mit der Pipe
rm -f  expdat.dmp

Das sollte es eigendlich sein. exp schreibt seine Ausgabe in die pipe, und die gibt die Daten an comress weiter. Der Trick hierbei ist, das eine Pipe immer nur einige Kilobyte groß wird.

top

6.8 Export direkt auf ein Tape

Man kann ein Bandlaufwerk beim Export wie eine Datei verwenden. Man muß nur (wenn man ein Device direkt verwendet) den VOLSIZE-Parameter mit angeben:
exp userid/password file=/dev/rmt0 table=emp volsize=1.2G

Hinweis: Der VOLSIZE-Parameter ist eine Nummer die mit "m", "k", oder "b" (M, K, or B) endet. Der default ist bytes.

top

6.9 Export über das Netzwerk direkt in eine andere Datenbank


Host A:
mknod FIFO.dmp p
exp u/p FILE=FIFO.dmp rest_of_parameters...

Host B:
mknod FIFO2.dmp p
rsh host1 dd if=FIFO.dmp > FIFO2.dmp &
imp u/p FILE=FIFO2.dmp rest_of_parameters...

Wichtig ist, das sichergestellt wird, das die named pipe auf beiden Seiten fertig ist befor der Prozess gestartet wird.

top

6.10 Verbesserung der Performance beim Im- und Export

Export

  • Setze den BUFFER-Parameter auf einen hohen Wert (z.B. 2M)
  • Setze den RECORDLENGTH-Parameter auf einen hohen Wert (z.B. 64K)
  • Beende unnötige Applikationen um soviel Ressourcen wie möglich für den Import freizumachen.
  • Falls gleichzeitig mehrere Exporte laufen, stelle sicher, das sie auf verschiedene Festplatten schreiben.
  • Exportiere NIEMALS auf ein Netzwerklaufwerk (NFS). Es wird ewig dauern.

Import

  • Erzeuge ein Index-File, so das die Indices nach dem Import der Daten erstellt werden können
    Diese Datei kann durch einen Import mit dem Parameter INDEXFILE= erzeugt werden. Dabei wird nur das Index-File erstellt, ohne das Daten importiert werden. Die Datei sollte nach der Erstellung editiert werden, und alle Passwörter für alle CONNECT-Statements müssen angepasst werden.
  • Die zu importierende Datei sollte auf einer physikalisch anderen Festpatte liegen, als alle anderen Oracle-Dateien.
  • Erhöhe die DB_CACHE_SIZE (DB_BLOCK_BUFFERS vor 9i) in dem init$SID.ora file
  • Setze den LOG_BUFFER-Parameter auf einen großen Wert und starte die Datenbank neu.
  • Stoppe redo log archiving falls es Eingeschaltet ist (ALTER DATABASE NOARCHIVELOG;)
  • Erzeuge ein GROßES Tablespace mit einem GROßEN Rollback-Segment. Setze alle anderen Rollback-Segmente offline (außer den System Rollback-Segment natürlich) Dieses Rollback-Segment sollte so groß sein wie die größte Tabelle (denke ich??)
  • Benutze COMMIT=N als Import-Parameter (Wenn das Rollback-Segment groß genug ist)
  • Benutze ANALYZE=N als Import-Parameter um zeitraubende ANALYZE-Statments zu unterbinden.
  • Vergesse NICHT das (oben erzeugte) Index-File auszuführen.


top

6.11 Häufige Import / Export Probleme

  • ORA-00001: Unique constraint (...) violated Die Zeile, die gerade versucht wurde zu Importieren ist schon vorhanden (Unique oder Primärschlüssel).
    Mit IGNORE=NO fährt imp fort anstatt sich zu beenden. (Nützlich falls beim Import, die Tabellen schon vorhanden sind.)
  • ORA-01555: Snapshot too old Es wurden zu viele Veränderungen vorgenommen.
    Bitte die User nicht mehr mit der Datenbank zu arbeiten solange der export läuft oder benutze dem Parameter CONSISTENT=NO
  • ORA-01562: Failed to extend rollback segment Rollbacksegement ist zu klein.
    Erzeuge ein größeres Rollback-Segement oder benutze den Parameter COMMIT=Y während des Imports.
  • IMP-00015: Statement failed ... object already exists Benutzt den Parameter IGNORE=Y um diese Meldungen zu ignorieren, aber sei vorsichtig, es könnten doppelte Zeilen eingefügt worden sein.
top

7. Hostname IP-Auflösung innerhalb der Datenbank

7.1 Auf welcher Maschine läuft die Datenbank zu der ich gerade connected bin ?

Manchmal ist es Interessant zu wissen, ob man gerade mit seiner Entwicklungs-Datenbank verbunden ist (eine Verwechslung mit Produktion währe meistens SEHR SCHLECHT)
mit:

SELECT NAME FROM V$DATABASE;

bekommt mann zwar die SID der Datenbank heraus, was mir aber in meinem Fall nicht weitergeholfen hat, da Entwicklung und Produktion die gleiche SID verwenden.
aber mit:

SELECT S.MACHINE
   FROM V$SESSION S, V$PROCESS P
   WHERE P.SPID = S.PROCESS AND MACHINE IS NOT NULL AND ROWNUM = 1;

bekommt mann zumindest den Namen der Maschine zu sehen, auf dem die Datenbank läuft.
Was einem nicht sonderlich weiterhilft, wenn Produktion und Test den gleichen Maschinennamen verwenden. z.B:
Produktion: oraclebox.prod.test.de
Development: oraclebox.dev.test.de
Glücklicherweise bin ich letztens über ein SQL gestolperd, das dieses Problem löst:

SELECT GLOBAL_NAME FROM GLOBAL_NAME;

Dieses SQL liefert als Ergebnis SID.DEV.TEST.DE so das man endlich weiss in welcher Domain man sich befindet.
Wenn mann jetzt die SID weglässt und den Namen der Maschine vorne anfügt, hat man den Kompletten Domain-Namen der Server-Maschine:

SELECT LOWER(S.MACHINE||
       (SELECT SUBSTR(GLOBAL_NAME,INSTR(GLOBAL_NAME,'.'),999) FROM GLOBAL_NAME))
  FROM V$SESSION S, V$PROCESS P
 WHERE P.SPID = S.PROCESS AND MACHINE IS NOT NULL AND ROWNUM = 1;

top

7.2 Welche IP-Adresse hat ein Host

Mit dem Package utl_inaddr bietet Oracle innerhalb der Datenbank die Möglichkeit Hostnamen in IP-Adressen und umgekehrt umzuwandeln:

SELECT utl_inaddr.get_host_address('google.de') FROM dual;

Damit bekommt mann die IP-Adresse zu einem Host-Namen
216.239.59.104
.. in meinem Fall. (Kann sich aber ändern ... je nach DNS-Server)

Mit einem beherzten

SELECT  sid, machine,
utl_inaddr.get_host_address(SUBSTR(machine,
INSTR(machine,'\')+1)) ip
FROM gv$session
WHERE type = 'USER'
INSTR(machine,'\')+1)) ip

bekommt man dir IP-Adressen der verbundenen Clients.

19 DM02\CP021   172.16.1.229
17 DM02\CP022   172.16.1.228 

Und mit der Funktion get_host_name steht einer der umgekehrte Weg zur Verfügung

SELECT utl_inaddr.get_host_name('140.142.15.233') from dual;

Liefert zum Beispiel

www4.cac.washington.edu

top

7.3 Welche Version der Datenbank läuft denn ?

ein SELECT * FROM V$VERSION;
hilft in dem meisten Fällen weiter.
 
SELECT DBMS_UTILITY.PORT_STRING() FROM DUAL;
liefert das Betriebssystem, unter dem die Datenbank läuft, und die Versionsnummer der Datenbank.
Die Procedure
DBMS_UTILITY.DB_VERSION(VERSION OUT VARCHAR2,COMPATIBILITY OUT VARCHAR2);
ist auch ganz nett. Sie liefert die aktuelle Version der DB im String version (z.B: 7.1.0.0.0) und die Compatibilität der DB (wird in der init.ora gesetzt).

top

7.4 Wie lange läuft die Datenbank schon ?

ist doch manchmal interessant
 
SET LINESIZE=250 "Host"
 
select 'Hostname : ' || host_name || chr(10)||
  'Instanz Name : ' || instance_name || chr(10)||
  'Started  : ' || to_char(startup_time,'DD-MON-YYYY HH24:MI:SS')||chr(10)||
  'Uptime : ' || floor(sysdate - startup_time) || ' days(s) ' ||
  trunc( 24*((sysdate-startup_time) -
  trunc(sysdate-startup_time))) || ' hour(s) ' ||
  mod(trunc(1440*((sysdate-startup_time) -
  trunc(sysdate-startup_time))), 60) ||' minute(s) ' ||
  mod(trunc(86400*((sysdate-startup_time) -
  trunc(sysdate-startup_time))), 60) ||' seconds' uptime
from v$instance
/

top

7.5 Wie groß sind meine Files, und wo legen sie ?

Zeigt die Größe und den Pfad der Data-Files, Redo-Files und Control-Files an

 
column tablespace_name format a25
column file_name format a40
col Mb format 9,999 heading "Size (Mb)"
 
select file_name,tablespace_name,bytes/1024/1024 Mb
from dba_data_files
  union all
select  member file_name,'log group '||a.group# tablespace_name
  ,b.bytes/1024/1024 Mb
from v$logfile a,v$log b
where a.group#=b.group#
  union all
select name file_name,'control file' tablespace_name,0 Mb
from v$controlfile
order by 2;

top

7.6 Ist eine Oracle Erweiterung (z.B: die Java-VM) installiert ?

Welche Optionen sind in einer Oracle-Datenbank installiert ?

Für manche Software-Projekte, die auf Oracle-Erweiterungen aufbauen (wie z.B: Java) ist es wichtig zu wissen ob die benötigte Erweiterung installiert ist (oder nicht).

Das kann man mit folgendem selet überprüfen:

SELECT COMP_ID, VERSION FROM DBA_REGISTRY;

Das Ergebnis sieht dann etwa folgendermaßen aus:

COMP_ID          VERSION
---------------- -------------------
CATALOG          9.2.0.5.0
CATPROC          9.2.0.5.0
OWM              9.2.0.5.0
JAVAVM           9.2.0.5.0

Im obigen Beispiel ist die Java VM installiert.

top

8. Nette und Nützliche SQL's

Hoffe ich jedenfalls

8.1 UNIX-Time in ein lesbares Datum umwandeln

Einfaches SQL um UNIX-Time lesbar zu machen:
 
SELECT  to_char(
  TO_DATE('01-JAN-1970','DD-MON-YYYY') + &unix_time/86400
  ,'dd-mon-yyyy hh24:mi:ss') normal_date
FROM dual;

top

9. Sonstiges

9.1 Welche Oracle-Produkte sind installiert

Man kann sich eine Liste aller Intallierter Oracle-Produkte mit Version durch ausführen eines der folgenden Befehle anzeigen lassen

Oracle 7 bis 8.0
cd $ORACLE_HOME/orainst
./inspdver

Oracle 8i und höher
cd $ORACLE_HOME/install
cat unix.rgs

top

9.2 Verhindern, das Datenbankobjekte gelöscht werden.

Falls einem ab und zu der Lieblingstrigger von Praktikanten gedropt wird....
kann dieser Trigger Abhilfe schaffen:
Zuerst muss eine Tabelle angelegt werden, in der die Namen der Ojekte gespeichert werden, die NICHT gedropt werden sollen:
CREATE TABLE SECURED_OBJECTS ( OBJECTNAME VARCHAR2(20));
Jetzt müssen wir nur noch den Trigger erzeugen:
CREATE OR REPLACE TRIGGER CHECK_BEFOREDROP
BEFORE DROP ON DATABASE
DECLARE
  ONAME CHAR(20);
BEGIN
  SELECT OBJECTNAME INTO ONAME FROM SECURED_OBJECTS
    WHERE UPPER(OBJECTNAME)=ORA_DICT_OBJ_NAME;
  IF SQL%FOUND THEN
    RAISE_APPLICATION_ERROR(-20001,'Du willst nicht, das dies gedropt wird !');
  END IF;
EXCEPTION
  WHEN NO DATA FOUND
  THEN DBMS_OUTPUT.PUT_LINE('Drop OK');
END;
/
Wunderbar ... alle Objekte (Trigger) deren Name jetzt in der Tabelle SECURED_OBJECTS eingetragen ist, können nicht mehr so einfach gedropt werden.

top

9.3 Anlegen der Tabelle EXPLAIN_PLAN

Diese Tabelle wird zu optimiertung der Zugriffe eines SQL's verwendet.

Falls diese Tabelle noch nicht angelegt ist findet sich unter Unix im Verzeichnis:
$ORACLE_HOME/rdbms/admin
oder unter Windows im Verzeichnis:
%%ORACLE_HOME%%/RDBMS80/admin
die Datei utlxplan.sql mit der die Tabelle angelegt werden kann.

top

9.4 Erzeugen View s DBA_BLOCKERS, DBA_WAITERS und DBA_LOCK

Locks sind etwas, das kein DBA in der Datenbank haben möchte. Daher bietet Oracle einige View, mit denen man die Ursache eines Locks aufspüren kann an.

Falls diese Viewse noch nicht vorhanden ist findet sich unter Unix im Verzeichnis:
$ORACLE_HOME/rdbms/admin
oder unter Windows im Verzeichnis:
%%ORACLE_HOME%%/RDBMS80/admin
die Datei catblock.sql mit der die Views angelegt werden können.
Diese Script sollte als SYS aufgerufen werden

top

9.5 Oracle Umgebungsvariblen

Hier sind ein paar Basis-ORACLE Umgebungsvariblen. Mehr Variablen können im Installation-Guide für Unix gefunden werden.

Variable Bedeutung
LD_LIBRARY_PATH Pfad zu dem Libraries z.B:
/usr/lib:/usr/openwin/lib:$ORACLE_HOME/lib:/usr/games/lib
ORACLE_BASE Voller Pfad yum Basis-Directory für alle Versionen und alle Oracle-Produkte.
ORACLE_HOME Voller Pfad zu der Version von Oracle die gerade benutzt wird. ORACLE_HOME ist normalerweise über dem ORACLE_BASE-Verzeichnis. Diese Variable wird verwendet um ausführbare Programme(und die Message-Files) zu lokalisieren.
ORACLE_SID O RACLE S erver S ystem identifier (SID) oder Instanz-Name. Der Datenbankname ist normalerweise die ORACLE_SID.
Diese Variable wird vom oraenv -Script gesetzt und wird von allen Oracle-Produkten ausgewertet.
ORACLE_PATH Definiert den Suchpfad für Dateien. Wenn ORACLE_PATH gesetzt ist, werden zuerst die in dieser Variable definierten Directories durchsucht, und danach erst das lokale Directory.
Falls ORACLE_PATH nicht gesetzt ist sucht die Applikation nur im momentanen Directory.
Diese Variable wird von SQL*Plus, Forms und Menu benutzt.
ORACLE_TERM Definiert ein Terminal. Falls nicht gesetzt, wird der Wert aus der TERM Umgebungs-Variable verwendet.
Diese Variable wird von alle Character-Mode Produkten von Oracle benutzt (svrmgrl ...).
ORAENV_ASK Das Script oraenv fragt nicht nach einer SID falls diese Variable auf NO gesetzt ist.
(z.B. automatisiertes Setzen der Oracle Umgebung in .bashrc ...)
TNS_ADMIN Definiert den Pfad, in dem Oracle nach den TNS ( T ransparent N etwork S ubstrate) Dateien suchen soll (z.B:TNSNAMES.ORA, SQLNET.ORA etc.)
ORACLE_TRACE Trace Oracle's Unix shell scripts as they execute (using set -x).
TWO_TASK Die TWO_TASK Umgebungs-Variable spezifiziertden Teil eines SQL*Net Connect-Strings der benötigt wird um sich zu einer entfernten Maschine zu verbinden (in einen Client/Server Configuration)
SQL*Net überprüft diese Variable und hängt sie automatisch an den Connect-String an.

> sqlplus scott/tiger@db1
ist das gleiche wie
> export TWO_TASK=db1
> sqlplus scott/tiger
top
  ©2016· Claus Ebert · Emailemail senden