Zurück

Akadia Information Technology


Content

Partitionierung von Tabellen und Indexen
Slave-Prozesse
Offline-Redologfiles duplizieren
MAXDATAFILES und DB_FILES
Dynamische Grösse der Controlfiles
Multiple DB-Block Buffer Pool
Large Pool für MTS-Session Data und RMAN
Tablespace MINIMUM EXTENT
NOLOGGING (Kein Redo schreiben)
Neue Datentypen (BLOB, CLOB, BFILE)
Index only Tables (Index Organized Tables) IOT's
Reverse Key Indexes
Inline (Immediate) Views
DML-Return Werte
Index Fast Full Scans (FFS)
Neues ROWID Format
Index Rename
CONNECT als SYS
Remote CONNECT als SYS
Oracle Passwort Verification mit anpassbarer Routine
Deferred Constraints
ALTER TABLE MODIFY CONSTRAINT
ON DELETE SET NULL
Deferred PRIMARY KEYs und UNIQUE CONSTRAINTs
Enforced (Enable Novalidate) Constraints
Disable Validate
Aufruf einer Betriebssystem-Procedure aus PL/SQL auf lokalem oder remote Host
Parallele SELECTs
Parallele DMLs (INSERT, DELETE, UPDATE)
Bulk-Operationen mit dem Oracle-8 DBMS_SQL Package
Basic Object Types
Relationale und Object Tabelle ohne Memberfunktion
Object Tabelle mit Memberfunktion
Reference Types
Collection Types (VARRAY)
Collection Types (Nested Tables)
Unterschiede VARRAYs und Nested Tables
Object Views und Instead of Trigger
Recovery Manager RMAN

  

Partitionierung von Tabellen und Indexen

Siehe dazu die separate Dokumentation.

Slave-Prozesse

Der Oracle-7 INIT.ORA Parameter DB_WRITERS = n existiert nicht mehr. Neu existiert die Möglichkeit, sogenannte Slave Prozesse zu definieren für DBWR, LGWR und ARCH. Dies wird vorallem für stark I/O orientierte Systeme angewendet. Man beachte, dass der Checkpoint-Prozess, welcher unter Oracle-7 mit dem INIT.ORA Parameter CHECKPOINT_PROCESS aktiviert wurde, unter Oracle-8 immer aktiv ist. Der Parameter CHECKPOINT_PROCESS existiert also nicht mehr.

LGWR_IO_SLAVES = n (0 - n)
DBWR_IO_SLAVES = n (0 - n)
ARCH_IO_SLAVES = n (0 - n)

Offline-Redologfiles duplizieren

Neu ist es möglich, offline Redologfiles zu duplizieren, eine ausführliche Beschreibung und Anleitung zur Implementation finden Sie: hier.

MAXDATAFILES und DB_FILES

Der Parameter MAXDATAFILES beim CREATE DATABASE gab unter Oracle-7 öfters Probleme. Wollte man nämlich nachträglich die Anzahl DB-Files mit dem INIT.ORA Parameter DB_FILES vergrössern war dies nicht möglich, da MAXDATAFILES kleiner gesetzt war. Unter Oracle-8 ist dieses Problem behoben, da das Controlfile nun dynamisch wachsen kann. Das Maximum an DB-Files kann nun also mit dem INIT.ORA Parameter DB_FILES übersteuert werden. Man beachte, dass die Parameter MAXLOGMEMBERS und MAXLOGFILES nicht übersteuert werden können mit einem INIT.ORA Parameter. Man sollte diese also beim CREATE DATABASE genügend gross spezifizieren (mindestens 5).

Dynamische Grösse der Controlfiles

Die Oracle-8 Controlfiles beinhalten mehr Informationen, insbesondere wird das Repository des Recovery-Managers (RMAN) im Controlfile gespeichert um bei einem Verlust des RMAN-Repository die wichtigen Backup-Informationen weiterhin zur Verfügung zu haben. Wie lange zyklisch überschriebene Informationen im Controlfile verfügbar bleiben kann mit dem INIT.ORA Parameter CONTROL_FILE_RECORD_KEEP_TIME = n (0 - n Tage, Default = 7 Tage) gesteuert werden. Die Einträge im Controlfile findet man in V$CONTROLFILE_RECORD_SECTION.

Multiple DB-Block Buffer Pool

Unter Oracle-8 kann der DB-Buffer Pool in drei Bereiche unterteilt werden. Objekte können diesen Bereichen zugeteilt werden.

DB-Buffer Pool unter Oracle-8

Default

Normaler Bereich wie unter Oracle-7

Keep

Im Keep-Buffer versucht Oracle die gecachten Buffer in der SGA zu halten. Dies kann für häufig benutzte Tabellen angwendet werden (Lookup Tabellen)

CREATE TABLE keep_db_pool
  (test NUMBER NOT NULL)
  STORAGE (BUFFER_POOL keep INITIAL 10K NEXT 10K)
  TABLESPACE tab;

Recycle

Aus diesem Buffer entfernt Oracle die Blöcke sobald sie nicht mehr benötigt werden. Für grosse Tabellen mit kleiner Wahrscheinlichkeit, dass ein anderer User auf denselben Block zugreifen will. Vorallem für Tabellen welche mit Full-Table-Scans gelesen werden und kleiner als die Grösse von CACHE_SIZE_THRESHOLD sind.

CREATE TABLE keep_db_pool
  (test NUMBER NOT NULL)
  STORAGE (BUFFER_POOL recycle INITIAL 10K NEXT 10K)
  TABLESPACE tab;

Die Grösse der Buffer wird im INIT.ORA festgelegt.

Beispiel: 7000-1500-1000 = 4500 Default, 1500 Keep, 1000 Recycle.

db_block_buffers      = 7000
buffer_pool_keep     = (buffers:1500,lru_latches:1)
buffer_pool_recycle  = (buffers:1000,lru_latches:1)

Large Pool für MTS-Session Data und RMAN

Unter Oracle-7 gab es oft ORA-4031 Shared-Pool Probleme. Unterschiedlich grosse Objekte, vorallem grosse PL/SQL Packages führten zu Flushing-Problemen im Shared Pool. Wird zudem Multithreaded Server MTS eingesetzt, dessen Session Daten ebenfalls im Shared Pool sind verstärkt sich das Problem noch mehr. Unter Oracle-8 können die MTS-Session Daten in einen eigenen Pool, den Large-Pool ausgelagert werden. Ist ein solcher Pool definiert wird er automatisch für MTS und die I/O-Buffer für den RMAN (Recovery-Manager) verwendet.

Large Pool unter Oracle-8

Konfiguration:

large_pool_size       = n bytes/K/M  (0K - 2GB)
large_pool_min_alloc  = n bytes/K/M  (16K - 64M)

Tablespace MINIMUM EXTENT

Durch Setzen des neuen Storage Parameters MINIMUM EXTENT werden die Tablespaces weniger fragmentiert. Jedes kleinere Extent wird mindestens auf diesen Wert gerundet. In der Regel wird 64K definiert.

NOLOGGING (Kein Redo schreiben)

Unter Oracle-7 hiess der Parameter UNRECOVERABLE. Unter Oracle-8 heisst der Parameter neu NOLOGGING, er wurde auf weitere Anwendungen ausgeweitet (Tablespace, Table, Partition, Index)

  • Bestimmter Tablespace soll kein Redo schreiben, zB für SQL*Loader Direct Loads. Dadurch erhalten alle neu erstellten Tables, Indexe automatisch das Attribut NOLOGGING. Grundsätzlich ist es jedoch besser, diese Option auf Tabellen oder Index Ebene zu spezifizieren.

