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)
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
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.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.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.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
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.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
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.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
|