ALTER TABLESPACE temp_load NOLOGGING;

  • Index-Rebuild mit NOLOGGING

ALTER INDEX idx_big
REBUILD NOLOGGING PARALLEL (DEGREE 4)
STORAGE (INITIAL 128M, NEXT 16M)
TABLESPACE idx;

  • CREATE TABLE AS SELECT

CREATE TABLE emp_temp AS SELECT * FROM emp NOLOGGING;

Neue Datentypen (BLOB, CLOB, BFILE)

Folgende neuen Datentypen stehen zur Verfügung, BLOB, CLOB und BFILE. Ebenso steht ein Package DBMS_LOB zur Verfügung um das Handling mit diesen Daten zu erleichtern.

  • BLOB (Unstrukturierte binäre Daten wie Videos)
  • CLOB (Unstrukturierte Texte)
  • BFILE (Binary LOB ausserhalb der Datenbank)

LOB Datentypen haben immer zwei Komponenten:

  • LOB Value: Actuelle Daten des LOBs, solange diese < 4K sind werden sie mit der Tabelle gespeichert, bei > 4K LOB Daten, werden diese in einem eigenen Segment gespeichert. BFILE sind immer extern und unterliegen nicht dieser Regel.
  • LOB Locator: Pointer auf die wirklichen LOB-Daten.

Erstellen eines BLOB / CLOB:

CREATE TABLE book (
  title       VARCHAR2(40),
  author      VARCHAR2(40),
  text        CLOB,
  author_pic  BLOB)
  LOB(text,author_pic) STORE AS(
    STORAGE(INITIAL 1M NEXT 1M PCTINCREASE 0)
    CHUNK 50
    PCTVERSION 30
    NOCACHE LOGGING
    INDEX (STORAGE (INITIAL 1M NEXT 1M))

);

Erstellen eines BFILEs:

CREATE TABLE word_processing_docs (
  doc_name    VARCHAR2(100),
  doc_content BFILE);

CREATE OR REPLACE DIRECTORY wp_docs
  AS '/data/docs/wp_docs';

GRANT READ ON DIRECTORY wp_docs TO ppb;

Es wird erst beim Zugriff auf das Directory mittels des Package DBMS_LOB geprüft ob das Directory vorhanden ist. BFILES können nur gelesen werden, nicht geschrieben, sie werden durch Betriebssystem Tools erstellt.

Index only Tables (Index Organized Tables) IOT's

Für Tabellen bei denen die meisten Attribute im Index sind (zB Intersection Tabellen) bieten IOT's Performance Vorteile. Einzelne, weniger häufig benutzte Attribute können zudem in einem Overflow Tabespace gespeichert werden. IOT's brauchen zwingend einen Primary Key, da sie keine ROWID mehr besitzen. Sehr hohe Performance bei ORDER BY auf dem Primary Key. Zur Zeit können IOT's nicht repliziert werden. Es existiert das Package DBMS_IOT um beispielsweise ein ANALYZE auf IOT' durchzuführen.

CREATE TABLE my_intersection (
  id1 NUMBER(15) NOT NULL,
  id2 NUMBER(15) NOT NULL,
  job VARCHAR2(500) NULL,
    CONSTRAINT pk_my_intersection
    PRIMARY KEY (id1,id2))
ORGANIZATION INDEX
STORAGE (INITIAL 1M NEXT 250K PCTINCREASE 0)
TABLESPACE idx
INCLUDING job
OVERFLOW TABLESPACE tab;

Reverse Key Indexes

Die Bytes der Attribute werden umgedreht, was zur Folge hat, dass Hotspots bei einem ständigen UPDATE an der gleichen Stelle im Index verhindert werden können.

CREATE INDEX deptno_ename ON emp (deptno, ename) REVERSE;

Inline (Immediate) Views

Inline Views sind zwar keine Neuerung von Oracle-8, sie existieren bereits seit Oracle-7.2. Auf diese Weise können Views "on the Fly" angelegt werden. Damit können auch User, welche keine Views anlegen können, Views benutzen. Ein einfaches Beispiel: Die Anzahl Rows von emp und dept sollen auf einer Zeile dargestellt werden; anhand zweier inline Views die in der FROM Klausel definiert werden, kann dies erreicht werden.

SELECT e.emp_count, d.dept_count
  FROM (SELECT COUNT(*) emp_count FROM emp) e,
       (SELECT COUNT(*) dept_count FROM dept) d;

DML-Return Werte

Oracle 8 bietet die Möglichkeit, dass DML-Befehle einen Return-Wert liefern. Dies ist aus der Sicht des Applikationsentwicklers besonders interessant. Zuerst denkt man sofort an das INSERT Problem, welches nun elegant gelöst werden kann. Unter Oracle-7 musste man zuerst ein INSERT machen, die Applikation liest dann den eingefügten Wert wieder mit einem SELECT, damit die Row gesperrt werden kann in der Maske. Mit Oracle-8 macht man ein INSERT und verlangt die ROWID als Return-Wert. Jeder Wert kann zurückverlangt werden, sinnvoll sind natürlich Werte, die der Applikation nicht bekannt sind weil sie durch Orcale generiert werden.

set serveroutput on;
DECLARE
  local_rowid ROWID;
BEGIN
  INSERT INTO dept (deptno,dname,loc)
  VALUES (99,'Akadia AG','Seftigen')
  RETURNING ROWID INTO local_rowid;
  dbms_output.put_line('local_rowid: ' || ROWIDTOCHAR(local_rowid));
END;

Index Fast Full Scans (FFS)

Oracle-7 liest einen Index immer Block für Block, dadurch kann kein Multiblock-Read gemacht werden, da die physische Speicherung nicht der logischen Sortierung entsprechen muss. Oracle-8 kann nun einen Full Table Scan durch einen Fast Full Index Scan ersetzen. Dies unter den folgenden Bedingungen

  • Alle Attribute des Befehls müssen im Index sein
  • Index muss mindestens ein NOT NULL Attribut beinhalten
  • Kein ORDER BY im SELECT Statement

Die Aktivierung erfolgt für den COST based Optimizer mittels Hint /*+ Index_FFS (table index) */. Insbesondere sind SELECT COUNT(*) Abfragen durch den FFS schneller.

SELECT /*+ Index_FFS(grosse_tabelle my_index) */ COUNT(*)
  FROM grosse_tabelle;

Neues ROWID Format

Die Oracle-8 ROWID unterscheidet sich wesentlich von der Oracle-7 ROWID. Sie hat zum Ziel Partitionen und Objektrelationale Objekte zu unterstützen. Die Änderung ist selbstverständlich vollständig transparent für bestehende Applikationen.

select rowid,ename from emp where deptno = 10;

ROWID              ENAME
------------------ ----------
AAAAl8AAFAAAAA/AAG CLARK
AAAAl8AAFAAAAA/AAI KING
AAAAl8AAFAAAAA/AAN MILLER

Aufbau:

  • OOOOOOFFFBBBBBBSSS
  • O = Datenobject Nummer
  • F = File Nummer
  • B = Block Nummer
  • S = Slot Nummer im Block

Um das Handling mit der neuen ROWID zu erleichern stellt Oracle das Package DBMS_ROWID zur Verfügung mit den Functionen: ROWID_CREATE, ROWID_INFO, ROWID_TO_RESTRICTED, ROWID_TO_EXTENDED, ROWID_VERIFY.

Index Rename

Nun kann (endlich) auch ein Index umbenennt werden !

alter index PRICE_INDEX rename to PRICE_INDEX1;

CONNECT als SYS

Mittelfristig will Oracle das altbekannte CONNECT INTERNAL als hochprivilegierter DBA unterbinden. Folgender Ausschnitt stammt aus dem Oracle8i README:

CONNECT INTERNAL DESUPPORT
--------------------------
CONNECT INTERNAL is currently supported for backwards compatibility only.
It will be completely desupported in a maintenance release after
Oracle 8.1, so that CONNECT INTERNAL may no longer be used to connect to
Oracle. If you have not done so already, you should plan to migrate your
applications to use other connection syntax.

Mit dem neuen INIT.ORA Parameter

O7_DICTIONARY_ACCESSIBILITY = TRUE

kann bereits jetzt ein Passwortfile für den Account SYS erzwungen werden. Mit der Oracle Rolle SYSDBA kann nun jeder beliebige Oracle User "SYS" Rechte bekommen, er muss aber im Passwortfile aufgenommen werden, was durch das Erteilen der SYSDBA Rolle automtisch erfolgt. Alle SYSDBA User haben dann also das gleiche Passwort für den "SYS" Account.

Erstellen des "SYS" Passwortfiles:

NT:   orapwd80 file=D:\Orant\Database\pwdDOR1.ora password=manager entries=5
UNIX: orapwd file=$ORACLE_HOME/dbs/orapwd password=manager entries=5

Vergeben der SYSDBA oder SYSOPER Rolle an "normalen" Oracle User:

GRANT SYSDBA to scott;
CONNECT scott/tiger;           /* Normaler Connect */
CONNECT scott/tiger as SYSDBA; /* Privilegierter Connect für SHUTDOWN etc /*

Remote CONNECT als SYS

Wenn ein "SYS" Passwortfile auf einer DB vorhanden ist, so kann man von Remote aus, via SQL*Net diese DB als SYS administrieren sofern der INIT.ORA Parameter

REMOTE_LOGIN_PASSWORD_FILE = EXCLUSIVE

gesetzt wird. Das folgende Beispiel verdeutlicht dies (Beachte auch die wichtige View v$pwfile_users)

SVRMGR> connect sys/manager@RAB1 as sysdba;
Connected.
SVRMGR> select * from v$pwfile_users;

USERNAME                        SYSDB SYSOP
------------------------------ ----- -----
INTERNAL                         TRUE   TRUE
SYS                              TRUE   TRUE
SCOTT                            TRUE FALSE

Oracle Passwort Verification mit anpassbarer Routine

Siehe dazu den eigenen Artikel: Oracle Passwort Verification mit anpassbarer Routine

Deferred Constraints

Unter Oracle-7 sind Constraintverletzungen nur innerhalb eines Statments möglich, dies ist oft etwas einschränkend, vorallem bei einem CASCADE UPDATE. Unter Oracle-8 können Constraints nun so definiert werden, dass diese erst beim COMMIT überprüft werden, man nennt dies deferred. Jedes Constraint bestimmt beim Anlegen ob es immediate (Defualt) oder deferred ist. Ist es deferred, so kann später mittels SET CONSTRAINT das Constraint auf deferred oder immediate geändert werden.

Anlegen eines deferred / immediate Constraints

Ein Constraint kann logischerweise nicht den Zustand NOT DEFERRABLE INITIALLY DEFERRED annehmen.

alter table emp
  add constraint fk_deptno
  foreign key(deptno) references dept (deptno)
  deferrable initially immediate;

alter table emp
  add constraint fk_deptno
  foreign key(deptno) references dept (deptno)
  deferrable initially deferred;

alter table emp
  add constraint fk_deptno
  foreign key(deptno) references dept (deptno)
  not deferrable initially immediate;

alter table emp
  add constraint fk_deptno
  foreign key(deptno) references dept (deptno)
  not deferrable initially deferred;

ERROR at line 3:
ORA-02447: cannot defer a constraint that is not deferrable

Cascade Update als Beispiel

  • Normales Verhalten mit not deferrable initially immediate (Oracle-7)

SQL> update dept set deptno = 21
               where deptno = 20;

ERROR at line 1:
ORA-02292: integrity constraint (SCOTT.FK_DEPTNO) violated
child record found

  • Nun wird das Constraint auf "deferrable initially immediate" gesetzt (Oracle -8)

SQL> set constraint fk_deptno deferred;

Constraint set.

SQL> update dept set deptno = 21 where deptno = 20;

1 row updated.

Datenbank ist jetzt inkonsistent.

SQL> update emp set deptno = 21 where deptno = 20;

5 rows updated.

SQL> commit;

Commit complete.

SQL> set constraint fk_deptno immediate;

Constraint set.

Mit SET CONSTRAINT kann also später ein beliebiges oder alle Constraints auf deferred oder immediate gesetzt werden, hier das Syntax Diagramm.

ALTER TABLE MODIFY CONSTRAINT (Oracle 8.1.5)

With Oracle 8i it's possible to modify the state of an existing constraint. For example change from INITIALLY DEFERRED to INITIALLY IMMEDIATE.

ALTER TABLE emp MODIFY CONSTRAINT emp_foreign_key INITIALLY IMMEDIATE;

ON DELETE SET NULL  (Oracle 8.1.5)

determines how Oracle automatically maintains referential integrity if you remove a referenced primary or unique key value. If you omit this clause, Oracle does not allow you to delete referenced key values in the parent table that have dependent rows in the child table

  • CASCADE specifies that Oracle removes dependent foreign key values.
  • SET NULL specifies that Oracle converts dependent foreign key values to NULL.

alter table emp
  add constraint fk_deptno
  foreign key(deptno) references dept (deptno)
  on delete set NULL;

Deferred PRIMARY KEYs und UNIQUE CONSTRAINTs

Unter Oracle-7 und 8 wird bekanntlich beim Anlegen eines PRIMARY KEY und UNIQUE CONSTRAINT automatisch ein UNIQUE INDEX angelegt. So weit so gut, beim Disablen des PRIMARY KEY / UNIQUE CONSTRAINT wird der Index von Oracle ebenfalls automatisch gedroppt. Bei sehr grossen Tabellen ist dies ein Problem, da es stundenlang dauern kann bis der PRIMARY KEY / UNIQUE CONSTRAINT wieder aufgebaut ist. Oracle-8 bietet nun neu die Möglichkeit auch PRIMARY KEYs / UNIQUE CONSTRAINTs als DEFERRED anzulegen. Der grosse Vorteil besteht darin, das kein UNIQUE INDEX angelegt wird und dass dieser beim Disablen nicht gedroppt wird. Man kann auch bei sehr grossen Tabellen diesen PRIMARY KEY / UNIQUE CONSTRAINT sehr rasch wieder aktivieren, da der Index bereits besteht.

Nachfolgend ein Beispiel:

  • DEFERRED PRIMARY KEY anlegen

  • ALTER TABLE emp ADD (
      CONSTRAINT pk_emp
      PRIMARY KEY (empno)
      DEFERRABLE INITIALLY DEFERRED
      USING INDEX
        TABLESPACE idx
        STORAGE
          (INITIAL 100K
           NEXT 100K
           MINEXTENTS 1
           MAXEXTENTS UNLIMITED
           PCTINCREASE 0
           FREELISTS 2)
          )
    /

  • Controlle der Constraints EMP

  • select c.constraint_name,
        i.search_condition,
        c.table_name,
        c.column_name,
        i.r_constraint_name,
        i.status
    from user_cons_columns c,
    user_constraints i
    where i.table_name = c.table_name
    and i.constraint_name = c.constraint_name
    and c.table_name = 'EMP';

    Constraints of Tabelle: EMP

    Constraint                                         Column
    Name                     Text                      Name
    ------------------------ ------------------------- ---------------
    NN_EMPNO                 EMPNO IS NOT NULL         EMPNO
    PK_EMP                                             EMPNO

  • Controlle der Indexe auf EMP

  • select i.table_owner,
           i.index_name,
           c.table_name,
           c.column_name,
           decode(i.uniqueness,'UNIQUE','YES','NONUNIQUE','NO','???') uni,
           i.tablespace_name
    from user_ind_columns c, user_indexes i
    where i.table_name = c.table_name
    and i.index_name = c.index_name
    and i.table_name like upper('EMP');

    Indexes of Tabelle: EMP

    Table      Index               Column              Uniq-
    Owner      Name                Name                ness  Tablespace
    ---------- ------------------- ------------------- ----- ----------
    SCOTT      PK_EMP              EMPNO                NO    IDX

    Beachte, dass der Index auf dem Primary Key NON UNIQUE ist !

  • Nun wird der PRIMARY KEY disabled

  • ALTER TABLE EMP DISABLE CONSTRAINT pk_emp;

  • Erneute Kontrolle der Constraints auf EMP

  • Constraint   Column          Reference
    Name         Name            Constraint      Status
    ------------ --------------- --------------- ----------
    PK_EMP       EMPNO                            DISABLED

  • Erneute Kontrolle der Indexe auf EMP

  • Indexes of Tabelle: EMP

    Table      Index               Column              Uniq-
    Owner      Name                Name                ness  Tablespace
    ---------- ------------------- ------------------- ----- ----------
    SCOTT      PK_EMP              EMPNO                NO    IDX

    Beachte, dass der Index auf dem Primary Key noch vorhanden ist !

Fazit

Oracle-8 erstellt bei DEFERRED Primary Keys und Unique Indexen ein NON Unique Index, der bei einem DROP/DISABLE des Constraints nicht gedroppt wird. Ein nachfolgendes Enablen oder Neuanlegen des Constraints erfolgt dadurch viel schneller, da der Index nicht erneut aufgebaut werden muss. Oracle garantiert die Uniqness also auch mit NON Unique Indexen !

Enforced (Enable Novalidate) Constraints

Oracle-7 Constraints sind entweder enabled oder disabled:

  • Enabled heisst:
     

    • Das Constraint ist aktiv
    • Bestehende Daten sind geprüft und korrekt
    • Neue Daten werden geprüft
       
  • Disabled heisst:
     

    • Das Constraint ist deaktiviert, aber im Datadictionary noch vorhanden
    • Bestehende Daten können falsch sein
    • Neue Daten werden nicht geprüft

Dieser Sachverhalt hat einen grossen Nachteil. Befinden sich in einer (sehr grossen) Tabelle nur einige wenige Rows die das Constraint verletzen, so kann das Constraint nicht rasch wieder enabled werden. Falsche Rows können also weiterhin eingefügt werden. Man möchte aber oft, das neue Rows geprüft werden, bestehende aber (noch) falsch sein dürfen. Diese "falschen" Rows werden dann in einer ruhigen Minute korrigiert und dann wird das Constraint wieder enabled. Genau dies ermöglicht das neue Constraint unter Oracle-8: ENABLE NOVALIDATE.

  • Enable Novalidate heisst:
     

    • Bestehende Daten können falsch sein
    • Neue Daten werden geprüft

Beispiel Datenload

ALTER TABLE emp DISABLE CONSTRAINT check_salary;

Datenload durchführen

ALTER TABLE emp ENABLE NOVALIDATE CONSTRAINT check_salary;

Ab diesem Zeitpunkt werden neue Daten sofort wieder geprüft.

Disable Validate (Oracle 8.1.5)

  • Das Constraint ist weiterhin aktiv, aber der UNIQUE bzw PRIMARY Key Index ist gelöscht.
  • Sinnvoll für schnellen Datenload, Daten werden geprüft.

ALTER TABLE emp DISABLE VALIDATE CONSTRAINT emp_primary_key CASCADE;

Primary Key Index ist gelöscht
Constraint ist weiterhin aktiv

insert into emp (empno,deptno) values (7369,10);

ORA-25128: No insert/update/delete on table with
  constraint (SCOTT.EMP_PRIMARY_KEY) disabled and validated

Datenload durchführen

ALTER TABLE emp ENABLE NOVALIDATE CONSTRAINT emp_primary_key;

Ab diesem Zeitpunkt werden neue Daten sofort wieder geprüft.

Aufruf einer Betriebssystem-Procedure aus PL/SQL auf lokalem oder remote Host

Siehe dazu die separate Dokumentation.

Parallele SELECTs

Oracle-7 konnte nur SELECTs parallelisieren, in Oracle-8 können zusätzlich auch Table-Partitionen von parallelen SELECTs profitieren. Neu kann Oracle-8 auch DML-Kommandos parallel ausführen.

INIT.ORA Parameter welche gesetzt werden müssen für die Parallel Query Option

parallel_min_server

The minimum number of parallel processes created at instance startup to be used by the parallel operations in the database. This pool remains available for the life of the instance.

parallel_max_servers

The maximum number of parallel processes that can be created for the instance of any time to be used by parallel operations. The system creates the additional processes when all the parallel processes in the initial pool are being used by various parallel operations and a new operation has requested parallel execution.

parallel_server_idle_time

The amount of time an additional spawned parallel process can remain idle before it is terminated (provided the size of the query server pool remains at least the value of the parallel_min_servers).

parallel_min_percent

The minimum percentage of requested parallel processes that must be available in order for the operation to execute in parallel. I recommend at least 50 percent.

Beispiele-1: Auf Tabellenstufe, Overhead ist relativ gross, deshalb nur auf einem DSS so ausführen

ALTER TABLE emp PARALLEL DEGREE (5);

SELECT durchführen

ALTER TABLE emp NOPARALLEL;

Beispiel-2: Gezielt für ein bestimmtes SELECT Statement (empfohlene Methode)

SELECT /*+ PARALLEL (emp,5) */ *
FROM emp;

Parallele DMLs (INSERT, DELETE, UPDATE)

Unter Oracle-8 ist es nun möglich auch parallele DMLs durchzuführen. Dabei gibt es eine Reihe von Randbedingungen zu berücksichtigen, ansonsten wird das DML-Kommando nicht parallel ausgeführt.

Parallele SELECTS werden über die ROWID ausgeführt.

Parallele UPDATEs und DELETEs sind nur auf Partitionen möglich.

Parallele INSERTs nur in Zusammenhang mit SELECT, durch Starten mehrerer I/O Prozess

Einschränkungen, Regeln für Parallele DMLs

  • INSERT muss von der Form INSERT INTO table_name SELECT  .... sein
  • Table muss mit ALTER TABLE table_name PARALLEL; aktiviert worden sein, oder man verwendet einen Hint: INSERT /*+ PARALLEL (emp,2) */ INTO SELECT ....
  • Parallelele INSERTs an normalen und partitionierten Tabellen möglich.
  • Parallele UPDATEs und DELETEs nur an partitionierten Tabellen möglich.
  • Nach einem parallelen Insert muss sofort ein COMMIT folgen, ansonsten ORA-12838

Der Ablauf eines parallelen DMLs erfolgt in folgenden fix vorgegebenen Schritten:

1). Parallel DML enablen

ALTER SESSION ENABLE PARALLEL DML;

2). Paralleles DML durchführen, zB

CREATE TABLE emp_new AS
SELECT * FROM emp
WHERE 1 = 2;

INSERT /*+ PARALLEL (emp_new,5) */
INTO emp_new
SELECT /*+ PARALLEL (emp,2) */ *
FROM emp;

COMMIT;

3). Parallel DML disablen

ALTER SESSION DISABLE PARALLEL DML;

Bulk-Operationen mit dem Oracle-8 DBMS_SQL Package

Nebst vielen anderen Verbesserungen betreffend PL/SQL in Oracle-8 wie beispielsweise PRAGMAS (Packages auch in User Defined Functions verwenden), DEBUG-Package (DBMS_DEBUG), weitere Packages (DBMS_IOT, DBMS_RANDOM, etc) sind sicher die Bulk-Operationen mit dem Package DBMS_SQL von besonderer Bedeutung. Anstelle von LOOP-Programmierung wird der DBMS_SQL.Varchar2_Table Datentyp verwendet um (viele) Datenwerte darin abzuspeichern und dann mit einer Operation zu verarbeiten.

Im folgenden Beispiel wird ein UPDATE mit allen Werten die der Bind-Variablen ThisEname zugeordnet sind durchgeführt. Mittels DBMS_SQL.Bind_Array, werden die Werte in vEmps mit ThisEname gekoppelt.

DECLARE
  vCursor INTEGER := DBMS_SQL.Open_Cursor;
  vCount INTEGER;
  vStatement VARCHAR2(2000);
  vEmps DBMS_SQL.Varchar2_Table;
BEGIN
  vStatement := 'UPDATE emp SET sal = sal + 1' ||
                ' WHERE ename = :ThisEname';
  vEmps(1) := 'KING';
  vEmps(2) := 'MILLER';
  vEmps(3) := 'HUBER';
  vEmps(4) := 'SCOTT';
  vEmps(5) := 'ADAMS';

  BEGIN
    DBMS_SQL.Parse(vCursor,vStatement, DBMS_SQL.Native);
    DBMS_SQL.Bind_Array(vCursor,'ThisEname',vEmps);
    vCount := DBMS_SQL.Execute(vCursor);
    DBMS_SQL.Close_Cursor(vCursor);
    DBMS_OUTPUT.PUT_LINE('vCount = ' || TO_CHAR(vCount));
  END;
END;

Basic Object Types

Object Types ermöglichen die Definition von eigenen Datentypen. Nach der Definition können diese neue Datentypen in normalen relationalen Tabellen oder in Object Tabellen benutzt werden. Man unterscheidet drei Arten von Object Types:

  • Simple Types, enthalten alle scalar, collector und reference Typen vin Oracle-8
  • Composite Object Types, enthalten auch andere Object Types
  • Self Referencing Types, enthalten sich selber

Object Types enthalten normalerweise auch Memberfunktionen, sie weisen eine Ähnlichkeit mit dem Package Konzept auf. Nachfolgend ein Beispiel eines Object Types mit einer Memberfunktion.


Relationale und Object Tabelle ohne Memberfunktion

--
-- Erstellen des simple Object Types
--

CREATE TYPE paycheck_type AS OBJECT (
  check_number           NUMBER(20),
  payer                  VARCHAR2(40),
  payee                  VARCHAR2(40),
  date_issued            DATE,
  payment_authorization  VARCHAR2(10),
  payer_account_number   VARCHAR2(20),
  routing_number         VARCHAR2(20),
  payment_amount         NUMBER(10));

--
-- Relationale Tabelle mit Object Type ohne Memberfunktion
--

DROP TABLE paycheck_tab;
CREATE TABLE paycheck_tab (
  empid                  VARCHAR2(10)     NOT NULL,
  emp_check              paycheck_type,
CONSTRAINT pk_paycheck_rel
PRIMARY KEY (empid));

-- Daten einfügen

To insert data into an object column, the user must refer to the object type that defines the column. This reference is called a constructor. The constructor is used for insertion of data into object tables as well. The use of insert statements on a relational and object table with use of constructors is listed in the following code block

INSERT INTO paycheck_tab
  VALUES (39283,
  paycheck_type (4596854,'Acme','HANSON',
  TO_DATE('14.07.2001','DD.MM.YYYY'),'YES','59439585','00584857479',2016));

-- Zugriff auf Element des Object Types

SELECT p.emp_check.check_number
  FROM paycheck_tab p
  WHERE empid = 39283;

--
-- Object Tabelle mit Object Type ohne Memberfunktion
--

DROP TABLE paycheck_obj;
CREATE TABLE paycheck_obj
  OF paycheck_type;

-- Daten einfügen

INSERT INTO paycheck_obj
  VALUES (
  paycheck_type (4596854,'Acme','HANSON',
  TO_DATE('14.07.2001','DD.MM.YYYY'),'YES','59439585','00584857479',2016));

-- Zugriff auf Element des Object Types

SELECT check_number FROM paycheck_obj
  WHERE routing_number = '00584857479';


Object Tabelle mit Memberfunktion

The other component of an object is the set of methods that can be used to operate on it. Each method is a member function that contains input parameters and output values in the same way that procedures and functions have. In fact, the methods of an object are procedures and functions developed to operate specifically on the attributes defined as part of the object type. Unlike in Oracle7, however, where tables and procedures are designed, stored, and used separately, member functions and procedures are defined directly within the object type

--
-- Erstellen des simple Object Types mit Memberfunktion
--

DROP TYPE payroll_type;
CREATE TYPE payroll_type AS OBJECT (
  check_number               NUMBER(20),
  payer                      VARCHAR2(40),
  payee                      VARCHAR2(40),
  date_issued                DATE,
  payment_authorization     VARCHAR2(10),
  payer_account_number      VARCHAR2(20),
  routing_number             VARCHAR2(20),
  payment_amount             NUMBER(10),
  MEMBER FUNCTION adjust_amount (p_number  IN NUMBER,
                                 p_amount IN NUMBER) RETURN NUMBER,
  PRAGMA RESTRICT_REFERENCES (adjust_amount, WNDS));

Though not necessary, the developer can identify whether the type methods will modify database tables or not using the pragma restrict_references clause. The developer must identify the procedure or function that restrict_references refers to and the restrictions on the references of the procedure or function. In this case, wnds was used, which stands for "write no database state." Once the type is defined both with attributes and methods, then the developer can create the code body for the procedures, defined separately in the type body.

-- Memberfunktion codieren

DROP TYPE BODY payroll_type;
CREATE TYPE BODY payroll_type AS MEMBER FUNCTION adjust_amount
  (p_number IN NUMBER,
   p_amount IN NUMBER) RETURN NUMBER IS
  BEGIN
    RETURN p_number - p_amount;
  END;
END;

-- Object Tabelle erstellen

DROP TABLE payroll_obj;
CREATE TABLE payroll_obj
  OF payroll_type;

-- Object Tabelle mit Daten füllen

INSERT INTO payroll_obj
  VALUES (
  payroll_type (4596854,'Acme','HANSON',
  TO_DATE('14.07.2001','DD.MM.YYYY'),'YES','59439585','00584857479',2016));

-- Memberfunktion benutzen

The applications can then refer to the methods for an object type using the same dot notation used to reference the attributes. The following PL/SQL statement demonstrates the use of a method from the PAYROLL type to update the data in an attribute. The value( ) operation in the following PL/SQL block is designed to return all attribute values stored in an object so that those values may be placed into a variable declared to be the same type as the object table.

set serveroutput on;
DECLARE
  my_payroll    payroll_type;
  my_pay_amount NUMBER(10);
BEGIN
  --
  SELECT VALUE(p)
    INTO my_payroll
    FROM payroll_obj p
   WHERE check_number = 4596854;
  --
  DBMS_OUTPUT.PUT_LINE('my_payroll.payer = ' || my_payroll.payment_amount);
  --
  UPDATE payroll_obj
     SET payment_amount = my_payroll.adjust_amount(my_payroll.check_number,200)
   WHERE check_number = my_payroll.check_number;
  --
  SELECT VALUE(p)
    INTO my_payroll
    FROM payroll_obj p
   WHERE check_number = 4596854;
  --
  DBMS_OUTPUT.PUT_LINE('my_payroll.payer = ' || my_payroll.payment_amount);
  --
END;

Reference Types

So far, all object types discussed have been simple types containing attributes declared with all scalar datatypes. Oracle8 also allows the definition of two new classes of datatypes, called reference types and collection types. These two datatypes are designed to allow object types to have referential integrity on a one-to-one and one-to-many level. However, reference and collection types extend the concept of referential integrity to a new level. In relational databases, foreign keys provide referential integrity between columns of the same datatype containing the same data. Reference datatypes are used to provide a one-to-one relationship between a row of an object table or object type column of a relational table and another object table or object type column of a relational table. Collection types are designed to store a grouping or collection of like-structured elements, to provide a one-to-many relationship in the same situation. This section will explain reference and collection types in further detail and provide syntax and examples for the creation of each.

-- Create Object Type

DROP TYPE paycheck_type;
CREATE TYPE paycheck_type AS OBJECT (
  check_number            NUMBER(20),
  payer                   VARCHAR2(40),
  payee                   VARCHAR2(40),
  date_issued            DATE,
  payment_authorization  VARCHAR2(10),
  payer_account_number   VARCHAR2(20),
  routing_number         VARCHAR2(20),
  payment_amount         NUMBER(10));

-- Create Oject table

DROP TABLE paycheck_obj;
CREATE TABLE paycheck_obj
  OF paycheck_type;

-- Daten einfüllen

INSERT INTO paycheck_obj
  VALUES (
  paycheck_type (4596854,'Acme','HANSON',
  TO_DATE('14.07.2001','DD.MM.YYYY'),'YES','59439585','00584857479',2016));

-- Reference Typ erstellen mit Referenz auf paycheck_type

Developers can use the reference type to define a "foreign key relationship" between two objects. The reference type can reference all columns in the table for a particular row—it is a pointer to a particular object within an object table. The definition of a reference type should include a definition of scope—the table to which the reference type will refer. A special keyword called REF should be used for defining the reference type. The definition of the reference type is demonstrated with the following code block:

CREATE TYPE debit_type AS OBJECT (
  acc_wd_num  NUMBER(10),
  debit REF    paycheck_type);

-- Create Object Table mit Verwendung der Referenz

CREATE TABLE debit_obj
  OF debit_type
  (SCOPE FOR (debit) IS paycheck_obj);

-- Daten einfüllen

INSERT INTO debit_obj
  SELECT 1, REF(pc)
    FROM paycheck_obj pc
   WHERE pc.check_number = 4596854;

-- Daten abfragen (Achtung DEREF benutzen, sonst wird Pointer zurückgegeben)

Selecting the reference type itself using the ref( ) operation produces not the data in the object, but the pointer used to refer to the object. The user can use the pointer value created as the reference type and execute a special function called deref( ) to produce the actual values from the pointer to those values.

SELECT acc_wd_num,DEREF(d.debit)
  FROM debit_obj d
WHERE d.debit.check_number = 4596854;

Collection Types (VARRAY)

Objects can be collected into types. A collection is a gathering of like-defined elements. The two types of collection types available in Oracle8 are variable-length arrays with the VARRAY type and nested tables with the TABLE type. Focus first on VARRAYs. A VARRAY can be thought of as a "list" of objects, defined to have two special attributes in addition to those attributes contained in each of the objects contained therein, called a count for the number of elements in the VARRAY, and the limit for the maximum number of elements that can appear in a VARRAY. The limit is user defined, and if the number of elements stored in the VARRAY exceeds 4K, Oracle will store the data in the VARRAY in overflow. If the amount of data stored in the VARRAY is less than 4K, the data will be stored with the rest of the information for the object. Constraints and default values may not be created for elements in a VARRAY, and once created, the user only refers to an individual element in a VARRAY with PL/SQL (although SQL can be used to access the entire VARRAY).

DROP TABLE staff;
DROP TYPE staff_type;
DROP TYPE phone_array;
DROP TYPE phone_type;

-- Object Type erstellen

CREATE TYPE phone_type AS OBJECT (
  location   VARCHAR2(20),
  phone_num  VARCHAR2(10));

-- VARRAY erstellen

CREATE TYPE phone_array AS VARRAY(10)
  OF phone_type;

-- Object Type mit VARARY erstellen

CREATE TYPE staff_type AS OBJECT (
  empid   VARCHAR2(10),
  name    VARCHAR2(40),
  phone   phone_array);

-- Object Table erstellen welche den VARARY benutzt

CREATE TABLE staff
  OF staff_type;

-- Daten einfüllen

INSERT INTO staff VALUES
  ('1234','Zahn',phone_array(phone_type('Seftigen','3450240')));

INSERT INTO staff VALUES
  ('1235','Steiner',phone_array(phone_type('Linden','4857664')));

INSERT INTO staff VALUES
  ('1236','Gächter',phone_array(phone_type('Spiez','209876')));

INSERT INTO staff VALUES
  ('1237','Müller',phone_array(phone_type('Thun','3450239')));

INSERT INTO staff VALUES
  ('1238','Hodel',phone_array(phone_type('Bern','5986')));

Collection Types (Nested Tables)

The other collection type is the nested table. A nested table is exactly that—a table within a table. The nested table architecture is exceptionally suited for applications that in Oracle7 have parent/child tables with referential integrity.

--
-- Nested Tables
--

CREATE TYPE phone_type AS OBJECT (
  location   VARCHAR2(20),
  phone_num  VARCHAR2(10));

-- Object Type erstellen

CREATE TYPE phone_tab AS TABLE
  OF phone_type;

-- Nested Table erstellen

CREATE TABLE staff (
  empid         VARCHAR2(10),
  name          VARCHAR2(40),
  phone_details phone_tab)
NESTED TABLE phone_details STORE AS phone_details_tab;

-- Daten einfüllen

INSERT INTO staff VALUES
  ('1234','Zahn',phone_tab(phone_type('Seftigen','3450240')));

INSERT INTO staff VALUES
  ('1235','Steiner',phone_tab(phone_type('Linden','4857664')));

INSERT INTO staff VALUES
  ('1236','Gächter',phone_tab(phone_type('Spiez','209876')));

INSERT INTO staff VALUES
  ('1237','Müller',phone_tab(phone_type('Thun','3450239')));

INSERT INTO staff VALUES
  ('1238','Hodel',phone_tab(phone_type('Bern','5986')));

Nested tables and variable-length arrays share many similarities, but also have many differences. The differences between the nested table and a variable-length array can be identified as follows. The VARRAY works well for storing like units of information. These units ideally have few attributes, all of which may be populated and to which a specific order can be placed. Consider the example given of employee annual paycheck information. Each element in the array corresponds directly to the pay week for the year, in which order is important. With the presence of a limit attribute, the VARRAY also stores only a limited number of elements, while the nested table may store an unlimited number of objects, just as the base object table can. Another key difference between VARRAY and nested table data is indexing. An object column composed of VARRAY types cannot be indexed, while a nested table can be indexed. Storage for VARRAY data is also integrated with the storage segments of the data in the object table, up to a certain size. Data in nested tables is stored in another segment.

Unterschiede VARRAYs und Nested Tables

  • VARRAYs limitieren die Anzahl der Elemente im Object, Nested Tables nicht
  • VARRAYs erlauben keine Indexierung ihrer Attribute, Nested Tables erlauben dies
  • Nested Tables speichern die Daten separat vom Object, VARRAYs zusammen mit dem Objekt solange der VARRAY kleiner als 4K ist.
  • Constraints und Default Werte können nicht erstellt werden für Elemente des VARRAYs

Object Views und Instead of Trigger

The final area of object relational databases to be discussed is the process of evolving a relational application into an object application. Although there is no pressing need to migrate a relational application into an object one, the organization may want to do so for several reasons, including the fact that object applications have more features for advanced data definition and usage. To ease the transition, object views can be created to allow object applications to access relational database objects, allowing for coexistence of both types of applications using the same base data. Object views are similar to Oracle7 views in that both views provide a method for simplifying the underlying complexity of data. In addition, object views allow the user to apply object concepts to relational data. Object views even allow for advanced update of data in relational tables via object views using instead of triggers. Creation of object views begins with the creation of relational database objects like tables.

--
-- Object Views und Instead Trigger
--

-- Relationale EMPLOYEE Tabelle erstellen

CREATE TABLE employee (
  empid      VARCHAR2(10)  NOT NULL,
  lastname   VARCHAR2(30),
  firstname  VARCHAR2(30),
  salary     NUMBER(15,4),
CONSTRAINT pk_employee
PRIMARY KEY (empid));

-- Relationale ADDRESS Tabelle erstellen

CREATE TABLE address (
  empid VARCHAR2(10) NOT NULL,
  street1 VARCHAR2(30),
  street2 VARCHAR2(30),
  city VARCHAR2(30),
  state_prov VARCHAR2(30),
  postcode VARCHAR2(30),
CONSTRAINT pk_address
PRIMARY KEY (empid));

-- Object Type 1 erstellen

CREATE TYPE address_type AS OBJECT (
  street1    VARCHAR2(30),
  street2    VARCHAR2(30),
  city       VARCHAR2(30),
  state_prov VARCHAR2(30),
  postcode   VARCHAR2(30));
/

-- Object Type 2 erstellen

CREATE TYPE employee_type AS OBJECT (
  empid      VARCHAR2(10),
  lastname   VARCHAR2(30),
  address    address_type);

-- Object View erstellen basierend auf den Object Types

CREATE OR REPLACE VIEW employee_obj_view OF employee_type
WITH OBJECT OID (empid) AS
SELECT E.empid,E.lastname,
       address_type(A.street1,A.street2,A.city,A.state_prov,A.postcode)
FROM employee E, address A
WHERE E.empid = A.empid;

-- Instead of Trigger zum Daten einfüllen

CREATE OR REPLACE TRIGGER empl_trigger INSTEAD OF
INSERT ON employee_obj_view FOR EACH ROW
BEGIN
  INSERT INTO employee (empid,lastname)
    VALUES (:NEW.empid,:NEW.lastname);
  INSERT INTO address (empid,street1,street2,city,state_prov,postcode)
    VALUES (:NEW.empid,
            :NEW.address.street1,
            :NEW.address.street2,
            :NEW.address.city,
            :NEW.address.state_prov,
            :NEW.address.postcode);
END;

-- Daten einfüllen

INSERT INTO employee_obj_view VALUES
(49384,'MANFRAN',address_type('506 Pudding Street',
'Apt. Q','Moan','WY','70506'));

Advanced Queuing mit DBMS_QUEUE

Unter Oracle-7 erfolgte die Interprocess Kommunikation ausschliesslich über Pipes (DBMS_PIPE) und Alerts (DBMS_ALERT). Der wesentlich Nachteil von "Oracle Pipes und Alerts" ist, dass sie nicht persistent sind, also nach einem Shutdown / Startup nicht mehr vorhanden sind. Unter Oracle-8 wird eine wesentlich komplexere Implementation, basierend auf den Object Relationalen Erweiterungen angeboten -- das Advanced Queuing.

Messages werden zwischen Prozessen ausgetauscht, ein Message besteht aus Daten und Controlinformationen.

Ein Prozess schreibt die Message in eine Queue mittels DBMS_AQ.ENQUEUE, ein anderer liest die Message mittels DBMS_AQ.DEQUEUE.

Die Queue selbst ist in einer Oracle Queue Tabelle gespeichert. Ein Queue Tabelle kann mehrere Queues haben, eine DB kann mehrere Queue Tabellen haben. Die Queue Tabelle wird mit dem Package DBMS_AQADM erstellt.

Damit Advanced Queuing funktioniert muss der INIT.ORA Parameter AQ_TM_PROCESSES = 1 gesetzt werden. Die Role AQ_USER_ROLE dient dazu EXECUTE Rechte auf dem DBMS_AQ Package zu vergeben, während die Role AQ_ADMINISTRAOR_ROLE dazu dient EXECUTE Rechte auf dem Package DBMS_AQADM zu definieren

Recovery Manager RMAN

RMAN ist ein neues Tool mit Oracle-8 für alle Backup und Recovery Aufgaben. Es beinhaltet sowohl ein GUI als auch eine Kommandosprache, um Backups weitgehend zu automatisieren.

Folgende Merkmale sind von Bedeutung

  • The new architecture for backup and recovery in Oracle8 consists of Recovery Manager and a recovery catalog in another Database on another Host.

  • A recovery catalog is a service run on another Oracle database that tracks all backup and archived redo logs produced for the database.

  • There are some enhancements to the control file and a much larger control file in Oracle8 to support RMAN. RMAN information is stored for a period of time corresponding to the CONTROL_FILE_RECORD KEEP_TIME initialization parameter.

  • RMAN is created with the catrman.sql script, found in rdbms/admin under the Oracle software home directory.

  • RMAN has four sets of commands: recovery catalog maintenance commands, reporting commands, scripting commands, and run commands.

  • To run RMAN, type rman at the OS command prompt. One mandatory option and four optional ones are used: target to identify the production or target database; rcvcat to identify the recovery catalog database; cmdfile to execute RMAN in batch mode with a command script; and msglog to keep a log of all activity with append, allowing RMAN to append information to an old log file for the current RMAN session.

  • Communication with the operating system is possible in RMAN with the allocate channel command.

  • Recovery catalog management commands include register database to register a target database, reset database when the target database is opened and the redo log sequence reset, resync catalog after log switches in target database, change to alter the control file or other database filenames used, list incarnation to show the current database data version, and catalog to identify copies of files made outside of RMAN.

  • Reports show information about files of the database and recoverability. One of the reports that can be used is report need backup to show the files of the database that need backup. Another report includes report unrecoverable to show files that are not recoverable.

  • There are several commands available in RMAN for script creation. They are create script, replace script, delete script, and print script.

  • The final set of commands in RMAN are run commands. These commands handle most of the processing in RMAN, such as execution of scripts, SQL, and backup/recovery operations.

  • The backup command runs backups. RMAN creates incremental or full copies of files for the entire database, the files of a tablespace, or individual datafiles.

  • The backups of files and archived redo logs are placed into collections called backup sets. A backup can contain only archived redo logs or only datafiles and control files.

  • Datafiles can be multiplexed into a backup set, meaning that the blocks of datafiles are stored noncontiguously on the sequential offline storage media such as tape.

  • Oracle8 and RMAN support the incremental backup of datafiles, which store only the blocks of a datafile that have been changed since the last full backup. A full backup is one containing all blocks of datafiles.

  • There are eight levels of incremental backups and a level 0 backup, which is a full backup.

  • To recover a database component from backup, the component must first be restored.

  • The copy command will create an image copy of a database file component. This component is immediately usable for recovery.

  • The copy command only produces image copies to disk, while backup can send database file components directly to tape.

  • The switch command will substitute a datafile copy for a current file. The datafile switched will then need media recovery.

  • The restore command will retrieve the files from the backup copy and put them where the DBA specifies.

  • The recover command will conduct media recovery using backups restored in combination with archived redo logs.

Several old and new dictionary views exist in Oracle8 to support RMAN.

V$ARCHIVED_LOG

Displays name and information in the control file about archived redo logs.

V$BACKUP_CORRUPTION

Displays information in the control file about corrupt datafile backups

V$BACKUP_DATAFILE

Offers information from the control file about backup datafiles and control files.

V$BACKUP_DEVICE

Offers operating-system-specific information about supported third-party vendors for RMAN in Oracle8.

V$BACKUP_REDOLOG

Displays information about archived redo logs in backup sets

V$BACKUP_SET

Displays information from the control file about all backup sets.

V$BACKUP_PIECE

Displays information from the control file about all pieces in all backup sets

V$DATAFILE

Lists information about datafiles in the Oracle8 database.

V$DATAFILE _HEADER

Lists information about datafile headers in the Oracle8 database

Beispiel

Tablespace für Recovery Catalog erstellen

CREATE TABLESPACE rcvcat
        DATAFILE 'E:\Oradata\ARK1\rcv\ARK1_rcv1.dbf' SIZE 20M REUSE 
        AUTOEXTEND ON NEXT 10M MAXSIZE UNLIMITED
        DEFAULT STORAGE (INITIAL     100K 
                         NEXT        100K
                         MINEXTENTS  5
                         MAXEXTENTS  100)
        PERMANENT
        ONLINE;

RMAN Owner erstellen

DROP USER rman CASCADE;
CREATE USER rman IDENTIFIED BY rman_1
    DEFAULT TABLESPACE rcvcat
    TEMPORARY TABLESPACE temp
    QUOTA UNLIMITED ON rcvcat;

GRANT RECOVERY_CATALOG_OWNER TO rman;

Recovery Catalog generieren

SQL> @D:\Orant\rdbms80\admin\catrman.sql

Datenbank DOR1 auf Host Dorint registrieren

rman80 target "sys/manager@DOR1" rcvcat "rman/rman_1@ARK1"

RMAN> register database;
RMAN> list incarnation of database;

RMAN-03022: compiling command: list
RMAN-06240: List of Database Incarnations
RMAN-06241: DB Key  Inc Key DB Name  DB ID       CUR Reset SCN  Reset Time
RMAN-06242: ------- ------- -------- ----------- --- ---------- ----------
RMAN-06243: 1       2        DOR1     1730733701     YES   1    03-APR-99

Tablespace Save mit Commandfile: save_ts.rcv

connect sys/manager@DOR1
connect rman/rman_1@ARK1
run {
  allocate channel 'c1' type disk;
  backup (tablespace system, tab format 'C:\Users\Zahn\Work\TS_%s_%p');
}

ARKUM:zahn> rman80 cmdfile=save_ts.rcv

RMAN-06005: connected to target database: DOR1
RMAN-06008: connected to recovery catalog database
RMAN-03022: compiling command: allocate
RMAN-03023: executing command: allocate
RMAN-08030: allocated channel: c1
RMAN-08500: channel c1: sid=14 devtype=DISK
RMAN-03022: compiling command: backup
RMAN-03023: executing command: backup
RMAN-08008: channel c1: starting datafile backupset
RMAN-08502: set_count=3 set_stamp=366279858
RMAN-08010: channel c1: including datafile 5 in backupset
RMAN-08010: channel c1: including datafile 1 in backupset
RMAN-08011: channel c1: including current controlfile in backupset
RMAN-08013: channel c1: piece 1 created
RMAN-08503: piece handle=C:\USERS\ZAHN\WORK\TS_3_1 comment=NONE
RMAN-03023: executing command: partial resync
RMAN-08003: starting partial resync of recovery catalog
RMAN-08005: partial resync complete
RMAN-08031: released channel: c1
Recovery Manager complete.

Datenfile Save mit Commandfile: save_df.rcv

connect target "sys/manager@DOR1"
connect rcvcat "rman/rman_1@ARK1"
run {
  allocate channel 'c1' type disk;
  backup (datafile
  'E:\Oradata\Dor1\Tab\DOR1_TAB1.DBF',
  'E:\Oradata\Dor1\Usr\DOR1_USERS1.DBF' 
  format 'C:\Users\Zahn\Work\DF_%s_%p');
}

ARKUM:zahn> rman80 cmdfile=save_df.rcv

RMAN-06005: connected to target database: DOR1
RMAN-06008: connected to recovery catalog database
RMAN-03022: compiling command: allocate
RMAN-03023: executing command: allocate
RMAN-08030: allocated channel: c1
RMAN-08500: channel c1: sid=14 devtype=DISK
RMAN-03022: compiling command: backup
RMAN-03023: executing command: backup
RMAN-08008: channel c1: starting datafile backupset
RMAN-08502: set_count=4 set_stamp=366280852
RMAN-08010: channel c1: including datafile 5 in backupset
RMAN-08010: channel c1: including datafile 4 in backupset
RMAN-08013: channel c1: piece 1 created
RMAN-08503: piece handle=C:\USERS\ZAHN\WORK\DF_4_1 comment=NONE
RMAN-03023: executing command: partial resync
RMAN-08003: starting partial resync of recovery catalog
RMAN-08005: partial resync complete
RMAN-08031: released channel: c1
Recovery Manager complete.

Image Copy von Datenfiles erstellen: save_df.rcv

connect target "sys/manager@DOR1"
connect rcvcat "rman/rman_1@ARK1"
run {
allocate channel 'c1' type disk;
copy datafile 'E:\Oradata\Dor1\Tab\DOR1_TAB1.DBF'
    TO 'C:\Users\Zahn\Work\RMAN_DOR1_TAB1.dbf';
copy datafile 'E:\Oradata\Dor1\Usr\DOR1_USERS1.DBF'
    TO 'C:\Users\Zahn\Work\RMAN_DOR1_USERS1.dbf';
backup current controlfile FORMAT 'C:\Users\Zahn\Work\RMAN_DOR1_CTRL_%s_%p';
}

RMAN-06005: connected to target database: DOR1
RMAN-06008: connected to recovery catalog database
RMAN-03022: compiling command: allocate
RMAN-03023: executing command: allocate
RMAN-08030: allocated channel: c1
RMAN-08500: channel c1: sid=14 devtype=DISK
RMAN-03022: compiling command: copy
RMAN-03023: executing command: copy
RMAN-08000: channel c1: copied datafile 5
RMAN-08501: output filename=C:\USERS\ZAHN\WORK\RMAN_DOR1_TAB1.DBF
            recid=5 stamp=366282257
RMAN-03023: executing command: partial resync
RMAN-08003: starting partial resync of recovery catalog
RMAN-08005: partial resync complete
RMAN-03022: compiling command: copy
RMAN-03023: executing command: copy
RMAN-08000: channel c1: copied datafile 4
RMAN-08501: output filename=C:\USERS\ZAHN\WORK\RMAN_DOR1_USERS1.DBF
            recid=6 stamp=366282268
RMAN-03023: executing command: partial resync
RMAN-08003: starting partial resync of recovery catalog
RMAN-08005: partial resync complete
RMAN-03022: compiling command: backup
RMAN-03023: executing command: backup
RMAN-08008: channel c1: starting datafile backupset
RMAN-08502: set_count=7 set_stamp=366282271
RMAN-08011: channel c1: including current controlfile in backupset
RMAN-08013: channel c1: piece 1 created
RMAN-08503: piece handle=C:\USERS\ZAHN\WORK\RMAN_DOR1_CTRL_7_1 comment=NONE
RMAN-03023: executing command: partial resync
RMAN-08003: starting partial resync of recovery catalog
RMAN-08005: partial resync complete
RMAN-08031: released channel: c1
Recovery Manager complete.