Oracle 10g für den DBA
EDITION Oracle Oracle 10g Hochverfügbarkeit – Die ausfallsichere Datenbank mit RAC, Data Guard und Flashback Andrea Held ISBN 3-8273-2163-8 Oracle-Programmierung – Datenbankprogrammierung und -administration Heinz-Gerd Raymans ISBN 3-8273-1733-9 Oracle9i für den DBA – Effizient konfigurieren, optimieren und verwalten Johannes Ahrends, Dierk Lenz, Günter Unbescheid, Uwe Herrmann ISBN 3-8273-1559-X
Johannes Ahrends, Dierk Lenz, Patrick Schwanke, Günter Unbescheid
Oracle 10g für den DBA Effizient konfigurieren, optimieren und verwalten
An imprint of Pearson Education München • Boston • San Francisco • Harlow, England Don Mills, Ontario • Sydney • Mexico City
Bibliografische Information Der Deutschen Bibliothek Die Deutsche Bibliothek verzeichnet diese Publikation in der Deutschen Nationalbibliografie; detaillierte bibliografische Daten sind im Internet über http://dnb.ddb.de abrufbar. Die Informationen in diesem Produkt werden ohne Rücksicht auf einen eventuellen Patentschutz veröffentlicht. Warennamen werden ohne Gewährleistung der freien Verwendbarkeit benutzt. Bei der Zusammenstellung von Texten und Abbildungen wurde mit größter Sorgfalt vorgegangen. Trotzdem können Fehler nicht vollständig ausgeschlossen werden. Verlag, Herausgeber und Autoren können für fehlerhafte Angaben und deren Folgen weder eine juristische Verantwortung noch irgendeine Haftung übernehmen. Für Verbesserungsvorschläge und Hinweise auf Fehler sind Verlag und Herausgeber dankbar. Alle Rechte vorbehalten, auch die der fotomechanischen Wiedergabe und der Speicherung in elektronischen Medien. Die gewerbliche Nutzung der in diesem Produkt gezeigten Modelle und Arbeiten ist nicht zulässig. Fast alle Hardware- und Softwarebezeichnungen und weitere Stichworte und sonstige Angaben, die in diesem Buch verwendet werden, sind als eingetragene Marken geschützt. Da es nicht möglich ist, in allen Fällen zeitnah zu ermitteln, ob ein Markenschutz besteht, wird das Symbol ® in diesem Buch nicht verwendet. Umwelthinweis: Dieses Produkt wurde auf chlorfrei gebleichtem Papier gedruckt. Die Einschrumpffolie – zum Schutz vor Verschmutzung – ist aus umweltverträglichem und recyclingfähigem PE-Material. 10 9 8 7 6 5 4 3 2 1 08 07 06 ISBN 3-8273-2171-9 © 2006 by Addison-Wesley Verlag, ein Imprint der Pearson Education Deutschland GmbH, Martin-Kollar-Straße 10–12, D-81829 München/Germany Alle Rechte vorbehalten Einbandgestaltung: Lektorat: Korrektorat: Herstellung: Satz: Druck und Verarbeitung: Printed in Germany
Thomas Arlt,
[email protected] Sylvia Hasselbach,
[email protected] Sandra Gottmann,
[email protected] Elisabeth Prümm,
[email protected] Michael und Silke Maier,
[email protected] Bercker, Kevelaer
Inhaltsverzeichnis 1
Einführung ....................................................................................................... 15 1.1 Allgemeines ........................................................................................... 15 1.1.1 Kleine Versionshistorie ............................................................... 15 1.2 Oracle-Komponenten............................................................................. 17 1.2.1 Funktionsumfang....................................................................... 17 1.2.2 Optionen................................................................................... 20 1.2.3 Weitere Produkte ....................................................................... 21 1.3 Datenbank-Paradigmen.......................................................................... 22 1.3.1 Das Transaktionsverhalten ......................................................... 22 1.4 Aufgaben eines DBA............................................................................... 26 1.4.1 Kerngebiete der DB-Administration............................................ 27 1.4.2 Bereiche mit DBA-Unterstützung ............................................... 28 1.4.3 Aufgaben, die nicht beim DBA angesiedelt sein sollten .............. 29
2
Installation und Aufbau einer Datenbank ....................................................... 31 2.1 Basisinstallation ...................................................................................... 32 2.2 Installationsplanung ............................................................................... 34 2.2.1 Hardware und Betriebssystem.................................................... 35 2.2.2 Art der Anwendung ................................................................... 43 2.2.3 Versionstechnische Planung ....................................................... 45 2.2.4 Betriebssystemspezifische Planung ............................................. 45 2.2.5 Software-Komponenten............................................................. 46 2.2.6 Globalization Support ................................................................ 48 2.2.7 Die Planung von Instanzen und Datenbanken............................ 49 2.3 Software-Installation............................................................................... 55 2.3.1 Vorbereitungen ......................................................................... 55 2.3.2 Oracle Flexible Architecture (OFA) ............................................. 57 2.3.3 Universal Installer....................................................................... 59 2.3.4 Silent Installation ....................................................................... 63 2.3.5 Cluster Ready Services ............................................................... 65 2.4 Datenbankkonfiguration......................................................................... 66 2.4.1 Database Configuration Assistant (DBCA) .................................. 66 2.4.2 Skriptbasierte Installation ........................................................... 75 2.5 Patches und Patch-Sets .......................................................................... 81 2.5.1 Patch-Sets.................................................................................. 81 2.5.2 Interim-Patches.......................................................................... 83 2.6 Release-Wechsel ..................................................................................... 83 2.6.1 Vorbereitung ............................................................................. 84 2.6.2 Database Upgrade Assistant (DBUA) .......................................... 85 2.6.3 Manueller Upgrade.................................................................... 88 2.6.4 Downgrade ............................................................................... 93
6
Inhaltsverzeichnis
3
Datenbank-Architektur .................................................................................... 95 3.1 Namenskonventionen ............................................................................ 95 3.1.1 Datenbanken ............................................................................. 96 3.1.2 Systemobjekte ........................................................................... 99 3.2 Komponenten einer Oracle-Datenbank ................................................ 100 3.3 Tablespaces und Datendateien............................................................. 101 3.3.1 Planung ................................................................................... 102 3.3.2 Erstellen eines Tablespaces....................................................... 103 3.3.3 SYSTEM- und SYSAUX-Tablespace ........................................... 109 3.3.4 Temporär-Tablespaces und Temporärsegmente....................... 114 3.3.5 Undo-Tablespaces.................................................................... 116 3.3.6 Read-only-Tablespaces............................................................. 122 3.3.7 Tablespaces offline setzen ........................................................ 122 3.4 Datenbankblöcke ................................................................................. 123 3.5 Online-Redolog-Dateien....................................................................... 124 3.5.1 Konfiguration .......................................................................... 125 3.5.2 Administrationskommandos .................................................... 128 3.5.3 Überwachung von Redolog-Dateien ........................................ 129 3.5.4 Überlegungen zur Spiegelung von Redolog-Dateien ................ 130 3.6 Kontrolldateien .................................................................................... 131 3.6.1 Administration der Kontrolldateien .......................................... 132 3.7 Parameterdateien ................................................................................. 135 3.8 Block-Change-Tracking-Datei ............................................................... 136 3.9 Physikalisches Layout............................................................................ 138 3.9.1 Dateisystem ............................................................................. 138 3.9.2 Cluster-Dateisystem ................................................................. 143 3.9.3 Raw Devices ............................................................................ 144 3.9.4 Automatic Storage Management (ASM) .................................. 145 3.10 Ältere Funktionen................................................................................. 153 3.10.1 Dictionary-Managed Tablespaces............................................. 153 3.10.2 Rollback-Segmente .................................................................. 154
4
Instanz-Verwaltung ....................................................................................... 157 4.1 Werkzeuge und Voraussetzungen......................................................... 157 4.1.1 Startup .................................................................................... 158 4.1.2 Shutdown................................................................................ 160 4.1.3 Alter Database ......................................................................... 161 4.1.4 Alter System ............................................................................ 162 4.2 Parametrierung .................................................................................... 164 4.2.1 Checkpoints ............................................................................ 166 4.2.2 Dynamische SGA ..................................................................... 167 4.3 Oracle Cluster Synchronization Service Daemon................................... 170 4.4 ASM-Instanzen ..................................................................................... 171 4.5 Ältere Versionen ................................................................................... 172
Inhaltsverzeichnis
7
5
Datenbankobjekte ......................................................................................... 173 5.1 Namenskonventionen .......................................................................... 173 5.2 Datenobjekte ....................................................................................... 175 5.2.1 Datentypen ............................................................................. 176 5.2.2 Tabellen................................................................................... 179 5.2.3 Partitionierte Tabellen.............................................................. 180 5.2.4 Indexorganisierte Tabellen (IOT).............................................. 183 5.2.5 Temporäre Tabellen................................................................. 184 5.2.6 Externe Tabellen ...................................................................... 185 5.2.7 Cluster..................................................................................... 188 5.2.8 Objekttypen und Kollektoren ................................................... 190 5.3 Indexstrukturen.................................................................................... 195 5.3.1 Allgemeine Regeln ................................................................... 196 5.3.2 B*Tree Index............................................................................ 197 5.3.3 Bitmap-Index........................................................................... 198 5.3.4 Bitmap-Join-Index.................................................................... 201 5.3.5 Function-based Index .............................................................. 203 5.3.6 Partitionierte Indizes ................................................................ 204 5.3.7 Komprimierung von Indizes ..................................................... 209 5.3.8 Reverse Key-Indizes.................................................................. 210 5.3.9 Weitere Aspekte der Indexverwaltung...................................... 210 5.4 Constraints........................................................................................... 213 5.4.1 Constraint-Definitionen ........................................................... 214 5.4.2 Constraint-Handhabung .......................................................... 218 5.5 Views ................................................................................................... 223 5.5.1 Standard-Views........................................................................ 223 5.5.2 Materialized Views ................................................................... 229 5.5.3 Object-Views ........................................................................... 230 5.6 PL/SQL-Objekte.................................................................................... 232 5.7 Directory-Objekte für den Dateizugriff.................................................. 242
6
Administrationswerkzeuge............................................................................ 245 6.1 Oracle Enterprise Manager ................................................................... 245 6.1.1 Enterprise Manager Database Control...................................... 247 6.1.2 Enterprise Manager Grid Control ............................................. 257 6.2 Scheduler............................................................................................. 264 6.2.1 Alter Scheduler ........................................................................ 264 6.2.2 Neuer Scheduler ...................................................................... 267 6.3 Weitere Werkzeuge .............................................................................. 275 6.3.1 SQL*Plus.................................................................................. 275 6.3.2 TOAD ...................................................................................... 276 6.3.3 Hora ........................................................................................ 278
8
Inhaltsverzeichnis
7
Zugriff auf die Datenbank ............................................................................. 281 7.1 Oracle Net ........................................................................................... 281 7.1.1 Architektur und Konfiguration ................................................. 281 7.1.2 Shared Server .......................................................................... 306 7.1.3 Spezielle Parameter.................................................................. 312 7.1.4 Instant Client ........................................................................... 316 7.2 Alternative Methoden zur Namensauflösung ........................................ 317 7.2.1 Hostnaming und Easy Connect ................................................ 317 7.2.2 JDBC Thin Driver ..................................................................... 318 7.2.3 LDAP-Verzeichnisse.................................................................. 319 7.2.4 Welche Methode ist die beste? ................................................ 321 7.3 Connection Manager ........................................................................... 323 7.4 Firewall ................................................................................................ 326 7.5 Java in der Datenbank .......................................................................... 327 7.5.1 Java-Grundlagen ...................................................................... 327 7.5.2 Java-APIs in der Datenbank ...................................................... 329 7.5.3 Server-seitige Installation ......................................................... 330 7.5.4 Clientseitige Installation ........................................................... 332 7.5.5 JDBC-Treiber............................................................................ 333 7.5.6 Verbindungen via JDBC ........................................................... 334 7.5.7 NLS-Einstellungen für JDBC...................................................... 335 7.5.8 Java-Objekte in der Datenbank ................................................ 337 7.5.9 Resolving ................................................................................. 338 7.5.10 Tools zur Java-Verwaltung........................................................ 338 7.5.11 Ausgabeumleitung................................................................. 340 7.5.12 Publishing von Java-Klassen ................................................... 340 7.5.13 Deinstallation der Oracle JVM ................................................ 341 7.6 Die Oracle XML DB .............................................................................. 341 7.6.1 Installation der XML DB ........................................................... 342 7.6.2 Einrichtung der Protokollserver ................................................ 343 7.6.3 Benutzung der Protokollserver ................................................. 344 7.6.4 Konfiguration der Protokollserver............................................. 346
8
Globalization Support ................................................................................... 347 8.1 Überblick ............................................................................................. 347 8.2 Grundeinstellung ................................................................................. 348 8.3 Sprachen und landesspezifische Konventionen ..................................... 349 8.3.1 Sprache, Gebiet und Datumsformat......................................... 349 8.3.2 Zeitzonen, Zeitstempel und Intervalle ...................................... 352 8.3.3 Sortierreihenfolgen .................................................................. 354 8.3.4 Weitere NLS-Parameter............................................................ 355
Inhaltsverzeichnis
8.4
9
9
Zeichensätze ........................................................................................ 355 8.4.1 Single-Byte-Zeichensätze ......................................................... 356 8.4.2 Multi-Byte-Zeichensätze, insbesondere UNICODE.................... 357 8.4.3 Migration von Zeichensätzen................................................... 359
Sicherheit ....................................................................................................... 363 9.1 Einführung ........................................................................................... 363 9.2 Grundlegende Maßnahmen ................................................................. 366 9.2.1 Maßgeschneiderte Installation ................................................. 366 9.2.2 Standardpasswörter ................................................................. 366 9.2.3 Vordefinierte Rollen und Grants ............................................... 368 9.2.4 Patches .................................................................................... 369 9.3 Sichern der Datenübertragung ............................................................. 370 9.3.1 Konfiguration des Listener-Prozesses ........................................ 370 9.3.2 Verschlüsselung und Integrität ................................................. 374 9.4 Benutzerplanung.................................................................................. 376 9.5 Interne Benutzerverwaltung ................................................................. 379 9.5.1 Möglichkeiten der Authentifizierung ........................................ 380 9.5.2 Interne Authentifizierung ......................................................... 380 9.5.3 Externe Authentifizierung ........................................................ 382 9.5.4 Globale Authentifizierung ........................................................ 385 9.5.5 Proxy-Authentifizierung ........................................................... 385 9.5.6 Authentifizierung von Datenbankadministratoren .................... 390 9.5.7 Benutzerverwaltung................................................................. 392 9.6 Internet Directory, LDAP und SSL ......................................................... 395 9.6.1 Die Möglichkeiten im Überblick ............................................... 396 9.6.2 Grundlegende Standards und Begriffe ..................................... 399 9.6.3 Modell 1: Auflösung von Dienstbenennungen ......................... 408 9.6.4 Modell 2: Authentifizierung globaler Benutzer ......................... 411 9.6.5 Modell 3: Enterprise-Benutzer und Enterprise-Rollen ................ 417 9.6.6 Verwaltung von Oracle Internet Directory................................ 429 9.7 Privilegien und Rollen........................................................................... 430 9.7.1 Systemprivilegien..................................................................... 430 9.7.2 Objektprivilegien ..................................................................... 436 9.7.3 Rollen ...................................................................................... 438 9.8 Virtual Private Database........................................................................ 448 9.8.1 Einführung............................................................................... 448 9.8.2 Aufbau einer VPD-Umgebung.................................................. 450 9.9 Labels................................................................................................... 462 9.9.1 Überblick ................................................................................. 462 9.9.2 Die Grundlagen ....................................................................... 463 9.9.3 Konfiguration eines Label-Systems ........................................... 467
10
Inhaltsverzeichnis
9.10
9.11
9.12
Profile .................................................................................................. 473 9.10.1 Management von Ressourcen .................................................. 473 9.10.2 Password-Management ........................................................... 475 Management von Ressourcen mit dem Resource Manager................... 476 9.11.1 Überblick ................................................................................. 476 9.11.2 Der Aufbau einer Beispielumgebung........................................ 477 9.11.3 Monitoring .............................................................................. 484 Auditing............................................................................................... 484 9.12.1 Zwanghaftes Auditing.............................................................. 485 9.12.2 Aktivieren von Auditing ........................................................... 486 9.12.3 Kommando-Auditing ............................................................... 487 9.12.4 Privilegien-Auditing ................................................................. 488 9.12.5 Objekt-Auditing ....................................................................... 488 9.12.6 Fine-Grain-Auditing ................................................................. 489 9.12.7 Audit-Trigger ........................................................................... 490 9.12.8 Empfehlungen ......................................................................... 491
10 Wiederherstellungstechniken........................................................................ 493 10.1 Planung ............................................................................................... 493 10.1.1 Generelles................................................................................ 493 10.1.2 Hardware................................................................................. 494 10.1.3 Archivierung ............................................................................ 494 10.1.4 Flash-Recovery Area ................................................................. 501 10.2 Sicherung und Wiederherstellung ........................................................ 503 10.2.1 Fehleranalyse ........................................................................... 504 10.2.2 Wiederherstellungsstrategie ..................................................... 505 10.2.3 Instanzwiederherstellung, Prozess- und Netzwerkfehler............ 506 10.2.4 Wiederherstellung von Medienfehlern ..................................... 507 10.2.5 Anwenderfehler ....................................................................... 509 10.3 Der Recovery Manager......................................................................... 510 10.3.1 Architektur............................................................................... 512 10.3.2 Sicherung ................................................................................ 521 10.3.3 Rücksicherung und Wiederherstellung ..................................... 527 10.3.4 Berichte und Überprüfung ....................................................... 531 10.3.5 Aufräumen .............................................................................. 532 10.3.6 Verwaltung im Oracle Enterprise Manager ............................... 532 10.4 Flashback Database .............................................................................. 535 10.5 Tablespace-Point-in-Time Recovery (TSPITR) ........................................ 538
Inhaltsverzeichnis
10.6
10.7
11
Objektbasierte Techniken ..................................................................... 540 10.6.1 Data Pump .............................................................................. 540 10.6.2 Export und Import ................................................................... 550 10.6.3 LogMiner................................................................................. 558 10.6.4 Flashback Query ...................................................................... 560 10.6.5 Flashback Table ....................................................................... 563 Ältere Techniken zur Sicherung ............................................................ 567 10.7.1 Offline-Sicherung..................................................................... 567 10.7.2 Online-Sicherung..................................................................... 569 10.7.3 Spezielle Techniken.................................................................. 571
11 Tuning ............................................................................................................ 573 11.1 Strategie .............................................................................................. 573 11.2 Hilfsmittel............................................................................................. 575 11.2.1 Oracle Performance-Views ....................................................... 575 11.2.2 Monitoring und Engpassanalyse .............................................. 583 11.2.3 Anwendungs-Tracing............................................................... 593 11.3 Der Optimizer ...................................................................................... 609 11.3.1 Die Ausführung von SQL-Code ............................................... 609 11.3.2 Erstellung und Pflege von Statistiken....................................... 612 11.3.3 Serverparameter mit Relevanz für den Query Optimizer........... 621 11.4 Zugriffsoptimierung ............................................................................. 623 11.4.1 Ausführungspläne.................................................................... 623 11.4.2 Indizierung .............................................................................. 632 11.4.3 Hints........................................................................................ 638 11.4.4 Automatisches SQL-Tuning...................................................... 649 11.5 Ältere Features ..................................................................................... 659 11.5.1 Regelbasierter Optimizer.......................................................... 659 11.5.2 Optimizer-Statistiken mittels ANALYZE..................................... 659 11.5.3 Diverse Optimizer-Hints ........................................................... 659 11.5.4 Oracle-Trace ............................................................................ 659 11.5.5 Erweitertes SQL-Tracing........................................................... 660 12 Troubleshooting ............................................................................................ 661 12.1 Einführung ........................................................................................... 661 12.2 Informationsquellen und Anwendungskontext ..................................... 661 12.3 Die Strategien ...................................................................................... 665 12.4 Werkzeuge und Fehlersituationen......................................................... 666 12.4.1 Log- und Trace-Dateien ........................................................... 667 12.4.2 Statistiken, Metriken, servergenerierte Alerts ............................ 676 12.4.3 Programmatische Möglichkeiten.............................................. 685 12.4.4 Validieren von Blöcken............................................................. 688 12.4.5 Feature-Nutzung und Hochwassermarken ............................... 694 12.4.6 Die Arbeit mit Events ............................................................... 694
12
Inhaltsverzeichnis
13 Hochverfügbarkeit ......................................................................................... 709 13.1 Einleitung............................................................................................. 709 13.2 Hardware-Architekturen ....................................................................... 710 13.2.1 Speicher .................................................................................. 710 13.2.2 Server ...................................................................................... 712 13.2.3 Infrastruktur............................................................................. 713 13.3 Oracle Real Application Clusters ........................................................... 713 13.3.1 Architektur............................................................................... 714 13.3.2 Lage der Datendateien ............................................................ 717 13.3.3 Software-Installation ................................................................ 718 13.3.4 Konfiguration einer RAC-Datenbank ........................................ 724 13.3.5 Oracle Net-Konfiguration......................................................... 728 13.4 Oracle Data Guard ............................................................................... 730 13.4.1 Physical-Standby-Datenbank.................................................... 732 13.4.2 Logical Standby ....................................................................... 742 13.4.3 Data Guard Broker................................................................... 751 13.5 Replikation ........................................................................................... 756 13.5.1 Replikationsarten ..................................................................... 757 13.5.2 Advanced Replication .............................................................. 759 13.5.3 Oracle Streams ........................................................................ 785 13.5.4 Shareplex ................................................................................ 800 14 Monitoring/Reorganisation........................................................................... 807 14.1 Was wird beobachtet?.......................................................................... 807 14.1.1 Platzbedarf .............................................................................. 807 14.1.2 Grenzen................................................................................... 808 14.1.3 Tuningparameter..................................................................... 808 14.2 Wie wird beobachtet? .......................................................................... 808 14.2.1 Alert-Datei ............................................................................... 809 14.2.2 Tablespace und Datendatei...................................................... 811 14.2.3 Extents .................................................................................... 812 14.2.4 Filesystem ................................................................................ 814 14.2.5 Unvorhergesehene Engpässe ................................................... 815 14.2.6 Online-Monitoring................................................................... 816 14.3 Reorganisieren ..................................................................................... 819 14.3.1 Warum reorganisieren?............................................................ 819 14.3.2 Wie wird reorganisiert? ............................................................ 820 14.3.3 Womit wird reorganisiert? ....................................................... 822 14.3.4 CREATE TABLE ... AS SELECT ... (CTAS) .................................... 824 14.3.5 COPY Table ............................................................................. 826 14.3.6 REBUILD INDEX ....................................................................... 826
Inhaltsverzeichnis
13
14.3.7 Move Tablespace..................................................................... 827 14.3.8 Shrink Space............................................................................ 828 14.3.9 Online-Table-Reorganisation.................................................... 829 14.3.10 Oracle Enterprise-Manager-Reorganisationen........................... 831 15 Data Warehousing ......................................................................................... 835 15.1 Extraktion, Transformation, Laden........................................................ 836 15.1.1 Transportable Tablespaces ....................................................... 837 15.1.2 Parallelisierung........................................................................ 842 15.1.3 Komplexe Laderoutinen.......................................................... 844 15.1.4 Laden aus Non-Oracle-Datenbanken ....................................... 847 15.1.5 Überwachung der Ladeoperation............................................. 850 15.2 Datenbankdesign für Data Warehouses ................................................ 852 15.2.1 Hardware-Architekturen.......................................................... 853 15.2.2 Tablespace-Layout ................................................................... 857 15.2.3 Partitionierung........................................................................ 859 15.2.4 Indizierung ............................................................................. 865 15.2.5 Konsolidierung und Verdichtung ............................................ 868 15.2.6 Aggregationsfunktionen .......................................................... 877 15.3 Darstellung .......................................................................................... 880 15.3.1 Dimensionen ........................................................................... 881 15.3.2 Parallele Abfragen.................................................................... 883 Stichwortverzeichnis...................................................................................... 885
Einführung 1.1
Allgemeines
Das relationale Datenbankmanagementsystem (RDBMS) Oracle Database 10g ist ein kommerzielles Produkt, das auf Basis von theoretischen Grundlagen implementiert wurde. Als Standardprodukt basiert die Datenbank auf der Datenbanksprache SQL (steht für Structured Query Language, »SEQUEL« gesprochen1). Es erfüllt in weiten Teilen die Bedingungen an Core SQL:2003, den Pflichtteil des SQL:2003-Standards, der 2003 sowohl von der ANSI- als auch von den ISO/IEC-Organisationen verabschiedet wurde. Neben den Standardelementen enthält Oracle SQL eine Reihe von Erweiterungen. Genaue Angaben zur Standardkonformität finden sich im Anhang B der Dokumentation Oracle 10g SQL Reference. SQL selbst besteht sowohl aus dem SELECT-Befehl für die Abfrage als auch aus verschiedenen Befehlsgruppen wie DML-Befehlen (Data Manipulation Language, umfasst INSERT, UPDATE, DELETE) und DDL-Befehlen (Data Definition Language, zur Definition von Tabellen, Indizes usw.). Als Literaturhinweise für den interessierten Leser sei die theoretische Grundlage für relationale Systeme genannt, E.F. Codd: A Relational Model of Data for Large Data Banks, Communications of the ACM, Volume 13, 1970, Number 6, und das Standardwerk über Datenbanksysteme, C.J. Date, Introduction to Database Systems, Volume 1, 6th Edition, Addison-Wesley, 1995. Als Referenz der Oracle-Produkte sei natürlich auch auf die umfangreichen Handbücher zum Oracle Server verwiesen, die als zusätzliche CD sowohl im HTML- als auch im PDF-Format mit zur Softwarelieferung gehören.
1.1.1 Kleine Versionshistorie Bevor die Komponenten der Oracle-Datenbank einzeln näher betrachtet werden, folgen zunächst einige Anmerkungen zum Begriff »Oracle-Datenbank«. Nachdem die Datenbanksoftware der Firma Oracle bis einschließlich Version 6 ausschließlich unter der Bezeichnung RDBMS (Relationales Datenbankmanagementsystem) verkauft wurde, wurde ab Version 7 der Begriff »Oracle Server«, zur Verdeutlichung der aktuellen Version auch »Oracle7 Server« verwendet. Dieser Begriff betont die ab Version 7 stark ausgeprägten Serverfähigkeiten der Datenbanksoftware im Netzwerk. Im Hause Oracle wurde zwar bereits Mitte der 80er-Jahre mit Release 5.1 und dem Produkt SQL*Net die Client-Server- und Server-Server-Kommunikation eingeführt, mit Version 7 wurden diese Fähigkeiten dann aber stärker 1
Man erkennt an dieser Wortwahl, dass die Abfrage (engl. Query) im Vordergrund steht, dennoch sind natürlich auch Datenmanipulationen (DML) möglich.
16
Einführung
ausgeprägt und wesentlich verfeinert. Das Produkt SQL*Net wurde mit dem Erscheinen des Oracle8 Servers in Net8 umbenannt. Um die Ausrichtung auf Internettechnologien zu betonen, wurde das erste Folge-Release von Oracle mit Oracle8i bezeichnet; die Release-Nummer hierzu war 8.1. Beim Übergang auf Oracle9i (Release 9.0) wurde die offizielle Produktbezeichnung von »Oracle Server« auf »Oracle Database« geändert, so dass die deutsche Bezeichnung Oracle-Datenbank sich mehr denn je anbietet. SQL*Net heißt seit Oracle9i schlicht Oracle Net. Mit Version 10g wurde dann ein weiterer Paradigmenwechsel eingeleitet. Das »g« steht für Grid-Control. Unter diesem heute von Hard- und Softwarefirmen verwendeten Begriff versteht man die Verknüpfung unterschiedlicher Ressourcen für eine gemeinsame Aufgabe. Für Oracle ist dies im Wesentlichen die Weiterentwicklung der Oracle Parallel Server (OPS) bzw. Real-Application-Clusters(RAC)-Architektur zu einem Verbund an Rechnern. Dafür wurden bereits in der Version 9i die Grundlagen durch eine eigene Cluster-Software gelegt, die mit Version 10g jetzt auch eine eigene Filesystem-Implementierung (ASM, Automatic Space Management) umfasst. Leider ist es derzeit noch nicht möglich, Hardware mit unterschiedlichen Betriebssystemen zu verknüpfen, aber weitere Releases werden dieser Möglichkeit sicher ein Stück näher kommen. Die ersten beiden Stellen der insgesamt fünfstelligen Oracle-Versionsnummer – Version und Release – sind »marketingrelevant«, d.h., mit einem neuen Release werden neben Fehlerkorrekturen zum Vorgänger auch neue Funktionen ausgeliefert. Sie tauchen damit u.a. in Buchtiteln auf. Die Versionsnummer kann z.B. nach erfolgreicher Anmeldung in SQL*Plus gelesen werden: Verbunden mit: Oracle Database 10g Enterprise Edition Release 10.1.0.4.0 - Production
Normalerweise bezeichnet die dritte Stelle der Versionsnummer das MaintenanceRelease, das nicht mit neuen Funktionen aufwartet, höchstens mit kleineren Schnittstellenänderungen im Rahmen von Fehlerkorrekturen oder PerformanceVerbesserungen. Für Oracle9i und Oracle 10g gilt wieder die alte Logik, d.h., Oracle 10g steht für Version 10.1; das als Nächstes erscheinende Oracle 10g Release 2 für Version 10.2. Zur vollständigen Beschreibung der Versionsnummer fehlen nun noch die vierte und fünfte Stelle, die für Patchsets und plattformspezifische Patches benutzt werden. Patchsets (z.B. 10.1.0.4) sind plattformunabhängig, d.h., für die verschiedenen Portierungen des Oracle-Systems steht ein identisches Basiscode-Release zur Verfügung. Erst bei der letzten Stelle können plattformspezifische Patches nachgeschoben werden, z.B. als 10.1.0.4.1 für MS-Windows. Damit Oracle-Administratoren und -Entwickler sich nicht Dutzende von Versionsnummern merken müssen, wurden die Versionsnummern praktisch aller Produkte im Umfeld der Datenbank sinnvollerweise synchronisiert, d.h., zur Datenbank Version 10.1.0 gibt es SQL*Plus Version 10.1.0, Oracle Net Version 10.1.0 usw.
Oracle-Komponenten
1.2
17
Oracle-Komponenten
Oracle Database 10g gibt es in vier unterschiedlichen Editionen, die teilweise über zusätzliche Optionen erweitert werden können. Oracle Database 10g Personal Edition (PE) ist eine spezielle Einplatzlösung mit allen Funktionen der Oracle Database 10g Enterprise Edition inklusive der Optionen mit Ausnahme des Real Application Clusters. Oracle Database 10g Standard Edition One ist eine spezielle Lizenz für den Einsatz auf Rechnern mit einer maximalen Kapazität von zwei Prozessoren. Der Funktionsumfang ist identisch mit der Oracle Database 10g Standard Edition bis auf die Möglichkeit, Real Application Clusters zu nutzen. Oracle Database 10g Standard Edition (SE) ist eine erweiterte Lizenz für den Einsatz auf Systemen mit einer maximalen Kapazität von vier Prozessoren, die entweder in einem System oder verteilt auf bis zu vier Knoten in einer RealApplication-Clusters-Umgebung eingesetzt werden können. Oracle Database 10g Enterprise Edition (EE) enthält alle möglichen Funktionen des Oracle-Datenbank-Kerns und ist über zusätzliche Optionen (z.B. Partitioning) erweiterbar. Auch wenn es einige Dokumente gibt, die etwas anderes behaupten, so ist die Standard Edition bzw. Standard Edition One in der Anzahl der Benutzer oder der Größe der Datenbank nicht beschränkt. Wenn Sie also mit der Funktionalität und der Anzahl der Prozessoren auskommen, sollten Sie sich überlegen, ob SE für Sie nicht ausreichend ist. Interessant ist auch, dass die Personal Edition von ihrem Funktionsumfang mit der Enterprise Edition identisch ist, so dass es möglich ist, auf einem Arbeitsplatz-PC eine PE für die Anwendungsentwicklung zu installieren, die anschließend in einer EE zum Einsatz kommt.
1.2.1 Funktionsumfang Die folgende Tabelle listet den Funktionsumfang der Standard Edition gegenüber der Enterprise Edition auf. Die Standard Edition One ist hierbei identisch mit der Standard Edition, die Personal mit der Enterprise Edition. Funktion
Standard Edition
Enterprise Edition
Oracle Data Guard (physical und logical)
NEIN
JA
Online Reorganisation (dbms_redefinition)
NEIN
JA
Flashback Query
JA
JA
Flashback Table, Database, Transaction Query
NEIN
JA
Block-Level Media Recovery
NEIN
JA
Incremental Backup und Recovery
JA
JA
Point-in-Time Tablespace Recovery
NEIN
JA
18
Einführung
Funktion
Standard Edition
Enterprise Edition
Transportable Tablespaces
NEIN
JA
Trial Recovery
NEIN
JA
JA
JA
JA
JA
Oracle Failsafe
a
Oracle Real Application Clustersb Automatic Workload Management
JA
JA
Advanced Security*)
NEIN
JA
Oracle Label Security*)
NEIN
JA
Encryption Toolkit
JA
JA
Virtual Private Database
NEIN
JA
Fine grained Auditing
NEIN
JA
Reguläre Ausdrücke
JA
JA
VLM und 64-Bit-Support für Windows
JA
JA
Oracle Change Management Pack*)
NEIN
JA
Oracle Configuration Management Pack*)
NEIN
JA
Oracle Diagnostic Pack*)
NEIN
JA
Oracle Tuning Pack*)
NEIN
JA
Enterprise Manager Database Control
JA
JA
Automatic Memory Management
JA
JA
Automatic Storage Management
JA
JA
Legato Storage Manager
JA
JA
Duplex Backup Sets
NEIN
JA
Database Resource Manager
NEIN
JA
Oracle Partitioning*)
NEIN
JA
Oracle OLAP*)
NEIN
JA
Oracle Data Mining*)
NEIN
JA
Data Compression
NEIN
JA
Analytische Funktionen
JA
JA
Bitmapped Index und Bitmapped Join Index
NEIN
JA
Function-Based Index
JA
JA
Parallelisierungen
NEIN
JA
Materialized View Query Rewrite
NEIN
JA
Externe Tabellen
JA
JA
Oracle Streams
NEIN
JA
Oracle-Komponenten
19
Funktion
Standard Edition
Enterprise Edition
Advanced Queuing
JA
JA
Messaging Gateway
NEIN
JA
Basic Replication
c
Advanced Replication
JA
JA
NEIN
JA
Distributed Queries and Transactions
JA
JA
Heterogeneous Services
JA
JA
Oracle Connection Manager
NEIN
JA
Oracle Names
JA
JA
Infiniband Support
NEIN
JA
Oracle Spatial*)
NEIN
JA
Oracle Database Workspace Manager
JA
JA
Ultra Search
JA
JA
interMedia
JA
JA
Oracle Text
JA
JA
Index-organized Tables
JA
JA
LogMiner
JA
JA
Multiple Block Size Support
JA
JA
Temporary Tables
JA
JA
a. b. c. *)
nur MS-Windows Nicht für Standard Edition One und Personal Edition, bei der Enterprise Edition kostenpflichtige Option Nur Updatable Materialized View Diese Optionen sind kostenpflichtig in der Enterprise Edition verfügbar.
Diese Liste deckt nur einen Teil der Funktionen ab, kann aber in vielen Fällen als Hinweis dienen, ob sich der Kauf der erheblich teureren Enterprise Edition rentiert. In unseren Projekten hat sich herausgestellt, dass speziell die Data-Guard-Funktionalität, die Bitmapped Indexes, Transportable Tablespaces sowie die Advanced Replication den Ausschlag für den Einsatz der Enterprise Edition gegeben haben. Da diese Liste einer permanenten Anpassung unterzogen wird, bitten wir Sie, im Bedarfsfall auf die Oracle Homepage zu gehen und dort nach »Product Family« zu suchen. Leider ist die Dokumentation nicht immer eindeutig. Es gibt ein Dokument Oracle Database 10g Product Family, das als Grundlage für die Tabelle diente und aus der hervorgeht, dass analytische Funktionen mit der SE möglich sind, laut aktuellem Overview auf der Oracle Homepage sind diese jedoch scheinbar nicht möglich.
20
Einführung
1.2.2 Optionen Wie bereits erwähnt, gibt es für die Enterprise Edition eine Reihe von Optionen, die teilweise auch in diesem Buch besprochen werden. Dazu gehören: Oracle Real Application Clusters (RAC): Diese Option ermöglicht den Aufbau eines Rechnerverbundes mit einer zentralen Datenbank. Sie bildet bei Oracle die Basis für das Grid-Computing. Nähere Informationen dazu finden Sie in Kapitel 13. Oracle Partitioning: Damit können Tabellen und Indizes aufgeteilt werden, ohne dass die Anwendung hiervon etwas mitbekommt. Durch Partitionen können große Objekte einfacher verwaltet werden. Außerdem kann der Zugriff optimiert werden. Wir gehen auf die Möglichkeiten der Partitionierung in den Kapiteln 5 und 15 näher ein. Oracle Advanced Security: Hiermit können die Möglichkeiten der Verschlüsselung von Daten im Netzwerk und in der Datenbank erweitert werden. Dazu gehört z.B. ein Single-Sign-One über Kerberos oder Radius-Server. Oracle Label Security: Hierbei handelt es sich um die Funktion, die früher als Trusted Oracle bekannt war. Es ist damit möglich, eine sehr fein granulare Zugriffssteuerung zu erreichen. Nähere Informationen dazu bekommen Sie in Kapitel 9. Oracle OLAP: Diese Kernel-Erweiterung ist die Fortführung der von Oracle Ende der Neunzigerjahre gekauften Datenbank Express der Firma IRI. Damit ist es möglich, in der Oracle-Datenbank multidimensionale Analysen durchzuführen. Oracle Data Mining: Diese Option erlaubt über eine Java API den Aufbau einer Datenbank speziell für den Bereich Data Mining. Oracle Spatial: Mit dieser Option kann die Datenbank um Funktionen für die Speicherung von geokodierten Daten erweitert werden. Weitere Optionen gibt es für die Erweiterung des Oracle Enterprise Managers Grid Controls: Oracle Change Managment Pack: Hiermit können über den Enterprise Manager Strukturänderungen verwaltet bzw. synchronisiert werden. Darüber hinaus können komplette Schemata kopiert und als Skript abgelegt werden. Oracle Diagnostic Pack: Dieses Paket bietet als wesentliches Werkzeug eine grafische Unterstützung des Automatic Database Diagnostic Monitors (ADDM). Außerdem gibt es Monitoring Tools und eine event-basierte Überwachung. Oracle Tuning Pack: Über den SQL Access Advisor und SQL Tuning Advisor können hiermit SQL-Befehle einfach optimiert werden. Das Tool Reorganize Objects bietet außerdem eine Schnittstelle für die Online-Reorganisation von Tabellen und Indizes.
Oracle-Komponenten
21
Oracle Configuration Managment Pack: Während es die anderen drei Pakete schon in der Version 8 und folgende gab, ist dieses Paket in Oracle 10g neu hinzugekommen. Oracle empfiehlt den Einsatz dieses Paketes auch deshalb, weil es dadurch möglich ist, Patches automatisch einzuspielen. Ein direkter Link zum Oracle Metalink ermöglicht dies. Außerdem kann eine Oracle-Installation komplett kopiert (Cloning) und Konfigurationen können verglichen werden. Mit einigen dieser Funktionen haben wir uns im Buch näher beschäftigt, da sie häufiger in Projekten zum Einsatz kommen. Andere Funktionen (wie z.B. die Spatial Option) haben einen derart spezialisierten Anwendungskontext, dass wir nicht näher darauf eingehen.
1.2.3 Weitere Produkte In der folgende Auflistung werden einige Produkte erwähnt, die im Umfeld der Oracle Database 10g eine Rolle spielen: Oracle Database Lite: Diese Datenbank ist speziell für den Einsatz auf mobilen Systemen mit wenig Hauptspeicher und Plattenkapazität (z.B. PDA, Windows Mobile) entwickelt worden. Da sie eine eigene Architektur hat, die von der »Standard«-Datenbank abweicht, werden wir sie nicht weiter betrachten. Hervorzuheben ist, dass es umfangreiche Funktionen für den Abgleich von Oracle Database Lite mit der Oracle Database 10g gibt. HTML DB: Hierbei handelt es sich nicht, wie eventuell vermutet, um eine Datenbank, sondern um die Möglichkeit, über einen Webbrowser schnell und bequem Datenbankanwendungen zu schreiben. Sie ist in allen Oracle Database 10g-Editionen enthalten, und auf der Oracle Homepage gibt es eine Vielzahl von Dokumenten für den Einsatz von HTML DB. Oracle Application Server 10g: Sie bildet die Basis für internetbasierende Anwendungen im Oracle-Kontext. Als Middleware wird sie z.B. für den Aufbau von LDAP-Servern (siehe Kapitel 9) oder für den Oracle Developer verwendet. Oracle Collaboration Suite 10g: Hierbei handelt es sich um eine fertige Software für die Informationssammlung bzw. die Kommunikation in Unternehmen. Als Konkurrenzprodukt zu Microsoft Exchange bilden die Oracle Database 10g und der Oracle Application Server 10g die Basis, auf dem dann E-Mails und Terminplanung, aber auch eine eigene Dateiverwaltung implementiert sind. Sicherlich gibt es eine ganze Reihe weitere Produkte, die im Umfeld der OracleDatenbank zum Einsatz kommen. Ihnen allen ist aber gemein, dass die zugrunde liegende Datenbank eine Oracle Database 10g ist.
22
1.3
Einführung
Datenbank-Paradigmen
1.3.1 Das Transaktionsverhalten Hinter dem Begriff Transaktionsverhalten verbirgt sich eine Reihe von Mechanismen, die im Hintergrund der Oracle-Datenbank stattfinden. Sie sind so implementiert, dass ein möglichst reibungsloser Datenbankbetrieb für viele gleichzeitig arbeitende Benutzer sichergestellt wird. Bei der Entwicklung von Datenbankanwendungen ist es ratsam, sich mit diesen Dingen vertraut zu machen, da andernfalls beim Übergang von der EinbenutzerEntwicklungsumgebung zum Mehrbenutzerbetrieb im produktiven Einsatz manche böse Überraschung lauern kann. Transaktionen Einer der ganz großen Unterschiede zwischen einem Datenbankmanagementsystem wie Oracle und flachen Dateisystemen oder einfachen Datenbanken wie MS Access ist die Möglichkeit der Transaktionsverarbeitung, und zwar transparent und automatisch. Eine Transaktion ist dabei wie folgt zu charakterisieren: Eine Transaktion besteht aus einer Folge von Kommandos, die den Inhalt der Datenbank manipulieren. Das Datenbankmanagementsystem garantiert, dass bei erfolgreichem Transaktionsabschluss (COMMIT) alle Änderungen wiederherstellbar in die Datenbank integriert sind oder bei einem Fehler bzw. nicht erfolgreichem Abschluss (ROLLBACK) keine der Änderungen in die Datenbank gelangt. Hierzu kann als einfaches Beispiel eine Überweisung in einer konten-Tabelle dienen: Ein UPDATE-Befehl zieht einen Betrag x vom Kontostand des Kontos A ab, ein weiterer UPDATE-Befehl addiert den Betrag auf den Kontostand des Kontos B. Hierbei sollte der Alles-oder-nichts-Ansatz der Transaktionsverarbeitung schnell klar werden. Die Transaktions-Lesekonsistenz garantiert zusätzlich, dass andere Sitzungen die Auswirkungen einer Transaktion erst nach deren Bestätigung mit COMMIT sehen können. In der Zwischenzeit verhalten sich alle Operationen so, als habe die Transaktion nicht stattgefunden. Alle DML (Data Manipulaton Language)- und DDL(Data Definition Language)Befehle finden in der Oracle-Datenbank im Rahmen von Transaktionen statt; es gibt keine Möglichkeit, das Transaktionsverhalten »auszuschalten«. Autonome Transaktionen Innerhalb der Programmiersprache PL/SQL gibt es die Möglichkeit, einzelne Programmblöcke oder Module als autonome Transaktion zu kennzeichnen. Damit verhalten sich diese als geschachtelte Transaktion, d.h., die autonome Transaktion kann mit COMMIT bestätigt werden, während die übergeordnete zurückgerollt wird. Dies ermöglicht Funktionen wie eine Fehlerprotokollierung als INSERT-Befehle in eine Fehlertabelle, die robust funktioniert. Ohne die autonome Transaktion würde im Fall eines ROLLBACK der übergeordneten Transaktion auch der Eintrag in die Fehlertabelle wieder entfernt.
Datenbank-Paradigmen
23
Sperren Sperren (engl. Locks) werden zur Transaktionssicherung eingesetzt, und zwar ebenso automatisch wie die Transaktionen. Es gibt grundsätzlich zwei verschiedene Arten von Sperren: DML und DDL. DML-Sperren beschützen die Daten selbst, DDL-Sperren Objektdefinitionen (Tabellen, Indizes usw.) im Data Dictionary. Sperren können wiederum verschiedene Typen haben, z.B. kann eine DML-Sperre auf einer Tabelle Row-Exclusive- (der Satz wird exklusiv gesperrt) oder Share-Modus haben (der Satz wird zwar gesperrt, aber nicht exklusiv, d.h., weitere Share-Sperren sind möglich). Sperren verschiedener Modi können wiederum kompatibel oder inkompatibel sein; z.B. ist eine Share-Modus-DDL-Sperre auf einer Tabelle inkompatibel mit einer Row-Exclusive-Modus-DML-Sperre auf der gleichen Tabelle. Kompatible Sperren können gleichzeitig von verschiedenen Sitzungen gehalten werden; inkompatible Sperren führen zu Wartezuständen. Übersetzt in Befehle heißt das z.B., dass ein CREATE INDEX-Befehl, der eine ShareModus-DDL-Sperre auf der zugrunde liegenden Tabelle benötigt, nicht gleichzeitig mit einem UPDATE auf der gleichen Tabelle laufen kann, das eine DML-Sperre im Row-Exclusive-Modus erzeugt. Bis auf wenige Ausnahmen sind DML- und DDL-Sperren nicht kompatibel. Mit anderen Worten heißt das, dass Änderungen im physischen Datenmodell nur dann durchgeführt werden können, wenn keine Anwendungen die Tabelle gleichzeitig modifizieren und umgekehrt. In neueren Versionen versucht Oracle, nach und nach DDL-Befehle so umzubauen oder zu ergänzen, dass sie keine Share-Modus-DDL-Sperren mehr benötigen. Z.B. hat der Befehl SQL> ALTER INDEX
REBUILD ...
ab Oracle8i die Option ONLINE, mit deren Hilfe man einen Index auch bei laufenden Anwendungen neu aufbauen kann. Da es hier jedoch noch viel für die Oracle-Entwickler zu tun gibt, können wir zunächst davon ausgehen, dass auf einer Tabelle entweder nur DDL- oder nur DML-Befehle laufen. In beiden Fällen können mehrere gleichartige Operationen gleichzeitig laufen, z.B. können mehrere Indizes für eine Tabelle aus mehreren Sitzungen gleichzeitig erstellt werden. DDL-Sperren DDL-Sperren befinden sich entweder im Share-Modus (z.B. bei CREATE INDEX- oder AUDIT-Befehlen), im Exclusive-Modus (z.B. bei DROP TABLE) oder sind Breakable Parse Locks. Im Share- oder Exclusive-Modus lassen sie keine gleichzeitigen DML-Sperren zu; als Breakable Parse Locks tauchen sie im Shared Pool gerade bei DML-Befehlen auf. Sie erlauben die Rückverfolgung von SQL-Befehlen im Shared Pool, um diese bei Änderungen der Struktur, z.B. durch ALTER TABLE, als INVALID zu markieren und bei wiederholter Ausführung eine Neuübersetzung zu erzwingen. Sperren im Share-Modus verhalten sich kompatibel zu weiteren Sperren im ShareModus; der Exclusive-Modus ist nur für eine einzige Sperre erlaubt.
24
Einführung
DML-Sperren Eine Besonderheit der Oracle-Datenbank ist sicherlich die Behandlung von Datensatzsperren. Hierfür ist, wie bereits weiter oben erwähnt, der Row-Exclusive-Modus der DML-Sperre zuständig. Dieser Modus ist grundsätzlich automatisch von der Oracle-Datenbank eingestellt, sobald DML-Befehle benutzt werden. Hierbei wird eine Sperre pro Datensatz erstellt, sobald dieser vom DML-Befehl bearbeitet wird. Da die eigentliche Datensatzsperre an einer dafür vorgesehenen Stelle im Row Directory des Datenbankblocks geführt wird, gibt es keinerlei Einschränkung der erlaubten Datensatzsperren pro Transaktion, pro Sitzung oder pro Datenbank. Daher sind Verfahren wie Lock Escalation, bei denen Datensatzsperren in Blocksperren umgewandelt werden, sobald eine bestimmte Anzahl von Datensätzen gesperrt werden soll, in der Oracle-Datenbank nicht notwendig – und daher auch nicht implementiert. Die Datensatzsperre ist grundsätzlich eine sehr gut geeignete Einheit für Sperrverfahren, da für viele Anwendungen hiermit sinnvolles Arbeiten mit mehreren Benutzern möglich ist. Dies bedeutet im Übrigen nicht, dass die Verwaltung der Datensatzsperren keinen Aufwand für die Datenbank bedeutet. Falls man z.B. große Mengen von DML-Befehlen als Batch zu verarbeiten hat und gleichzeitig keine weiteren Operationen laufen, lohnt sich die Anforderung einer ExclusiveModus-DML-Sperre mit dem Befehl: SQL> LOCK TABLE IN EXCLUSIVE MODE;
Oft lassen sich Laufzeiten hiermit um etwa die Hälfte (!) reduzieren. Weiterhin existieren für DML-Sperren die Modi Row Share (für SELECT ... FOR UPDATE), Share und Share Row Exclusive. Letztere sind aus Kompatibilitätsgründen zu früheren Oracle-Versionen (es handelt sich hier um Version 5!) vorhanden und sollten i.A. nicht eingesetzt werden. Alle Modi können mit LOCK TABLE-Befehlen explizit angefordert werden. Deadlocks Mit einem Deadlock ist eine Situation bezeichnet, in der mehrere Sitzungen zyklisch aufeinander warten. Hierzu ein Beispiel mit zwei Sitzungen, die Datensätze einer Tabelle test bearbeiten, deren Datensätze durch die Primärschlüsselspalte x eindeutig bestimmt sind. Sitzung 1
Sitzung 2
UPDATE test SET c='AAA' WHERE x=1; o.k. UPDATE test SET c='AAA' WHERE x=2; o.k. Tabelle 1.1: Deadlock
Datenbank-Paradigmen
Sitzung 1
25
Sitzung 2
UPDATE test SET c='AAA' WHERE x=2; Wartet UPDATE test SET c='AAA' WHERE x=1; wartet ORA-00060: deadlock detected while waiting for resource
o.k.
Tabelle 1.1: Deadlock (Forts.)
In der Praxis kommen Deadlocks eher dann vor, wenn sich Entwickler verschiedener Module einer Anwendung nicht darüber einig sind, in welcher Reihenfolge Datensätze grundsätzlich zu sperren sind, wenn sie aus verschiedenen Tabellen kommen. Z.B. sollte bei Tabellen, die über einen Fremdschlüssel verknüpft sind, immer zuerst die Master-Tabelle, dann die Detail-Tabelle gesperrt werden. Lesekonsistenz Als äußerst wichtige Eigenschaft der SQL-Verarbeitung in der Oracle-Datenbank gilt, dass lesende Befehle (SELECT) keinerlei DML-Sperren verursachen. Damit ist die Lauffähigkeit von Berichten parallel zur Transaktionsverarbeitung grundsätzlich sichergestellt. Neben dem Lesekonsistenz-Grundsatz bei der Transaktionsverarbeitung, der besagt, dass keine Änderungen einer Transaktion von anderen Sitzungen gesehen werden, wenn die Transaktion noch nicht beendet ist, gibt es in diesem Zusammenhang jedoch eine weitere Lesekonsistenz-Eigenschaft. Diese besagt, dass keine Änderungen bei der Abarbeitung eines SQL-Befehls gesehen werden, die beim Start der Verarbeitung noch nicht durch COMMIT bestätigt sind. Hierdurch wird sichergestellt, dass das Ergebnis einer Abfrage immer korrekt ist, auch wenn es sich auf einen Zeitpunkt in der Vergangenheit bezieht. Würde die Lesekonsistenz in dieser Form nicht eingehalten werden, so würden dadurch falsche Ergebnisse möglich, eben weil beim SELECT keine Sperren ausgelöst werden. Isolation Level Das Setzen des Lesekonsistenzzeitpunkts auf den Anfang einer Abfrage hat zur Folge, dass eine Abfrage, die mehr als einmal innerhalb einer Transaktion ausgeführt wird, unter Umständen bei jeder Ausführung ein anderes Ergebnis liefert. Für die Transaktionsverarbeitung von Datenbanken sind von den Standardisierungsgremien Isolation Level definiert worden. Der eben beschriebene wird dabei als Read Committed bezeichnet. Es besteht die Möglichkeit, dass eine Anwendung hiermit nicht ausreichend geschützt ist. Hierfür ist der Isolation Level Serializable vorgesehen. Dieser erlaubt einer Transaktion, immer nur die Änderungen zu sehen, die bereits bei Transaktionsanfang bestätigt waren (und natürlich die eigenen Änderungen). Mehrfach ausgeführte Abfragen innerhalb der Transaktion garantieren hiermit stets das gleiche Ergebnis,
26
Einführung
es sei denn, die eigene Transaktion hat die Daten modifiziert. Sobald die Transaktion versucht, Datensätze zu bearbeiten, die von anderen Transaktionen seit dem Transaktionsanfang bereits bearbeitet worden sind, wird dies mit folgender Fehlermeldung abgelehnt: ORA-08177: can't serialize access for this transaction
In diesem Fall sollte die Transaktion zurückgerollt und neu gestartet werden, da die Startbedingungen sich geändert haben. Auch wenn der Isolation Level Serializable ein noch konsistenteres Arbeiten ermöglicht als Read Commited, empfiehlt Oracle aus Performancegründen letzteren. Weiterhin kann der Anwendungsentwickler durch explizites Sperren (mittels SELECT ... FOR UPDATE) für konsistentes Verhalten sorgen und so trotzdem die Performancevorteile nutzen. Praxisrelevant ist außerdem der Isolation Level Read Only. Dieser setzt wie Serializable den Lesekonsistenzzeitpunkt auf den Beginn der Transaktion, erlaubt jedoch keine eigenen DML-Kommandos, sondern ausschließlich SELECT-Befehle. Hiermit können z.B. in sich konsistente Berichte bei gleichzeitig laufenden Transaktionen erzeugt werden. Mit der Einführung der Flashback-Technologie ist es über die Flashback-Query außerdem möglich, über den Zusatz AS OF TIMESTAMP … den Zeitpunkt für die Selektion der Daten zu bestimmen.
1.4
Aufgaben eines DBA
Welches Aufgabenspektrum sich hinter der Bezeichnung Datenbankadministration verbirgt, ist pauschal nicht so einfach zu beantworten und erfahrungsgemäß auch nicht unumstritten. Wir möchten daher an dieser Stelle aus unseren Erfahrungen heraus Antworten und Empfehlungen auf einige zentrale Fragen geben: Was sollten die zentralen Aufgaben eines DBA sein (das Kerngebiet)? Wo müssen Interdependenzen mit anderen Teilen der IT-Infrastruktur (Storage, Netzwerk, Betriebssystem, kaufmännischer Bereich etc.) berücksichtigt werden? In welchen Bereichen sollte der DBA unterstützend bzw. für strategische Entscheidungen beratend arbeiten? Welche Aufgaben sollten nicht beim DBA angesiedelt sein, sind es aber in der Praxis? Wo sind Kompetenzüberschneidungen mit anderen IT-Abteilungen zu erwarten?
Aufgaben eines DBA
27
1.4.1 Kerngebiete der DB-Administration Dazu gehören sicherlich die folgenden Themen, die eindeutig in die Kompetenz des DBA fallen, da sie zentrale Datenbankressourcen betreffen bzw. schema-übergreifende und anwendungsunabhängige Auswirkungen haben. Installation von Oracle-Software und -Datenbanken. Vorher muss geklärt werden, welche Anforderungen bzgl. Datenbankfunktionen seitens der Benutzer bzw. Anwendungen bestehen und ob entsprechende Lizenzen zur Verfügung stehen. Sicherung der Datenbanken. Bei der Sicherung existiert ein breites Spektrum von Varianten, wie dieses Thema technisch umgesetzt wird. Auf der einen Seite kann bei wenigen, kleinen Datenbanken das Thema vollständig beim DBA angesiedelt sein. Dagegen existieren gerade bei größeren Datenbanken oder umfangreichen DB-Landschaften starke Abhängigkeiten zum Storage-Bereich, wo mit Technologien wie z.B. EMC2 BCVs das Splitting einzelner Disk-Gruppen und das Abziehen der BCVs auf Band geleistet wird. Die Koordinierung der Backup-Jobkette geschieht häufig über Scheduler wie bspw. Maestro. Im Extremfall beschränkt sich die Arbeit des DBA auf das Scripting einzelner Schritte der Job-Kette. Rücksicherung/Wiederherstellung einer Datenbank. Diese Arbeit lässt sich viel weniger automatisieren als das Backup, da zahlreiche Szenarien mit sehr unterschiedlichen, sich zum Teil überschneidenden Lösungswegen denkbar sind. Eine genaue Situationsanalyse (Sichtung des Alert-Logs und sonstiger Trace-Dateien) mit spezifischem Datenbank-Know-how ist nötig, bevor eine Entscheidung für eine bestimmte Wiederherstellungsprozedur gefällt werden kann. Sind Plattensysteme beeinträchtigt, ist ggf. wiederum eine Abstimmung mit dem StorageBereich angesagt, ebenso für die Rücksicherung einzelner Komponenten. Monitoring der Datenbanken. Abhängig von der Art auftretender Probleme ist eine Lösung entweder selbsttätig möglich (z.B. Hinzufügen einer Datendatei), oder es ist eine Abstimmung mit anderen Beteiligten notwendig. Damit – vor allem im ersten Fall – nach außen hin nicht der unzutreffende Eindruck entsteht, die Datenbank sei ein Selbstläufer (typische Frage: »Was macht eigentlich unser DBA?«), sollte Monitoring immer auch mit einem Reporting, also der Erstellung regelmäßiger Berichte (wöchentlich oder monatlich) über das Verhalten der Datenbank sowie aufgetretene und gelöste Probleme verbunden sein (»Health Checks«). Einspielen von Updates und Patches: Bei 24x7-Systemen ist hier eine Abstimmung über eine mögliche Auszeit notwendig. Wichtig ist, solche Operationen vorher einmal möglichst realitätsnah durchzuspielen, um auftretende Probleme zu erkennen und eine zeitliche Abschätzung geben zu können. In manchen Fällen wird von einer Anwendung nur ein bestimmter Oracle-Patch-Level (z.B. 10.1.0.4) unterstützt, höhere Patch-Level dagegen werden (noch) nicht offiziell unterstützt.
28
Einführung
Troubleshooting: Auftretende Probleme verlangen zum einen spezifisches Datenbank-Know-how, zum anderen auch die Fähigkeit einzuschätzen, ob das Problem datenbankseitig zu lösen ist oder eher Ursachen im Storage- oder Netzwerkbereich hat. Entsprechende Informationen (Performance-Statistiken) finden sich in V$-Statistiken und deren archivierten Varianten, den dba_hist%Tabellen (bspw. schlechte I/O-Zeiten für einzelne Datendateien oder unrealistisch hohe CPU-Zeiten, die auf ein Paging seitens des Betriebssystems hinweisen). An dieser Stelle kann es immer wieder zu Problemen kommen, wenn die Oracle-seitigen Statistiken von anderen IT-Beteiligten nicht anerkannt werden und auf diese Weise Pingpong mit den Verantwortlichkeiten gespielt wird. Regelmäßige Performance-Berichte (»Health Checks«) können auch hier eine große Hilfe darstellen, da sie allmähliche oder plötzliche Veränderungen gut dokumentieren. Grundlegendes Tuning der Datenbank: Hier geht es nicht um SQL-Tuning oder das Anlegen von Indizes, sondern um datenbankweite Maßnahmen wie Instanz-Parametrierung oder die Analyse von Trefferquoten. Globale Sicherheitsaspekte, z.B. Auditing, also das Überwachen bestimmter Aktionen wie An- und Abmeldungen, die Verschlüsselung der Oracle Net-Kommunikation (nicht jedoch die Verschlüsselung von Daten, das ist Aufgabe der Anwendungen) sowie Zugriffsrechte auf Datenbankdateien, die PasswortVerwaltung für Administrator-Accounts, Instanz-Parametrierung etc.
1.4.2 Bereiche mit DBA-Unterstützung In einigen Bereichen sollte der DBA unterstützend bzw. in Abstimmung mit anderen Gruppen arbeiten, insbesondere: bei strategischen Entscheidungen für oder gegen bestimmte Tools, Programme, und Technologien. Hierfür ist neben monetären Aspekten vor allem eine Einschätzung über die Praxistauglichkeit einer Technologie und über ihre Verträglichkeit mit anderen bereits eingesetzten Technologien notwendig. Dies erfordert in den allermeisten Fällen tief gehendes Know-how und Erfahrungswerte. Natürlich fallen solche Fragen nicht vom Himmel, sondern ergeben sich aus den Anforderungen von Entwicklern und Anwendungen bzw. aus Service-Level-Agreements (z.B. Hochverfügbarkeit durch Cluster- und Replikationslösungen oder RAC). Hier wirkt der DBA gewissermaßen als Dienstleister, der ein bestimmtes Technologie-Portfolio bereitstellt. Der DBA sollte auch mit der Lizenzpolitik und den lizenztechnischen Einzelheiten von Oracle vertraut sein, um kaufmännische Entscheidungen bzgl. Erwerb, Aufstockung oder Konsolidierung von Lizenzen zu unterstützen.
Aufgaben eines DBA
29
1.4.3 Aufgaben, die nicht beim DBA angesiedelt sein sollten Benutzer-, Rollen- und Rechteverwaltung für Anwendungen: Obwohl dies häufig als eine der typischen DBA-Tätigkeiten angesehen wird, möchten wir dieser Auffassung hier widersprechen. Der DBA hat in den meisten Fällen keine Sachkompetenz im Hinblick auf Privilegien. Er kann nicht entscheiden, ob ein bestimmter Anwender das Recht haben darf, bestimmte Tätigkeiten im Rahmen einer Applikation auszuführen. Da die technische Durchführung einer Rechtevergabe unproblematisch ist, stellt sich die Frage, warum der DBA überhaupt mit dem ganzen Thema berührt werden sollte. Sinnvoller erscheint uns folgende Aufgabenteilung: Alle Rechte, die von einer Anwendung und deren Benutzer benötigt werden, werden von den Entwicklern in geeigneten Rollen zusammengestellt. Die Standardbenutzer einer Anwendung (Eigentümer der Objekte, Staging-Benutzer usw.) werden ebenfalls durch die Anwendungsentwicklung vorgegeben und mit Rechten versehen. Das Anlegen und die Rechteausstattung sonstiger Anwender kann technisch in PL/SQL-Prozeduren ausgelagert werden, die bereits entsprechende Plausibilitätsprüfungen enthalten. Diese Prozeduren werden vom DBA bereitgestellt, Ausführungsrechte werden an spezielle Anwendungsadministratoren gegeben, die eine Schnittstelle bilden zwischen den Entwicklern und dem DBA. Diese können somit im Rahmen der Plausibilitäten autonom entscheiden, wer welche Rechte für die Anwendung erhält. Unterstützung bei der Anwendungsentwicklung: Auch wenn ein DBA sicherlich gute Tipps bspw. im Hinblick auf Performance-Aspekte bei der Entwicklung (Anlegen geeigneter Indizes, Schreiben von effizientem SQL) geben kann, ist es schon aus Zeitgründen i.A. nicht möglich, dies regelmäßig zu tun. Es sollte vielmehr Aufgabe der bereits genannten Anwendungsadministratoren sein, die Entwickler zu betreuen und für diese eine Schnittstelle zum DBA zu bilden. Anwendungs-Tuning: Die Argumente des letzten Punkts können hier analog wiederholt werden. Es kommt noch hinzu, dass ein Großteil des AnwendungsTunings aus dem Überarbeiten von SQL-Kommandos sowie dem Abschätzen von Datenmengen und Datenverteilungen besteht. Dies setzt ein genaues fachliches Verständnis der Anwendungsobjekte und SQL-Befehle voraus (»Was soll diese Abfrage eigentlich liefern?«), daher ist hier Teamarbeit zwischen den Entwicklern und den Anwendungsadministratoren notwendig. Neue Software-Releases: Auch hier gilt dieselbe Argumentation: Natürlich ist vor dem Einspielen eines neuen Software-Release eine Abstimmung zwischen Anwendungsadministrator und DBA erforderlich, eine tiefer gehende Beschäftigung mit den technischen Eigenheiten des neuen Release sollte aber nicht notwendig sein. Allerdings liegt es im Aufgabenbereich eines Administrators, sich bezüglich der Oracle-Releases auf dem Laufenden zu halten. Naturgemäß lassen sich nicht alle Situationen in die oben genannten Schubladen einordnen, speziell in kleineren Unternehmen gibt es immer wieder Überschneidungen zwischen Entwicklung und Administration, aber auch in großen Unternehmen sollten Administratoren gleichberechtigt beim Aufbau neuer Anwendungen beteiligt sein.
Installation und Aufbau einer Datenbank In diesem Kapitel wollen wir Ihnen zeigen, wie Sie eine Datenbank schnell und einfach aufbauen können, die in vielen Fällen ausreichend für den Betrieb einer produktiven Anwendung ist. Oracle verfolgt mit der Version 10g den Ansatz, die Installation und Konfiguration einer Standarddatenbank möglichst unkompliziert zu machen, d.h., ohne die diversen Optionen, Parameter und Spezialfälle zu betrachten. Das wird schon dadurch ersichtlich, dass für die Software nur eine CD benötigt wird. Nach deren Einlegen wird wie bei Windows-Systemen üblich das Setup aufgerufen, durch das der Universal Installer gestartet wird. Auf dem Eingangsbildschirm können dann alle erforderlichen Parameter eingegeben werden, um damit eine so genannte Basisinstallation durchzuführen. Diese Installationsart werden wir in Kapitel 2.1 als Erstes betrachten. Im Weiteren werden wir dann auf einige alternative Konfigurationsmöglichkeiten eingehen. Bevor wir aber mit der Installation starten, sollen zum besseren Verständnis einige Variablen geklärt werden: ORACLE_BASE: Dieser Parameter kennzeichnet das Basisverzeichnis für alle Installationen. Wenn dieser Parameter gesetzt wird, werden die Komponenten Software, Datenbank und administrative Dateien automatisch voneinander getrennt (z.B. D:\oracle). Näheres hierzu finden Sie im Kapitel 2.3 (Software Installation). ORACLE_HOME: Dieser Parameter ist der wichtigste für alle Oracle-Datenbanken. Zunächst gibt er bei der Installation an, in welches Verzeichnis die Software installiert werden soll (z.B. D:\oracle\product\10.1.0\db). Nach der Installation befindet sich im Unterverzeichnis bin der Oracle-Kernel, so dass hierüber während des normalen Betriebs angegeben wird, mit welchem Kernel diese Datenbank arbeitet. ORACLE_SID: Dieser Parameter kennzeichnet den Namen der Datenbankinstanz und damit in den meisten Fällen zunächst den Namen der Datenbank. Bei einer neuen Installation über Easy Installation oder den Database Configuration Assistant wird diese Variable mit dem Datenbanknamen gefüllt. Der hier verwendete Name darf allerdings nicht länger als acht Zeichen sein. ORACLE_HOME_NAME: Außerdem erhält jede Oracle-Installation einen eigenen logischen Namen, über die z.B. unter MS-Windows die Dienste identifiziert werden können. (z.B. Ora10g_home1). In der MS-Windows Registry finden Sie unter dem Eintrag HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE das Unterverzeichnis KEY_%ORACLE_ HOME_NAME% mit allen wichtigen Parametern dieser Installation.
32
Installation und Aufbau einer Datenbank
Sie sollten immer darauf achten, wie diese Parameter gesetzt sind. Beispiel Unix: ORACLE_BASE=/app/oracle ORACLE_HOME=$ORACLE_BASE/product/10.1.0/db_1 ORACLE_SID=SUN10G
Beispiel MS-Windows set ORACLE_BASE=D:\oracle set ORACLE_HOME=%ORACLE_BASE%\product\10.1.0\db_1 set ORACLE_SID=WIN10G
2.1
Basisinstallation
Das folgende Bild erscheint, wenn Sie den SETUP-Befehl auf der CD ausführen oder unter Unix den Befehl runInstaller im Basisverzeichnis der CD aufrufen.
Abbildung 2.1: Basisinstallation
Der erste Bereich kennzeichnet die Basisinstallation – auch Easy Installation genannt, in der Sie die zu installierende Version und den Speicherort auswählen. Im Gegensatz zu früheren Versionen wird als Speicherort ein weiteres Unterverzeichnis (hier Db_1) angelegt. Der Grund hierfür ist unter anderem, dass der Enterprise Manager Grid Control ein eigenes ORACLE_HOME braucht. In einigen Fällen kann es außerdem sinnvoll sein, je Produktionsdatenbank eine eigene Software zu installieren, da dadurch im Falle eines Release-Wechsels oder dem Einspielen eines Patches alle Datenbanken einzeln migriert werden können. Natürlich sind auch
Basisinstallation
33
andere Verzeichnisstrukturen möglich, Sie sollten aber immer bedenken, dass diese Struktur ein Höchstmaß an Flexibilität gewährleistet. Das gewählte Verzeichnis sollte leer sein (Unterverzeichnis Lost+Found bei Unix-Filesystemen ist natürlich erlaubt). Bei den verwendeten Versionen können Sie wählen zwischen Personal, Standard und Enterprise Edition. Diese sollte Ihrer tatsächlich lizenzierten Version entsprechen. Nähere Informationen erhalten Sie im Kapitel 2.2. Als Nächstes haben Sie die Möglichkeit, eine Datenbank direkt mit anzulegen. Dabei müssen Sie dann den Datenbanknamen sowie das Kennwort der wichtigsten Datenbank-Schemata (SYS, SYSTEM, SYSMAN und DBSNMP) angeben. Bekannte Kennwörter wie z.B. MANAGER, CHANGE_ON_INSTALL, SYSMAN oder DBSNMP werden abgelehnt. Außerdem ist es nicht möglich, unterschiedliche Kennwörter zu vergeben, später können Sie das natürlich nachholen. Nachdem Sie diese Informationen eingegeben haben, bekommen Sie nochmals eine Übersicht über die ausgewählten Komponenten, bevor dann mit der Installation begonnen wird. Bei MS-Windows-Systemen wird nach einiger Zeit folgende Fehlermeldung erscheinen:
Abbildung 2.2: OCR-Fehlermeldung
An dieser Stelle müssen Sie ein DOS-Fenster öffnen und eine Änderung vornehmen. Gehen Sie dafür in das ORACLE_HOME\bin–Verzeichnis, und führen Sie folgende Befehle aus: > clscfg –local –o %ORACLE_HOME% -l > net start oraclecsservice
Danach sollte der Oracle Cluster Synchronization Service gestartet sein, und Sie können mit der Installation fortfahren. Wenn Sie keine ASM-Instanzen benötigen (siehe Kapitel 2.4), können Sie die Fehlermeldung einfach ignorieren. Zum Schluss erhalten Sie dann die Meldung, dass die Datenbank erfolgreich angelegt worden ist. Hier haben Sie dann nochmals die Möglichkeit, die Kennwörter der Administrationsschemata zu ändern. Sie können jetzt mit verschiedenen Werkzeugen als J2EE-Anwendungen auf die Datenbank zugreifen. Die Liste der verfügbaren Werkzeuge mit den entsprechenden TCP-Ports erhalten Sie auf der letzten Seite der Installation.
34
Installation und Aufbau einer Datenbank
Abbildung 2.3: J2EE-Anwendungen
Diese Liste finden Sie nochmals im Verzeichnis %ORACLE_HOME%/install in der Datei portlist.ini. Diese Installation dauert unter MS-Windows ca. eine Stunde, und danach haben Sie eine voll funktionsfähige Oracle-Datenbank. Natürlich ist es später jederzeit möglich, bestimmte Parameter zu ändern; alternativ können Sie aber auch direkt zur benutzerdefinierten Installation wechseln, die wir im Folgenden besprechen.
2.2
Installationsplanung
Nachdem wir in Kapitel 2.1 eine Basisinstallation besprochen haben, wenden wir uns jetzt einer komplexeren Installation zu, in der alle Komponenten und Optionen wählbar sind. Diese Art der Installation findet man in allen größeren Unternehmen, bei denen Hochverfügbarkeit (z.B. Trennung von Software und Datenbank) eine Rolle spielt oder in denen eigene Verfahren bzw. Verzeichnisstrukturen verwendet werden. Die hier mögliche größere Flexibilität bedeutet aber auch, dass es vor der eigentlichen Installation eine Planung geben muss. Diese teilt sich in folgende Bereiche: 1. Hardware und Betriebssystem 2. Art der Anwendung 3. Benötigte Optionen und Features 4. Anzahl Datenbanken
Installationsplanung
35
Im Kapitel 2.2.1 werden wir uns daher zunächst einmal näher mit den unterschiedlichen Hardware-Komponenten und Betriebssystemen befassen, bevor wir in Kapitel 2.2.2 die Anwendungen betrachten und damit auch schon auf die Optionen von Kapitel 2.2.3 eingehen. In Kapitel 2.2.4 schließlich beschäftigen wir uns mit der Frage, wie viele Datenbanken man braucht bzw. wann eine Konsolidierung oder Diversifizierung notwendig ist.
2.2.1 Hardware und Betriebssystem Eine Eigenschaft des Oracle-Datenbanksystems, die immer wieder beobachtet werden kann, ist die bedingungslose Ausnutzung bereitgestellter Ressourcen. Diese Tatsache kann man aus mehreren Blickwinkeln betrachten und sowohl positive – »Das System besitzt einen hohen Durchsatz.« – als auch negative – »Das System beschränkt Ressourcen für andere Dienste auf der gleichen Hardware.« – Schlussfolgerungen ziehen. Man kann jedoch genauso gut aus den Fakten lernen und einige Tipps für eine gut funktionierende Gesamtkonfiguration ableiten. Die erste Grundregel für Oracle-Installationen lautet, dass, soweit möglich, andere Software-Systeme auf getrennten Rechnern installiert werden sollen. Diese Vorgehensweise verhindert, dass Datei- und Druckserver, Domänen-Kontrollsysteme sowie das Oracle-Datenbanksystem die meiste Zeit damit verbringen, sich gegenseitig Ressourcen streitig zu machen. Jedes Software-System kann bei getrennter Hardware exakt die per Installation zugeteilten Ressourcen nutzen. Umgekehrt heißt das, dass ein überlastetes System die anderen Systeme nicht in Mitleidenschaft ziehen kann. Die Auslegung von Prozessorstärke, Hauptspeichergröße und EA-System ist naturgemäß stark abhängig von den Aufgaben des Datenbankservers: Von der Kundenverwaltung für einige Mitarbeiter bis zu zentraler Verwaltung von riesigen Datenmengen mit mehreren tausend Verbindungen ist alles mit einem Oracle-System machbar. Als Minimalkonfiguration sollte folgende Konstellation angenommen werden: Der Prozessor sollte einer recht neuen Generation angehören. Falls große Leistungsreserven bereitgestellt werden müssen, sollten zunächst die einzelnen Prozessoren so leistungsfähig wie möglich eingesetzt und erst dann eine Mehrprozessorkonfiguration in Betracht gezogen werden. Gründe hierfür sind, dass eine solche Konfiguration immer eine gewisse zusätzliche Belastung gegenüber einem Einprozessorsystem bedeutet und dass für jedes System eine absolute Grenze der Skalierbarkeit bezüglich der Anzahl der Prozessoren gegeben ist, die man mit kleinen Prozessoren natürlich schneller erreicht. Die Grenzen der Skalierbarkeit sind im Allgemeinen weniger vom Oracle-System gegeben als vom darunter liegenden Betriebssystem oder der verwendeten Anwendungssoftware. Natürlich spielt auch die Lizenzierung der Oracle-Software eine Rolle, da in der Regel die Software je CPU lizenziert werden muss. Daher ist ein sehr leistungsfähiger Prozessor (z.B. AMD Opteron oder Intel Itanium) weniger starken Mehrprozessorsystemen vorzuziehen. Die eingesparten Lizenzkosten sind sicherlich größer als die Mehrkosten durch neue CPUs.
36
Installation und Aufbau einer Datenbank
Der Hauptspeicherausbau für ein Oracle-System sollte auf keinen Fall weniger als 1 GByte betragen. Je nach Konfiguration nimmt die Oracle-Instanz im Minimalfall 100 MByte in Anspruch, dazu kommen Ressourcen für das Betriebssystem und zusätzliche Oracle-Prozesse, wie z.B. der Enterprise Manager. Je nach Anwendung und Zahl der Verbindungen beträgt die Größe des Hauptspeichers eines Oracle-Servers durchaus einige GB bis einige zehn GB. Daher sollte auf die Skalierbarkeit des Hauptspeichers geachtet werden, eine 64-Bit-CPU ist somit erste Wahl. Beim EA-System sind neben den reinen Kapazitätsüberlegungen auch Lastverteilungs- und Redundanzfragen zu klären. Grundsätzlich ist eine Verteilung anzustreben, in der Betriebssystem- und Oracle-Software-Installation, eventuelle Auslagerungsbereiche, Datendateien, Redo-Log-Dateien sowie die archivierten Redo-Log-Dateien und Recovery-Bereiche jeweils auf unterschiedlichen Festplatten oder Festplattengruppen liegen. Diese Verteilung ist mit modernen Festplattensystemen nicht leicht einsehbar, da für viele Installationen die Summe des Platzbedarfs für alle genannten Bereiche nicht größer als die Kapazität einer handelsüblichen Festplatte ist. In solchen Fällen hilft nur die wiederholte Überlegung, in welcher Art und Weise eine Datenbanksoftware auf EA-Ressourcen zugreift und wie wichtig die gespeicherten Daten schließlich sind. Die wichtigste Empfehlung von allen ist: Halten Sie Ihr System erweiterbar! Nur dadurch verhindern Sie, dass Sie auf eine komplett andere Hardware umstellen müssen, sobald Sie in einer zukünftigen Optimierungsbetrachtung auf Ressourcenengpässe stoßen. Die Erweiterung von Rechen-, Speicher- oder EA-Kapazität ist eine durchaus häufig vorkommende – und durch die am Kapitelanfang diskutierte Eigenschaft des Oracle-Datenbanksystems meist erfolgreiche – Maßnahme. Betriebssystem Die Wahl eines geeigneten Betriebssystems für eine Oracle-Software-Installation ist wohl eine der meistdiskutierten Fragen in der Gemeinschaft der Oracle-Administratoren. Wo vor einigen Jahren noch eine klare Grenze zwischen MS-Windows1 (für kleinere Installationen) und Unix (für größere Installationen und bei Bedarf für große Reserven) zu ziehen war, ist mittlerweile eine Diskussion an diversen Fronten entbrannt. Einerseits wird MS-Windows immer erwachsener, d.h., Eigenschaften wie Verfügbarkeit, Skalierbarkeit und Administrierbarkeit werden immer mehr in die Oracle-für-Windows-Welt projiziert; andererseits bekommt MS-Windows als Basis für Oracle-Installationen auf dem angestammten PC-Server-Sektor ernst zu nehmende Konkurrenz durch Linux. 1
Um ein ständiges Aufzählen der möglichen Varianten für Oracle-Serverinstallationen, nämlich MSWindows 2000, MS-Windows 2003, MS-Windows XP etc., zu vermeiden, wird ab sofort MS-Windows als Synonym für alle Varianten verwendet. Nur bei der expliziten Betrachtung werden die Varianten jeweils benannt.
Installationsplanung
37
Dieses Buch wird gar nicht erst versuchen, eine abschließende Antwort auf die Frage nach dem besten Betriebssystem zu geben, da – abgesehen von persönlichen Präferenzen – jedes System sicherlich neben seinen Nachteilen auch Vorteile gegenüber den anderen Systemen zu bieten hat. In diesem Abschnitt soll lediglich versucht werden, einige Fakten über die diversen Systeme objektiv darzustellen, um Ihre persönliche Entscheidung ein wenig zu erleichtern. Am Anfang steht jedoch die Diskussion der betriebssystemunabhängigen Eigenschaften, die auf jeden Fall zur Verfügung stehen. Für Oracle gibt es eine einfache Antwort auf diese Frage: Wählen Sie das Betriebssystem, das zu Ihnen bzw. den Hard- und Software-Anforderungen passt. Das heißt, Oracle bietet die gleiche Datenbanksoftware für unterschiedliche Betriebssysteme an, wobei es auch keinen Unterschied in der Administration macht, mal abgesehen davon, dass beim Betriebssystem VMS ein Verzeichnis anders aussieht als unter Unix oder MS-Windows. Die Frage nach dem Betriebssystem wird also entweder durch Vorgaben des Unternehmens (welches Betriebssystem wird bereits eingesetzt, wo haben wir das größte Know-how) geklärt, oder es richtet sich nach der benötigten Hardware. Wir werden nur in wenigen Fällen eine Unterscheidung zwischen des Systemen machen und uns in den Beispielen auf MS-Windows (Windows 2000 und Windows XP), SUN Solaris und Linux beschränken. Betriebssystemunabhängige Eigenschaften der Oracle-Datenbank Zunächst einmal ist es wichtig klarzustellen, dass eine Entscheidung für das Betriebssystem unter einer Oracle-Datenbank keine endgültige ist. Es ist zwar jeweils mit Aufwand verbunden, aber eine Oracle-Datenbank kann immer von einer Plattform auf eine andere migriert werden. Programme, die mit einer OracleDatenbank auf einer Plattform laufen, tun dies mit Sicherheit auch auf jeder anderen Oracle-Datenbankplattform. Zur Migration muss – neben lizenztechnischen Dingen – jeweils das Problem der Auszeit zwischen der letzten Verfügbarkeit des Quellsystems und der ersten Verfügbarkeit des Zielsystems gelöst werden. Diese Auszeit kann relativ lang sein, da die Daten aus der Quelldatenbank entladen und in die Zieldatenbank geladen werden müssen, was z.B. einen Neuaufbau aller Indizes erfordert. Das simple Kopieren der Datenbankdateien ist definitiv nicht möglich. Es lohnt sich also, einen solchen Übergang gut zu planen und eventuell mit einer Datenbankreorganisation zusammenzuführen. Die wichtigsten betriebssystemunabhängigen Werkzeuge, mit denen eine Migration von einer Plattform zur anderen möglich ist, sind Export und Import bzw. die in Oracle 10g erstmals vorhandenen Tools DataPump-Export und Import. Ihre Unabhängigkeit erlangen diese mit dem Export-Dateiformat, das eine betriebssystemunabhängige Binär-Struktur hat und somit von einer Plattform zur anderen transferiert werden kann. Durch die Abwärtskompatibilität des Importwerkzeugs ist zusätzlich auch eine Versionsmigration möglich (nur Export/Import). Mit einigen Tricks2 – und dem Verzicht auf Beibehaltung neuester Merkmale – kann man 2
Hierbei handelt es sich um das Einspielen eines älteren Exportkatalogs sowie den Zugriff mit einem der Versionsnummer entsprechenden Exportwerkzeug auf die Datenbanksoftware mit neuerer Versionsnummer.
38
Installation und Aufbau einer Datenbank
sogar Daten in einen Export mit kleinerem Versionsstand entladen, so dass das Zurückmigrieren auf eine kleinere Versionsnummer im Bedarfsfall (z.B. wenn auf der Zielplattform die neueste Version noch nicht verfügbar ist) ebenfalls machbar ist. Die Oracle-Systemarchitektur ist als Mehrprozessarchitektur inklusive der Nutzung gemeinsamer Hauptspeicherbereiche bei allen Plattformen vorhanden; allein die Implementierung ist teilweise stark unterschiedlich. Damit sind auf allen Plattformen die Voraussetzungen für gute Skalierbarkeit mit den Hardware-Ressourcen gegeben. Vor der eigentlichen Installation sind – unabhängig vom gewählten Betriebssystem – die plattformspezifischen Installationsanweisungen zu beachten: Oft finden sich hier Hinweise auf erforderliche Betriebssystemversionen oder Patch-Level sowie im Betriebssystem zu konfigurierende Parameter. Eine Aufstellung der aktuellen Richtwerte an dieser Stelle macht leider keinen Sinn, da diese sich für neue Releases zu schnell ändern. Aktuelle Installationsanweisungen sind für die wichtigsten Plattformen im Oracle Technet (http://otn.oracle.com) frei verfügbar; außerdem sind entsprechende Anweisungen als HTML- und/oder PDF-Dokumente bei jeder SoftwareAuslieferung enthalten. Oracle unter Unix Durch die große Anzahl an Unix-Plattformen, die in den Unternehmen als Serverplattformen betrieben werden, ist der Einsatz von Oracle auf Unix-Systemen wohl immer noch die am meisten eingesetzte Variante. Aus diesem Grund ist das UnixDerivat (Sun) Solaris auch die Entwicklungsplattform für die Oracle Database-Software; andere Derivate wie HP-UX, (IBM) AIX und HP-Tru64 werden sehr schnell nach Verfügbarkeit der Solaris-Version freigegeben. Aufgrund der langjährigen Erfahrung der Oracle-Entwickler mit Unix-Systemen können den entsprechenden Oracle-Versionen sowohl große Stabilität als auch sehr gute Performance-Eigenschaften bescheinigt werden. Die Prozessarchitektur für die Oracle Database-Software ist de facto der Standard, der nur bei wenigen Ausnahmen modifiziert wird (siehe die Implementierung unter MS-Windows).
Abbildung 2.4: Oracle-Prozesse unter Unix mit Speicherstruktur SGA
Installationsplanung
39
Diese Struktur lässt sich sofort an der Ausgabe eines ps-Kommandos (in diesem Beispiel unter Linux) nachvollziehen: UID oracle oracle oracle oracle oracle oracle oracle oracle oracle oracle oracle oracle oracle oracle oracle oracle oracle oracle
PID PPID C STIME TTY TIME CMD 2204 1 0 13:37 ? 00:00:00 ora_pmon_JAUX10G 2206 1 0 13:37 ? 00:00:00 ora_mman_JAUX10G 2208 1 0 13:37 ? 00:00:00 ora_dbw0_JAUX10G 2210 1 0 13:37 ? 00:00:00 ora_lgwr_JAUX10G 2212 1 0 13:37 ? 00:00:00 ora_ckpt_JAUX10G 2214 1 0 13:37 ? 00:00:00 ora_smon_JAUX10G 2216 1 0 13:37 ? 00:00:00 ora_reco_JAUX10G 2218 1 0 13:37 ? 00:00:00 ora_cjq0_JAUX10G 2222 1 0 13:37 ? 00:00:00 ora_rvwr_JAUX10G 2226 1 0 13:38 ? 00:00:00 ora_arc0_JAUX10G 2228 1 0 13:38 ? 00:00:00 ora_arc1_JAUX10G 2230 1 0 13:38 ? 00:00:00 ora_ctwr_JAUX10G 2233 1 0 13:38 ? 00:00:00 ora_qmnc_JAUX10G 2236 1 1 13:38 ? 00:00:00 ora_mmon_JAUX10G 2238 1 0 13:38 ? 00:00:00 ora_mmnl_JAUX10G 2292 1 14 13:38 ? 00:00:02 ora_j000_JAUX10G 2295 1 6 13:38 ? 00:00:00 ora_q000_JAUX10G 2224 1 6 13:38 ? 00:00:03 oracleJAUX10G (DESCRIPTION=(LOCAL=YES)(ADDRESS=(PROTOCOL=beq)))
Listing 2.1: Oracle-Prozesse unter Unix
Am obigen Beispiel wird deutlich, dass im Standardbetrieb durchaus mehr Hintergrundprozesse existieren. Die weiteren werden wir an entsprechender Stelle näher beschreiben. Die Interprozesskommunikation wird unter Unix grundsätzlich mit Semaphoren realisiert; der Zugriff auf den gemeinsamen Speicherbereich, die SGA, mit Shared Memory. Bei der Installationsvorbereitung ist darauf zu achten, dass beide Komponenten installiert und mit ausreichenden Parametern konfiguriert sind. Hierzu sind vor einer Installation unbedingt die plattformspezifischen Installationsanweisungen zu konsultieren. Je nach Plattform sind zusätzliche Schritte vor der eigentlichen Installation durchzuführen. Unter IBM Unix-Derivat AIX wird z.B. ein spezieller, von Oracle mitgelieferter Post-Wait-Treiber für die Oracle-Interprozesskommunikation verwendet. Dieser wird als AIX-Kernel-Erweiterung installiert und muss während der Oracle-Installation bereits vorhanden sein. Typischerweise muss hierzu die Datei rootpre.sh vom Oracle-Installationsmedium als Benutzer root ausgeführt werden. Neben der Installation des Post-Wait-Treibers wird in diesem Skript dafür gesorgt, dass im AIX Kernel der asynchrone IO eingeschaltet ist, der ebenfalls von der Oracle-Software vorausgesetzt wird. Bei der Installation einer neueren Oracle-Version ist darauf zu achten, dass der Post-Wait-Treiber eventuell ebenfalls in der neuen Version benötigt wird (Kompatibilität der Versionen untereinander im Readme nachlesen!). Das bedeutet wiederum, dass eine eventuell vorhandene Instanz, die eine ältere Oracle-Version benutzt, für den Tausch des Post-Wait-Treibers heruntergefahren werden muss.
40
Installation und Aufbau einer Datenbank
Viele Unix-Anbieter liefern ihre Betriebssysteme in 64-Bit-Versionen aus oder bieten eine entsprechende Variante an. Der hierdurch mögliche riesige virtuelle Adressraum (264 Bytes = 16.777.216 TB) ermöglicht – im Gegensatz zum virtuellen Adressraum von 4 GB bei 32-Bit-Versionen – ohne Probleme Prozessgrößen und Shared-Memory-Konfigurationen von mehreren zehn GB. Für diese Unix-Derivate bietet Oracle 64-Bit-Versionen an, so dass entsprechend große SGA-Konfigurationen möglich sind. Da heute mit reellen Speichergrößen von einigen zehn GB entsprechende Hardware-Ausbaumöglichkeiten vorhanden sind, kann der Einsatz einer solchen 64-Bit-Version erhebliche Vorteile bringen. Oracle unter MS-Windows Oracle-Installationen unter MS-Windows erfreuen sich sowohl in Entwicklungsund Test- als auch in produktiven Umgebungen sehr großer Beliebtheit. Generell wird bei Oracle-Installationen unter MS-Windows zwischen einer Clientund einer Server-Variante unterschieden. In diesem Buch ist grundsätzlich die Server-Variante gemeint, da nur hiermit die Installation der Oracle Database Standard und Enterprise Edition möglich ist. Die Client-Version erlaubt lediglich die Installation der Oracle Net-Produkte, diverse APIs sowie Entwicklungskomponenten. Die Oracle Server-Installation setzt im übrigen nicht voraus, dass eine MS-Windows Server-Version installiert ist; auch auf den MS-Windows 2000 Workstation-Varianten oder MS-Windows XP Home läuft die Oracle Database-Software problemlos. Dies ist insbesondere für Entwicklungs- und Übungsumgebungen auf Desktop-PCs oder Laptops interessant. Viele spezielle Merkmale der Oracle-Software unter MS-Windows sorgen mittlerweile für eine sehr gute Integration in die Windows-Welt. Hierunter zählen u.a. die Integration der Alert-Informationen in die Windows-Ereignisanzeige, diverse Möglichkeiten zur Nutzung von Windows-Anmeldungen bei der Oracle-Autorisierung, die Verfügbarkeit zahlreicher Werkzeuge und Programmierschnittstellen sowie die schnelle Verfügbarkeit der kompletten Oracle-Software-Palette unter MS-Windows. Der letzte Punkt ist ausschlaggebend dafür, dass mit MS-Windows wohl die vollständigste Entwicklungsumgebung in a box für Oracle-basierte Systeme gegeben ist. Ein grundlegender Unterschied zwischen der Oracle-Implementierung unter MSWindows und praktisch allen anderen Implementierungen ist die Prozessarchitektur: Anstelle der sonst üblichen Multiprozess-Variante wurde der Oracle Server unter MS-Windows mit Hilfe der Multi-Threaded-Architektur des Betriebssystems implementiert.
Installationsplanung
41
Abbildung 2.5: Einzelprozessarchitektur unter MS-Windows mit Threads-Abbildung
Mit dieser Architektur ist eine Betriebssystemressource wie Shared Memory für die SGA nicht notwendig, da Speicheranforderungen am Prozess durchgeführt werden und somit automatisch allen Oracle-Threads zur Verfügung stehen. Diese Architektur kann man mit dem MS-Windows TASK-MANAGER nachvollziehen: Die Spalte THREADS in der Abbildung 2.6 ist standardmäßig nicht eingestellt, sie muss erst über den Punkt SPALTEN AUSWÄHLEN im Menü ANSICHT aktiviert werden. Neben drei Threads, die grundsätzlich für den Oracle-Prozess gestartet sind, gibt es für jeden Oracle-Hintergrund-»Prozess«3 sowie für jeden Dedicated Server genau einen Thread, im Beispiel sind es insgesamt 19. Der Oracle-Prozess wird nicht als Anwendung auf der Oberfläche, sondern als Dienst gestartet. Nur so ist die Lauffähigkeit des Oracle-Systems ohne Abhängigkeit von einer Benutzeranmeldung am System möglich.
3
An dieser Stelle ist der »Prozess« in seiner Oracle-Bedeutung gemeint!
42
Installation und Aufbau einer Datenbank
Abbildung 2.6: Oracle-Prozess mit Threads unter MS-Windows
Oracle unter Linux Es gibt derzeit vier (!) unterschiedliche Oracle-Portierungen für Linux. Zunächst einmal die sicherlich meist verbreitete Version für 32 Bit Intel CPUs (x86). Daneben für die erweiterten 64 Bit CPUs (z.B. AMD64, EM64T) die Linux x86-64. Für neuere Prozessoren (Intel Itanium und AMD Opteron) gibt es eine spezielle Version Linux Itanium. Die vierköpfige Familie wird dann durch die 64 Bit z/Linux-Variante für IBM eServer komplettiert. Wichtig ist, dass nur spezielle Linux-Derivate zertifiziert sind, dazu gehören Red Hat Enterprise Linux AS/ES und SuSE Linux Enterprise Server. Die komplette Liste finden Sie jederzeit in der Zertifizierungsmatrix im Oracle-Metalink (metalink.oracle.com). Ansonsten gilt für die Oracle-Implementierung unter Linux alles, was bereits für Oracle unter Unix beschrieben wurde. Andere Betriebssysteme Nach wie vor gibt es Oracle-Portierungen auf weiteren Betriebssystemen, z.B. auf Compaq OpenVMS, IBM MVS oder Apple Mac OS X. Auch hier gibt es Eigenheiten und spezielle Eigenschaften, allerdings ist die Verbreitung der Oracle-Datenbank auf diesen Plattformen nicht sonderlich groß. Wir verweisen daher auf die jeweiligen Installationsanweisungen.
Installationsplanung
43
2.2.2 Art der Anwendung Was wird mit der Datenbank gemacht? Das ist die Frage, nach der sich die Art der Anwendung richtet. Dabei wird zwischen folgenden Anwendungen unterschieden: OLTP4: Diese Art der Anwendung zeichnet sich durch eine große Anzahl von Anwendern mit relativ einfachen Abfragen und einer kontinuierlichen Transaktionslast aus. Dabei sind die einzelnen Transaktionen eher klein, beispielsweise die Auftragsannahme eines Großhandels. Die SQL-Befehle sind immer die gleichen, und die Datenbankgröße liegt wahrscheinlich im Bereich einiger Gigabyte. Für eine solche Datenbank ist es wichtig, ein optimales Backup-Konzept zu haben, da der Verlust von Daten kaum zu tolerieren ist. Außerdem muss diese Datenbank in der Regel hochverfügbar sein, da ein Ausfall erhebliche Kosten nach sich zieht. Das bedeutet, die Redo-Log-Dateien sollten gespiegelt werden, und die Archivierung muss auf eine separate Festplatte erfolgen. Das Ganze muss von der Hardware optimal unterstützt werden (IO-Verteilung). Die eingesetzte Hardware sollte außerdem in der Lage sein, die Anzahl der Benutzer optimal zu unterstützen (Anzahl CPUs) und die wesentlichen Daten aus dem Cache zur Verfügung zu stellen (Größe des Hauptspeichers). Von Seiten der Performance muss gewährleistet sein, dass Abfrageergebnisse in wenigen Sekunden verfügbar und die Änderungen sofort gespeichert sind. Oracle-Optionen sind in der Regel für diese Art der Anwendung nicht notwendig. Eine Ausnahme bildet die Real-Application-Cluster-Option für die Verfügbarkeit sowie die Oracle Enterprise Manager Packages für Monitoring und Diagnose. OLAP5 oder Data Warehouse: Die Datenbank kann unter Umständen mehrere Terabyte groß sein. Auf Basis dieser Daten werden von relativ wenigen Anwendern umfangreiche Berichte als Reports oder Analysen erstellt. Die SQL-Befehle sind kaum vorhersehbar. Die Transaktionslast ist zu bestimmten Spitzenzeiten (z.B. nachts) sehr groß, weil dann neue Daten geladen werden. Ein Data Warehouse wird in der Regel nicht online, sondern über Batch-Jobs aktualisiert. Einen Spezialfall hierbei bilden so genannte Data Marts, die aus einem Data Warehouse erzeugt werden, um mit einer kleineren Datenmenge komplexe Berechnungen z.B. auch für den Bereich Data Mining anzustellen. Für diese Datenbank gibt es zwei unterschiedliche Konfigurationen: Während der Ladeoperationen muss eine genügend große IO-Bandbreite zur Verfügung stehen, da große Datenmengen in kurzer Zeit verarbeitet werden müssen (z.B. nachts). Während des Tagesbetriebs muss hingegen ein möglichst großer Cache die aktuellsten Daten vorhalten. Außerdem kann über eine Parallelisierung der Abfragen (Parallel Query) nachgedacht werden, um damit die Abfragegeschwindigkeit noch weiter zu steigern.
4 5
OLTP = Online Transaction Processing OLAP = Online Analytic Processing
44
Installation und Aufbau einer Datenbank
Für die Hardware gibt es nur ein Ziel: in möglichst kurzer Zeit die Daten zu liefern. Daher ist hier die IO-Optimierung entscheidendes Kriterium für die Hardware. Natürlich gilt: Je mehr Hauptspeicher, umso besser. Im Gegensatz zum OLTP-System ist es hierbei aber üblich, dass Abfragen einige Minuten benötigen. Batch-Reports können durchaus eine Dauer von mehreren Stunden haben. Als Optionen kommt hier vor allen Dingen die Partitioning-Option zum Einsatz, da nur durch sie die großen Datenmengen effektiv bearbeitet werden können. Die Real Application Clusters-Option wird hier vor allen Dingen als Skalierungsoption eingesetzt, um damit neben der Ausfallsicherheit eine bessere Verteilung der Last zu erreichen. Für Data Marts kommen dann die OLAPund Data Mining-Option zum Einsatz. Mischbetrieb: In diesen Datenbanken werden OLTP-Anteile und abfrageorientierte Anwendungen gemischt. Dabei enthalten diese Datenbanken oftmals auch noch eine Batch-Komponente, die z.B. nachts Daten von nachgelagerten Systemen ausliest. Welche Anforderungen an die einzelnen Bereiche gestellt werden, richtet sich im Wesentlichen nach der Abfragelast, da diese den OLTPBereich immer behindern wird. Wenn es also nicht zu vermeiden ist, ein solches System aufzubauen, sollte der Bereich Data Warehouse möglichst klein bleiben, ansonsten wird das gesamte System in Mitleidenschaft gezogen. Es ist bei diesen Systemen davon abzuraten, tatsächlich frei wählbare SQL-Abfragen starten zu können (so genannte Power User, die mit Werkzeugen wie Quest TOAD oder dem guten alten SQL*Plus arbeiten), da die Konfiguration dann kaum noch auf die unterschiedlichen Anforderungen anpassbar ist. In dieser Konstellation kann die Real-Application-Cluster-Option sehr effektiv eingesetzt werden, indem die OLTP-Anwendungen auf einem Server und Abfrage-Anwendungen auf einem anderen Server verteilt werden, die immer noch auf den gleichen Datenbestand zugreifen. Spezialanforderungen: Neben diesen weit verbreiteten Anwendungen gibt es spezielle Anforderungen z.B. für die Verarbeitung von Multimedia-Daten oder geokodierten (Spatial) Informationen. Da diese Fälle jedoch Ausnahmen sind, werden wir nicht weiter darauf eingehen. Wenn Sie ein solches System aufbauen wollen, sollten Sie sich entsprechende Unterstützung aus Beratungsunternehmen holen. Sicherlich gibt es neben diesen Arten noch weitere, wie z.B. Fileserver oder reine Batchsysteme, die sich aber im Wesentlichen in die oben genannten Beispiele eingliedern lassen. Neben der Art der Anwendung spielt sicherlich noch die Anzahl der Anwender und Größe der Datenbank eine entscheidende Rolle. Hier ist auch die Frage zu stellen, welche Oracle-Edition eingesetzt werden soll. Die Größe der Datenbank und die Anzahl der Benutzer hat dabei keinen direkten Einfluss auf die Edition, wohl aber die eingesetzte Hardware. Die Standard Edition One darf nur auf Systemen mit bis zu zwei CPUs eingesetzt werden, die Standard Edition auf bis zu vier CPUs. Die Größe des Hauptspeichers oder gar die Plattenkapazität ist davon nicht betroffen. Allein die Möglichkeit, Optionen zu verwenden, kann damit ein Grund sein, die
Installationsplanung
45
Enterprise Edition einzusetzen. Im nächsten Kapitel werden daher zunächst die Editionen beschrieben und anschließend auf die Optionen eingegangen.
2.2.3 Versionstechnische Planung Die versionstechnische Planung durchzuführen bedeutet festzulegen, ob und wann eine bestimmte Oracle-Version auf einem bestimmten Betriebssystem zum Einsatz kommt. Diese Frage entscheidet sich keinesfalls nur vor dem Hintergrund der produktiven Verfügbarkeit der betreffenden Version, sondern wird von einer Vielzahl zusätzlicher Faktoren bestimmt. Ein »äußerer« Faktor kann sich aus der begrenzten Unterstützungsdauer seitens des Herstellers ergeben. Für offiziell nicht mehr unterstützte Versionen werden keine neuen Patches erstellt, wohl aber bestehende ausgeliefert und telefonische Auskünfte gewährt. Im Fehlerfall kann dies unter Umständen zu unangenehmen Ausfällen führen, die eine Versionsaktualisierung notwendig machen. »Innere« Faktoren ergeben sich aus der Verfügbarkeit oder Qualität von SoftwareMerkmalen, die für geplante oder bestehende Anwendungen benötigt werden. Die Nutzung der Replikation über Oracle Streams kann z.B. die Migration von Oracle8i oder Oracle9i nach Oracle 10g rechtfertigen. Die geringere Fehlerrate oder größere Stabilität einer Version kann einen weiteren Auslöser für eine Aktualisierung darstellen. In manchen Fällen können sich jedoch unangenehme Abhängigkeiten zu bestehenden Anwendungen ergeben. Wenn diese für den neuen Release-Stand noch nicht freigegeben sind, kann es notwendig werden, vorhandene Instanzen aufzuteilen und die für die Migration nicht geeigneten Anwendungen unter der alten Version zu belassen. In den meisten Fällen empfiehlt es sich, eine dem eigenen Umfeld angepasste »Oracle-Versionspolitik« auszuarbeiten und Versionen für das eigene Unternehmen gesondert freizugeben. Nach Verfügbarkeit einer Beta- oder produktiven Version wird eine entsprechende Testumgebung aufgebaut, in der die neue Software im Zusammenspiel mit allen für das Unternehmen kritischen Anwendungen getestet wird. Nach erfolgreichem Abschluss der Tests kann dann eine entsprechende Richtlinie für das Unternehmen herausgegeben werden. Abteilungen, die den uneingeschränkten Support des betreffenden Rechenzentrums – z.B. im Rahmen von Backup und Recovery – wünschen, können dann zur Einhaltung dieser Richtlinien verpflichtet werden. Diese Richtlinien beschränken sich in der Regel nicht nur auf die Version der Datenbank, sondern können ebenso Namenskonventionen und Installationsregeln umfassen.
2.2.4 Betriebssystemspezifische Planung Die Oracle-Software hat sich naturgemäß in eine vorhandene Rechnerlandschaft einzugliedern. Oracle-Versionen sind auf Betriebssystemen zu unterschiedlichen Zeitpunkten und – in manchen Fällen – in unterschiedlicher Stabilität verfügbar. Mit jedem neuen Software-Release wächst bekanntlich auch der Verbrauch an Systemressourcen – Hauptspeicher sowie Plattenplatz. Darüber hinaus gilt es, die für eine Version minimal notwendige Betriebsystemversion zu beachten und bei Bedarf auch hier eine Aktualisierung vorzubereiten und rechtzeitig einzuleiten.
46
Installation und Aufbau einer Datenbank
2.2.5 Software-Komponenten Die Aufteilung der Software-Komponenten auf Installationsmedien bzw. Installationssets hat sich für Oracle 10g grundlegend geändert. Für die Installation der Oracle Database 9i Release 2 unter MS-Windows waren drei CDs notwendig. Diese enthielten neben der reinen Datenbank-Software u.a. den kompletten Enterprise Manager inklusive der zentralen Komponente Management Server, Beispieldaten, den Oracle HTTP Server (einen um einige Oracle Mods erweiterten Apache Server) und vieles mehr. Natürlich kann man das alles unter gewissen Umständen gut gebrauchen; in den meisten Fällen braucht man jedoch die Zusatzkomponenten nicht. Im Gegenteil – was haben Beispieldaten auf einer produktiven Datenbankumgebung verloren? Die Installation der Oracle Database 10g-Software unter MS-Windows findet nun mit genau einer CD (nicht etwa DVD!) statt. Es befinden sich jedoch nur noch die wirklich datenbanknahen Komponenten darauf – alles andere befindet sich auf weiteren CDs. Oracle Database 10g Dies ist zentrale Installationskomponente: die Oracle Datenbank-Software. Gegenüber früheren Versionen wurde sie deutlich entschlackt, was sich in einer wesentlich kürzeren Installationszeit bemerkbar macht. Dieses Kapitel beschreibt hauptsächlich die Installation dieser Datenbank-Software. Zusätzlich zur Datenbank-Software sind hier lediglich die wirklich datenbanknahen Werkzeuge (SQL*Plus, Data Pump, Loader, DB-Verify usw.), der Enterprise Manager Database Control sowie iSQL*Plus untergebracht. Der Enterprise Manager Database Control wird nicht mehr – wie von den 9er-Versionen gewohnt – als Java-Client ausgeliefert, sondern läuft als Serverprozess zusätzlich zu einer Instanz. Bedient wird der Enterprise Manager Database Control über einen Webbrowser – daher benötigt ein DBA keine zusätzliche Software-Installation mehr. Die größte Einschränkung der Database Control-Variante des Enterprise Managers ist, dass sie an genau eine Datenbank gekoppelt ist. Will man mehr als eine Datenbank aus einer Anwendung heraus überwachen, so muss man den Enterprise Manager Grid Control ins Spiel bringen, der aber auf der Database-CD nicht enthalten ist. Weiterhin wird bei jeder Installation der Datenbank-Software eine »kleine Version« der Oracle Clusterware installiert, sofern die Cluster Ready Services nicht bereits installiert sind. Dies wird benötigt, wenn man die von Oracle entwickelte Speichervariante ASM für Datenbankdateien verwenden möchte. Oracle Database 10g Companion-CD Auf dieser CD gibt es diverse Produkte, die bei früheren Versionen auf der Database CD enthalten waren und meist sogar ohne Nachfrage mitinstalliert wurden. Es handelt ich u.a. um:
Installationsplanung
47
Beispielschemata und Daten den Oracle HTTP-Server die Datenbank-Programmierumgebung HTML DB die Sicherungssoftware Legato Single Server einige Java- und XML-Produkte Die Beispielschemata sind in einem eigenen Handbuch dokumentiert und sicherlich hilfreich beim Testen von Anwendungen, Optionen usw. Bei einer produktiven Datenbanksoftware-Installation haben sie jedoch nichts zu suchen und sind demnach richtigerweise auf einer eigenen CD. Gleiches gilt für den Oracle HTTP Server und HTML DB. Gerade letzteres Produkt erfreut sich großer Beliebtheit und ist – gerade als kostenloses Add-on – sehr sinnvoll zur Erstellung kleinerer Anwendungen. Aber auch hier gilt der Ausschluss bei Standard-Datenbanksoftware-Installationen. Die Kooperation zwischen Legato und Oracle besteht nunmehr auch seit einigen Versionen. Für den Oracle-Kunden hat das den Vorteil, dass für Maschinen, die sowohl Datenbanksoftware als auch die Sicherung der Datenbank betreiben, keine weitere Software angeschafft werden muss, um mit dem Recovery Manager ein belastbares Sicherungskonzept zu betreiben. Oracle Database 10g Client Der Client enthält alle Softwarekomponenten, die für eine Anbindung von Arbeitsplätzen an eine Oracle Database benötigt werden. Hier gibt es mittlerweile eine recht große Bandbreite an Techniken: Oracle Net, ODBC, JDBC usw. Auf der CD sind – je nach Betriebssystem – die entsprechenden Treiber und Komponenten vorhanden. Des Weiteren gibt es hier viele Bibliotheken, die z.B. zum Betrieb einer OCI-Anwendung notwendig sind. Oracle Cluster Ready Services Die Installation der Cluster Ready Services (CRS) ist Voraussetzung für eine RACInstallation. Hierbei werden die CRS vor der Installation der Oracle Database in ein eigenes ORACLE_HOME installiert. Instant Client Eine komplett neue Variante der Client-Installation bietet der Instant Client: Dieser wird nicht mehr über eine Installationsprozedur bzw. den Universal Installer installiert, sondern durch einfaches Kopieren von Bibliotheken. Diese müssen lediglich vom Betriebssystem gefunden werden (PATH-Variable). Falls die geplante Anwendung OCI-, OCCI- oder JDBC-OCI-basiert ist, kann der Instant Client als Ersatz für den Standard-Client verwendet werden. Für einige Spezialfälle gibt es Erweiterungen (z.B. eine spezielle SQL*Plus-Version und für ODBC). Im Zweifelsfall sollte dies ausprobiert werden. Ein großer Vorteil des Instant Clients ist die einfache Handhabung für große Umgebungen, bei denen manchmal auch eigene Installationsvorschriften und -verfahren eingesetzt werden. Als nachteilig
48
Installation und Aufbau einer Datenbank
kann sich die fehlende Komplexität dann herausstellen, wenn zusätzliche Optionen für den Client eingeschaltet werden sollen (z.B. Tracing), was mangels der fehlenden Oracle Net-Umgebung nicht geht. Oracle Enterprise Manager 10g Grid Control Die Grid Control-Variante des Enterprise Managers wird zur zentralen Verwaltung komplexer Datenbankumgebungen benötigt. Hierfür wird dann in der Regel ein eigener Rechner vorgesehen, dessen Ausstattung, insbesondere im Hauptspeicherbereich, nicht zu knapp bemessen sein sollte. Die Minimalausstattung liegt bei 1 GB – ohne den Hauptspeicherbedarf für die zugehörige Oracle-Instanz zur Verwaltung der Daten. Der Vorteil der »großen« Variante des Enterprise Managers ist sicherlich die zentrale Sicht auf mehrere bzw. viele Datenbanken. Weiterhin können mit Grid Control nicht nur Datenbanken, sondern auch Listener, Application Server u.v.m. administriert werden. Wie beim Enterprise Manager Database Control erfolgt der Zugriff auf die GridControl-Komponenten über einen Webbrowser, so dass auch für dieses Werkzeug keine Installation auf dem Administrator-Arbeitsplatz notwendig ist.
2.2.6 Globalization Support Unter dem Thema Globalization Support (früher: National Language Support, NLS) werden alle Themen im Oracle-Umfeld zusammengefasst, die mit verschiedenen Sprachen, ländertypischen Konventionen und Zeichensätzen zu tun haben. Das Thema an sich ist recht umfangreich; daher ist Kapitel 8 für eine genauere Diskussion vorgesehen. An dieser Stelle muss lediglich der Sachverhalt der Datenbank-Zeichensätze geklärt werden, da man bei der Erstellung einer Datenbank die Zeichensätze auswählen muss. Diese Entscheidung kann für eine bestehende Datenbank praktisch nicht mehr rückgängig gemacht werden. Pro Datenbank sind zwei Zeichensätze auszuwählen, weil es zwei Sätze von Datentypen gibt, die Zeichenketten definieren. Die Standard-Datentypen für Zeichenketten sind CHAR, VARCHAR2 und CLOB. Hierfür muss der Datenbank-Zeichensatz ausgewählt werden. Die gängigsten Zeichensätze hierfür sind: WE8ISO8859P1: ISO 8859-1 West-European WE8ISO8859P15: ISO 8859-15 West-European WE8MSWIN1252: MS-Windows Code Page 1252 8-bit West European Viele Datenbanken, die bereits länger existieren und über einige Oracle-Versionen immer wieder migriert worden sind, nutzen den ISO-Zeichensatz WE8ISO8859P1. In früheren Versionen wurde dieser Zeichensatz bei Installationen unter MS-Windows standardmäßig eingestellt, so dass bei der Verwendung dieser Clients keine Zeichensatzkonvertierung zwischen Client und Server stattfinden musste. Die Migration zu WE8ISO8859P15, einer Weiterentwicklung von WE8ISO8859P1, die das Euro-Symbol enthält, hat nur selten stattgefunden, da bei der Verwendung des neuen Zeichensatzes ältere Clients oft keine Verbindung aufbauen konnten.
Installationsplanung
49
Da seit einigen Versionen der Standard-Zeichensatz für MS-Windows-Installationen WE8MSWIN1252 ist, bietet sich dieser Zeichensatz nunmehr für viele Installationen an, insbesondere im Client-Server-Umfeld. Sobald Web- bzw. Applikationsserver ins Spiel kommen und Webbrowser das Frontend darstellen, bieten sich eher die ISO-Zeichensätze an, da viele Webbrowser standardmäßig damit arbeiten. Der zweite Zeichensatz einer Datenbank wird als nationaler Zeichensatz bezeichnet und muss (seit Oracle 9i) ein Unicode-Zeichensatz sein. Man hat die Wahl zwischen AL16UTF16 und UTF8. Der nationale Zeichensatz ist relevant für die Datentypen NCHAR, NVARCHAR2 und NCLOB. Weitere Informationen über Zeichensätze, insbesondere über Unicode, befinden sich in Kapitel 8.
2.2.7 Die Planung von Instanzen und Datenbanken Neben den Versions- und Betriebssystemfragen ist die Planung von Instanzen und ihnen zugeordneten Datenbanken von großer Bedeutung. Diese Planung wird vor allem dort wichtig sein, wo der Administrator die Aufgabe der Versionsanpassung mit der Reorganisation der Datenbanklandschaft verbinden möchte oder muss. Bei der hier angesprochenen Planung von Datenbanken sollten vor allem folgende Aspekte Beachtung finden: Zum einen ist zu entscheiden, welche Anwendungen und Schemata zusammen in welcher Datenbank installiert und betrieben werden. Diesen Aspekt wollen wir hier als Datenbankmodell bezeichnen. Ähnlich einem Datenmodell sind hierbei auch die Beziehungen der einzelnen Datenbanken untereinander wichtig, etwa im Zusammenhang mit dem Einsatz der Replikation. Der einfache, zu Zeiten der Versionen 6 und 7 nahe liegende Leitsatz: »jedes Projekt bekommt eine eigene Instanz und Datenbank« kann sehr schnell eine Inflation von Instanzen nach sich ziehen, die den Administrator mit entsprechend komplexen Anforderungen in Sachen Backup, Recovery, Optimierung und Verfügbarkeit konfrontiert. Auf der anderen Seite kann eine ganzheitliche Lösung, bei der alle Daten eines Unternehmens in nur einer Datenbank gespeichert sind, den DBA oft vor unlösbare Tuning-Aufgaben stellen und – im Falle eines Systemabsturzes – das operative Geschäft sämtlicher Abteilungen gefährden. Der zweite Aspekt, der bei der Installationsplanung Beachtung finden muss, ist die Festlegung all jener Datenbankparameter, die nicht oder nur mit großem Aufwand im laufenden Betrieb anpassbar sind – mit anderen Worten die Datenbankparametrierung, die bereits mit der Initialisierung der Datenbank festzulegen ist. Die Instanzplanung verfolgt im Wesentlichen zwei Ziele: 1. eine für den DBA verwaltbare und überschaubare Datenbanklandschaft zu schaffen und 2. den einzelnen Anwendungen und Schemata eine in Sachen Verfügbarkeit und Laufzeitverhalten optimierte Umgebung zu bieten. Beide Aspekte werden im Folgenden näher erläutert.
50
Installation und Aufbau einer Datenbank
Das »Datenbankmodell« Die Frage, welche Daten und Schemata und welche Anwendungen mit ihnen in welcher Datenbank installiert und betrieben werden sollen, lässt sich am besten vor dem Hintergrund der wesentlichen, zentralen Attribute einer Oracle-Datenbank und -Instanz erörtern. Die Festlegung der folgenden Datenbankattribute ist in diesem Zusammenhang wichtig: Bestimmung der Blockgröße Bis zur Version Oracle8i hat jede Datenbank eine globale Blockgröße, die über den Serverparameter db_block_size festgelegt wird und Größen zwischen 2 K und 64 K annehmen kann. Die Blockgröße stellt die kleinste Dateneinheit und EA-Einheit dar, mit der das System arbeiten kann. Je größer der einzelne Block ist, desto mehr Daten(sätze) kann er enthalten. Dies führt u.a. zu »flacheren« und damit effizienteren Indexbaumstrukturen sowie zu potenziell größeren Datenmengen pro Blockzugriff. Die internen Strukturen für die Verwaltung von Zeilensperren – so genannte Transaction Entries – werden innerhalb jedes Datenblockes angelegt. Je mehr Datensätze ein Block enthalten kann, desto mehr Ressourcen sollten daher für Zeilensperren aufgebaut werden6, um nicht mit einem erhöhten Risiko für Zugriffskonflikte konfrontiert zu werden. Da der minimale Platzbedarf für Tabellen zwei Oracle-Blöcke beträgt – ein Header- und ein Datenblock –, steigt auf der anderen Seite bei großen Blöcken der minimale Speicherplatz, was für kleine Tabellen sehr schnell zu einem zusätzlichen Bedarf von Speicherplatz führen kann. Da die Blockgröße auch die Puffergröße im Cache bestimmt, sinkt – bei gleich bleibenden Cache-Größen – die Anzahl der Puffer und damit die Trefferquote. Aufgrund dieser Sachverhalte sind Datenbanken mit großen durchschnittlichen Satzlängen und einem großen Datenvolumen pro Objekt prädestiniert für Blockgrößen von 16 K und mehr. Die erhöhten Blockgrößen reduzieren in diesem Fall das Aufteilen von Datensätzen über mehrere Blöcke (Row Splitting, Row Chaining) und die Höhe der Indexbäume. Beides kann zu einem optimierten Zugriffsverhalten der Anwendungen beitragen. Für alle Datenbanken, die in diesem Sinne keine besonderen Anforderungen stellen, eignen sich Blockgrößen von 4 K oder 8 K. Beginnend mit der Version 9i ist es möglich, unterschiedliche Blockgrößen innerhalb einer Oracle-Datenbank zu definieren und dementsprechend separate Pufferbereiche für die unterschiedlichen Blockgrößen in der SGA anzulegen. Aus diesem Grunde können nun auch Anwendungen, die bisher aufgrund ihrer Speicheranforderungen separat installiert werden mussten, gemeinsam in einer Datenbank betrieben werden. Der oben erwähnte Serverparameter db_block_size bestimmt nun die Blockgröße für den SYSTEM-Tablespace und dient als Standardwert für die Blockgrößen der übrigen Tablespaces. Darüber hinaus lassen sich maximal vier weitere Blockgrößen zwi6
Die Anzahl der Transaction Entries pro Datenblock lässt sich sehr einfach über den Storage-Parameter initrans festlegen.
Installationsplanung
51
schen 2 K und 32 K nutzen. Die gewünschte Blockgröße wird beim Anlegen eines Tablespace über die BLOCKSIZE-Klausel eingestellt. Für jede genutzte Blockgröße müssen zusätzliche Pufferbereiche in der SGA angelegt werden. Hierzu steht der Serverparameter db_nk_cache_size zur Verfügung, wobei n durch die gewünschte Blockgröße zu ersetzen ist. Die Größe des Puffers für die Standardblöcke wird dagegen über den Parameter db_cache_size festgelegt. Alle Parameter geben die Größe des Puffers – z.B. 120M – und nicht die Anzahl der Puffer an. Die Parameter lassen sich darüber hinaus dynamisch mit Hilfe des Befehls ALTER SYSTEM bei laufender Datenbank ändern, sofern die für die SGA vorgegebene Maximalgröße7 dabei nicht überschritten wird. Festlegung des Zeichensatzes Jede Datenbank hat einen normalen und einen länderspezifischen Zeichensatz für die Speicherung von Zeichenketten. Der normale Zeichensatz wird in den skalaren Datentypen CHAR, VARCHAR2, CLOB und LONG und darüber hinaus für Bezeichner von Tabellen, Spalten, Variablen und Programmeinheiten verwendet. Der länderspezifische Zeichensatz findet entsprechend in den Datentypen NCHAR, NVARCHAR2 und NCLOB seine Anwendung. Unterschiedliche Zeichensätze auf Seiten der Datenbank und der Clients werden durch Konvertierungen angepasst, sofern der Zieldatensatz alle Zeichen des Quellzeichensatzes enthält. Zeichen, die im Zieldatensatz nicht dargestellt werden können, werden durch Ersatzzeichen – in den meisten Fällen »?« – repräsentiert. Bei der Initialisierung der Datenbank sind entsprechend den Anforderungen der Anwendungen die geeigneten Zeichensätze auszuwählen. Sowohl der normale als auch der länderspezifische Zeichensatz können über einen einfachen Befehl8 angepasst werden. Diese Anpassung kann aber nur dann erfolgen, wenn der neue Zeichensatz eine strikte Obermenge des aktuellen Zeichensatzes darstellt. In allen anderen Fällen muss die Anpassung stets – sehr aufwändig – durch einen vollständigen Neuaufbau der Datenbank erfolgen! Eine gültige Neudefinition ist beispielsweise die Umstellung von US7ASCII nach WE8SO8859P15. Festlegung des Datenbanknamens Jede Datenbank hat einen globalen Namen, der – in verteilten Umgebungen – die Namensgebung von Datenbankverbindungen (Database Links) bestimmt.9 Der globale Name einer Oracle-Datenbank wird bei der Initialisierung aus den Serverparametern db_name und db_domain gebildet, also z.B. lager.database_consult.de für db_name = lager und db_domain = database_consult.de. Obwohl der Name nachträglich über den ALTER DATABASE-Befehl10 geändert werden kann, empfiehlt es sich, bereits bei der Initialisierung der Datenbank eine sinnvolle Entscheidung zu treffen. Bei Verwendung des globalen Namensmodells ist es zwingend notwendig, dass die Namen der Datenbankverbindungen mit den globalen Namen der Zieldatenbanken übereinstimmen. 7 8
Bestimmt über den Serverparameter sga_max_size. Die Befehle lauten: alter database character set ; bzw. alter database national character set ;
9
Dies gilt für Instanzen, bei denen das globale Namensmodell eingeschaltet ist (Serverparameter global_names = true).
10 alter database rename global_name to ;
52
Installation und Aufbau einer Datenbank
Version des Datenbankkerns Jede Datenbank ist an eine Version gebunden und damit an die in dieser Version verfügbaren softwaretechnischen Merkmale. Die Verfügbarkeit von Merkmalen kann darüber hinaus mit Hilfe des Serverparameters compatible kontrolliert werden. Auf diese Weise kann eine installierte Datenbankversion nach unten »korrigiert« werden. Der Parameter compatible muss allerdings für alle Instanzen einer Datenbank identisch gesetzt werden. Festlegung der Transaktionsverwaltung In der Version 9i können die bis dahin gebräuchlichen Rollback-Segmente durch eine automatische Undo-Verwaltung ersetzt werden. Über den Serverparameter undo_management wird für jede Instanz die Art der Transaktionsverwaltung festgelegt, der Wert AUTO schaltet auf die hier besprochene Methode der automatischen UndoVerwaltung. Der Undo-Tablespace ist zuvor über den Befehl CREATE UNDO TABLESPACE anzulegen und mit dem Serverparameter undo_tablespace für die betreffende Instanz zu reservieren. In Oracle9i wurde alternativ auch noch die herkömmliche Nutzung von Rollback-Segmenten unterstützt, mit Version 10g sollte diese Alternative nicht mehr benutzt werden. Die Festlegung des Datenbankmodus Jede Datenbank hat einen Datenbankmodus, der ihr Verhalten im Falle von Backupund Recovery-Operationen bestimmt. Oracle-Datenbanken können im ArchiveLog- oder Noarchive-Log-Modus betrieben werden. Der Datenbankmodus legt fest11, ob alle Datenmodifikationen – in Form von so genannten Offline-Redo-Log-Dateien – fortlaufend archiviert werden oder nicht. Für Datenbanken im Archive-LogModus können Online-Sicherungen sowie vollständige und unvollständige Recovery-Aktionen durchgeführt werden, bei denen auch Transaktionen, die nach der Sicherung durchgeführt wurden, rekonstruiert werden können. Datenbanken im Noarchive-Log-Modus dagegen können nur offline gesichert werden. Ihr Recovery beschränkt sich auf das Einspielen der Offline-Sicherung; nach der Sicherung durchgeführte Transaktionen gehen damit verloren. Neben dem Archive-Modus steht in der Version 10g auch noch die Flashback-Database-Funktionalität zur Verfügung, die ebenso wie die Archivierung in der MountPhase aktiviert werden kann. Mit der Flashback-Database-Funktionalität kann die Datenbank auf einen Zeitpunkt zurückgesetzt werden, ohne ein Backup einspielen zu müssen. Anwendungen, die aufgrund der oben dargestellten Merkmale zusammenpassen, d.h. gleiche Anforderungen an die Oracle-Blockgröße haben, gleiche Anforderungen an den normalen und länderspezifischen Zeichensatz haben, mit gleichen Datenbankversionen arbeiten können, über ein gemeinsames Transaktionsmanagement betrieben werden können, 11 Die Einstellung erfolgt in der Mount-Phase über den Befehl alter database archivelog;.
Installationsplanung
53
gleiche Voraussetzungen für Backup und Recovery erfordern, und darüber hinaus die Ressourcen – Plattenplatz und Memory – einer gegebenen Hardware-Plattform nicht überfordern, können prinzipiell gemeinsam in einer Datenbank konfiguriert und über eine oder mehrere Instanzen12 bedient werden. Die in den Oracle-Versionen 9i und 10g realisierte Datenbanktechnik ist mittlerweile wesentlich effizienter als früher in der Lage, sehr große Mengen an Daten, Benutzern und Datenbanksitzungen zu verwalten, und kann ebenso sehr große Speicherbereiche – für die System Global Area – effizient nutzen. Durch die damit mögliche Reduzierung der Anzahl der Datenbanken lassen sich die Aufgaben der Administratoren weitaus besser und effizienter umsetzen, und einer »Inflation von Instanzen« mit allen ihren administrativen Alpträumen kann wirkungsvoll begegnet werden. Die Datenbank-Parametrierung Sind im Rahmen des Datenbankmodells die Entscheidungen gefallen, welche Anwendungen in welchen Datenbanken und Instanzen installiert werden, können die einzelnen Systeme parametriert werden. Einige der Parameter – wie z.B. die Blockgröße, die Zeichensätze, der globale Name und der Datenbankmodus – können direkt aus den Anforderungen des Datenbankmodells abgeleitet werden. Darüber hinaus sollten jedoch weitere Parameter, wie zum Beispiel die Puffergrößen, geplant werden. Eine wesentliche Neuerung waren schon in der Version 9i die dynamisch änderbaren Speicherparameter. Durch die Möglichkeit, während der Laufzeit die Werte für die verschiedenen Pufferbereiche der SGA anzupassen, lassen sich die Systeme – auch ohne Neustart – an veränderte oder unbekannte Anforderungen anpassen. Da der Parameter sga_max_size den notwendigen Speicherplatz zwar überprüft, aber nicht allokiert, kann dieser Parameter entsprechend hoch gesetzt werden, um im laufenden Betrieb die Möglichkeit zu haben, die SGA zu vergrößern. Für die Version 10g empfiehlt sich das Automatische Shared-Memory-Management (Automatic Memory Management). Hierbei wird nur noch die Gesamtgröße des Shared Memorys über den Serverparameter sga_target vorgegeben. Aufgrund von Systemstatistiken, die über den Serverparameter statistics_level = TYPICAL oder ALL ermittelt werden, werden dann die einzelnen Komponenten (Buffer Cache, Shared Pool, Large Pool und Java Pool) automatisch parametriert und im laufenden Betrieb ebenfalls automatisch geändert. Alternativ können wie bisher die Parameter manuell gesetzt werden: Blockpuffer (Database Buffer Cache) Der Blockpuffer speichert Kopien von Oracle-Blöcken aus den Datendateien der Datenbank. Er ist Teil der System Global Area. Ab Oracle9i sind hierfür die bereits erwähnten Parameter db_cache_size und db_nk_cache_size zuständig, welche die Größe des Pufferbereiches (in Byte) festschreiben. In älteren OracleVersionen wurde der Bereich über den Parameter db_block_buffers angegeben, der die Anzahl der Datenbank-Blöcke angab.
12 Die Real-Application-Cluster-Konfiguration erlaubt den Zugriff über mehrere Instanzen auf eine Datenbank. Die Instanzen können in einer Cluster- oder Massiv-Parallel-Umgebung konfiguriert sein.
54
Installation und Aufbau einer Datenbank
Neben diesen Standardbereichen lassen sich unter Oracle noch Blockpuffer mit alternativen Ein- und Ausgabealgorithmen definieren: der Keep-Pool – für Objekte, die konstant im Puffer gehalten werden sollten – und der Recycle-Pool – für Objekte, die nur kurzzeitig im Speicher verbleiben sollen. Beide Bereiche gelten allerdings nur für Objekte in Tablespaces mit der Standardblockgröße (db_block_size). Gemeinsamer Pool (Shared Pool) Der gemeinsame Pool speichert u.a. Informationen aus dem Data Dictionary (Dictionary Cache), ausführbaren PL/SQL-Programmcode und Zugriffspfade für ausgeführte SQL-Befehle (Shared SQL Areas). Die Größe des gemeinsamen Pools wird über den Serverparameter shared_pool_size festgelegt. Weitere spezielle Shared-Memory-Bereiche existieren für Java und Oracle Streams. Die entsprechenden Parameter werden zu gegebener Zeit erklärt. Des Weiteren müssen die Verzeichnisstrukturen und Namen der Dateien festgelegt werden. Dazu gehören: Kontrolldateien (Parameter Control Files). Sie enthalten u.a. Listen aller Dateien einer Datenbank sowie interne Systeminformationen, die u.a. für Backup- und Recovery-Aktionen sowie für die Konsistenzsicherung (Checkpoints) notwendig sind. Entsprechend sind Zugriffe auf Steuerdateien – im Vergleich zu denen der anderen Gruppen – eher gering an der Zahl. Datendateien. Sie enthalten alle Benutzer- und Metadaten der betreffenden Datenbank. Die Häufigkeit und die Art der Zugriffe hängen vom Zugriffsverhalten der abhängigen Anwendungen und darüber hinaus auch von der Größe des Buffer-Caches ab – je größer der Buffer-Cache, desto geringer die Anzahl der physischen Zugriffe. Der Zugriff auf Datendateien erfolgt stets wahlfrei. Redo-Log-Dateien. Sie enthalten Änderungsprotokolle, die durch Datenmanipulationen generiert und über den Log-Puffer der System Global Area in die Redo-Log-Dateien geschrieben werden. Redo-Log-Dateien werden im laufenden Datenbankbetrieb nur geschrieben, während eines Recovery dagegen auch gelesen. Zugriffe auf Redo-Log-Dateien erfolgen stets sequenziell. Die Schreibhäufigkeit hängt ganz von der DML-Charakteristik des betreffenden Systems ab. In vielen Fällen gehören die Redo-Log-Dateien jedoch zu den im Hinblick auf die Ein- und Ausgabe am intensivsten genutzten Dateien eines Oracle-Systems. Zusätzlich kann es Bereiche für das Backup und Recovery geben (Flash Recovery Area), die ebenfalls über die Datenbank verwaltet werden (siehe Kapitel 10). Die Installationsplanung hat auf der einen Seite die Aufgabe, ein Regelwerk zum Aufbau von Verzeichnisstrukturen13 und Namenskonventionen zu schaffen, das den Administratoren eine schnelle Orientierung auf unterschiedlichen Rechnern des Unternehmens erlaubt und auch Skripte besser portierbar macht. Ab der Version Oracle9i ist es möglich, Dateien der drei oben beschriebenen Dateigruppen vollständig über die Datenbank zu verwalten (Oracle Managed Files). Die Datenbank übernimmt in diesem Fall nicht nur das Anlegen, sondern auch das Löschen der Dateien, z.B. dann, wenn der betreffende Tablespace gelöscht wird. Das automatisierte Dateimanagement wird über unterschiedliche Serverparameter 13 Oracle bietet hierzu die so genannte OFA-Struktur an (Oracle flexible Architecture).
Software-Installation
55
aktiviert: db_create_file_dest bezeichnet das – bereits vorhandene – Verzeichnis, das die Datendateien aufnehmen soll. db_create_online_log_dest_n gibt die Verzeichnisse für die Redo-Log-Dateien und die Steuerdateien vor – n wird dabei durch eine positive Ganzzahl ersetzt, die den Grad der Spiegelung bestimmt. Für die einfache Spiegelung ist der Parameter zweifach – mit n = 1 und 2 – zu setzen. Datenund Redo-Log-Dateien werden mit einer anfänglichen Größe von 100 MByte erzeugt. Alle genannten Parameter sind sowohl auf der Ebene der gesamten Datenbank als auch auf der Ebene einer einzelnen Datenbanksitzung änderbar. Auf diese Weise lassen sich Dateien eines Typs auch über unterschiedliche Verzeichnisse verteilen, was bei großen Installation zur Verteilung der Ein- und Ausgabeoperationen sinnvoll ist. Auf der anderen Seite sind die Dateien jeder Oracle-Datenbank den IO-Anforderungen entsprechend sinnvoll zu verteilen. Als Minimalforderung für produktive Systeme gilt hier die strikte Trennung von Steuer-, Daten- und Redo-Log-Dateien auf den Platten des Systems.
2.3
Software-Installation
Im Kapitel 2.1 haben wir schon einmal die Software-Installation beschrieben. Warum also noch mal ein Kapitel? Die Antwort ist recht einfach: Die Basisinstallation ist zwar für eine einfache Installation ausreichend, sie kann aber unter Umständen dazu führen, dass Sie Software installieren und eine Datenbank konfigurieren, die Sie in der Form nicht lizenziert haben. Wenn Sie also die Enterprise Edition über die Basisinstallation anwählen, werden folgende Optionen automatisch installiert, die Sie in der Regel nicht lizenziert haben. Dies sind in der Version 10.1.0.3: Oracle Advanced Security Oracle Partitioning Oracle Spatial Oracle OLAP Sowie die Enterprise Manager Packages Natürlich ist es kein Lizenzverstoß, wenn Sie die Software installieren. Wenn Sie allerdings eine Datenbank anlegen und diese Optionen verwenden, müssen Sie die entsprechenden Lizenzen besitzen. Aufgrund dieser Tatsachen wählen wir in der Regel bei der Enterprise Edition die benutzerdefinierte Installation, da dadurch Funktionen und Optionen gezielt ausgewählt werden können.
2.3.1 Vorbereitungen Während auf MS-Windows nur darauf geachtet werden muss, dass genügend Plattenkapazität (ca. 1,5 GByte) zur Verfügung steht, müssen unter den diversen UnixDerivaten unterschiedliche Voraussetzungen geprüft werden. Dazu gehört z.B. der Post-Wait-Treiber unter IBM-AIX.
56
Installation und Aufbau einer Datenbank
Unter Windows sollte die Installation immer als lokaler Administrator erfolgen, die Installation über einen Terminalserver-Client ist nicht möglich. In jedem Fall (ob MS-Windows oder Unix) muss eine grafische Benutzeroberfläche zur Verfügung stehen, es sei denn, Sie verwenden eine so genannten Silent Installation. Unter Unix sollte die Software jedoch nicht als Administrator (Root), sondern unter einem separaten Benutzer installiert werden. Das bedeutet, dass Sie bei der Erstinstallation unter Unix einen Benutzer und eine Gruppe anlegen müssen. Im einfachsten Fall ist dies der Benutzer oracle mit der Gruppe dba. Natürlich können die Namen beliebig gewählt werden, allerdings sollten Sie bedenken, dass in den meisten Dokumentationen genau diese Benennungen benutzt werden. Offen ist allerdings, ob man für die Installation unterschiedlicher Oracle-Versionen auch unterschiedliche Benutzer wählen sollte. Diese Frage wird sicherlich nur im Rahmen von Sicherheitsrichtlinien beantwortet werden können, prinzipiell raten wir aber davon ab, da man sich natürlich die Passwörter merken muss. In vielen Oracle-Dokumenten wird zusätzlich empfohlen, die Gruppe oinstall anzulegen und die Oracle Software Installation unter dieser Gruppe durchzuführen. Der Vorteil ist hierbei, dass Datenbank- und Software-Installation voneinander getrennt verwaltet werden, allerdings bringen zusätzliche Gruppen immer auch einen Mehraufwand bei der Pflege mit sich. Wann ist es sinnvoll, getrennte Gruppen (dba und oinstall) zu haben? Die Gruppe dba wird bei der Datenbankkonfiguration verwendet, um festzulegen, welche Gruppenmitglieder sich ohne Passwort als SYSDBA an die Datenbank anmelden können. Daher stellt diese Gruppe ein Sicherheitsrisiko dar, so dass sie nur wenige Mitglieder haben sollte. Die Gruppe oinstall hingegen legt fest, welche Mitglieder die Oracle-Software und Patches installieren dürfen. Damit ist es in großen Unternehmen möglich, diese Aufgaben zu verteilen und damit den Sicherheitsanforderungen gerecht zu werden. In kleineren Unternehmen oder in Unternehmen, bei denen die Installation der Software und Konfiguration der Datenbank in einer Gruppe vereint sind (und das ist wohl in den meisten Unternehmen der Fall), reicht es daher aus, nur mit der Gruppe dba zu arbeiten. Wir werden daher im Weiteren auf die Gruppe oinstall verzichten. Nachdem Benutzer und Gruppe eingerichtet sind, empfiehlt es sich, für die Software ein separates Filesystem auszuwählen. In unseren Beispielen – aber auch in vielen Dokumenten) wird dieses in der Regel mit dem Mount-Point /app angesprochen. Unter diesem Mount-Point wird dann noch ein Unterverzeichnis (z.B. oracle) angelegt, und damit sind die wesentlichen Voraussetzungen für die Installation erfüllt. Natürlich muss das Verzeichnis /app/oracle dem Betriebssystembenutzer oracle und der Gruppe dba gehören. Je nach Unix-Derivat müssen vor dem Aufbau einer Datenbank außerdem die Semaphore- bzw. Shared-Memory-Segmente konfiguriert werden. Unter SUN Solaris bedeutet dies, dass Sie in die Datei /etc/system folgende Mindestgrößen eintragen müssen:
Software-Installation set set set set set set set set set
57
noexec_user_stack=1 semsys:seminfo_semmni=100 semsys:seminfo_semmns=1024 semsys:seminfo_semmsl=256 semsys:seminfo_semvmx=32767 shmsys:shminfo_shmmax=4294967295 shmsys:shminfo_shmmin=1 shmsys:shminfo_shmmni=100 shmsys:shminfo_shmseg=10
Listing 2.2: Shared Memory und Semaphore für SUN Solaris
Weitere Informationen auch bezüglich Betriebssystempatches finden Sie in der entsprechenden Installationsdokumentation für Ihr Betriebssystem.
2.3.2 Oracle Flexible Architecture (OFA) Wenn Sie die Oracle Software installieren, sollten Sie beachten, dass es unterschiedliche Komponenten gibt. Daher empfiehlt es sich, eine gewisse Verteilung vorzunehmen. Oracle bietet mit der Oracle Flexible Architecture (OFA) seit der Version 8 eine entsprechende Gruppierung an. Dazu gehören: Das Verzeichnis mit der installierten Software, das durch die Variable ORACLE_HOME gekennzeichnet ist. Dieses Verzeichnis enthält alle Programme (binVerzeichnis), Skripte, Packages und Komponenten für den Betrieb einer Datenbank. Das wichtigste Programm in diesem Verzeichnis ist oracle bzw. oracle.exe, d.h. der Kernel der Datenbank. Falls Sie also unterschiedliche Oracle Software-Versionen benutzen, ist es wichtig, den »richtigen« Pfad für die Programme zu wählen, da Sie sonst u.U. die Datenbank mit dem falschen Kernel starten. Des Weiteren befinden sich in diesem Verzeichnis die Konfigurationsdateien der Datenbank (dbs- bzw. database-Verzeichnis) und der Netzwerkkomponenten (network/admin). Ab Oracle 10g gibt es außerdem ein Unterverzeichnis für die Oracle Enterprise Manager Database Control Konfiguration. Das Verzeichnis, in dem die versionsunabhängigen Komponenten installiert werden. In der Vergangenheit waren dies der Universal Installer sowie die Informationen über die installierte Software (Inventory). Mit Version 10 bzw. auch bei den Oracle9i Patches ab Version 9.2.0.5 gibt es je Version wieder einen eigenen Installer, so dass diese Software jetzt im ORACLE_HOME liegt. Je Datenbank ein Verzeichnis für die zugehörigen Log- und Trace-Dateien Ein oder mehrere Verzeichnisse für die Datenbankdateien Zusätzliche Verzeichnisse für Sicherungen (Archivierungen, Flash-Recovery, Backup)
58
Installation und Aufbau einer Datenbank
Abbildung 2.7: Oracle Flexible Architecture
Während es bei den vorherigen Versionen üblich war, je Oracle-Version ein eigenes ORACLE_HOME zu haben, bei der die Versionsnummer in dreistelliger Form den Abschluss bildete (z.B. D:\oracle\product\9.2.0), wird bei Version 10g standardmäßig noch ein weiteres Unterverzeichnis hinzugefügt, also wie in Abbildung 2.7 D:\oracle\product\10.1.0\db_1. Der Grund hierfür ist die Versionsgleichheit für unterschiedliche Oracle Software-Pakete. Dadurch kann z.B. im Verzeichnis db_1 die Datenbank-Software, im Verzeichnis em_1 der Enterprise Manager, im Verzeichnis as_1 der Application-Server und im Verzeichnis ag_1 der Enterprise-ManagerAgent installiert werden; alle in der Version 10.1.0. Ob Sie allerdings diese Unterscheidung vornehmen oder wie in den Vorgängerversionen nur bis zur Produktversion gehen, bleibt Ihnen überlassen.
Software-Installation
59
2.3.3 Universal Installer Nachdem Sie unter Windows den Befehl setup gestartet (falls das CD-ROM-Laufwerk kein autorun unterstützt) oder unter Unix den Befehl runInstaller aufgerufen haben, wird zunächst einmal ein Check des Systems durchgeführt. Dabei wird geprüft, ob die notwendigen Voraussetzungen erfüllt sind. Dazu gehören u. a.: Hauptspeicher (mindestens 512 MB) Swap-Space (ca. 1 GB) Temp-Space (ca. 400 MB) Betriebssystem und Patches (wichtig beim Einsatz eines Linux-Derivats) Bei MS-Windows taucht daher für kurze oder längere Zeit ein DOS-Fenster auf. Mit dem Aufruf runInstaller –ignoreSysPrereqs kann der Check übersprungen werden. So ist es z.B. möglich, eine Installation unter Debian-Linux durchzuführen. Es versteht sich natürlich, dass Sie damit keinen Anspruch auf Support haben, d.h., diese Option sollten Sie nur bei Testinstallationen verwenden. Anschließend sollte das Fenster mit dem Oracle Universal Installer und der Willkommen-Meldung erscheinen. Falls es die erste Installation auf diesem Host ist, können Sie auf Unix-Systemen anschießend die Lage des Oracle-Inventorys angeben. In diesem Verzeichnis werden alle Installationen, die mit dem Universal Installer ausgeführt wurden, protokolliert.
Abbildung 2.8: Inventory unter Unix
60
Installation und Aufbau einer Datenbank
Auf Unix-Systemen empfiehlt es sich, vorher die Variable ORACLE_BASE zu setzen, so dass als Standardvorgabe dann das Verzeichnis $ORACLE_BASE/oraInventory gewählt wird. Außerdem erfolgt bei Unix-Betriebssystemen noch die Abfrage nach der Betriebssystemgruppe, unter der die Software installiert werden soll, in diesem Fall dba; aber wie bereits besprochen, sollte hier bei einer Trennung von Software-Installation und Datenbankkonfiguration die Gruppe oinstall gewählt werden. Bei MS-Windows erfolgt diese Abfrage nicht, sondern es wird standardmäßig das Verzeichnis C:\Programme\Oracle\Inventory gewählt. Um das zu verhindern, sollten Sie den Befehl setup aus einer DOS-Box heraus starten und vorher die Variable ORACLE_BASE auf das Verzeichnis stellen, in das Sie diese versionsunabhängigen Komponenten speichern möchten. Also z.B.: set ORACLE_BASE=D:\oracle
Damit wird während der Installation ein Unterverzeichnis inventory erstellt, in dem sich alle Installations-Logs sowie Informationen über die installierte Software befinden. Die Lage dieser Dateien kann bei späteren Installationen nicht mehr verändert werden, so dass Sie sich kurz Gedanken machen sollten, wohin Sie diese Informationen speichern wollen. Wichtig: Beim Verlust der Inventory-Informationen können keine weiteren Patches etc. installiert werden. Daher empfiehlt es sich, dieses Verzeichnis regelmäßig mit der Oracle-Software zu sichern. Daher wählen wir bei der Installation oftmals das gleiche Verzeichnis aus, in dem sich auch die Oracle-Software befindet (siehe Beispiel). Bei der Installation unter Unix wird als Nächstes die Meldung erscheinen, dass bestimmte Aktionen als root ausgeführt werden müssen. Öffnen Sie also ein zusätzliches X-Windows und führen Sie das Skript orainstRoot.sh aus (steht im o.a. Inventory-Verzeichnis). Mit diesem Befehl werden je nach Betriebssystem zusätzliche Dateien außerhalb des Oracle-Installationskontextes angelegt. Die wichtigsten sind: oratab: In dieser Datei werden später die Namen der Instanzen und deren ORACLE_HOME-Verzeichnisse eingetragen. oraInst.loc: In dieser Datei steht, wo sich das Inventory-Verzeichnis befindet und unter welcher Gruppe die Software installiert wurde (dba oder oinstall). In den meisten Fällen befinden sich die Dateien im Verzeichnis /etc, bei SUN Solaris im Verzeichnis /var/opt/oracle.
Software-Installation
61
Nachdem Sie das Skript ausgeführt haben, können Sie mit der Installation fortfahren. Sie gelangen jetzt zur Auswahl des ORACLE_HOME-Verzeichnisses, dem Sie einen eindeutigen Namen (ORACLE_HOME_NAME) geben müssen.
Abbildung 2.9: Dateiverzeichnisse
Als Nächstes kommen wir dann zum entscheidenden Punkt, der Auswahl der Installationsart. Wie bereits angesprochen, empfehlen wir Ihnen, bei der Enterprise-Edition die benutzerdefinierte Installation auszuwählen.
62
Installation und Aufbau einer Datenbank
Abbildung 2.10: Benutzerdefinierte Installation
Bitte beachten Sie, dass Sie für die Standard Edition in keinem Fall eine benutzerdefinierte Installation durchführen dürfen. Diese Installationsart bezieht sich ausschließlich auf die Enterprise Edition. Auf der folgenden Seite finden Sie die verfügbaren Produktkomponenten. Für eine in den meisten Fällen ausreichende Datenbank empfehlen wir Ihnen, folgende Komponenten auszuwählen: Oracle Database 10g Keine Enterprise-Edition-Optionen Oracle Net Services Oracle Enterprise Manager Database Control Oracle Development Kit iSQL*Plus Legato Networker Single Server (falls Sie keine andere Backup-Software einsetzen) Anschließend kann die Software installiert und – falls gewünscht – die Datenbank aufgebaut werden. Am Schluss werden Sie, wie bei der Basisinstallation, die Liste der verwendeten Ports erhalten (siehe Abbildung 2.3).
Software-Installation
63
Abbildung 2.11: Ausgewählte Produktkomponenten
2.3.4 Silent Installation Die Installation der Oracle-Software mit Hilfe des Universal Installers ist grundsätzlich übersichtlich gestaltet und komfortabel. Allerdings gibt es zwei Nachteile: 1. Wenn man viele Installationen gleicher Art durchzuführen hat, ist die wiederholte Auswahl der Komponenten zeitraubend und verleitet zu Fehlern. 2. Die interaktive Installation setzt ein grafisches Benutzerinterface voraus (XWindows) – was bei reinen Servermaschinen nicht immer gegeben ist. Man kann diese Nachteile mit einer so genannten Silent Installation in den Griff bekommen. Bei der Silent Installation gibt es keinerlei Benutzereingaben; alle Informationen, die der Installationsprozess benötigt, werden in einer Parameterdatei (response file) definiert. Die Silent Installation ist sowohl für Basisinstallationen (meist mit InstallationsCDs) als auch für Patchsets möglich. Die unten angeführten Beispiele beziehen sich auf die Installation der Oracle Database 10g-Komponenten; Silent Installationen sind aber auch für andere Komponenten möglich und machen insbesondere bei Client-Software Sinn, da für diesen Fall viel mehr Installationen anfallen als für Serverkomponenten.
64
Installation und Aufbau einer Datenbank
Vorlagen für Parameterdateien befinden sich grundsätzlich auf den Installationsmedien im Verzeichnis response. Meist gibt es je eine Datei pro Installationsart, also z.B. custom.rsp für eine Custom Installation der Enterprise Edition oder standard.rsp für eine Installation der Standard Edition. Diese Dateien müssen dann zunächst auf die eigene Umgebung angepasst werden. Sie enthalten einige Variablen; hier ein Beispiel inklusive des Originalkommentars: #-----------------------------------------------------------------#Name : ORACLE_HOME #Datatype : String #Description: Complete path of the Oracle Home. #Example: ORACLE_HOME = "C:\OHOME1" #-----------------------------------------------------------------ORACLE_HOME=
Die Zeile mit der Variablen muss angepasst werden, d.h., man trägt den gewünschten Wert ein: ORACLE_HOME = "C:\OraBase\Product\O1010"
Anstelle der – recht aufwändigen – Anpassung der Vorlagen kann man sich die Parameterdatei auch während einer interaktiven Installation erzeugen lassen. Dazu verwendet man folgenden Installer-Aufruf:14 runInstaller –record –destinationFile
gibt die zu erstellende Parameterdatei (Empfehlung: mit vollständigem
Pfad) an. Die erstellte Parameterdatei kann eventuell noch eigenen Wünschen angepasst werden. Die eigentliche Installation mit Hilfe der Parameterdatei erfolgt schließlich mit: runInstaller –silent –responseFile
Der Universal Installer schreibt wie gewohnt sämtliche Log-Informationen in das logs-Unterverzeichnis des Inventorys. Allerdings gibt es auf dem Bildschirm (Unix: stdout/stderr) eine gut lesbare Zusammenfassung der Installation mit allen durchgeführten Checks, so dass sich ein Aufruf folgender Art empfiehlt: runInstaller –silent –responseFile 2>&1 | tee screen.log
Hierdurch kann man sowohl die Installation auf dem Bildschirm verfolgen als auch später noch einmal nachvollziehen. Die komplette Ausgabe wäre an dieser Stelle zu umfangreich; daher hier nur ein Beispiel für einen der Prerequisite Checks: Performing check for GLIBC Checking recommended glibc version Expected result: 2.2.4.31.7 Actual Result: 2.3.2.95.6 Check complete. The overall result of this check is: Passed Check complete: Passed
14 Bitte bei den Parametern peinlich genau auf Groß-/Kleinschreibung achten!
Software-Installation
65
Bei einer Installation unter Unix müssen nach dem Installer-Aufruf noch ein oder mehrere Aktionen als root durchgeführt werden: 1. Falls es sich um die erste Installation auf dem System handelt, muss die Datei /etc/oraInst.loc erzeugt und mit Inhalt gefüllt werden. Dies wird durch das Skript orainstRoot.sh erreicht, das während der Installation im Hauptverzeichnis des Inventorys abgelegt wird. 2. Im ORACLE_HOME-Verzeichnis wird das Skript root.sh abgelegt, das weitere Strukturen im Unix-Verzeichnisbaum sowie bei Single-Node-Installationen die entsprechende »kleine« Variante der Cluster-Services erzeugt. Es ist möglich, mit einem späteren Aufruf aus einer grafischen Benutzerumgebung die von Oracle empfohlenen Konfigurationswerkzeuge aufzurufen. Wenn man jedoch die Oracle Software-Installation bereits automatisiert, dann macht es wahrscheinlich mehr Sinn, die Oracle Net-Parameterdateien ebenfalls per Skript auf die Maschinen zu bringen.
2.3.5 Cluster Ready Services Die Cluster Ready Services (CRS) werden auf einer eigenen CD ausgeliefert und stellen die Oracle Clusterware dar. Sie sind nicht etwa als Plug-in für bestehende Cluster-Systeme gedacht, sondern enthalten alles, was die Oracle Database für den Betrieb eines Datenbank-Clusters (mit RAC) benötigt. Da Cluster-Software mit Funktionen wie Bereitstellung von virtuellen IP-Adressen, Quorum, Heartbeat usw. recht tief ins Betriebssystem eingreift, sind die Abhängigkeiten zu Betriebssystem und Hardware in diesem Bereich besonders hoch. Bei der Installation ist darauf zu achten, dass die im betriebssystemspezifischen Installations-Handbuch beschriebenen Voraussetzungen sehr genau eingehalten werden. Falls dies nicht geschieht, wird entweder die weitere Installation fehlschlagen oder sich zumindest sehr schwierig gestalten; außerdem kann das Verhalten des späteren RAC-Systems Unregelmäßigkeiten (z.B. Performance-Probleme bei der Verwendung der falschen Netzwerkschnittstellen für die Cluster-Kommunikation) aufweisen. Bei der Installation der CRS werden sowohl interne als auch externe Netzwerke (mit eigenen Schnittstellen) definiert. Das interne Netzwerk ist ausschließlich für die Cluster-Kommunikation vorgesehen, während das externe Netzwerk für die Anbindung der Clients vorgesehen ist. Die fest mit den Knoten verbundenen primären IP-Adressen werden ergänzt durch virtuelle IP-Adressen, die für die Verbindungen von Clients benutzt werden. Die Definition des Clusters mit all seinen Adressen und Beziehungen wird in die Cluster-Registrierung eingetragen. Dies ist entweder eine eigene Raw Partition oder eine Datei im Cluster-Dateisystem, natürlich grundsätzlich im Zugriff von allen Cluster-Knoten.
66
Installation und Aufbau einer Datenbank
Die CRS selber sind unter MS-Windows als Dienst implementiert (und automatisch gestartet); unter Unix wird der Start der entsprechenden Prozesse im Betriebssystemstart verankert. Ein kill-Kommando reicht nicht aus, um die CRS zu stoppen: Das Betriebssystem startet nach kurzer Zeit automatisch Prozesse nach. Abhilfe schafft erst der Aufruf: /etc/init.d/init.cssd stop
Mit dem Parameter start werden die Prozesse erneut gestartet. Diese Vorgehensweise braucht man, wenn die CRS gepatched werden sollen.
2.4
Datenbankkonfiguration
Nachdem Sie die Software erfolgreich installiert und eventuelle Patches nachgespielt haben, ist es jetzt an der Zeit, die Datenbanken anzulegen. Tipp: Installieren Sie alle Patches, bevor Sie die Datenbanken anlegen, ansonsten müssen Sie nach der Patch-Installation die Datenbanken ebenfalls upgraden. Daher sollten Sie immer überlegen, ob die sofortige Konfiguration der Datenbank bei der SoftwareInstallation sinnvoll ist. Die einfachste Form ist, den Datenbank-Konfigurations-Assistenten aufzurufen, da dieser für jede Version und jeden Patch angepasst ist. Alternativ kann man natürlich auch eigene Skripte benutzen, hier sollte man jedoch darauf achten, diese von Zeit zu Zeit an die neuen Anforderungen anzupassen. Dies gilt speziell für die Oracle 10g-Konfiguration, da ein unter Oracle9i oder älter erstelltes Skript unter 10g nicht lauffähig ist (es fehlt u.a. der SYSAUX-Tablespace).
2.4.1 Database Configuration Assistant (DBCA) Unter MS-Windows sollten Sie im Startmenü unter PROGRAMME → ORACLE → CONFIGURATION AND MIGRATION TOOLS den DATABASE CONFIGURATION ASSISTANT finden. Unter Unix setzen Sie bitte Ihr ORACLE_HOME und den Pfad entsprechend, und rufen Sie dbca auf, z.B. in der Form: % % % %
ORACLE_BASE=/app/oracle ORACLE_HOME=$ORACLE_BASE/product/10.1.0/db_1 PATH=$PATH:$ORACLE_HOME/bin dbca
Listing 2.3: Aufruf dbca unter Unix (Bourne-Shell)
Nach dem Aufruf werden Sie wieder willkommen geheißen und können im Schritt 1 auswählen, ob Sie eine neue Datenbank erstellen oder eine Vorlage (Template) verwalten wollen. Die Verwaltung von Vorlagen bietet sich an, wenn Sie mehrere Datenbanken in der gleichen Form (unterschiedliche Namen, aber gleiche Struktur) anlegen wollen.
Datenbankkonfiguration
67
Für die Erstinstallation wählen Sie hier DATENBANK ERSTELLEN aus und gelangen bei Schritt 2 zu einer Auswahlliste wie in Abbildung 2.12.
Abbildung 2.12: Auswahlliste Datenbankvorlagen
Wenn Sie eigene Vorlagen erstellt haben, werden diese ebenfalls hier dargestellt. Der rechte Teil (»Umfasst Datendateien«) gibt an, dass diese Datenbank nicht neu erstellt wird, sondern dass es bereits eine vorkonfigurierte Datenbank gibt, die nur noch an die entsprechende Stelle kopiert wird (die Vorlagen befinden sich im Verzeichnis ORACLE_HOME/assistants/dbca/templates). Dadurch kann die Installation in wenigen Minuten erfolgen, allerdings mit dem bereits erwähnten Nachteil, dass auch Komponenten installiert werden, die Sie nicht benötigen bzw. für die Sie gar keine Lizenzen besitzen. Die drei Vorlagen (ALLGEMEINE AUFGABEN, DATA WAREHOUSE, TRANSAKTIONSVERARBEITUNG) unterscheiden sich nur hinsichtlich der Größe der Datenbankdateien sowie je nach Betriebssystem der Größe der Datenbankblöcke (db_block_size). Im Schritt 3 müssen Sie den Namen der Datenbank sowie den Namen der Instanz (SID) angeben. In der Regel werden beide Namen identisch sein, daher trägt der Wizard den angegebenen Datenbanknamen automatisch als Instanznamen ein. Eine Ausnahme bilden hierbei die Real Application-Cluster-Datenbanken, da dort mehrere Instanzen auf eine Datenbank zugreifen.
68
Installation und Aufbau einer Datenbank
Schritt 4 enthält die Informationen zur Konfiguration des Oracle Enterprise Managers.
Abbildung 2.13: Verwaltungsoptionen
Wenn Sie den Enterprise Manager Grid Control verwenden und bereits einen entsprechenden Agenten auf dem System installiert haben, können Sie die Datenbank in dieses Management Framework einhängen. In unserem Beispiel in Abbildung 2.13 kann nur der Enterprise Manager Database Control benutzt werden, da keine Agenten installiert sind. Für kleinere Umgebungen reicht der Database Control sicherlich aus und sollte daher an dieser Stelle mit installiert werden. In großen Umgebungen sollte man den Enterprise Manager Grid Control verwenden und daher entweder einen bereits installierten Agenten einbinden oder an dieser Stelle auf die Konfiguration des Enterprise Managers verzichten. Da der Enterprise Manager bereits vorkonfigurierte Alarme verwendet, kann an dieser Stelle entschieden werden, ob im Fehlerfall E-Mails versendet werden sollen. Außerdem kann hier schon der Recovery Manager parametriert werden, so dass täglich zu einer festgelegten Zeit über den Enterprise Manager ein Backup der Datenbank erfolgt.
Datenbankkonfiguration
69
In Schritt 5 können dann die Passwörter für die Standardschemata der Datenbank gesetzt werden. Im Gegensatz zur Basisinstallation sind hier auch die »alten« Passwörter »manager« oder »change_on_install« möglich, Sie sollten aber vielleicht doch langsam von diesen Passwörtern Abschied nehmen und sicherheitshalber andere verwenden. In Schritt 6 wird das Speicherungsverfahren gewählt.
Abbildung 2.14: Speicherungsoptionen
Die Speicherung im Dateisystem ist sicherlich immer noch erste Wahl, d.h., die Datenbankdateien werden in einem oder mehreren Verzeichnissen gespeichert. Sie sollten darauf achten, dass es sich hierbei um neu formatierte Dateisysteme handelt, in denen ausschließlich Datenbankdateien gespeichert werden, da es sonst auf Betriebssystemebene zu Fragmentierungen kommen kann. Die Speicherung auf so genannten Raw Devices hat im Unix-Umfeld immer noch große Anhänger, speziell wenn es um die optimale I/O-Performance geht, da hier jeglicher Betriebssystem-Overhead ausgeschaltet wird. Messungen auf unterschiedlichen Betriebssystemen zeigen, dass durch die Speicherung auf Raw Devices ein bis zu 20% besserer I/O-Durchsatz erreicht werden kann. Neu ist in Oracle 10g die Möglichkeit, die Dateien im Automatic Storage Management (ASM) zu speichern.
70
Installation und Aufbau einer Datenbank
Nähere Informationen zu den Speicherungsarten finden Sie in Kapitel 3.9. In der Regel werden Sie hier die Speicherung im Dateisystem auswählen und kommen dann in Schritt 7 zur Auswahl des Speicherortes. Bei großen Datenbanken empfiehlt es sich, unterschiedliche Dateisysteme für die Speicherung der Dateien auszuwählen, bei kleineren Datenbanken kann hier die Option GEMEINSAMEN SPEICHERORT FÜR ALLE DATENBANKDATEIEN VERWENDEN ausgewählt werden. Damit muss nur noch das Verzeichnis angegeben werden, in das diese Dateien installiert werden sollen. Während der Installation wird in diesem Verzeichnis ein Unterverzeichnis mit dem Namen der Datenbank erstellt, und in diesem Verzeichnis werden alle Datenbankdateien angelegt. Alternativ kann die Speicherung als ORACLE MANAGED FILES erfolgen, wobei dann keine Namen für die Dateien angegeben werden müssen, sondern Oracle diese Dateien verwaltet. Hierzu finden Sie ebenfalls in Kapitel 3.9 nähere Informationen. Neu ist in der Version 10g der Schritt 8, die Wiederherstellungsoptionen für die Datenbank. Hier werden das Verzeichnis und die Größe des Flash-Recovery-Bereiches angegeben. Achten Sie bitte darauf, dass die Größe für Ihre Anwendung ausreichend bemessen ist, die vorgegebenen 2 GB reichen in den wenigsten Fällen aus. Sie sollten hier ein eigenes Dateisystem mit einer ausreichenden Größe zur Verfügung stellen.
Abbildung 2.15: Wiederherstellungsoptionen
Datenbankkonfiguration
71
An dieser Stelle können Sie bereits die Archivierung aktivieren, allerdings ist das in den seltensten Fällen sinnvoll, da es wahrscheinlich noch einige Zeit dauern wird, bis Ihre Datenbank in Produktion geht, und erst zu dem Zeitpunkt ist eine Archivierung sinnvoll bzw. erforderlich. Nähere Informationen zu diesen Optionen finden Sie in Kapitel 10. Schritt 9 gibt die möglichen Komponenten an, die in dieser Datenbank installiert werden können. Die Optionen, die Sie bei der Software-Installation mit ausgewählt haben oder die zum Standardumfang der Installation gehören, können Sie hier auswählen, die anderen sind ausgegraut.
Abbildung 2.16: Datenbankkomponenten
Wie bereits erwähnt, sollten Sie sich vorher informieren, ob Sie die entsprechenden Komponenten lizenziert haben. Abbildung 2.16 zeigt, dass die Oracle OLAPOption nicht installiert worden ist, die Oracle Data-Mining-Komponente lässt sich jedoch installieren, ist aber ebenfalls kostenpflichtig. Die Beispielschemata können – obwohl sie zum Standardumfang gehören – nicht ausgewählt werden, da diese nicht installiert worden sind. Die Skripte und Anwendungen sind nicht auf der Basis-CD, sondern müssen über die Companion-CD nachinstalliert werden. Unter dem Punkt STANDARD-DATENBANKKOMPONENTEN befindet sich die Liste der nicht kostenpflichtigen Pakete, die je nach Bedarf mit installiert werden können.
72
Installation und Aufbau einer Datenbank
Abbildung 2.17: Standard-Datenbankkomponenten
Ob Sie in jedem Fall Intermedia und die XML DB brauchen, sollten Sie von Fall zu Fall entscheiden, dabei aber immer beachten, dass ein Upgrade oder eine PatchInstallation durch diese Komponenten erheblich länger dauern kann. Bei der Installation der Oracle Java Virtual Machine (JVM) scheiden sich die Geister. Einerseits gibt es mittlerweile einige Oracle-Anwendungen, die diese Komponente benutzen, andererseits sind Installation oder Upgrade gerade für Java eine langwierige Prozedur. Sie müssen entscheiden, welchen Nutzen Sie aus der Installation ziehen. In Schritt 10 geht es um die Datenbankparameter.
Abbildung 2.18: Serverparameter
Datenbankkonfiguration
73
Zunächst wird die Größe der SGA (System Global Area) und der PGA (Process Global Area) angegeben. Diese beiden Parameter bestimmen, wie viel Hauptspeicher auf dem Server für den Betrieb der Datenbank verwendet werden soll. Alternativ zur Angabe dieser beiden Parameter kann auch einfach ein Prozentsatz des gesamten physikalischen Hauptspeichers angegeben werden. Im Reiter SKALIERUNG können die Blockgröße (Standard 8 KB) und die maximale Anzahl von Prozessen (Standard 150) geändert werden. Der Reiter ZEICHENSÄTZE dient zur Auswahl des Datenbank-Zeichensatzes und des länderspezifischen Zeichensatzes (National Characterset). Der Reiter VERBINDUNGSMODUS gibt abschließend an, ob je Datenbankverbindung ein separater Prozess erzeugt werden soll (Dedicated Server) oder ob sich eine Anzahl von Verbindungen einen Prozess teilen soll (Shared Server). Im Schritt 11 der Datenbankkonfiguration schließlich können die Datenbankdateien parametriert werden. Wenn Sie für alle Dateien ein Verzeichnis ausgewählt haben oder die Oracle-Managed Files verwenden, bleibt Ihnen hier nicht viel zu tun. Wenn Sie allerdings die Datendateien auf unterschiedliche Filesysteme verteilen wollen oder mit Raw Devices arbeiten, dann können Sie hier die notwendigen Einstellungen vornehmen. Folgende Einstellungen sollten Sie aber in jedem Fall vornehmen. Standardmäßig sind die Datendateien mit der Option Autoextend angelegt, wodurch sich diese Dateien bei Erreichen der vorgegebenen Größe automatisch um eine bestimmte Größe erweitern; und dieses bis zur maximal möglichen Größe je Betriebssystem.
Abbildung 2.19: Autoextend TEMP-Tablespace
74
Installation und Aufbau einer Datenbank
In Abbildung 2.19 bedeutet dies, dass sich die Datei des Tablespaces TEMP immer um 640 KB erweitert, wenn zusätzlicher Platz für Sortierungen benötigt wird. Die maximale Größe ist nicht beschränkt, sodass die Datei auf dem dargestellten MS-Windows-System bei einer Standard-Blockgröße von 8 KB 32 GB groß werden kann, bei 16 KB Blockgröße 64 GB. Da es nur schwer möglich ist, einen einmal allokierten Platz wieder freizugeben, könnte diese Einstellung zu Problemen im Produktionsbetrieb führen. Daher empfehlen wir, wenn Sie die Option Autoextend für Datendateien benutzen, dass Sie die maximale Größe entsprechend beschränken, so dass die Datendateien zwar wachsen können, Sie aber immer einen Puffer im Filesystem behalten. Außerdem sollten Sie die Erweiterungen (Inkrement) so wählen, dass diese Funktion nur selten ausgeführt wird, da dies ein zusätzlicher Overhead beim Betrieb der Datenbank ist. Die oben angegebene Größe von 640 KB für den TEMP-Tablespace ist sicherlich sehr ungünstig gewählt, da in diesem Tablespace jedes Segment normalerweise 1 MB groß ist. Sie sollten daher folgende Inkrement-Einstellungen verwenden: Für Dateien bis ca. 1 GB Größe: Inkrement = 10 MB Für Dateien von 1 bis 10 GB Größe: Inkrement = 100 MB Darüber: Inkrement = 1000 MB Damit ist die Konfiguration der Datenbank abgeschlossen, und der Installation steht nichts mehr im Wege. In Schritt 12 können Sie jetzt die Datenbank direkt erstellen lassen, die Konfiguration als Vorlage speichern oder die Konfiguration als Skripte abspeichern.
Abbildung 2.20: Erstellen der Datenbank
Datenbankkonfiguration
75
Das Sichern der Skripte ist sicherlich in jedem Fall zu empfehlen, da hiermit zunächst einmal eine nachvollziehbare Dokumentation entsteht und zusätzlich die Möglichkeit geschaffen wird, eine fehlerhafte Installation zu wiederholen, ohne nochmals auf den DBCA zuzugreifen. Leider mussten wir immer wieder feststellen, dass die Speicherung der Skripte nicht mit dem übereinstimmt, was passiert, wenn man die Datenbank direkt erstellen lässt. Zum Abschluss erhalten Sie eine HTML-Datei mit der Konfiguration Ihrer Datenbank. Vergessen Sie nicht, diese abzuspeichern. Im folgenden Kapitel werden wir die erzeugten Skripte für eine skriptbasierte Installation benutzen.
2.4.2 Skriptbasierte Installation Für die Verwendung von Skripten bietet es sich an, entsprechend der Oracle Flexible Architecture entsprechende Verzeichnisse anzulegen und die Skripte im Unterverzeichnis create oder scripts abzulegen. Die aus dem DBCA erstellten Skripte werden, wenn Sie die Variable ORACLE_BASE gesetzt haben, im Verzeichnis scripts abgelegt (siehe Abbildung 2.7 und 2.20). In diesem Verzeichnis finden Sie die Dateien zur Erstellung der notwendigen Verzeichnisse und der Datenbank. Das folgende Beispiel ist für die Datenbank WIN10G unter MS-Windows erstellt worden. Bis auf die Lage der Datenbankdateien und der Verwendung einer Batch-Datei anstelle eines Shell-Skriptes ist es aber ebenso unter Unix lauffähig. WIN10G.bat mkdir D:\oracle\admin\WIN10G\bdump mkdir D:\oracle\admin\WIN10G\cdump mkdir D:\oracle\admin\WIN10G\create mkdir D:\oracle\admin\WIN10G\pfile mkdir D:\oracle\admin\WIN10G\udump mkdir D:\oracle\flash_recovery_area mkdir D:\oracle\oradata\WIN10G mkdir D:\oracle\product\10.1.0\db1\database set ORACLE_SID=WIN10G D:\oracle\product\10.1.0\db1\bin\oradim.exe -new -sid WIN10G -startmode manual -spfile D:\oracle\product\10.1.0\db1\bin\oradim.exe -edit -sid WIN10G -startmode auto -srvcstart system D:\oracle\product\10.1.0\db1\bin\sqlplus /nolog @D:\oracle\admin\WIN10G\scripts\WIN10G.sql Listing 2.4: WIN10G.bat
Zunächst werden die benötigten Verzeichnisse erstellt. Mit dem Befehl oradim, den Sie immer mit vollem Pfad aufrufen sollten, wird der Diensteintrag in MS-Windows durchgeführt. Der erste Aufruf erstellt den Dienst WIN10G und besagt, dass dieser Dienst die Serverparameter aus einer Serverparameterdatei (SPFILE) erhalten soll.
76
Installation und Aufbau einer Datenbank
Der zweite Aufruf veranlasst, dass der Dienst beim Starten des Systems automatisch unter dem Benutzer Lokales System gestartet werden soll. Als Letztes erfolgt der Aufruf von sqlplus mit dem SQL-Skript WIN10G.sql. Auch beim Aufruf von sqlplus sollten Sie darauf achten, die richtige Version zu verwenden. WIN10G.sql set verify off PROMPT specify a password for sys as parameter 1; DEFINE sysPassword = &1 PROMPT specify a password for system as parameter 2; DEFINE systemPassword = &2 PROMPT specify a password for sysman as parameter 3; DEFINE sysmanPassword = &3 PROMPT specify a password for dbsnmp as parameter 4; DEFINE dbsnmpPassword = &4 host D:\oracle\product\10.1.0\db1\bin\orapwd.exe file=D:\oracle\product\10.1.0\db1\database\PWDWIN10G.ora password=&&sysPassword force=y @D:\oracle\admin\WIN10G\scripts\CreateDB.sql @D:\oracle\admin\WIN10G\scripts\CreateDBFiles.sql @D:\oracle\admin\WIN10G\scripts\CreateDBCatalog.sql @D:\oracle\admin\WIN10G\scripts\emRepository.sql @D:\oracle\admin\WIN10G\scripts\postDBCreation.sql Listing 2.5: WIN10G.sql
Zunächst werden hier die Passwörter für die vordefinierten Benutzer abgefragt. Anschließend wird mit dem Befehl orapwd eine neue Passwortdatei erstellt, die für die Remote-Administration der Datenbank erforderlich ist. Zum Schluss werden nacheinander die Skripte zur Erstellung der Datenbank ausgeführt. CreateDB.sql connect SYS/&&sysPassword as SYSDBA set echo on spool D:\oracle\product\10.1.0\db1\assistants\dbca\logs\CreateDB.log startup nomount pfile="D:\oracle\admin\WIN10G\scripts\init.ora"; CREATE DATABASE "WIN10G" /* 1. */ MAXINSTANCES 8 /* 2. */ MAXLOGHISTORY 1 MAXLOGFILES 16 MAXLOGMEMBERS 3 MAXDATAFILES 100 DATAFILE 'D:\oracle\oradata\WIN10G\system01.dbf' /* 3. */ SIZE 300M REUSE AUTOEXTEND ON NEXT 10240K MAXSIZE 500M EXTENT MANAGEMENT LOCAL SYSAUX /* 4. */ DATAFILE 'D:\oracle\oradata\WIN10G\sysaux01.dbf'
Datenbankkonfiguration
77
SIZE 120M REUSE AUTOEXTEND ON NEXT 10240K MAXSIZE 500M DEFAULT TEMPORARY TABLESPACE TEMP TEMPFILE 'D:\oracle\oradata\WIN10G\temp01.dbf' SIZE 100M REUSE AUTOEXTEND ON NEXT 10240K MAXSIZE 500M UNDO TABLESPACE UNDOTBS1 DATAFILE 'D:\oracle\oradata\WIN10G\undotbs01.dbf' SIZE 100M REUSE AUTOEXTEND ON NEXT 10240K MAXSIZE 500M CHARACTER SET WE8ISO8859P15 /* 5. */ NATIONAL CHARACTER SET AL16UTF16 LOGFILE /* 6. */ GROUP 1 ('D:\oracle\oradata\WIN10G\redo01.log') SIZE 10240K, GROUP 2 ('D:\oracle\oradata\WIN10G\redo02.log') SIZE 10240K, GROUP 3 ('D:\oracle\oradata\WIN10G\redo03.log') SIZE 10240K USER SYS IDENTIFIED BY "&&sysPassword" /* 7. */ USER SYSTEM IDENTIFIED BY "&&systemPassword"; spool off Listing 2.6: CreateDB.sql
In Schritt 1 erfolgt die Anmeldung an die Datenbank als SYSDBA mit dem im Skript WIN10G.sql angegebenen Passwort. Diese Anmeldung kann auf MS-Windows-Systemen nur erfolgen, wenn der Dienst bereits gestartet ist. Mit dem Befehl spool werden die folgenden SQL-Befehle protokolliert. Das Protokollverzeichnis ist %ORACLE_HOME%\assistants\dbca\logs, wodurch manchmal eine gewisse Verwirrung herrscht, wo die Dateien zu finden sind. Eventuell sollten Sie das Verzeichnis für alle folgenden SQL-Skripte anpassen. Mit dem Befehl STARTUP NOMOUNT wird die Instanz gestartet, die Parameter hierfür werden aus der ebenfalls in diesem Verzeichnis befindlichen Initialisierungsdatei init.ora genommen. Mit dem Befehl CREATE DATABASE wird die Datenbank erstellt. Im Folgenden werden die wesentlichen Befehlsteile beschrieben. Diese sind im Skript mit /* Nr. */ gekennzeichnet. 1. CREATE DATABASE “WIN10G“ gibt an, wie die Datenbank heißen soll. 2. Die MAX-Werte bezeichnen Limitierungen in der Kontrolldatei der Datenbank; damit wird in dieser Datei ein entsprechender Platz allokiert. Je größer die Werte, umso mehr Platz muss reserviert werden, aber umso länger dauert u.U. das Einfügen oder Suchen von Informationen. Eine spätere Änderung ist zwar möglich, allerdings nur indem eine neue Kontrolldatei erzeugt wird, was mit einem gewissen Aufwand verbunden ist. Die Parameter im Einzelnen: – MAXINSTANCES 8: Diese Datenbank kann beim Betrieb als Real Application Cluster (RAC) maximal acht Instanzen besitzen. In dem meisten Fällen kann hier 1 eingetragen werden, wenn kein RAC benutzt wird.
78
Installation und Aufbau einer Datenbank
– MAXLOGHISTORY 1: Dieser Parameter ist nur im Umfeld einer Real-ApplicationCluster-Datenbank interessant, und zwar für das so genannte Cross Instance Recovery. In diesen Fällen sollte der Wert laut Oracle-Dokumentation ein Vielfaches des Parameters MAXINSTANCES sein. Warum dieser Wert bei einer Konfiguration über den dbca auf 1 steht, entzieht sich derzeit unserer Kenntnis. Bei einer Single-Instance-Installation wird der Parameter dynamisch angepasst. – MAXLOGFILES 16: Maximale Anzahl von Redo-Log-Gruppen. Dieser Wert bezieht sich auf alle Online-Redo-Log-Dateien, inklusive einer eventuellen logischen Spiegelung über Logfile-Member. – MAXLOGMEMBERS 3: Maximal ist eine dreifache Spiegelung der Online-Redo-LogDateien möglich. Der Wert ist absolut ausreichend. – MAXDATAFILES 100: Diese Datenbank kann maximal 100 Datendateien enthalten. In dem meisten Fällen reicht diese Größe aus, da eine Datendatei mehrere GB groß sein darf. 3. Als Nächstes wird der SYSTEM-Tablespace angelegt. Dieser Tablespace hat keine explizite Tablespace-Klausel, sondern es werden nur der Name und das Verzeichnis der zugehörigen Datendatei angegeben. 4. Die weiteren Tablespaces, die für den Minimalbetrieb einer Datenbank notwendig sind, werden erstellt. Dazu gehören der in Oracle 10g neue Tablespace SYSAUX, der Tablespace für temporäre Objekte TEMP und der Tablespace für die UNDOSegmente. Bei allen Tablespaces ist die Option REUSE angegeben. Da damit eine bereits vorhandene Datei überschrieben wird, sollte die Option mit Vorsicht genutzt werden. 5. Der Datenbank-Zeichensatz (hier: westeuropäischer nach ISO 8859 normierter Zeichensatz mit Euro-Symbol = WE8ISO8859P15) und der nationale Zeichensatz der Datenbank (AL16UTF16) werden angegeben. 6. Es werden drei Online-Redo-Log-Dateien mit einer Größe von je 10 MB angelegt. Eine Spiegelung (Member) erfolgt nicht. 7. Den Datenbankschemata SYS und SYSTEM wird das im Skript WIN10G.sql eingegebene Passwort zugewiesen. CreateDBFiles.sql connect SYS/&&sysPassword as SYSDBA set echo on spool D:\oracle\admin\WIN10G\scripts\CreateDBFiles.log CREATE TABLESPACE "USERS" LOGGING DATAFILE 'D:\oracle\oradata\WIN10G\users01.dbf' SIZE 100M REUSE AUTOEXTEND ON NEXT 10240K MAXSIZE 500M EXTENT MANAGEMENT LOCAL SEGMENT SPACE MANAGEMENT AUTO ; ALTER DATABASE DEFAULT TABLESPACE "USERS"; spool off Listing 2.7: CreateDBFiles.sql
Datenbankkonfiguration
79
Mit diesem SQL-Skript wird der Tablespace USERS angelegt, der anschließend Standard-Tablespace für alle Datenbankbenutzer wird. In diesem Beispiel erfolgt die Protokollierung in das gleiche Verzeichnis, in dem auch die Skripte liegen, um so eine bessere Kontrolle zu haben. CreateDBCatalog.sql connect SYS/&&sysPassword as SYSDBA set echo on /* Besser set echo off */ spool D:\oracle\admin\WIN10G\scripts\CreateDBCatalog.log @D:\oracle\product\10.1.0\db1\rdbms\admin\catalog.sql; @D:\oracle\product\10.1.0\db1\rdbms\admin\catblock.sql; @D:\oracle\product\10.1.0\db1\rdbms\admin\catproc.sql; @D:\oracle\product\10.1.0\db1\rdbms\admin\catoctk.sql; @D:\oracle\product\10.1.0\db1\rdbms\admin\owminst.plb; connect SYSTEM/&&systemPassword @D:\oracle\product\10.1.0\db1\sqlplus\admin\pupbld.sql; connect SYSTEM/&&systemPassword set echo on spool D:\oracle\admin\WIN10G\scripts\sqlPlusHelp.log /* Löschen */ @D:\oracle\product\10.1.0\db1\sqlplus\admin\help\hlpbld.sql helpus.sql; spool off spool off /* Löschen */ Listing 2.8: CreateDBCatalog.sql
In diesem Skript werden das externe Data Dictionary sowie zusätzliche Pakete und Hilfstabellen angelegt. Tipp: Ändern Sie den ersten Befehl set echo on auf set echo off, da dadurch die Protokollierung verkleinert und die Laufzeit dieses Skriptes erheblich reduziert wird. Die hier aufgerufenen Skripte sind: 1. catalog.sql: Mit diesem Skript wird das externe Data Dictionary erstellt. 2. catblock.sql: Es werden Views erzeugt, um blockierende Prozesse anzeigen zu können (so genannte Blocking/Waiting Locks). 3. catproc.sql: Das Skript erstellt die Basispakete für die Benutzung von PL/SQL. 4. catoctk.sql: Es werden Pakete für ein kryptografisches Toolkit und die Erzeugung von Zufallszahlen erstellt. 5. owminst.plb: Die Prozeduren und Tabellen für den Oracle Workspace Manager werden eingespielt. 6. pupbld.sql: Für das Werkzeug SQL*Plus wird die PRODUCT_USER_PROFILE-Tabelle angelegt. Die Tabelle kann benutzt werden, um SQL*Plus-Benutzern die Ausführung von Befehlen zu erlauben oder zu verweigern.
80
Installation und Aufbau einer Datenbank
7. hlpbld.sql: Ebenfalls für das Werkzeug SQL*Plus werden die englischen Hilfetexte erstellt, die mit dem Befehl HELP angezeigt werden können. Leider sind bei der Erstellung dieses Skriptes über den DBCA die Spool-Informationen etwas verrutscht, daher empfiehlt es sich, den zweiten SPOOL-Befehl und den letzten SPOOL OFF-Befehl zu löschen. postDBCreation.sql connect SYS/&&sysPassword as SYSDBA set echo on spool D:\oracle\admin\WIN10G\scripts\postDBCreation.log connect SYS/&&sysPassword as SYSDBA /* Löschen */ set echo on /* Löschen */ create spfile='D:\oracle\product\10.1.0\db1\database\spfileWIN10G.ora' FROM pfile='D:\oracle\admin\WIN10G\scripts\init.ora'; shutdown immediate; connect SYS/&&sysPassword as SYSDBA startup ; select 'utl_recomp_begin: ' || to_char(sysdate, 'HH:MI:SS') from dual; execute utl_recomp.recomp_serial(); select 'utl_recomp_end: ' || to_char(sysdate, 'HH:MI:SS') from dual; spool D:\oracle\admin\WIN10G\scripts\postDBCreation.log Listing 2.9: postDBCreation.sql
Warum der Connect-Befehl hier doppelt vorhanden ist, weiß wahrscheinlich nur das DBCA. Also können der zweite connect und das set echo on einfach gelöscht werden. Mit dem Befehl create spfile … wird aus der init.ora eine Serverparameter-Datei erzeugt. Anschließend wird die Datenbank heruntergefahren und durch den Befehl startup ohne Parameter mit der neuen Parameterdatei gestartet. Mit dem Befehl execute utl_recomp_recomp_serial() werden alle DatenbankPackages noch einmal kompiliert. emRepository.sql connect SYS/&&sysPassword as SYSDBA set echo off spool D:\oracle\admin\WIN10G\scripts\emRepository.log @D:\oracle\product\10.1.0\db1\sysman\admin\emdrep\sql\emreposcre D:\oracle\product\10.1.0\db1 SYSMAN &&sysmanPassword TEMP ON; spool off Listing 2.10: emRepository.sql
Dieses optionale Skript legt das Repository für den Oracle Enterprise Manager Database Control an.
Patches und Patch-Sets
2.5
81
Patches und Patch-Sets
Zunächst einmal muss man bei der Installation von Patches zwischen einem Interim-Patch und einem Patch-Set unterscheiden. Prinzipiell werden Fehlerbehebungen immer in Patch-Sets angeboten. Wenn ein Kunde einen Bugfix benötigt, muss er zunächst das letztgültige Patch-Set installiert haben. Wenn der Fehler damit nicht behoben ist, kann er einen Interim-Patch (auch »One-off« Patch genannt) anfordern. Ein Interim-Patch wird immer auf Basis des aktuellsten Patch-Sets aufgesetzt, was in machen Umgebungen zu Problemen führen kann, da ein Patch-Set in der Regel eine längere Auszeit für die Anwendung erfordert. Zusätzlich kann es erforderlich sein, für die Fehlerbehebung zunächst einen Diagnostic-Patch einzuspielen, mit dem dann der eigentliche Fehler lokalisiert werden kann. Bitte erwarten Sie an dieser Stelle kein generelles Kochrezept für das Einspielen von Patches, da es ein solches nicht gibt und geben kann. Es ist ein Unterschied, ob Sie z.B. den Universal Installer, der Datenbank-Kernel oder der Oracle Cluster Ready Service angepasst werden muss. Daher sollten Sie in jedem Fall zunächst die mit dem Patch oder Patch-Set mitgelieferte Dokumentation lesen. In jedem Fall sollten Sie aber vor der Installation eines Patches ein vollständiges Backup Ihrer Datenbank und der Software durchführen.
2.5.1 Patch-Sets Patch-Sets werden in unregelmäßigen Abständen herausgegeben und sind kumulativ, d.h., Sie müssen nur die letzte Version installieren, da diese alle Informationen vorheriger Patch-Sets enthält. Beim Einspielen eines Patch-Sets ändert sich die Versionsnummer der Oracle-Software an der vierten Stelle. Bei der Entstehung dieses Buches gab es für MS-Windows das Basis-Release 10.1.0.2 und das Patch-Set 10.1.0.4. Die Installation des Patch-Sets erfolgt über den Universal Installer, wobei es vorkommen kann, dass Sie zunächst den Universal Installer selbst anpassen müssen, bevor Sie mit der eigentlichen Installation beginnen können. Eine unschöne Einschränkung gibt es nach der Installation des Patch-Sets 10.1.0.3. Sie können nach dem Einspielen keine Datenbankoptionen mehr nachinstallieren, sondern erhalten in einem solchen Fall die Fehlermeldung, dass die installierte Version neuer ist als diejenige, die Sie nachinstallieren wollen. Der Fehler ist bei Oracle bekannt, und unter der Bug-Nummer 3870317 können Sie aus dem Oracle-Metalink einen Universal Installer laden, mit dem eine Nachinstallation von Optionen möglich ist. Generell gilt aber bei Nachinstallationen, dass Sie anschließend nicht vergessen sollten, das Patch-Set nochmals für diese Komponente durchlaufen zu lassen. Die Installation eines Patch-Sets gliedert sich in folgende Schritte: 1. Preinstallation: Herunterfahren der Datenbank und zugehöriger Komponenten, wie z.B. Listener, Agents oder Database Control.
82
Installation und Aufbau einer Datenbank
2. Installation: Das Patch-Set wird mit dem mitgelieferten Universal Installer eingespielt. Sie müssen dabei das richtige Zielverzeichnis (ORACLE_HOME) eingeben. Weitere Eingaben werden in der Regel nicht erwartet, da der Universal Installer im Inventory nachsieht, welche Komponenten installiert worden sind und somit angepasst werden müssen. Der Universal Installer ist in der Regel genauso aufzurufen wie bei einer »normalen« Software-Installation. Auch eine Silent Installation eines Patch-Sets ist daher möglich. 3. Postinstallation: Nach der Installation werden zunächst die Dienste wieder gestartet, allerdings nicht die Datenbankinstanz. Vor deren Hochfahren müssen einige Parameter überprüft werden, so kann es z.B. erforderlich sein, den Bereich für Java-Komponenten (java_pool_size) zu erhöhen. Gestartet wird die Instanz dann aus SQL*Plus mit dem MIGRATE-Befehl: Dieser Befehl sorgt dafür, dass einige zusätzliche Parameter gesetzt und eventuelle System-Trigger ausgeschaltet werden. Nachdem die Instanz gestartet ist, wird dann das Skript catpatch.sql aus dem Verzeichnis $ORACLE_HOME/rdbms/admin gestartet. Leider erfolgt hier keine automatische Protokollierung. Die vollständige Syntax für das Einspielen eines PatchSets sieht demnach folgendermaßen aus: SQL> SQL> SQL> SQL>
STARTUP MIGRATE spool c:\temp\patch10103.log @?/rdbms/admin/catpatch15 spool off
Listing 2.11: Einspielen eines Patch-Sets
Anschließend muss die Datenbankinstanz noch einmal neu gestartet werden, und es sollten alle PL/SQL-Programmpakete neu kompiliert werden. Dies geschieht mit folgenden Befehlen: SQL> SHUTDOWN IMMEDIATE SQL> STARTUP SQL> @?/rdbms/admin/utlrp Listing 2.12: Rekompilieren der PL/SQL-Pakete
Beachten Sie bitte, dass ein Patch-Set in der Regel nicht wieder deinstalliert werden kann. Es kann daher sinnvoll sein, ein neues Verzeichnis für die Oracle-SoftwareInstallation zu wählen und darin eine Basisinstallation und die Patch-Installation durchzuführen. Der Vorteil ist, dass während der Software-Installation die Datenbank weiter genutzt werden kann, und erst in der dritten Phase die Instanz neu gestartet werden muss. Der Ausfall der Datenbank beschränkt sich hierdurch je nach Anzahl und Komplexität der Java- und PL/SQL-Programmlogik auf wenige Minuten. Tipps für die Installation in einer Hochverfügbarkeitsumgebung (Real Application Clusters oder Data Guard) erhalten Sie in Kapitel 13.
15 Das »?« kann bei der Verwendung von SQL*Plus als Platzhalter für das ORACLE_HOME verwendet werden
Release-Wechsel
83
2.5.2 Interim-Patches Im Gegensatz zu den Patch-Sets werden Interim-Patches über ein eigenes Kommando »opatch« installiert. Während dieses Werkzeug in älteren Oracle-Versionen nicht enthalten war und daher zunächst umständlich im Oracle-Metalink gesucht und dann installiert werden musste, gibt es ab Version 9.2 ein eigenes Verzeichnis im ORACLE_HOME. Das Skript basiert auf der Sprache Perl und dementsprechend muss eine Perl-Umgebung installiert sein, was aber ab Oracle 9.2 ebenfalls gegeben ist. Bevor Sie einen Patch installieren, sollten Sie aber nochmals kontrollieren, ob eventuell doch eine neuere opatch-Version benötigt wird. Die Installation eines Patches erfolgt dann durch Aufruf von opatch mit dem Verzeichnis, in dem sich die Patch-Software (ausgepackt) befindet. Also z.B.: D:\oracle\product\10.1.0\db1\opatch\opatch C:\temp\patch_3874444 Listing 2.13: Aufruf von opatch
Im Gegensatz zu den Patch-Sets ist es bei Interims-Patches teilweise möglich, diese über den Befehl opatch –rollback <Patchid> wieder zu deinstallieren. Weitere Optionen erhalten Sie mit opatch –h.
2.6
Release-Wechsel
Für einen Release-Wechsel sollte man sich folgende Fragen stellen: 1. Welche Auswirkungen hat ein Release-Wechsel auf die Anwendungen? 2. Welche Auszeit steht zur Verfügung? 3. Welche neuen Funktionen sollten und können genutzt werden? Der wichtigste Punkt ist zunächst einmal die Frage nach den Anwendungen. Auch wenn Oracle immer versucht, eine entsprechende Kompatibilität zu gewährleisten, ist es dennoch Aufgabe des Software-Anbieters zu untersuchen, ob es Unverträglichkeiten zu einzelnen Oracle-Releases gibt. Der Betrieb von Oracle 10g ist in den meisten Fällen unkritisch, allerdings gibt es bezüglich der Oracle-Clients und Oracle Net-Komponenten einige Einschränkungen. Die verfügbare Auszeit ist oftmals entscheidend für die Wahl des Upgrade-Verfahrens und damit indirekt auch für die dritte Frage, welche neuen Funktionen genutzt werden können. Wenn die Auszeit nur wenige Stunden beträgt, dann kann ein Upgrade in der Regel nur über die direkte Anpassung der Datenbank erfolgen, wie sie über den Database Upgrade Assistant durchgeführt wird. Wenn eine längere Auszeit möglich ist, dann kann darüber nachgedacht werden, ob das Neuaufsetzen einer Datenbank mit anschließendem Import der Daten sinnvoller ist, da hierbei neue Funktionalitäten genutzt werden können. Das betrifft im Wesentlichen die Konfiguration der Tablespaces, erst recht, wenn die Datenbank noch – wie in Oracle8 üblich – mit Dictionary Managed Tablespaces betrieben wird.
84
Installation und Aufbau einer Datenbank
Beim Neuaufbau der Datenbank besteht die Möglichkeit, alle Tablespaces (inklusive des System-Tablespaces) als Locally Managed Tablespaces aufzubauen und für die Daten außerdem die ASSM-Funktionalität (Automatic Segment Space Management) zu nutzen. Ein weiterer Effekt beim Neuaufbau einer Datenbank ist sicherlich die Reorganisation aller Tabellen sowie eine Bereinigung des Data Dictionarys. In diesem Kapitel werden wir uns mit dem direkten Upgrade der Datenbank befassen. Die Möglichkeit, eine Datenbank mit minimaler Auszeit neu aufzubauen, besprechen wir in Kapitel 13, in dem es um die Hochverfügbarkeit von Datenbanken geht.
2.6.1 Vorbereitung Zunächst einmal muss festgelegt werden, welche Voraussetzungen für den Betrieb einer neuen Oracle-Version benötigt werden. Dazu gehören: Hardware-Ressourcen (Plattenplatz für die Oracle-Software, Memory-Bedarf) Betriebssystemversion und Patches Oracle Patches Wenn alle Voraussetzungen erfüllt sind, muss noch geprüft werden, in welcher Form ein Upgrade16 durchgeführt werden kann. Oracle erlaubt einen direkten Upgrade nur von folgenden Versionen: Oracle8 Version 8.0.6 Oracle8i Version 8.1.7 Oracle9i Version 9.0.1 Oracle9i Version 9.2.0 Diese Versionen werden als »Final Releases« bezeichnet, und alle Oracle Supportund Upgrade-Notizen beziehen sich auf diese. Wenn Sie also eine andere Version einsetzen, müssen Sie diese zunächst auf das Final Release bringen und können erst dann das endgültige Upgrade durchführen. Das bedeutet, wenn Sie beispielsweise Version 8.1.6 einsetzen, müssen Sie zunächst ein Upgrade nach Version 8.1.7 durchführen und können dann auf Version 10g upgraden. Patches oder Patch-Sets sind allerdings keine Voraussetzung für das Upgrade. Von Version 7.3.4 oder älteren Versionen aus gibt es keinen direkten Upgrade-Pfad. Der Oracle 10g Database Upgrade Guide gibt für diesen Fall als einzigen offiziellen Weg das Upgrade zunächst auf Version 8.1.7.4 und dann weiter auf Oracle 10g vor. Angesichts der zahlreichen neuen Funktionen ist in einem solchen Fall aber zu überlegen, ob es nicht besser ist, die Daten mit dem Exportbefehl aus der Datenbank herauszulesen und in eine neue Datenbank zu importieren.
16 Seit Oracle9i wird bei Oracle jeder Release-Wechsel als Upgrade bezeichnet
Release-Wechsel
85
Bevor Sie dann mit dem Upgrade beginnen, sollten Sie ein Backup der Datenbank und des Software-Verzeichnisses machen. Außerdem sollten Sie sich eine Liste aller »invaliden« Objekte in der Datenbank anfertigen. Warum sollten ungültige Objekte in der Datenbank vorhanden sein? Der Gründe sind vielfältig; es kann sich um Views handeln, die auf nicht mehr existierende Tabellen verweisen, Prozeduren, die nicht endgültig in Betrieb genommen wurden, oder Software-Pakete, die nicht »sauber« installiert worden sind. Am einfachsten kann man sich die Objektliste mit folgendem Befehl generieren. SQL> set lines 120 SQL> set object_name format a30 SQL> SELECT owner, object_name, object_type FROM dba_objects WHERE status = 'INVALID' ORDER BY owner, object_name; Listing 2.14: Liste der ungültigen Objekte
Nachdem Sie die Liste erstellt haben, sollten Sie zunächst herausfinden, warum die Objekte ungültig sind, und am besten die nicht mehr benötigten löschen. Wenn Sie alle Voraussetzungen erfüllt haben, sollten Sie als Nächstes die Software wie eingangs beschrieben in einem neuen ORACLE_HOME installieren. Wenn Sie keine Betriebssystem-Patches benötigen, kann diese Installation während des normalen Betriebs erfolgen. Ausnahme hierfür ist der Oracle Real Application Cluster, da die Oracle Cluster-Software in jeder bisherigen Oracle-Version exklusiv war, so dass eine gleichzeitige Nutzung unterschiedlicher Release-Stände nicht möglich war.
2.6.2 Database Upgrade Assistant (DBUA) Während der Installation der Software wird der Oracle Universal Installer Ihnen eine Liste der Datenbanken anzeigen, die migriert werden können. Nach unserer Erfahrung ist es sinnvoller, zunächst die Installation der Software zu beenden und erst in einem zweiten Schritt das Upgrade der Datenbanken durchzuführen. Bitte beachten Sie auch, dass Sie zunächst das Basis-Release einspielen und danach noch weitere Patches. Wenn Sie also direkt eine Migration aus dem Installer anstoßen würden, würden die entsprechenden Datenbanken auf das Basis-Release migriert, und Sie müssten dann, nachdem Sie die Patches eingespielt haben, die Datenbank nochmals upgraden. Wenn Sie mit der Software-Installation fertig sind, können Sie das Upgrade der Datenbank am einfachsten über den Database Upgrade Assistant (DBUA) durchführen. Bei MS-Windows-Systemen befindet sich das Programm im Menü CONFIGURATION AND MIGRATION TOOLS, bei Unix-Systemen wird es einfach über den Befehl dbua aufgerufen. Der Vorteil der Benutzung dieses Werkzeugs liegt darin, dass zunächst alle erforderlichen Voraussetzungen geprüft und im Umfeld des Real Application Clusters alle Knoten mit einbezogen werden. Außerdem ist hierbei ein Zurückrollen im Fehlerfall möglich.
86
Installation und Aufbau einer Datenbank
Nach dem Aufruf erscheint zunächst der obligatorische Willkommensbildschirm, anschließend erhalten Sie ein Auswahlmenü mit der Liste der verfügbaren Datenbanken. Hier wählen Sie die zu migrierende Datenbank aus und geben den Benutzernamen und das Kennwort eines SYSDBA-Benutzers an. Im nächsten Schritt müssen Sie die Größe und Lage des für Oracle 10g obligatorischen SYSAUX-Tablespace angeben.
Abbildung 2.21: Auswahl des SYSAUX Tablespace
Bei kleineren Datenbanken reicht die vorgegebene Größe von 500 MB aus. Die vorgegebene Erweiterung um 1 MB bis zur »unendlichen« Größe ist jedoch nicht sinnvoll. Besser ist es, eine Erweiterung um jeweils 10 MB vorzusehen und eine obere Grenze von 1 oder 2 GB zu wählen. Als Nächstes erfolgt eine Abfrage, ob ungültige Objekte am Ende der Installation neu kompiliert werden sollen. Die Dauer der Kompilierung hängt stark von der Anzahl der verwendeten PL/SQL- und Java-Prozeduren ab. In der Regel ist die sofortige Kompilierung sinnvoller, da bei Fehlern noch eine Nachbearbeitung erfolgen kann, ohne dass die Anwender betroffen sind. Wenn Sie allerdings nur eine sehr begrenzte Zeit für das Upgrade zur Verfügung haben, können Sie die Kompilierung auch den Anwendungsprozessen überlassen. In diesem Fall werden wie üblich alle ungültigen Objekte beim ersten Aufruf neu kompiliert. Nachdem nochmals abgefragt wurde, ob ein aktuelles Backup existiert, folgt die Konfiguration des neuen Oracle Enterprise Managers. Je nachdem, ob Sie die Database Control oder Grid Control verwenden, d.h., bereits einen Agenten installiert haben, können Sie hier die entsprechende Auswahl vornehmen. Beachten Sie bitte, dass keine Auswahl eines Tablespace erfolgt, da der Enterprise Manager seine Objekte im SYSAUX-Tablespace ablegt.
Release-Wechsel
87
Bevor das Upgrade durchgeführt wird, erfolgt eine Zusammenfassung.
Abbildung 2.22: Upgrade-Zusammenfassung
Hier sehen Sie auch einen weiteren Vorteil des Upgrade Assistants. Die nicht mehr benötigten Serverparameter werden automatisch entfernt. Ebenso werden Parameter, die während der Installation eine Minimalgröße haben müssen (in der Regel shared_pool_size und java_pool_size), automatisch gesetzt.
88
Installation und Aufbau einer Datenbank
Wichtig: Während des Upgrades mit dem Database Upgrade Assistant wird die automatische Archivierung ausgeschaltet. Bei der Verwendung von Data-Guard-Datenbanken kann dies zur Folge haben, dass diese neu aufgebaut werden müssen. Daher sollten Sie dieses Verhalten, sofern Sie eine lückenlose Archivierung benötigen, vorher ändern. Im Oracle-Metalink gibt es hierfür eine Notiz (Note: 276301.1, DBUA Took Primary to NOARCHIVELOG Mode During Migration). Daraus geht hervor, dass vor dem Aufruf des Database Upgrade Assistants folgende Änderung durchgeführt werden muss: Im Verzeichnis $ORACLE_HOME/assistants/dbma liegt die XML-Datei mep.cfg. Darin gibt es folgenden Eintrag:
Diesen Eintrag ändern Sie bitte auf:
Dadurch wird die Archivierung auch während des Upgrades gewährleistet. Beachten Sie aber bitte, dass während des Upgrades eine Reihe von archivierten RedoLog-Dateien anfallen, wodurch die gesamte Zeitdauer verlängert wird. Am Ende des Upgrades erhalten Sie eine Ergebnisseite mit den alten und neuen Parametern, und Ihre Datenbank läuft unter Oracle 10g. Wenn Sie mehrere Datenbanken in dieser Form upgraden wollen, bietet es sich an, die Silent Installation zu wählen. Dabei wird der Database Upgrade Assistant mit der Option -silent und unter Angabe der Datenbank-SID aufgerufen, z.B. in der Form: % dbua –silent –sid QJA92 Listing 2.15: DBUA Silent Installation
2.6.3 Manueller Upgrade In einigen Fällen kann es schneller und sinnvoller sein, das Upgrade manuell, d.h., anhand von Skripten durchzuführen. Dabei sind aber allerhand Vorkehrungen zu treffen, so dass Sie diese Art nur dann wählen sollten, wenn Sie: ein erfahrener Oracle Administrator sind sehr wenig Zeit für das Upgrade haben vor dem Upgrade Ihrer Produktionssysteme einige Male das Upgrade geübt haben Bevor Sie mit dem Upgrade beginnen, sollten Sie das Skript utlu101i.sql ausführen. Es liegt im Verzeichnis $ORACLE_HOME/rdbms/admin17. Dieses Skript wird als SYSDBA ausgeführt und liefert eine komplette Liste aller wichtigen Punkte, die für das Upgrade betrachtet werden müssen. 17 Hier ist das neue ORACLE_HOME gemeint, also z.B. /app/oracle/product/10.1.0/db_1.
Release-Wechsel
Das folgende Listing zeigt die Ausgabe des Skriptes für die Datenbank QJA92. Oracle Database 10.1 Upgrade Information Tool 02-19-2005 16:28:06 . ************************************************************************* Database: ************************************************************************* --> name: QJA92 --> version: 9.2.0.6.0 --> compatibility: 9.2.0.0.0 . ************************************************************************* Logfiles: [make adjustments in the current environment] ************************************************************************* --> The existing log files are adequate. No changes are required. . ************************************************************************* Tablespaces: [make adjustments in the current environment] **************************************************************** ******** --> SYSTEM tablespace is adequate for the upgrade. .... minimum required size: 286 MB --> TEMP tablespace is adequate for the upgrade. .... minimum required size: 50 MB . ************************************************************************* Options: [present in existing database] ************************************************************************* --> Partitioning WARNING: Listed option(s) must be installed with Oracle Database 10.1 . ************************************************************************* Update Parameters: [Update Oracle Database 10.1 init.ora or spfile] ************************************************************************* WARNING: --> "shared_pool_size" needs to be increased to at least "150944944" --> "pga_aggregate_target" is already at "104857600" calculated new value is "104857600" --> "large_pool_size" is already at "8388608" calculated new value is "8388608" . ************************************************************************* Deprecated Parameters: [Update Oracle Database 10.1 init.ora or spfile] ************************************************************************* -- No deprecated parameters found. No changes are required. . ************************************************************************* Obsolete Parameters: [Update Oracle Database 10.1 init.ora or spfile] ************************************************************************* --> "hash_join_enabled" .
89
90
Installation und Aufbau einer Datenbank
************************************************************************* Components: [The following database components will be upgraded or installed] ************************************************************************* --> Oracle Catalog Views [upgrade] VALID --> Oracle Packages and Types [upgrade] VALID --> Oracle Workspace Manager [upgrade] VALID . ************************************************************************* . ************************************************************************* SYSAUX Tablespace: [Create tablespace in Oracle Database 10.1 environment] ************************************************************************* --> New "SYSAUX" tablespace .... minimum required size for database upgrade: 500 MB Please create the new SYSAUX Tablespace AFTER the Oracle Database 10.1 server is started and BEFORE you invoke the upgrade script. . ************************************************************************* Listing 2.16: Check einer Oracle9i-Datenbank mit utlu101i.sql
Im
obigen
Fall
bedeutet
dies,
dass
Sie
zunächst
den
Serverparameter
shared_pool_size auf 150 MB vergrößern müssen. Außerdem sollte der Parameter hash_join_enabled gelöscht werden, da er nicht mehr ausgewertet wird. Wichtiger
wäre es, wenn so genannte deprecated Parameter aufgelistet worden wären, da das Starten der Datenbank unter Version 10g mit einem solchen Parameter nicht funktioniert. Der obsolete Parameter hash_join_enabled würde hingegen nur zu einer Warnung in der Alert-Datei führen. Das Starten einer zu migrierenden Datenbank unter Version 10g ist nur möglich, wenn der Parameter compatible mindestens den Wert 9.2.0 hat. Der manuelle Upgrade sieht also wie folgt aus: 1. Installation der Oracle 10g-Software in ein neues Home-Verzeichnis 2. Stoppen des Listeners Wenn Sie nur eine Datenbank je Listener verwenden, ist es sinnvoll, diesen zu stoppen, da dadurch jeglicher Zugriff durch Dritte vermieden werden kann. 3. Check der notwendigen Änderungen mit utlu101i.sql SQL> connect / as sysdba SQL> spool c:\temp\preupgrade.log SQL> @D:/oracle/product/10.1.0/rdbms/admin/utlu101i.sql18 SQL> spool off
4. Backup der Datenbank 18 Hier darf nicht das »?« als Substitution für ORACLE_HOME verwendet werden, da es sich ja nicht um das aktuelle ORACLE_HOME handelt. Wenn Sie wollen, können Sie sich das Skript natürlich in ein anderes Verzeichnis kopieren.
Release-Wechsel
91
5. Erstellen einer neuen Initialisierungsdatei mit den angepassten Parametern Sie sollten für die Oracle 10g-Datenbank eine so genannte Serverparameterdatei verwenden. Wenn Sie das Upgrade aus der Version 9i heraus durchführen und dort schon ein SPFILE verwendet haben, können Sie die folgenden Parameter mit dem Befehl ALTER SYSTEM SET … SCOPE = SPFILE setzen. Alternativ können Sie mit dem Befehl CREATE SPFILE … FROM PFILE … eine editierbare Initialisierungsdatei erstellen. COMPATIBLE >= 9.2.0 SHARED_POOL_SIZE >= 150 MB PGA_AGGREGATE_TARGET >= 100 MB JAVA_POOL_SIZE >= 50 MB19 LARGE_POOL_SIZE >= 8 MB
Falls Sie mit einer init.ora gearbeitet haben, erstellen Sie jetzt ein SPFILE im neuen ORACLE_HOME. SQL> CREATE SPFILE = 2>
’D:\oracle\product\10.1.0\database\QJA92.ora’
3>
FROM PFILE=’D:\temp\initQJA92.ora’;20
Falls Sie bereits ein SPFILE verwenden, kopieren Sie es in das neue Zielverzeichnis. 6. Kopieren der Passwortdatei in das neue $ORACLE_HOME/dbs- (Unix) bzw. %ORACLE_HOME%\database-Verzeichnis (MS-Windows). 7. Stoppen der Datenbank 8. Bei MS-Windows-Systemen muss jetzt der Service-Eintrag gelöscht und mit dem neuen ORACLE_HOME wieder eingetragen werden: set ORACLE_SID=QJA92 set ORACLE_HOME=D:\oracle\product\9.2.0 D:\oracle\product\9.2.0\bin\oradim –delete –sid QJA92 set ORACLE_HOME=D:\oracle\product\10.1.0 D:\oracle\product\10.1.0\bin\oradim –new –sid QJA92 –startmode a –spfile
9. Starten der Datenbank im neuen ORACLE_HOME mit der Option upgrade. SQL> startup upgrade
10.Erstellen des SYSAUX-Tablespace SQL> CREATE TABLESPACE SYSAUX 2>
DATAFILE 'D:\oradata\QJA92\sysaux01.dbf' SIZE 500M
3>
AUTOEXTEND ON NEXT 10M MAXSIZE 1000M
4>
EXTENT MANAGMENT LOCAL
5>
SEGMENT SPACE MANAGEMENT AUTO;
19 JAVA_POOL_SIZE muss nur gesetzt sein, wenn die Java –Virtual Machine in der Datenbank konfiguriert ist. 20 Bei Unix-Betriebssystemen ist das Zielverzeichnis dbs anstelle von database zu wählen.
92
Installation und Aufbau einer Datenbank
11.Anpassen des Data Dictionarys Dafür müssen Sie je nach Version, von der aus Sie kommen, ein entsprechendes Skript ausführen. Wenn Sie von der Version 9.2.0 kommen, heißt das Skript u0902000.sql. Version
Skript
8.0.6
u0800060.sql
8.1.7
u0801070.sql
9.0.1
u0900010.sql
9.2.0
u0902000.sql
Tabelle 2.1: aus unterschiedlichen Versionen
SQL> spool c:\temp\upgrade.log SQL> @?/rdbms/admin/u0902000.sql SQL> spool off
12.Optionaler Check des Upgrades Nach dem Upgrade können Sie sich das Ergebnis mit dem Skript utlu101s.sql ansehen. Es liegt im Verzeichnis $ORACLE_HOME/rdbms/admin und wird mit der Option TEXT aufgerufen. SQL> spool c:\temp\post_upgrade.log SQL> @?/rdbms/admin/utlu101s.sql TEXT SQL> spool off
13.Stoppen und Starten der Datenbank SQL> shutdown immediate SQL> startup restrict
14.Kompilieren der ungültigen Objekte SQL> spool c:\temp\recomp.log SQL> @?/rdbms/admin/utlrp.sql SQL> spool off
Bei der Verwendung von Mehrprozessorsystemen wird die Kompilierung auf Basis des Serverparameters cpu_count automatisch parallelisiert. 15.Starten der Datenbank für den normalen Betrieb SQL> shutdown immediate SQL> startup
16.Anpassung des Listeners. Wenn Sie eine listener.ora-Datei verwenden, müssen Sie zum Abschluss noch den neuen ORACLE_HOME-Pfad eintragen. In jedem Fall muss aber der Oracle 10g Listener für den Remote-Zugriff auf die Datenbank verwendet werden. Anschließend steht die Datenbank für den normalen Betrieb zur Verfügung.
Release-Wechsel
93
2.6.4 Downgrade Auch bei der besten Vorbereitung kann es doch passieren, dass nach einiger Zeit festgestellt wird, dass der Betrieb der Datenbank unter Version 10g nicht ordnungsgemäß möglich ist. Daher stellt sich die Frage, wie man am schnellsten wieder zurück auf die alte Version kommt. Sicherlich wäre es möglich, eine neue Datenbank unter der Version 9i oder älter aufzubauen und die Daten aus der 10g-Datenbank zu exportieren, um sie dann in die alte Datenbank wieder zu importieren. Dieser Vorgang kann aber bei großen Datenbanken Tage in Anspruch nehmen, währenddessen die Datenbank nicht zur Verfügung steht. Oracle bietet dafür schon seit einiger Zeit die Möglichkeit, ähnlich wie bei einem Upgrade, ein Downgrade auf das vorherige Release durchzuführen. Das bedeutet, dass eine Oracle 10g-Datenbank auf die Version 9.2.0 zurückgesetzt werden kann21. Voraussetzung für das Downgrade ist, dass noch keine Funktionalitäten benutzt wurden, die erst mit Oracle 10g möglich sind. Dafür gibt es den Serverparameter compatible. Mit diesem Parameter wird verhindert bzw. erlaubt, dass neue Funktionen benutzt werden können. Dieser Parameter muss also für dendas Downgrade auf Oracle9i einen Wert 9.2.x haben. Ein älterer Wert ist für die 10g-Datenbank nicht erlaubt, ein neuerer Wert führt unweigerlich zum Verlust der DowngradeMöglichkeit. Für das Downgrade sind folgende Schritte durchzuführen: 1. Ermitteln, ob ein Downgrade möglich ist SQL> show parameter compatible
2. Kopieren der Serverparameterdatei in das alte ORACLE_HOME 3. Stoppen der Datenbank SQL> shutdown immediate
4. Starten der Datenbank mit der Option downgrade (in der Oracle 10g-Umgebung) SQL> startup downgrade
5. Anpassen des Data-Dictionarys aus Oracle 10g-Sicht (Oracle 10g-Umgebung) SQL> spool c:\temp\downgrade.log SQL> @?/rdbms/admin/d0902000.sql SQL> spool off
6. Herunterfahren der Datenbank SQL> shutdown immediate
7. Ändern des ORACLE_HOME und – bei MS-Windows – Ändern der Service-Einträge für eine Oracle9i-Datenbank
21 Im Gegensatz zum Upgrade ist hier allerdings der Patch-Level der Oracle9i-Version wichtig. Es muss sich mindestens um die Version 9.2.0.3 handeln.
94
Installation und Aufbau einer Datenbank
8. Hochfahren der Datenbank unter dem alten ORACLE_HOME (Oracle9i) mit der Option MIGRATE SQL> startup migrate<
9. Endgültige Anpassung des Data Dictionarys SQL> spool c:\temp\relod.log SQL> @?/rdbms/admin/catrelod.sql SQL> spool off
Mit diesem Skript wird ein Reload der PL/SQL- und Java-Prozeduren sowie des externen Data Dictionarys durchgeführt. 10.Stoppen und Starten der Datenbank SQL> shutdown immediate SQL> startup
11.Kompilieren aller ungültigen Objekte SQL> spool c:\temp\recomp.log SQL> @?/rdbms/admin/utlrp.sql SQL> spool off
Damit ist das Downgrade geschafft, und die Datenbank arbeitet wieder in der alten Umgebung.
Datenbank-Architektur 3.1
Namenskonventionen
Beim Umgang mit einer Datenbank werden auf den verschiedensten Ebenen Dinge benannt: Datenbanken, Instanzen, Dienste, Dateien, Tablespaces usw. Neben den allgemein gültigen Regeln für die Namensvergabe, die z.B. die maximale Länge und die erlaubten Zeichen festlegen und vom Datenbanksystem vorgegeben werden, ist es empfehlenswert, eigene Richtlinien für die Namensbildung zu schaffen. Warum denken wir an dieser Stelle über diese Namenskonventionen nach? Einige der in Frage kommenden Beweggründe sind: 1. Wenn wir darüber nachdenken, nachdem die Datenbank konfiguriert und die Daten geladen sind, ist es zu spät. 2. Eine Oracle-Datenbank wird auf verschiedenen Ebenen mit diversen Namen identifiziert (u.a. Datenbankname, Instanzname, Net-Aliasname sowie Dienstname). Sie können alle verschieden sein, müssen aber nicht. 3. Es gibt immer mehr Situationen, bei denen die im Unternehmen vorhandenen Datenbanken global betrachtet werden – der Enterprise Manager oder ein Storage-Subsystem bzw. SAN sind nur zwei Beispiele. Wenn dann fünf von acht Datenbanken ORACLE heißen, ist die Übersichtlichkeit dahin. Im Folgenden wird zunächst über Datenbanken und deren Namensgebung diskutiert; im Anschluss daran über die Namensgebung bei Systemobjekten, also Tablespaces und Datendateien. Groß-, Kleinschreibung und Sonderzeichen Es ist möglich, alle Benennungen sowohl in Groß- als auch in Kleinbuchstaben vorzunehmen. In vielen Teilen sind außerdem auch Sonderzeichen möglich. Man muss allerdings zwischen der einfachen Schreibweise (CREATE TABLESPACE temp) und der tatsächlichen Maskierung (CREATE TABLESPACE "temp") unterscheiden. Im zweiten Fall wird tatsächlich ein Data-Dictionary-Eintrag mit Kleinbuchstaben generiert, während im ersten Fall Großbuchstaben verwendet werden. In der Praxis sollten Sie allerdings beachten, wenn Sie tatsächlich Sonderzeichen und Kleinbuchstaben verwenden, dass einige Tools unter Umständen nicht mehr funktionieren, da nicht jedes Werkzeug auf diese Besonderheit ausgelegt ist. Außerdem müssen Sie bei Abfragen ebenfalls diese Maskierung benutzen. In der Regel werden wir daher unmaskierte Namen verwenden, so dass wir ohne Maskierung auskommen. Für die ORACLE_SID verwenden wir außerdem oftmals auf Betriebssystemebene Großbuchstaben, da diese dadurch bei Pfadangaben oder Dateinamen besser erkennbar ist.
96
Datenbank-Architektur
3.1.1 Datenbanken Bei der Benennung von Datenbanken ist zunächst zu unterscheiden zwischen dem per Parameter vergebenen Datenbanknamen (db_name), dem Domänennamen der Datenbank (db_domain) und dem globalen Datenbanknamen, der aus den beiden genannten Parametern zusammengesetzt wird, jedoch auch – unabhängig davon – explizit gesetzt werden kann. Die Instanz, also die Prozess- und Speicherstrukturen, die auf die Datenbank zugreifen, werden über einen Instanznamen (ORACLE_SID) identifiziert. Die folgenden Abschnitte erläutern die Zusammenhänge zwischen diesen und weiteren Namen. Domänen Bei der Vergabe von Namen für eine Oracle-Datenbank gibt es zwei Stellen, an denen eine Domäne auftauchen kann: Die db_domain wird zusammen mit db_name (beides Serverparameter) interner Bestandteil des Datenbanknamens; zusammen ergeben diese Namen auch den Standardwert für den Serverparameter service_names, der ab Oracle8i zur Adressauflösung bei den Netzwerkdiensten genutzt werden kann.1 Net-Aliasnamen, früher auch mit SQL*Net Alias oder Net8-Name bezeichnet, können ebenfalls mit einer Domäne versehen werden. Einen hohen Bekanntheitsgrad unter langjährigen Oracle-DBAs dürfte die Standarddomäne früherer Releases, world, haben. Die Empfehlung lautet, die Domänen in beiden Fällen gezielt zu nutzen und identisch zu halten. Mittels eines weiteren Serverparameters können die Domänen zusammen mit Datenbanknamen auf Datenbank-Links übertragen werden: Sobald global_names = true
steht, dürfen Datenbank-Links nur so benannt werden wie der globale Name der Zieldatenbank. Diese Forderung ist gerade in gewachsenen Datenbanken schwer einzuhalten, da der funktionale Verlust, der durch das Deaktivieren eines DatenbankLinks entsteht, oft schwer zu überblicken ist. Fängt man jedoch mit einem neuen System bei null an, so ist diese Einstellung unbedingt zu empfehlen. Einfache Empfehlungen für Standarddomänen sind firma.de, firma.com oder einfach firma. Da die im Oracle-Namensmodell verwendeten Domänen nicht identisch zu den (meist jedoch zumindest ähnlichen) Netzwerkdomänen sein müssen, können mit Hilfe der Domänen zusätzliche Informationen hinterlegt werden; z.B. können alle produktiven Datenbanken in die Domäne prod.firma.de gelegt werden.
1
In der CONNECT_DATA-Klausel wird hierzu statt des Parameters (SID=XXX) der Parameter (SERVICE_NAME=XXX[.DOM]) angegeben. Eine Verbindung wird hergestellt, wenn der angegebene SERVICE_NAME einem der in service_names angegebenen Namen entspricht.
Namenskonventionen
97
Datenbanknamen Ausgehend davon, dass Domänen verwendet werden, kann sich der Datenbankname auf die Funktion der Datenbank fokussieren. Datenbanknamen wie oradb sind wenig sinnvoll. Es sollten eher Namen wie dwh für Data Warehouse, crm für die Datenbank eines CRM-Systems oder xyz für die Datenbank unter der Anwendung XYZ ausgewählt werden. Der Datenbankname kann insgesamt acht Zeichen lang sein. Im Hinblick auf die nächste Migration kann es sinnvoll sein, dem Datenbanknamen eine Nummer oder Versionsbezeichnung hinzuzufügen, also z.B. pps01 oder pps10g. Bei Datenbanken, die als RAC (Real Application Clusters, siehe Kapitel 13) ausgebaut werden, sollte der Datenbankname nicht länger als sieben Zeichen sein, um bei den Instanznamen (die ebenfalls maximal acht Zeichen lang sein dürfen) die Instanznummer als Suffix an den Datenbanknamen anhängen zu können. Der Datenbankname wird als Serverparameter db_name hinterlegt. Er kann beim CREATE DATABASE-Kommando angegeben werden. Es wird grundsätzlich empfohlen, dies zu tun – damit hat man die Sicherheit, mit den richtigen Serverparametern zu arbeiten. Arbeitet man z.B. mit der falschen Serverparameterdatei, so geht das CREATE DATABASE-Kommando schief, und das ist gut so. Der globale Datenbankname wird beim Anlegen der Datenbank aus den Serverparametern db_name und db_domain abgeleitet, und zwar als db_name. db_domain. Dieser kann über die View global_name abgefragt werden: SQL> SELECT global_name FROM global_name;
Er kann nach Erstellung der Datenbank unabhängig vom eigentlichen Datenbanknamen und der Domäne beliebig geändert werden: SQL> ALTER DATABASE RENAME GLOBAL_NAME TO globdb.firma.de;
Der globale Datenbankname wird dazu verwendet, die Namen von DatenbankLinks zu erzwingen. Mit gesetztem Serverparameter global_names = true
muss – wie bereits erwähnt – ein Datenbank-Link immer genauso heißen wie der globale Datenbankname der Zieldatenbank. Eine nachträgliche Änderung des Datenbanknamens kann über das Kommandozeilen-Tool nid erfolgen. Dazu muss die Datenbank exklusiv gemountet sein, also sich im MOUNT-Zustand befinden, und (im Falle einer RAC-Datenbank) der Serverparameter cluster_database=FALSE gesetzt sein. Bei gesetzter Umgebungsvariable ORACLE_SID ändert folgender Aufruf dann den Datenbanknamen: $ nid target=sys/passwort dbname=newname
Anschließend muss die Datenbank heruntergefahren und der Serverparameter db_name entsprechend angepasst werden. Bei Oracle 10g geht dies über ein Kommando der Form: SQL> ALTER SYSTEM SET db_name = newdb SCOPE=SPFILE;
Anschließend kann die Datenbank wieder hochgefahren werden.
98
Datenbank-Architektur
Eindeutigkeit von Datenbanknamen Vor der Version Oracle 10g galt die Restriktion, dass unterschiedliche Datenbanken auf demselben Knoten unterschiedliche Datenbanknamen (db_name) haben müssen. In den meisten Fällen ist dies nicht weiter problematisch. Manchmal kommt es allerdings vor, dass man zu Testzwecken eine Datenbank auf demselben Knoten klonen möchte. In diesem Fall musste man zunächst die Referenzdatenbank herunterfahren, die Klondatenbank mounten, mit dem oben beschriebenen nid-Werkzeug den db_name ändern, um anschließend beide Datenbanken hochfahren zu können. Dieses etwas umständliche Verfahren ist mit Oracle 10g nicht mehr notwendig. Möglich macht dies der neue Serverparameter db_unique_name. Unterschiedliche Oracle 10g-Datenbanken auf demselben Knoten müssen lediglich unterschiedliche Werte für db_unique_name haben. Der db_unique_name lässt sich einfach über die Parameterdatei oder im NOMOUNT-Status der Datenbank ändern: SQL> ALTER SYSTEM SET db_unique_name = neudb SCOPE=SPFILE;
Die db_unique_names von 10g-Datenbanken sowie die db_names älterer Datenbanken müssen nun also pro Knoten eindeutig sein. Der db_unique_name ist – wenn nicht explizit gesetzt – mit dem db_name identisch. Für Oracle 10g-Datenbanken besteht daher eigentlich kein Grund mehr, den db_name nachträglich zu ändern. Es sollte – wenn nichts dagegen spricht – auf das einfachere Verfahren der Änderung des db_unique_name ausgewichen werden. Achtung: Verstößt man versehentlich gegen die genannten Eindeutigkeitsforderungen, lässt sich die zweite Instanz zwar noch hochfahren, den MOUNT-Versuch quittiert Oracle aber mit der etwas irritierenden Fehlermeldung: ORA-01102: Datenbank kann nicht im EXCLUSIVE-Modus mit Mount angeschlossen werden.
Da der db_unique_name auch noch in anderen Zusammenhängen eine wichtige Rolle bei der Namensgebung spielt, beispielsweise für Data-Guard-Konfigurationen (siehe Kapitel 13) sowie für Oracle Managed Files (siehe Kapitel 3.9), ist es zu empfehlen, ihn nicht nur pro Knoten, sondern über die gesamte Datenbankumgebung eindeutig zu halten. Dies lässt sich u.U. am einfachsten erreichen, indem er mit dem globalen Datenbanknamen gleichgesetzt wird. Die Länge des db_unique_name ist allerdings auf 30 Zeichen begrenzt. Instanznamen In der Oracle-Architektur sind Datenbank und Instanz getrennt, und somit können auch unterschiedliche Namen vergeben werden. Der Instanzname verfügt nicht über eine Domäne; er muss allerdings – wie der Datenbankname auch – pro Knoten eindeutig sein. Auch wenn es nicht zwingend erforderlich ist – der Instanzname sollte gleich oder zumindest ähnlich dem Datenbanknamen sein. Auf Grund der fehlenden Domänen kann er aus Übersichtlichkeitsgründen leicht abgewandelt werden, z.B. kann die Instanz zur Datenbank dwh10g.prod.firma.de den Namen pdwh10g tragen, um die Eigenschaft Produktivsystem auch im Instanznamen zu verdeutlichen.
Namenskonventionen
99
Die maximale Länge des Instanznamens, hinterlegt im Umgebungsparameter ORACLE_SID, ist plattformspezifisch. Acht Stellen werden bei den getesteten Plattformen problemlos akzeptiert; mehr als acht Stellen werden generell nicht empfohlen. Bei RAC-Datenbanken empfiehlt es sich, die Instanzen mittels eines Suffix durchzunummerieren, z.B. pdwh10g1 und pdwh10g2. Datenbanken im Netzwerk Sobald man auf eine Datenbank im Netzwerk zugreifen will, kommt zusätzlich zu den bereits diskutierten Namen ein Net-Aliasname ins Spiel. Hiermit wird die Datenbank im Netzwerk identifiziert. Net-Aliasnamen können mit Domänen versehen werden. Sie sehen daher den globalen Datenbanknamen sehr ähnlich und werden oft mit diesen verwechselt. Hat man sich bei den Datenbanknamen Gedanken gemacht, so kann man natürlich die Net-Aliasnamen identisch zu den Datenbanknamen inklusive Domäne wählen. Oft gibt es für eine Datenbank mehrere Net-Aliasnamen. Dabei wird für jede Anwendung ein spezieller Net-Aliasname verwendet, so dass die Anwendungsdaten bei Bedarf zwischen verschiedenen Datenbanken verschoben werden können. Dieses Konzept findet sich auch bei den Dienstnamen als Serverparameter wieder: Hiermit kann jeder Instanz eine Liste von Diensten (Serverparameter service_names) mitgegeben werden. Der Parameter wird standardmäßig auf den Wert db_name.db_ domain gesetzt. Beim Verbindungsaufbau über die Oracle Net-Schnittstelle wird ein service_name mitgegeben, der mindestens einem Wert aus der Liste der service_names der Instanz entsprechen muss.
3.1.2 Systemobjekte Auch für Systemobjekte wie Tablespaces und Datendateien müssen Namen gefunden werden. Hierbei ist auf jeden Fall Kreativität gefragt, denn Systemobjekte sind für die Anwendung nicht unmittelbar erforderlich und spielen somit auch keine Rolle im System, die a priori benannt werden kann. Daher ist es wichtig, sich einige Grundregeln zu überlegen, um den Überblick im Datenbankdschungel nicht zu verlieren. Tablespaces für Systemobjekte wie Undo- und Temporärsegmente sollten immer gleich genannt werden, z.B. undotbs und temp. Bei Tablespaces für Anwendungsdaten bringt die Anwendung oft einen Vorschlag mit. Ansonsten nimmt man für eine Anwendung X gerne x_data für Tabellen, x_index für Indizes usw. Folgt man der zumindest für sehr große Datenbanken empfehlenswerten Strategie, Tabellen und Indizes sehr unterschiedlicher Größen in unterschiedlichen Tablespaces zu speichern, sollte sich dies auch im Tablespace-Namen widerspiegeln, z.B. x_data_big für die größten Tabellen, x_index_small für Indizes auf kleinen Tabellen etc.
100
Datenbank-Architektur
Bei den Datendateien sollte gewährleistet sein, dass man am voll qualifizierten Dateinamen folgende Eigenschaften erkennen kann: Diese Datei gehört zu einer Oracle-Datenbank (z.B. Pfad /oradata). Den Datenbanknamen (ohne Domäne) (z.B. Pfad /oradata/PROD10G/) Den Tablespace-Namen (z.B. Dateiname: temp01.dbf) Eine laufende Nummer für die n-te Datei des Tablespaces Die Benennung von Rollback-Segmenten sollte kein Thema mehr sein, da seit der Version Oracle9i die automatische Undo-Verwaltung zu empfehlen ist (siehe Kapitel 3.3.5).
3.2
Komponenten einer Oracle-Datenbank
Auf physikalischer Ebene besteht eine Oracle-Datenbank aus einer Reihe von Komponenten. Im Standardfall sind diese Komponenten als Dateien innerhalb eines normalen Dateisystems (z.B. NTFS, ReiserFS etc.) ausgeführt. Es gibt aber auch die Möglichkeit, anstelle eines Dateisystems so genannte Raw-Devices zu benutzen oder – seit Oracle 10g – den mitgelieferten Volume-Manager ASM. Diese Methoden werden weiter unten besprochen. Der Einfachheit halber spricht man aber in allen Fällen von Dateien, den so genannten Datenbankdateien. Folgende Komponenten sind unverzichtbar, gehören also in jedem Fall zu einer Oracle-Datenbank: Datendateien nehmen die eigentlichen Nutzdaten sowie sämtliche Metadaten auf. Sie determinieren in vielen Fällen den Gesamtspeicherbedarf einer Datenbank (eine Ausnahme bilden Datenbank mit sehr hoher Datenänderungsrate). Online-Redolog-Dateien bilden das Transaktionsprotokoll einer Datenbank. Es muss mindestens zwei Redolog-Dateien geben, typischerweise verwendet man zwischen drei und fünf (diese können ggf. noch gespiegelt werden, was die nominelle Anzahl entsprechend erhöht). Die Kontrolldatei enthält Metadaten über die physikalische Struktur und logische Konsistenz der Datenbank sowie backup-relevante Informationen. Sie ist typischerweise wenige MB groß und sollte einfach oder zweifach gespiegelt sein. Die Parameterdatei beinhaltet die gesamte Konfiguration der Oracle-Instanz. Sie ist nur wenige KB groß. Einige weitere Komponenten sind optional: Temporärdateien sind Container für Daten, die nur temporär anfallen (z.B. Zwischenergebnisse für Sortierungen). Zwar kann eine Datenbank auch ohne Temporärdateien betrieben werden, in der Praxis sollte aber aus PerformanceGründen jede Datenbank mindestens einen Temporär-Tablespace aus Temporärdateien haben. Archivierte Redolog-Dateien sind – wie der Name andeutet – im Wesentlichen Archivierungen, also Kopien voll geschriebener Online-Redolog-Dateien. Für Datenbanken mit hoher Änderungsrate können diese einen erheblichen Anteil des Gesamtspeicherbedarf einer Datenbank ausmachen. Produktionsdatenbanken
Tablespaces und Datendateien
101
sollten aus Gründen der Wiederherstellung im Fehlerfall unbedingt im Archivierungsmodus betrieben werden, für Test- und Entwicklungsumgebungen kann dies eventuell entfallen (siehe Kapitel 10.1). Die Flashback-Log-Dateien stellen eine Neuerung in Oracle 10g dar. Sie enthalten Abbilder alter Datenbankinhalte und werden für die Funktion FLASHBACK DATABASE benötigt. Je nach Änderungsrate der Datenbank und eingestellter Aufbewahrungszeit kann ein höherer Gesamtspeicherbedarf anfallen. Dieser kann aber durch geeignete Konfiguration nach oben limitiert werden. Weitere Informationen zu Flashback-Log-Dateien befinden sich in Kapitel 10.4. Die Block Change Tracking-Datei speichert Informationen darüber, welche Datenbankblöcke seit dem letzten Backup geändert wurden. Sie ist typischerweise wenige 10 MB groß. Die Passwortdatei erlaubt Administratoren eine spezielle Authentifizierung gegenüber der Datenbank, insbesondere um eine heruntergefahrene Datenbank zu starten (die normale Authentifizierung von Benutzern bei geöffneter Datenbank findet unabhängig davon durch die Datenbank selbst statt). Die Dateigröße beträgt wenige KB. Auf die Datei kann optional verzichtet werden, dann läuft die Authentifizierung über Gruppenzugehörigkeiten auf Betriebssystemebene. Alle Komponenten werden in den folgenden Abschnitten dieses Kapitels näher beleuchtet.
3.3
Tablespaces und Datendateien
Alle Daten werden in der Oracle-Datenbank in Tablespaces verwaltet, die auf der physikalischen Ebene durch Datendateien (Datafiles) repräsentiert werden. Durch diese Unterscheidung zwischen logischer Architektur und physikalischer Speicherung ist es möglich, auf unterschiedlichen Plattformen (MS-Windows, Unix, OpenVMS, MVS etc.) den gleichen Aufbau der Datenbank zu gewährleisten. Das folgende Bild macht den Zusammenhang zwischen physikalischen Platten, Datendateien und Tablespaces deutlich.
Abbildung 3.1: Tablespaces und Datendateien
102
Datenbank-Architektur
3.3.1 Planung Für die Planung einer Oracle-Datenbank stellt sich zunächst die Frage, wie man die Daten auf einzelne Tablespaces bzw. Datendateien verteilt. Dabei spielen unterschiedliche Gesichtspunkte eine Rolle: Performance Wie kann der Zugriff über mehrere IO-Kanäle optimiert werden, wie kann man Fragmentierungen vermeiden? Verfügbarkeit Wie kann im Fall eines Medienfehlers möglichst ohne Transaktionsverlust wieder aufgesetzt werden? Backup-Recovery Wie kann die Granularität eines notwendigen Backups oder Recoverys möglichst klein gehalten werden? Administration Welche Möglichkeiten gibt es, die Administration von umfangreichen Anwendungen transparent zu machen und notwendige Reorganisationen zu vereinfachen? Anwendungsgruppierung Wie kann man Anwendungen gruppieren, um sie einfacher verwalten oder um den Anwendern Ressourcen in Rechnung stellen zu können? Sicher gibt es je nach Unternehmen noch weitere Fragestellungen, die in ein Layout der Tablespaces einfließen müssen. Aber man kann schon erkennen, dass die unterschiedlichen Anforderungen sich teilweise ausschließen bzw. aus Sicht der heute üblichen Hardware schwer zu implementieren sind. Geht man z.B. von heute üblichen Festplattenkonfigurationen aus (Festplattenkapazitäten von mehr als 100 GB sind keine Seltenheit), so muss man sich fragen, wie man zum Beispiel die Verfügbarkeitsanforderung bei einer Datenbankgröße von weniger als 10 GB erfüllen kann. Für viele Unternehmen sind deshalb Raid 5- oder Raid S-Systeme (HP/UX auch Autoraid) das Maß aller Dinge bezüglich ihrer Verfügbarkeit. Bei großen Datenbanken mit mehreren 100 GB Datenvolumen verwendet man logische Devices, bei denen die physikalischen Platten mittels Raid 0+1 zunächst einmal gespiegelt (Raid 1) und dann über mehrere Controller in Stücken à 64 KB oder 128 KB »gestriped« (Raid 0) werden. Dadurch ist ein Optimum an Verfügbarkeit und IO-Verteilung (je nach Anzahl der Controller und Platten) möglich. Die Frage, die sich dabei stellt, ist: Braucht man in solchen Fällen dann überhaupt noch mehrere Tablespaces? Die Antwort ist: »Ja!« Zum einen muss das Data Dictionary geschützt werden, um ein unkontrolliertes Wachstum und damit einen eventuellen Absturz der Datenbank zu vermeiden. Daher gehören keine wie auch immer gearteten Benutzerdaten in diesen Tablespace!
Tablespaces und Datendateien
103
Des Weiteren stellt auch ein Raid 5- oder Raid 1-System keine Garantie für hohe Verfügbarkeit dar. Ein Fehler in einem Controller kann z.B. dazu führen, dass Teile des Systems korrumpiert werden. Die Punkte 3 und 4 in der obigen Aufzählung sind auch bei solchen Systemen nicht zu vernachlässigen; sofern der Leser nicht selber DBA ist: Der DBA wird es Ihnen danken! Folgende Tablespaces sollten deshalb bei jeder Datenbank zusätzlich zu den Tablespaces SYSTEM und SYSAUX (ab Oracle 10g) angelegt werden. Die Tablespace-Namen sind als Vorschläge gedacht und haben sich in der Praxis gut bewährt: 1. Temporär-Tablespace, z.B. temp 2. Undo-Tablespace, z.B. undotbs 3. Tablespace für Werkzeuge wie den Oracle Enterprise Manager, z.B. tools 4. Mindestens je ein Tablespace für die Daten einer Anwendung, z.B. xyz_data für eine Anwendung XYZ 5. Mindestens je ein Tablespace für die Indizes einer Anwendung, z.B. xyz_index für eine Anwendung XYZ 6. Eventuell ein Tablespace für Tests und Benutzerdaten, z.B. users 7. Eventuell ein oder mehrere Tablespaces für ungewöhnlich große Objekte, z.B. xyz_data_big, xyz_index_big für eine Anwendung XYZ Je nach Datenbank können zusätzliche Tablespaces notwendig sein, z.B. beim Einsatz von Partitionen.
3.3.2 Erstellen eines Tablespaces Mit dem folgenden Befehl wird ein Tablespace für die Anwendung Kundenverwaltung angelegt. Die Werte beziehen sich auf eine Unix-Installation, d.h., die Angabe der Klausel DATAFILE muss je nach Betriebssystem angepasst werden. SQL> CREATE SMALLFILE TABLESPACE kunden_daten DATAFILE '/oradata1/PDWH10G/kunden_daten01.dbf' SIZE 1000M AUTOEXTEND ON NEXT 100M MAXSIZE 5000M BLOCKSIZE 8K LOGGING EXTENT MANAGEMENT LOCAL UNIFORM SIZE 1M SEGMENT SPACE MANAGEMENT AUTO; Listing 3.1: CREATE TABLESPACE-Kommando
Die Klauseln im Einzelnen: TABLESPACE
Um einen Tablespace anzulegen, sollte man sich zunächst überlegen, welche Aufgabe es zu erfüllen hat, d.h., ob es der Speicherung von Tabellen und Indizes, der Verwaltung von Temporärsegmenten oder dem Undo-Management dient. Es bietet sich an, dem Tablespace einen Namen zu geben, mit dem er eindeutig seiner
104
Datenbank-Architektur
Bestimmung zugeordnet werden kann, also z.B. lager_data, um zu zeigen, dass es sich hierbei um die Daten der Anwendung LAGERVERWALTUNG handelt. Dazu würde noch ein Tablespace lager_index mit den zugehörigen Indizes gehören. Die Länge des Namens ist auf 30 Zeichen begrenzt. Wie bei allen Oracle Data-Dictionary-Einträgen wird standardmäßig nicht zwischen Groß- und Kleinschreibung unterschieden. Soll der Tablespace-Name explizit aus Kleinbuchstaben bestehen, muss der Name mit doppelten Hochkommata angegeben werden. Wie bereits erwähnt, warnen wir allerdings davor, dies zu tun. DATAFILE
Der Name der zugehörigen Datendatei sollte den Namen des Tablespaces beinhalten. Zusätzlich können die Datendateien eines Tablespaces durchnummeriert werden, und sie erhalten eine Endung, die sie auf der Ebene des Betriebssystems als zur Datenbank gehörende Datei kennzeichnet.2 Dies ist in den meisten Fällen die Endung .dbf, allerdings ist auch die Endung .ora gebräuchlich. Da Oracle mit den Oracle Managed Files entsprechende Vorschläge macht, werden diese im Folgenden verwendet. Die Endung .dbf steht demnach für eine Datendatei, die Endung .tmp für eine Temporärdatei. Oracle Managed Files Mit dem Serverparameter db_create_file_dest ist es ab Oracle9i möglich, ein Verzeichnis für die Erstellung von Datendateien vorzugeben, deren Name beim CREATE TABLESPACE oder ALTER TABLESPACE ADD DATAFILE nicht angegeben wird. Als Größe wird dabei 100 MB gewählt, wenn sie nicht explizit angegeben ist. Zusammen mit der seit Oracle9i möglichen Nutzung von Locally Managed Tablespaces ergibt sich damit eine erhebliche Vereinfachung bei der Erstellung von Tablespaces bzw. Redolog-Dateien. Im folgenden Beispiel wird veranschaulicht, wie ein Tablespace ohne Angabe von Lage und Größe der Datendateien angelegt werden kann. Der erste Befehl kann natürlich entfallen, wenn db_create_file_dest als Serverparameter gesetzt ist. Der Serverparameter db_unique_name sei auf PDWH10G gesetzt. SQL> ALTER SYSTEM SET db_create_file_dest = '/oradata1/'; SQL> CREATE TABLESPACE demo_data DATAFILE AUTOEXTEND ON NEXT 10M MAXSIZE 500M;
Auf die Angabe DATAFILE AUTOEXTEND sollte generell nicht verzichtet werden, da ansonsten die Datei beliebig wachsen kann. Dieser Befehl legt in diesem Beispiel einen Tablespace demo_data an mit der Datendatei: /oradata1/PDWH10G/datafile/o1_mf_demo_dat_1g4o4ycv_.dbf
Zu beachten ist, dass der Name des Tablespaces in der Datendatei auf acht Zeichen beschränkt wird, um ausreichend Platz für Prä- und Postfix zu behalten. Für nähere Informationen über Oracle Managed Files siehe Kapitel 3.9. 2
Endungen von Datenbankdateien haben weder Standardwerte noch sind sie Pflicht. Wir empfehlen jedoch wegen der besseren Lesbarkeit, die angegebenen oder ähnliche Endungen zu verwenden.
Tablespaces und Datendateien
105
SIZE
Mit einer initialen Größe (SIZE) wird Platz auf der Festplatte bzw. dem Filesystem angegeben. Da Oracle den Bereich sofort in Oracle-Blöcke einteilt, kann das Erstellen eines Tablespaces durchaus mehrere Minuten betragen. Bei der Verwendung von Oracle Managed Files wird eine Standardgröße von 100 MB angenommen, die jedoch jederzeit geändert werden kann. Es gibt je nach Betriebssystem maximale Größen von Dateien, allerdings liegt diese bei den neueren 64-Bitund auch einigen 32-Bit-Betriebssystemen bei mehr als 2 GB bis hin zu 256 GB. SMALLFILE
Diese Klausel ist neu in Oracle 10g und erleichtert die Verwaltung sehr großer Datenbanken. Bis einschließlich Oracle9i ist nämlich die Maximalgröße einer Datendatei (unabhängig von Betriebssystemgrenzen) von der verwendeten OracleBlockgröße des Tablespaces abhängig, die Obergrenze liegt konkret bei 4M Blöcken. Für eine Blockgröße von 8 KB ergibt sich somit eine maximale Datendateigröße von 32 GB. Über diese Grenze hinaus kann der Tablespace nur durch Hinzufügen weiterer Datendateien vergrößert werden. Unter Oracle 10g gibt es nun einen Ausweg: die so genannten BIGFILE-Tablespaces können bis zu 4G Blöcke umfassen, kommen bei einer Blockgröße von 8 KB also auf bis zu 32 TB Datendateigröße. Dies ist aber nur für Umgebungen mit Volume-Managern zu empfehlen, die ein Striping oder RAID leisten, auch vor dem Hintergrund, dass ein solcher Tablespace auf eine einzige Datendatei beschränkt bleibt. Die Möglichkeit, die logischen Volumes dynamisch – also im laufenden Betrieb – zu erweitern, sollte ebenfalls Voraussetzung für die Verwendung solcher Tablespaces sein. BIGFILE-Tablespaces sind nur als Locally Managed Tablespaces mit automatischer Segmentplatzverwaltung (ASSM) möglich (s.u.), hiervon ausgenommen sind das System-Tablespace, Temporär-Tablespaces und Undo-Tablespaces. Bei diesen Tablespaces ist die Bigfile-Option auch mit manueller Segmentverwaltung möglich.
Um kompatibel mit existierenden Skripten zu bleiben, ist die Klausel SMALLFILE die Standardeinstellung nach Erstellung einer Datenbank und hätte im obigen Beispiel somit weggelassen werden können. Durch die Klausel BIGFILE wird entsprechend ein BIGFILE-Tablespace erzeugt. Es ist sogar möglich, die Standardeinstellung der Datenbank zu ändern: SQL> ALTER DATABASE SET DEFAULT BIGFILE TABLESPACE; SQL> CREATE TABLESPACE bigts …;
Da ein BIGFILE-Tablespace nur aus einer einzigen Datendatei bestehen kann, ist für Größenänderungen dieser Datendatei nur der Tablespace-Name erforderlich, z.B.: SQL> ALTER TABLESPACE bigts RESIZE 200M;
Es muss auch berücksichtigt werden, dass im Falle einer Beschädigung und anschließenden Wiederherstellung eines Tablespaces die unterste Granularitätsstufe, nämlich Recovery einer einzelnen Datendatei, mit BIGFILE-Tablespaces grundsätzlich identisch zum Recovery des gesamten Tablespaces ist. Bei großen Tablespaces kann dies erheblich länger dauern als das Recovery einer oder weniger Datendateien des betroffenen Tablespaces.
106
Datenbank-Architektur
AUTOEXTEND
Mit der Option AUTOEXTEND ON kann eine automatische Vergrößerung der Datendatei nach Bedarf erfolgen. In diesem Falle wird, wenn der Platz in der Datendatei nicht mehr ausreicht, diese Datei um die Größe NEXT vergrößert – bis zu einer maximalen Größe von MAXSIZE. Wird der Parameter NEXT nicht angegeben, wird die Datei jeweils um einen einzigen Datenbankblock vergrößert! (Bei Oracle Managed Files immer um 100 MB.) Dies kann zu erheblichen Performance-Einbußen führen, so dass anzuraten ist, den Parameter NEXT nicht zu klein zu wählen (10 MB oder größer) und die Initialgröße von vornherein ausreichend zu dimensionieren. Sollten Sie mehrere Datendateien in einem Dateisystem anlegen, müssen Sie darauf achten, dass jede mit AUTOEXTEND angelegte Datei unter Umständen Platz reserviert, den Sie eigentlich für eine andere Datei vorgesehen hatten. Daher empfiehlt es sich, die maximale Größe der Datei mit dem Parameter MAXSIZE zu beschränken. Standardmäßig wird dieser Wert auf UNLIMITED gesetzt, so dass jede Datei beliebig viel Platz reservieren kann. Auch an diesen Parametern sieht man, wie wichtig die Aufteilung von Anwendungen auf unterschiedliche Tablespaces ist, da es nur so möglich ist, bestimmte Anwendungen auf ihren Plattenplatz hin zu limitieren. BLOCKSIZE
Mit dieser Klausel ist es möglich, einen Tablespace mit einer anderen Blockgröße als der Standardblockgröße der Datenbank anzulegen. Damit kann zum Beispiel für die Abspeicherung von Binärdaten in BLOB-Feldern ein spezieller Tablespace erstellt werden, der den Anforderungen dieser Felder entgegenkommt und somit eine Verkettung von Blöcken vermeidet oder zumindest minimiert. Außerdem können hierdurch die transportablen Tablespaces besser unterstützt werden, da jetzt in jeder Zieldatenbank ein Tablespace mit identischer Blockgröße aufgebaut werden kann. Um eine derartige Blockgröße nutzen zu können, müssen der zugehörige Serverparameter db_nk_cache_size und der Parameter db_cache_size gesetzt sein, damit im Buffer-Cache entsprechende Ressourcen zur Verfügung stehen. Es versteht sich daher von selbst, dass nur die Größen als BLOCKSIZE erlaubt sind, für die es einen entsprechenden Serverparameter gibt. Dies sind: 2 KB, 4 KB, 8 KB, 16 KB und 32 KB. LOGGING
Die Klausel LOGGING steht an dieser Stelle für das Standardverhalten der Objekte, die in dem Tablespace gespeichert werden. Logging besagt, dass wie üblich alle DMLOperationen über den Redolog-Mechanismus protokolliert werden. Alternativ kann durch ein NOLOGGING erreicht werden, dass bestimmte DML-Operationen (so genannte Direct Loads, beispielsweise durch den Oracle SQL*Loader) nicht mitprotokolliert werden. Das bedeutet, falls ein Media-Fehler auftritt, können die geladenen Daten nicht wiederhergestellt werden, und die zugehörige Data-DictionaryInformation (z.B. Extent-Verwaltung) wird als logisch korrupt gekennzeichnet.
Tablespaces und Datendateien
107
EXTENT MANAGEMENT LOCAL
Diese Klausel definiert den Tablespace als so genannten Locally Managed Tablespace (LMTS). Bei dieser Methode verwaltet der Tablespace seine Extents über eine lokale Bitmap-Struktur in jeder zugehörigen Datendatei. Seit Oracle8i ersetzt diese Methode zunehmend die alte Variante der so genannten Dictionary Managed Tablespaces (DMTS). Die Extent-Allokierung wird beschleunigt, und die früher üblichen rekursiven Operationen entfallen, es muss auch keine Rollback-Information erzeugt werden. Darüber hinaus wird die Verwaltung der Extents vereinfacht, so dass ein Zusammenlegen (Coalesce) von freien Extents entfallen kann. LM-Tablespaces sind mittlerweile die Standardeinstellung und haben sich in der Praxis ausnahmslos bewährt. Die alten DM-Tablespaces sollten nicht mehr verwendet werden. Damit entfällt auch die Notwendigkeit, die früher üblichen Klauseln für Default-Storage-Parameter sowie für eine minimale Extent-Größe anzugeben. Bei der Angabe der Extent-Größe für Objekte gibt es jetzt nur noch zwei Alternativen: UNIFORM SIZE legt eine einheitliche Größe für alle Extents fest, AUTOALLOCATE (Standard) kalkuliert die Größe der Extents. Dabei werden die Extents in der Regel wie folgt angelegt. 64 KB für die ersten 16 Extents 1 MB ab dem 17. Extent 8 MB ab dem 80. Extent 64 MB ab dem 200. Extent Die tatsächlich allokierten Extent-Größen können von diesem Schema abweichen, insbesondere z.B. bei der Nutzung von ALTER TABLE ALLOCATE EXTENT. Die Benutzung von AUTOALLOCATE empfiehlt sich fast immer; auch große Objekte können hiermit effizient behandelt werden. Lediglich für extrem große Objekte sollten Tablespaces mit UNIFORM SIZE benutzt werden. SQL> CREATE TABLESPACE kunden_daten_small DATAFILE '/oradata1/PDWH10G/kunden_daten_small01.dbf' SIZE 100M AUTOEXTEND ON NEXT 10M MAXSIZE 300M EXTENT MANAGEMENT LOCAL AUTOALLOCATE; Listing 3.2: Locally Managed Tablespace mit AUTOALLOCATE
SEGMENT SPACE MANAGEMENT
Die Verwaltung der freien Blöcke für ein Segment geschah bis einschließlich Oracle8i durch sog. Freilisten, d.h. verkettete Listen, die alle freien Blöcke diesseits der High Water Mark enthalten. Diese Listen werden schubweise beim Allokieren eines Extents gefüllt, und die INSERT-Operationen holen sich dann den nächsten freien Block aus dieser Liste. Wird eine bestimmte Marke (PCTFREE) in einem Block überschritten, dann wird dieser von der Freiliste gelöscht. Wird durch Änderungsoder Löschoperationen eine zweite Marke (PCTUSED) in einem Block unterschritten, dann wird der entsprechende Block wieder in die Freilisten eingetragen.
108
Datenbank-Architektur
Bei großer Transaktionslast, speziell mit INSERT- und DELETE-Operationen, kann eine solche Freiliste zu einem Engpass führen. Dadurch kommt es zu Wartezuständen bei der Verarbeitung, die in der Vergangenheit nur durch mehrere Freilisten ausgeglichen werden konnten. Als Tuning-Maßnahme war es üblich, die Parameter FREELISTS und FREELIST GROUPS hoch zu setzen, damit nicht alle INSERT-Operationen über die gleiche Freiliste abgewickelt werden. Die Änderung des Parameters FREELIST GROUPS kann jedoch nur durch eine Reorganisation der gesamten Tabelle erfolgen, wohingegen FREELISTS auch durch einen ALTER TABLE-Befehl angepasst werden kann. Seit Oracle9i und bei Verwendung von Locally Managed Tablespaces kann durch die Klausel SEGMENT SPACE MANAGEMENT AUTO auf eine Verwaltung über Freilisten verzichtet werden. Bei dieser Methode (ASSM für Automatic Segment Space Management genannt) wird über eine Bitstruktur der freie Platz in den Blöcken verwaltet. Die Bitstruktur ist je nach Segmenttyp (Daten, Index, LOB) unterschiedlich, hat aber generell folgende Struktur: Das erste Bit zeigt an, ob der Block als voll markiert wurde; dies geschieht, wenn der Wert PCTFREE überschritten wurde. – 1 = voll Das zweite und dritte Bit zeigen den Füllgrad des Blockes an (nur Datensegmente). – 00 = freier Platz größer 75 Prozent – 01 = freier Platz größer 50 Prozent – 10 = freier Platz größer 25 Prozent – 11 = freier Platz kleiner 25 Prozent Das letzte Bit zeigt an, ob der Block formatiert wurde. – 1 = formatiert Das zweite und dritte Bit ersetzen zusätzlich den Parameter PCTUSED, d.h., ein Block wird wieder mit Sätzen gefüllt, wenn der Platz unter die PCTFREE-Marke gesunken ist. Bei Indizes entfällt der Füllgrad der Blöcke, da es hier nur entscheidend ist, ob ein Block formatiert oder voll ist. Die Verwaltung des freien Platzes für ein Segment erfolgt jetzt in bis zu drei Stufen. Die erste Stufe bilden Bitmapped-Blöcke, die an den Segment-Header gebunden sind, eine Zwischenstufe von Bitmapped-Blöcken wird für große Tabellen verwendet. Die eigentliche Verwaltung in den Blöcken erfolgt dann in der dritten Stufe. Hier werden je Bitmapped-Block mehrere freie Blöcke verwaltet. Bei INSERT-Operationen wird jetzt vom Segment-Header aus geprüft, ob in einem Block noch genügend Platz vorhanden ist. Ist dies der Fall, wird der Datensatz eingefügt, und wenn ein Schwellenwert (25%, 50%, 75%) überschritten wurde, wird die entsprechende Bitstruktur angepasst. Wenn kein freier Block mehr zur Verfügung steht, werden neue Blöcke formatiert (je nach Verfahren mindestens 16 Blöcke), bzw. ein neues Extent wird allokiert. Wenn viele INSERT-Operationen (z.B. Parallel INSERT) ausgeführt werden, wird die Formatierung der Blöcke auf mehrere
Tablespaces und Datendateien
109
Prozesse über einen Hash-Algorithmus verteilt. Dadurch kann es vorkommen, dass bestimmte Blöcke, obwohl sie unterhalb der High –Water Mark liegen, nicht formatiert werden. Dies ist ein kleiner Nachteil dieser Freiplatzverwaltung, da u.U. Platz verschwendet wird (natürlich werden die Blöcke bei einer nächsten Formatierung mit benutzt). Der Vorteil des Verfahrens ist aber die geringe Latch-Contention (Sperren auf der Freelist eines Segmentes) und schnellere Vergabe von freiem Platz. Nach unseren Erfahrungen kann die automatische Segmentplatzverwaltung in den meisten Fällen uneingeschränkt empfohlen werden. Eine Ausnahme bilden jedoch Tablespaces, in denen LOB-Segmente gespeichert werden, da die Kombination von LOB-Segmenten und ASSM sowohl in Oracle9i als auch in Oracle 10g Gegenstand zahlreicher Bugs im Zusammenhang mit der Speicherplatzverwaltung war und ist. Hier muss sich letztlich zeigen, ob diese Problematik mit den nächsten SoftwarePatches entschärft wird. Bestimmte Anwendungen können aber nach wie vor von der manuellen Segmentplatzverwaltung profitieren. Hierzu gehören solche Anwendungen, in denen von Zeit zu Zeit größere Datenmengen gelöscht werden, ohne dass komplette Blöcke geleert werden. Bei der klassischen Segmentverwaltung führte dies dazu, dass die freien Bereiche unter Umständen nicht wieder verwendet wurden. Mit ASSM werden die neuen Daten jetzt auf alle teilgefüllten Blöcke verteilt. Obwohl dies im ersten Schritt besser erscheinen mag, birgt es einen – u.U. – entscheidenden Nachteil. Neue Daten haben oft eine Beziehung zueinander, z.B. die aktuellen Auftragseingänge. Durch die Verteilung über ASSM müssen in der Regel mehr Blöcke in den Buffer Cache gelesen werden, als es mit der älteren Methode, bei der neue Daten in einem neuen, d.h., leeren Block landen, der Fall gewesen wäre. Wenn Sie Objekte haben, bei denen das der Fall ist, sollten Sie überlegen, ob Sie für diese Objekte einen eigenen Tablespace mit manueller Segmentplatzverwaltung anlegen.
3.3.3 SYSTEM- und SYSAUX-Tablespace Jedem, der schon einmal eine Oracle-Datenbank administriert hat, wird der SYSTEMTablespace ein Begriff sein. Seit jeher handelt es sich hierbei um den ersten Tablespace einer Datenbank, in dem sämtliche Metadaten und Verwaltungsinformationen der Datenbank, das so genannte Data Dictionary, abgespeichert werden. Aus diesem Grund ist der SYSTEM-Tablespace höchst sensibel und sollte für alle »normalen« Benutzer oder Anwendungsbenutzer tabu sein. Der SYSAUX-Tablespace hingegen ist neu in Oracle 10g. Genau wie der SYSTEMTablespace ist er zwingender Bestandteil einer Oracle 10g-Datenbank. Dies ist insbesondere bei Migrationen von älteren Versionen nach Oracle 10g zu berücksichtigen. Der SYSTEM-Tablespace Der SYSTEM-Tablespace wird bei der Erstellung der Datenbank generiert. Seine Datendateien müssen über die DATAFILE-Klausel des CREATE DATABASE-Kommandos angegeben werden, es sei denn, es werden Oracle Managed Files verwendet, so dass die Datendatei mit Standardparametern angelegt werden kann. Wie bei jeder anderen Erstellung eines Tablespaces können bei Bedarf auch mehrere Dateien durch
110
Datenbank-Architektur
Kommata getrennt angegeben und die automatische Erweiterbarkeit (Klausel AUTOEXTEND) eingeschaltet werden. Sie sollten unbedingt auch die Klausel EXTENT MANAGEMENT LOCAL verwenden, da im Gegensatz zu anderen Tablespaces der SYSTEM-Tablespace standardmäßig noch als Tablespace des alten Typs (Dictionary-Managed) angelegt wird. Zu beachten ist allerdings, dass Sie dann generell keine DictionaryManaged Tablespaces mehr anlegen können. Mit dem Befehl CREATE DATABASE wird das interne Data Dictionary aufgebaut, über das sich die Datenbank verwaltet. Die dem Benutzer SYS gehörenden Tabellen liegen im SYSTEM-Tablespace und werden durch die Endung »$« gekennzeichnet. Es ist nicht erlaubt, DML-Befehle3 (INSERT, UPDATE, DELETE) auf Data-Dictionary-Tabellen auszuführen; die einzige Ausnahme bildet die Audit-Trail-Tabelle aud$, da sie vom Administrator in regelmäßigen Abständen bereinigt werden muss. Das interne Data Dictionary wird den Administratoren und Benutzern durch eine Reihe von Sichten (externes Data Dictionary) zur Verfügung gestellt. Das interne Data Dictionary Wie bereits erwähnt, verwaltet sich die Datenbank über das Data Dictionary. Genau wie jede Anwendung aus einer Reihe von Objekten besteht, die über Schlüsselwerte in Bezug zueinander stehen, ist auch das Data Dictionary eine Anwendung, die über Schlüssel verwaltet wird. Im Gegensatz zu »normalen« Tabellen wird hierauf jedoch nicht mit DML-Befehlen, sondern mit DDL-Befehlen zugegriffen. Warum dies notwendig ist, zeigt folgendes Beispiel: SQL> CREATE TABLE personen ( persnr NUMBER NOT NULL, anrede VARCHAR2 (5), vorname VARCHAR2 (20), nachname VARCHAR2 (20), geburtstag DATE ) TABLESPACE users; Listing 3.3: Erstellen einer Tabelle
Mit diesem Befehl wird eine Tabelle mit dem Namen personen und fünf Spalten im Tablespace users angelegt. Was als DDL-Befehl CREATE TABLE nur wenige Zeilen benötigt, wird durch den Kernel in 53 (!) Befehle aufgeteilt. Was geschieht mit diesem Befehl? Zunächst einmal muss überprüft werden, ob der Anwender, der den Befehl ausführt, die entsprechenden Rechte hat, d.h.: »Darf er ein CREATE TABLE-Kommando absetzen?« »Hat er das Recht, im Tablespace users eine Tabelle anzulegen?« Dann muss überprüft werden, ob in dem Tablespace ausreichend Platz für ein Extent mit der vordefinierten Größe vorhanden ist. Außerdem müssen die Speichereigenschaften aus den Standardvorgaben des Tablespaces gewonnen werden. Wenn diese Abfragen erfolgreich waren, können die entsprechenden Einträge im Data Dictionary vorgenommen werden. Dies sind unter anderem Einträge in tab$ für 3
DML steht für Data Manipulation Language (INSERT, UPDATE, DELETE), DDL für Data Definition Language (CREATE, ALTER, DROP).
Tablespaces und Datendateien
111
den Namen der Tabelle und col$ für die Spalten der Tabelle. Die folgende Liste zeigt alle Tabellen des Data Dictionarys, in die in diesem Fall Einträge vorgenommen wurden: obj$, seg$, tsq$, con$, tab$, col$, ccol$, cdef$
Auffallend ist die Endung »$«, die anzeigt, dass es sich hierbei um die Tabellen des Data Dictionarys handelt, die dem Benutzer SYS gehören. Ähnlich wie die Erstellung einer neuen Tabelle über DDL-Befehle versteckt wird, wird auch die Abfrage von Informationen über das externe Data Dictionary erleichtert. Das Beispiel, um die Struktur einer Tabelle anzuzeigen, verdeutlicht dies: SQL> SELECT * FROM user_tab_columns;
Dieser Befehl greift auf folgende Data-Dictionary-Tabellen zu: obj$, user$, col$, coltype$, hist_head$, tab$
Es ist also leicht nachzuvollziehen, warum es nicht erlaubt ist, mit DML-Befehlen auf das Data Dictionary zuzugreifen. Die Gefahr einer Inkonsistenz und damit der Korruption der Datenbank ist zu groß! Ebenso sollten die Views, die auf das Data Dictionary zugreifen, nicht manipuliert werden, allerdings ist hier die Gefahr nicht ganz so groß, da diese über das im Folgenden besprochene SQL-Skript catalog.sql jederzeit wiederhergestellt werden können. Das externe Data Dictionary Mit dem Skript catalog.sql (Verzeichnis: $ORACLE_HOME/rdbms/admin) wird die Benutzersicht auf das interne Data Dictionary aufgebaut. sqlplus / as sysdba @?/rdbms/admin/catalog.sql
Das »?« steht hierbei für das ORACLE_HOME-Verzeichnis und kann sowohl unter Unix als auch MS-Windows verwendet werden. Dieses Skript baut verschiedene Views auf. 1. Virtuelle Views (v$, gv$) Dies sind Informationen der Kontrolldateien sowie Zähler und Strukturen der Prozesse und des Shared Memorys. Zum Beispiel gibt v$datafile die Liste der Datenbankdateien aus Sicht der Kontrolldatei an. SQL> SELECT name,value FROM v$parameter WHERE name LIKE '%undo%'; NAME VALUE ------------------------------ ---------------undo_management AUTO undo_tablespace UNDOTBS1 undo_retention 7200 Listing 3.4: Auszug aus der View v$parameter
112
Datenbank-Architektur
Globale virtuelle Views sind eine Erweiterung für den RAC(Real Application Clusters)-Betrieb. Sie zeigen die entsprechenden Informationen zusammenfassend für alle Instanzen in einem RAC. Diese Views beginnen mit gv$ anstelle von v$. 2. DBA-Views (dba_) Dies ist die komplette Repräsentation des internen Data Dictionarys, d.h., über diese Views können alle relevanten Informationen über die Datenbank abgefragt werden. Die Informationen können nur von Benutzern gesehen werden, die zur Gruppe der Administratoren gehören bzw. die Rolle select_catalog_role zugeteilt bekommen haben. Als Beispiel die Abfrage der Datenbankdateien (dba_data_files) aus Sicht des Data Dictionarys: SQL> SELECT file_name, tablespace_name, bytes FROM dba_data_files; FILE_NAME ---------------------------------------D:\ORACLE\ORADATA\PS10\SYSTEM01.DBF D:\ORACLE\ORADATA\PS10\UNDOTBS01.DBF D:\ORACLE\ORADATA\PS10\SYSAUX01.DBF D:\ORACLE\ORADATA\PS10\INDX01.DBF D:\ORACLE\ORADATA\PS10\USERS01.DBF D:\ORACLE\ORADATA\PS10\TOOLS01.DBF
TABLESPA BYTES -------- ---------SYSTEM 272629760 UNDOTBS1 209715200 SYSAUX 209715200 INDX 209715200 USERS 209715200 TOOLS 104857600
Listing 3.5: Die View dba_data_files
3. Views für alle Benutzer (all_) Diese Views erlauben es den Benutzern, auf Objekte zuzugreifen, auf denen ihnen Rechte gegeben wurden. Dazu gehören natürlich auch die eigenen Objekte. Als Beispiel wird hier mit der View all_tables eine Liste aller lesbaren Tabellen für den momentan angemeldeten Benutzer (in diesem Fall demo) erstellt. SQL> SELECT owner, table_name FROM all_tables; OWNER ---------SYS SYS SYS SYS SYS SYS SYS SYS SYS SYS
TABLE_NAME --------------------------SCHEDULER$_JOB_STEP_STATE AUDIT_ACTIONS STMT_AUDIT_OPTION_MAP TABLE_PRIVILEGE_MAP SYSTEM_PRIVILEGE_MAP DUAL PLAN_TABLE$ KU$NOEXP_TAB ODCI_WARNINGS$ ODCI_SECOBJ$
Tablespaces und Datendateien SYS SYSTEM SYSTEM SYSTEM SYSTEM SYSTEM WMSYS WMSYS WMSYS WMSYS DEMO DEMO DEMO DEMO DEMO DEMO DEMO DEMO
113
PSTUBTBL HELP DEF$_TEMP$LOB OL$NODES OL$HINTS OL$ WM$VERSION_HIERARCHY_TABLE WM$NEXTVER_TABLE WM$VERSION_TABLE WM$WORKSPACES_TABLE AUFPOSITIONEN PRODUKTE AUFTRAEGE AUFSTATUS TELNUMMERN ADRESSEN TYPEN KUNDEN
Listing 3.6: Die View all_tables für den Benutzer demo
Für den Datenbankadministrator besteht oftmals kein Unterschied zwischen den dba- und den all-Views. 4. Views nur für den lokalen Benutzer (user_) Hier werden nur noch die Informationen zu Objekten des momentan angemeldeten Benutzers angezeigt. Als Beispiel hier die Sicht user_tables, die im Gegensatz zu all_tables keine Information über den Besitzer (owner) anzeigt. SQL> SELECT table_name FROM user_tables; TABLE_NAME -------------------------KUNDEN TYPEN ADRESSEN TELNUMMERN AUFSTATUS AUFTRAEGE PRODUKTE AUFPOSITIONEN Listing 3.7: Die View user_tables für den Benutzer demo
Zusätzlich zu dem Skript catalog.sql gibt es weitere Skripte, die das Data Dictionary für unterschiedliche Anwendungen (XML, Java etc.) erweitert (siehe Kapitel 2).
114
Datenbank-Architektur
Der SYSAUX-Tablespace Im Laufe der Oracle-Versionen ist eine ganze Reihe von erweiterten Funktionen entstanden, die zwar zum Teil eigenständige Schemata belegen, ihre Objekte aber dennoch im SYSTEM-Tablespace speichern, z.B. die Verwaltung von Stored Outlines (Schema OUTLN), der Workspace-Manager (Schema WMSYS), der Log Miner usw. Dies ist ungünstig, da diese Funktionen eine gewisse Dynamik mit sich bringen, die im sensiblen SYSTEM-Tablespace fehl am Platze ist. Andere Funktionen wie z.B. die XML DB oder das Performance-Werkzeug Statspack konnten ihre Daten in einem benutzerdefinierten Tablespace speichern. Oracle 10g kommt schließlich mit einigen neuen Funktionen, die insbesondere eine Archivierung diverser Performance-Statistiken beinhalten (Stichwort AWR, siehe auch Kapitel 11.2), was zu erheblichem Platzbedarf führen kann. Man hat daher die Gelegenheit genutzt, mit dem Wildwuchs diverser Daten-Repositories aufzuräumen und stattdessen einen einheitlichen Standard-Tablespace namens SYSAUX hierfür zu benutzen. Der SYSAUX-Tablespace wird beim Erstellen der Datenbank angelegt, seine Datendatei(en) müssen über die SYSAUX DATAFILE-Klausel angegeben werden (wie beim SYSTEM-Tablespace können natürlich auch hier Oracle Managed Files verwendet werden). Die View v$sysaux_occupants gibt Auskunft darüber, welche Komponenten der Datenbank den SYSUAX-Tablespace benutzen und wie viel Platz jede einzelne Komponente belegt. Für einige Komponenten besteht auch die Möglichkeit, sie in einen alternativen Tablespace zu migrieren. Das Verfahren dafür ist über die Spalten move_procedure und move_procedure_desc beschrieben. Als Startwert sollte für den SYSAUX-Tablespace ein Platzbedarf zwischen 500 MB und wenigen GB gewählt werden. Im Rahmen eines Upgrades von älteren Datenbankversionen muss der SYSAUXTablespace erstellt werden. Dies muss nach dem Hochfahren der Datenbank mittels STARTUP UPGRADE, aber noch vor dem Aufruf des Upgrade-Skripts (z.B. u0902000.sql) geschehen. Für Näheres siehe Oracle 10g Database Upgrade Guide.
3.3.4 Temporär-Tablespaces und Temporärsegmente In einem DBMS fallen immer wieder Sortier- oder Hash-Operationen oder damit verwandte Operationen wie Gruppierungen oder Index-Aufbau an. Diese Operationen benötigen Speicherplatz für Zwischenergebnisse und das Endergebnis. Man bezeichnet diesen Speicher als Temporärspeicher. Falls nur eine kleine Menge an Temporärspeicherplatz benötigt wird, wird im Oracle Server ein so genannter Sortierbereich benutzt. Dieser befindet sich im Hauptspeicher des Datenbanksystems und wird über den Serverparameter sort_area_size explizit oder pga_aggregate_target als Gesamtheit festgelegt. Werden allerdings größere Mengen Speicherplatz angefordert, so wird automatisch auf Temporärsegmente ausgewichen, d.h., es wird ein spezielles Segment in der Datenbank reserviert, das Zwischenergebnisse und das Endergebnis aufnimmt.
Tablespaces und Datendateien
115
Im Unterschied zu allen anderen Segmenttypen werden Temporärsegmente grundsätzlich implizit angelegt und können nicht explizit angesprochen oder ausgelesen werden. Die bisher einzige Ausnahme hierfür sind globale Temporärtabellen, deren Inhalte ebenfalls als Temporärsegmente abgelegt werden. Nach erfolgreicher Durchführung der Sortierung oder Gruppierung werden Temporärsegmente wieder freigegeben; der Inhalt von globalen Temporärtabellen wird je nach Definition nach Transaktions- bzw. Sitzungsende freigegeben. Durch den mit Oracle8i eingeführten Befehl CREATE TEMPORARY TABLESPACE ist es möglich, einen so genannten Temporär-Tablespace speziell für die Aufnahme von Temporärsegmenten aufzubauen. Entscheidend ist, dass die gesamte Verwaltung eines solchen Tablespaces ohne Beteiligung des Data Dictionarys stattfindet. Da Dateien eines Temporär-Tablespaces (so genannte Temporärdateien) in einem separaten Bereich in der Kontrolldatei gespeichert werden, »sieht« ein Checkpoint oder ein Backup über den Recovery-Manager diese Tablespaces nicht. Somit ist auch ein Restore nach einem Fehler nicht notwendig – man erstellt die Temporärdateien einfach neu. SQL> CREATE TEMPORARY TABLESPACE temp TEMPFILE '/oradata1/PDWH10G/temp01.tmp' size 1000M AUTOEXTEND ON NEXT 100M MAXSIZE 5000M EXTENT MANAGEMENT LOCAL UNIFORM SIZE 10M; Listing 3.8: Anlegen eines Temporär-Tablespaces
Mit diesem Befehl wird ein Tablespace mit Namen temp erstellt und durch die Angabe EXTENT MANAGEMENT LOCAL als Locally Managed Tablespace verwaltet. Auch hier ist die Angabe EXTENT MANAGEMENT LOCAL optional, da es zurzeit keine andere Möglichkeit gibt. Um Temporärdateien auch betriebssystemseitig von Datendateien unterscheiden zu können, empfiehlt es sich, sie mit der Endung .tmp anzulegen. Die Erstellung von Temporärdateien läuft unabhängig von ihrer Größe im Sekundenbereich ab, da für die Temporärdateien im Gegensatz zu Datendateien lediglich Plattenplatz reserviert, aber keine Oracle-Blockformatierung durchgeführt wird. Jedem Datenbankbenutzer ist ein Temporär-Tablespace zugewiesen, in dem vom Oracle-Server für umfangreiche Sortieroperationen Temporärsegmente angelegt werden. Findet keine explizite Zuweisung statt, wird dem Benutzer standardmäßig der SYSTEM-Tablespace als Temporär-Tablespace zugeordnet. Dies sollte natürlich nicht passieren. Um zu verhindern, dass dies versehentlich passiert, kann ein Temporär-Tablespace als Default –Temporary Tablespace für die Datenbank ausgewählt werden: SQL> ALTER DATABASE DEFAULT TEMPORARY TABLESPACE temp;
Diese Zuweisung kann auch gleich bei der Erstellung der Datenbank im Rahmen des CREATE DATABASE-Kommandos geschehen. Wichtig zu wissen ist, dass der Default-Temporär-Tablespace einer Datenbank – wenn er erst einmal als solcher definiert ist – nicht mehr gelöscht werden kann, bevor nicht ein anderer Temporär-Tablespace seine Rolle übernommen hat. Damit wird verhindert, dass die Benutzer auf den SYSTEM-Tablespace »zurückfallen«.
116
Datenbank-Architektur
Temporär-Tablespace-Gruppen Mit Oracle 10g ist es möglich, mehrere Temporär-Tablespaces zu einer Gruppe zusammenfassen und eine solche Gruppe wie oben beschrieben einem Benutzer zuzuordnen oder datenbankweit als Standard zu definieren. Dies ist vor allem im Hinblick auf bessere I/O-Verteilung beim Umgang mit Temporärsegmenten gedacht, da nun zufällig ausgewählt wird, in welchem Tablespace ein Temporärsegment erstellt wird. Die Temporärdateien der einzelnen Tablespaces sollten also möglichst verteilt liegen, um eine echte I/O-Parallelisierung zu erreichen. In Umgebungen mit Striping oder RAID 5 ist eine Parallelisierung ohnehin gegeben, so dass der Vorteil hier eher gering ist. Eine Tablespace-Gruppe wird nicht explizit definiert, sondern automatisch angelegt, wenn ein Tablespace der Gruppe zugeordnet wird, z.B.: SQL> SQL> SQL> SQL>
ALTER ALTER ALTER ALTER
TABLESPACE temp TABLESPACE GROUP temp_group; TABLESPACE temp2 TABLESPACE GROUP temp_group; DATABASE DEFAULT TEMPORARY TABLESPACE temp_group; USER demo TEMPORARY TABLESPACE temp_group;
Auch hier gilt, dass – sofern eine Tablespace-Gruppe als datenbankweiter Default definiert ist – kein Mitglied dieser Gruppe gelöscht werden kann. Um einen Tablespace aus einer Gruppe zu entfernen, wird er der leeren Gruppe '' zugewiesen: SQL> ALTER TABLESPACE temp TABLESPACE GROUP '';
Auch das Löschen einer Tablespace-Gruppe geschieht nicht explizit, sondern automatisch, sobald der letzte Tablespace aus ihr entfernt wird. Vorhandene Tablespace-Gruppen können über die View dba_tablespace_groups eingesehen werden. Achtung: Tablespaces und Tablespace-Gruppen teilen sich einen gemeinsamen Namensraum, können also nicht identische Namen haben.
3.3.5 Undo-Tablespaces Ein Undo-Tablespace beinhaltet ausschließlich Undo-Segmente. Primäre Aufgabe der Undo-Segmente ist es, den alten Zustand von Feldinhalten (before images) so lange zu speichern, bis der neue Zustand in der Datenbank festgeschrieben wurde. Dadurch kann sichergestellt werden, dass Befehle entweder vom System (PMONProzesss) oder vom Anwender wieder zurückgenommen werden können. Solche Situationen können entstehen, wenn interne Ressourcen aufgebraucht sind, z.B. nicht genug Platz in einem Tablespace vorhanden ist, oder wenn ein Anwender mit dem expliziten Befehl ROLLBACK eine Transaktion rückgängig macht. Für Zugriffe auf das Data Dictionary gibt es ein spezielles Undo-Segment SYSTEM im gleichnamigen Tablespace SYSTEM. Da dieses ausschließlich für Transaktionen im Tablespace SYSTEM – und damit in der Regel für DDL-Befehle – reserviert ist, benötigt man für eine produktive Datenbank weitere Undo-Segmente, die zyklisch beschrieben werden.
Tablespaces und Datendateien
117
Seit Oracle9i gibt es die Möglichkeit, die Instanz mit automatischer Undo-Verwaltung zu betreiben (Serverparameter undo_management = AUTO). Sowohl für Oracle9i als auch für Oracle 10g ist diese Technik der herkömmlichen, manuellen UndoVerwaltung vorzuziehen, daher wird hier auch nur dieser Fall betrachtet. Für ältere Datenbanken und Migrationsmöglichkeiten wird auf Kapitel 3.10 verwiesen. Bei automatischer Undo-Verwaltung werden die notwendigen Segmente vom System in einem speziellen Undo-Tablespace automatisch angelegt, der Administrator hat keinerlei Einfluss auf Anzahl und Größe der Undo-Segmente. Die interne Verwaltung der Undo-Segmente erfolgt in Form von Ringpuffern. Jedes Undo-Segment kann eine oder mehrere Transaktionen beherbergen, auch kann eine einzelne Transaktion sich durchaus über mehrere Undo-Segmente erstrecken. Jedes Extent eines Undo-Segmentes kann ebenfalls eine oder mehrere Transaktionen speichern. Es versteht sich, dass eine Transaktion umso mehr Speicherplatz belegt, je umfangreicher ihre Änderungen ausfallen. Undo-Segmente sind – wie bereits erwähnt – als logische »Ringe« aufgebaut sind. Ist ein Extent gefüllt, wird entweder das nächste, bereits existierende Extent wieder verwendet, aber nur dann, wenn es keine aktiven Transaktionen mehr enthält, oder eine neues Extent angelegt und logisch in den Ring eingefügt. Die automatische Undo-Verwaltung übernimmt nicht nur die Verwaltung von Anzahl und Größe der Undo-Segmente, sondern kann mit weiteren Raffinessen aufwarten: Nach Möglichkeit wird nur eine schreibende Transaktion pro Undo-Segment zugelassen, um die Wahrscheinlichkeit von Zugriffskonflikten auf den Transaktionstabellen im Header des Segments zu minimieren. Das Überschreiben von Extents ist nicht nur davon abhängig, ob alle schreibenden Transaktionen abgeschlossen wurden, sondern hängt auch von einer »Freigabezeit« ab, die über den Systemparameter undo_retention gesteuert wird und festlegt, wie lange before images aus beendeten Transaktionen für potenzielle Leser zur Verfügung gehalten werden sollen (Lesekonsistenz und Flashback Query). Diese »Freigabezeit« kann jedoch unterschritten werden, wenn der Platz in der Undo-Tablespace knapp zu werden droht (Space Pressure). Die Segmentverwaltung ist darüber hinaus so flexibel, Extents bei Bedarf zwischen den Segmenten auszutauschen. Auf diese Weise kann ein Segment in der Not, und um entsprechenden Speicherplatz in dem betreffenden Tablespace zu sparen, ein Extent eines fremden Undo-Segmentes »stehlen«, d.h., für sich nutzen. Die Oracle-Datenbank arbeitet nach einem optimistischen Ansatz, der besagt, dass jede Änderung permanent ist. Daher wird mit der Änderung eines oder mehrerer Datensätze eine Kopie des alten Zustandes in ein Undo-Segment geschrieben, und die neue Information wird als permanenter Datensatz gespeichert, obwohl der Anwender noch keinen COMMIT-Befehl ausgeführt hat. Wenn der Anwender mit ROLLBACK die Transaktion rückgängig machen möchte, muss also der neue Zustand wieder mit dem alten (before images) überschrieben werden.
118
Datenbank-Architektur
Neben dieser Möglichkeit des Zurückrollens von Transaktionen erlauben die UndoSegmente eine Lesekonsistenz von Abfragen. Da für einen gewissen Zeitraum alte und neue Datensätze zur Verfügung stehen können, kann eine Abfrage zeitlich ältere Daten sehen, obwohl diese von einer anderen Transaktion zwischenzeitlich geändert und bereits festgeschrieben wurden. Im folgenden Beispiel wird durch den Benutzer u1 eine Transaktion ausgeführt, die den Mitarbeitern der Abteilung 50 fünf Prozent mehr Gehalt zuweist. Es handelt sich um ein Unternehmen mit mehr als 100.000 Mitarbeitern, so dass die Änderung ca. fünf Minuten dauert. Eine Minute nach dem Start der Änderung wird aus der Personalabteilung eine Abfrage gestartet, um die Summe aller Gehälter pro Abteilung zu berechnen. Wenn jetzt auf bereits geänderte und nicht geänderte Daten zugegriffen werden würde, würde dies zu einem falschen Ergebnis führen. Durch das Lesekonsistenz-Modell von Oracle greift die Abfrage automatisch auf das before image der bereits geänderten Datensätze zu, um so zu gewährleisten, dass die Information gelesen wird, wie sie zum Start der Abfrage existierte. U1: UPDATE mitarbeiter SET gehalt = gehalt * 1,05 WHERE abtnr = 50; U2: SELECT abtnr, SUM(gehalt) FROM mitarbeiter ORDER BY abtnr; Listing 3.9: Lesekonsistenz-Modell
Abbildung 3.2: Consistent Read
Entscheidend ist in diesem Zusammenhang der Serverparameter undo_retention. Er gibt eine Zeitdauer an (Standardwert sind 15 Minuten), bis zu der auf before images für Lesekonsistenz oder sog. Flashback Queries zugegriffen werden kann. Allerdings gilt auch hier, dass bei unzureichend dimensioniertem Undo-Tablespace das Before-Image überschrieben wird, wenn eine DML-Operation den Platz beansprucht, d.h., eine DML-Operation hat Vorrang vor einer eventuellen Leseoperation auf ältere Datensätze. Als Alternative bietet Oracle 10g die Möglichkeit, die Undo-Retention zu garantieren. Da dies den operativen Betrieb jedoch beeinträchtigt, kommt er nur selten zum Einsatz.
Tablespaces und Datendateien
119
Das folgende Bild veranschaulicht das Transaktionsmanagement anhand eines Undo-Segments mit zwei Transaktionen. Die Information der ersten Transaktion T1 kann nach deren Beendigung sofort durch die Transaktion T2 überschrieben werden. Benötigt die Transaktion T2 dann noch weiteren Platz, wird ein zusätzliches Extent in den Ring eingebaut.
Abbildung 3.3: Undo-Segmente
Die automatische, d.h., systemgesteuerte Undo-Verwaltung erfordert Undo-Tablespaces. Ein Undo-Tablespace kann direkt beim Erstellen der Datenbank angelegt oder nachträglich aufgebaut werden. Im folgenden Beispiel wird der Undo-Tablespace UNDOTBS mit einer Größe von 2000 MB und einer automatischen Erweiterung auf maximal 5000 MB aufgebaut: SQL> CREATE UNDO TABLESPACE undotbs DATAFILE '/oradata1/PDWH10G/undotbs01.dbf' SIZE 2000M AUTOEXTEND ON NEXT 100M MAXSIZE 5000M;
Undo-Tablespaces sind stets Locally-Managed Tablespaces, deren Extent-Größen vom System bestimmt werden (AUTOALLOCATE). Zusätzliche Klauseln, wie die DEFAULT STORAGE- oder SEGMENT SPACE MANAGEMENT-Klausel, sind hierbei nicht zulässig und werden mit einer Fehlermeldung quittiert. CREATE UNDO TABLESPACE legt nicht nur einen Tablespace vom Typ UNDO (Attribut contents der View dba_tablespaces mit Wert UNDO) an, sondern erzeugt in diesem
Tablespace auch sofort zehn Undo-Segmente. Die Namen der Undo-Segmente lauten _SYSSMUxx$, wobei xx eine pro Datenbank fortlaufende Nummer darstellt.
120
Datenbank-Architektur
Undo-Tablespaces können darüber hinaus wie andere Tablespaces verwaltet werden: Über den Befehl ALTER TABLESPACE lassen sich zusätzliche Dateien anfügen oder der AUTOEXTEND-Klausel anpassen. Das Offline-Schalten gelingt allerdings nur, wenn der betreffende Tablespace sowohl nicht mehr aktiv ist als auch keine offenen Transaktionen mehr enthält. Grundsätzlich können mehrere Undo-Tablespaces pro Datenbank angelegt werden, Oracle arbeitet aber pro Instanz immer nur mit einem aktiven Undo-Tablespace. Das Umschalten zwischen vorhandenen Undo-Tablespaces ist grundsätzlich – auch im laufenden Betrieb – möglich, sofern der avisierte Tablespace nicht bereits von einer anderen Instanz aktiviert wurde. In unserem Beispiel wird der Tablespace mit Namen undotbs02 aktiviert, gleichzeitig sperrt Oracle den alten Undo-Tablespace für neue Transaktionen: SQL> ALTER SYSTEM SET undo_tablespace = undotbs02;
Das Umschalten gelingt auch dann, wenn offene Transaktionen existieren. Alte Transaktionen behalten nach wie vor ihren Undo-Kontext, neue Transaktionen werden einem Undo-Segment des neu aktivierten Tablespace zugeordnet. Achtung: Dies bedeutet auch, dass in RAC(Real Application Clusters)-Umgebungen jede aktive Instanz ihren eigenen Undo-Tablespace benötigt. Es muss hier also mindestens so viele Undo-Tablespaces wie gleichzeitig aktive Instanzen geben. Diese werden zweckmäßigerweise durchnummeriert, z.B. UNDOTBS01, UNDOTBS02 etc. Undo Management konfigurieren Die automatische Konfiguration von Undo-Segmenten wird pauschal über den Serverparameter undo_management geregelt: undo_management = auto
Dieser Parameter ist statisch, d.h., er kann nicht im laufenden Betrieb geändert werden, und er muss für alle Instanzen, die eine Datenbank geöffnet haben, identisch gesetzt sein. Es versteht sich, dass vor dem Umschalten auf die automatische Undo-Verwaltung ein entsprechender Tablespace angelegt worden sein muss. Der Wert manual schaltet auf die manuelle Konfiguration von Rollbacksegmenten um, die aus älteren Versionen von Oracle bekannt sind. Diese Einstellung ist zwar noch immer der Standardwert, aber nicht mehr zu empfehlen. Weitere Parameter Die automatische Undo-Verwaltung bringt einen weiteren Vorteil mit sich: Der Verbleib von Undo-Informationen bereits abgeschlossener Transaktionen muss nun nicht mehr mühsam durch Try-and-Error-Methoden ermittelt, sondern kann direkt per Systemparameter eingestellt werden. Im folgenden Beispiel wird festgelegt, dass Undo-Informationen pro Transaktion nach dem COMMIT für weitere 3600 Sekunden – also eine Stunde – für lesende Transaktionen verfügbar sind: undo_retention = 3600
Tablespaces und Datendateien
121
Achtung! Da Undo-Segmente nicht die gleiche Ringpuffer-Struktur fester Minimalgröße aufweisen wie Rollbacksegmente, zeigt die Erfahrung, dass in Produktivsystemen der Wert für undo_retention auf keinen Fall auf dem Standardwert (900 Sekunden) belassen werden sollte. Die hier gezeigte Alternative von einer Stunde ist der grundsätzlich bessere Startwert. Falls man Kenntnis über lang laufende Abfragen oder Transaktionen hat, empfiehlt es sich, mit der undo_retention großzügig über deren Laufzeit hinauszugehen. Der Parameter undo_retention ist dynamisch, kann also über den Befehl ALTER SYSTEM angepasst werden. Er muss allerdings für alle Instanzen einer Datenbank identisch eingestellt werden. Ein kleiner Wermutstropfen: Der DBA wird hier nicht von allen Überlegungen zur Konfiguration entlastet. Sollte der aktive UndoTablespace nicht genügend Platz für neu startende Transaktionen bereithalten und auch nicht dynamisch erweiterbar sein, werden Undo-Einträge abgeschlossener Transaktionen auch bereits vor dem Ablauf dieser Zeitspanne entfernt! Mit der Option RETENTION GUARANTEE wird garantiert, dass für die Dauer der undo_retention die alten Daten nicht überschrieben werden, auch wenn dies u.U. zu Fehlern bei der Transaktionsverarbeitung (ORA-01650 unable to extend rollback segment…) führen würde. Den in Oracle9i eingeführten Parameter undo_suppress_errors, mit dem Fehlermeldungen wie die unten abgebildete unterdrückt werden konnten, gibt es in Oracle 10g nicht mehr, entsprechende Fehler werden immer ignoriert. SQL> SET TRANSACTION USE ROLLBACK SEGMENT "_SYSSMU13$"; * FEHLER in Zeile 1: ORA-30019: Unzulässiger Rollback-Segment-Vorgang in Automatic Undo-Modus
Data Dictionary Views Die aus den Oracle-Versionen 7 und 8 bekannten Views sind auch im Kontext der automatischen Undo-Verwaltung noch relevant: dba_tablespaces listet die Undo-Tablespaces unter contents = 'UNDO'. dba_rollback_segs listet sowohl systemgenerierte Undo- als auch manuell erstellte Rollback-Segmente. Alle generierten Segmente von nicht aktiven Undo-Tablespaces haben konsequenterweise den Status Offline. dba_segments führt die systemgenerierten Undo-Segmente unter segment_type = 'TYPE2 UNDO'. v$rollstat und v$rollname geben in der gewohnten Weise Auskunft über aktive Undo- und Rollback-Segmente und ihre Statistiken. v$transaction erlaubt die Zuordnung von Transaktionen zu Undo-Segmenten. Seit Oracle9i gibt die View dba_undo_extents u.a. die letzte COMMIT-Zeit für jedes Extent des Undo-Tablespaces aus.
122
Datenbank-Architektur
Neu hinzugekommen ist auch die View v$undostat, über die Statistiken im Zusammenhang mit Undo-Tablespaces ausgegeben werden können. Die View gruppiert die Undo-Nutzung in Intervallen von jeweils zehn Minuten. Für die Optimierung sind vor allem die folgenden Attribute interessant: undoblks – die Anzahl benutzter Undo-Blöcke txncount – die Anzahl der Transaktionen maxconcurrency – die maximale Zahl gleichzeitig operierender Transaktionen unxpblkrelcnt – Freisetzen von Extents, deren Retention-Periode noch nicht ab-
gelaufen war, für andere Transaktionen. Die angestrebte Retention-Zeit konnte also nicht eingehalten werden. ssolderrcnt – Anzahl aufgetretener ORA-01555 Fehler (»snapshot too old«). Hohe Zahlen weisen auf einen zu geringen Wert für undo_retention oder (im Zusammentreffen mit hohen Werten der Spalte unxpblkrelcnt) auf einen zu kleinen Undo-Tablespace hin.
3.3.6 Read-only-Tablespaces Für spezielle Operationen kann es sinnvoll sein, einen Tablespace als Read-only zu spezifizieren, so dass nur lesend auf die Daten zugegriffen werden kann, DML-Operationen aber nicht mehr möglich sind. Ein Tablespace kann auch dann in den Read-only-Modus gebracht werden, wenn noch offene Transaktionen vorliegen. Diese offenen Transaktionen werden normal beendet, neue schreibende Transaktionen jedoch nicht mehr zugelassen. Wichtig: Es ist trotz des Read-only-Modus möglich, in dem Tablespace Objekte zu löschen! Eingesetzt werden Read-only-Tablespaces bei der Benutzung von CD-ROM-Laufwerken z.B. für Bilddateien und bei der Historisierung von Daten, die nicht mehr geändert werden dürfen. Der wesentliche Unterschied zu Read-Write-Tablespaces besteht darin, dass der Header der zugehörigen Datendateien eingefroren wird, wodurch die Notwendigkeit wiederholter Backups entfällt. Das Schreiben eines Checkpoints wird in diesem Fall ignoriert. Dadurch kann ein Recovery auf einem älteren Stand – einer einzigen Kopie des Read-only-Tablespaces – aufsetzen. Somit bieten sich Read-only-Tablespaces als Mittel zur Reduzierung des Sicherungsaufkommens an, wenn z.B. Tabellen mit nicht änderbarem Inhalt bzw. »alte Partitionen« von Tabellen in Read-only-Tablespaces ausgelagert werden.
3.3.7 Tablespaces offline setzen Ein bereits angesprochener Aspekt für die Aufteilung von Objekten auf mehrere Tablespaces ist die Verfügbarkeit. In diesem Punkt ist die Verwendung von OfflineTablespaces sinnvoll, da hierdurch erreicht wird, dass mit der Datenbank gearbeitet werden kann, obwohl eine Datendatei defekt ist und dadurch wiederhergestellt werden muss. Weitere Anwendungen sind administrative Aufgaben, wie das Sichern im konsistenten Modus oder das Verschieben des Tablespaces auf ein anderes Laufwerk. Folgende Optionen können verwendet werden, um ein Tablespace offline zu setzen:
Datenbankblöcke
123
SQL> ALTER TABLESPACE demo OFFLINE NORMAL;
Es wird ein Checkpoint geschrieben, um die Konsistenz des Tablespaces zu gewährleisten, anschließend werden alle Datendateien offline gesetzt. Dies ist die Standardoption. SQL> ALTER TABLESPACE demo OFFLINE TEMPORARY;
Für die noch geöffneten Datendateien wird ein Checkpoint geschrieben. Sollten alle zugehörigen Datendateien geöffnet sein, so ist das Verhalten identisch zur Option NORMAL. Der Befehl wird normalerweise verwendet, wenn eine oder mehrere Datendateien defekt sind und deshalb ein OFFLINE NORMAL nicht mehr funktioniert. SQL> ALTER TABLESPACE demo OFFLINE IMMEDIATE;
Es wird kein Checkpoint geschrieben, d.h., die Datendateien des Tablespaces sind inkonsistent. Diese Option wird verwendet, wenn es zu einem Fehler in einer Datei kommt, der nur durch ein Media-Recovery behoben werden kann. SQL> ALTER TABLESPACE demo OFFLINE FOR RECOVER;
Der Tablespace eines Recovery-Sets wird für Point-in-Time-Recovery offline gesetzt. Ein Recovery-Set bezieht sich hierbei auf eine Anzahl Tablespaces, welche die Konsistenz einer Anwendung gewährleisten können und damit für ein Point-in-TimeRecovery als Einheit betrachtet werden sollen.
3.4
Datenbankblöcke
Die in einem Datenbankmanagementsystem gehaltenen Daten müssen aus Gründen der Wiederherstellbarkeit permanent gespeichert werden, so dass Dateien naturgemäß eine zentrale Rolle für Datenbanken spielen. Die Dateien eines relationalen Datenbankmanagementsystems dürfen aber nicht als »flache Dateien«, d.h. Dateien mit einer simplen Satzstruktur, aufgebaut sein, da Änderungen der Datenstruktur, wie das Hinzufügen von Spalten an bestehende Tabellen, im laufenden Betrieb möglich sein müssen. Informationen über die Struktur der Daten (so genannte Metadaten) dürfen weiterhin nicht ausschließlich in den verarbeitenden Programmen, sondern müssen bei den Daten gespeichert werden: Dies garantiert die Offenheit der Schnittstellen und die Verwendbarkeit der Daten in unterschiedlichsten Programmen und Entwicklungsumgebungen. Auch um diese Flexibilität zu erreichen, verwendet der Oracle Server eine Blockstruktur als Grundlage für seine Dateistrukturen. Die kleinste Bearbeitungseinheit für fast alle Komponenten des Oracle Servers ist demnach ein Datenbankblock. Ob es sich um I/O-Problematiken, physikalische Zugriffskonflikte oder die Entscheidungsstrategien des Optimizers handelt, der Block spielt eine zentrale Rolle. Weiterhin ist zu erwähnen, dass alle Datenbankinhalte, also auch das Data Dictionary, das die Metadaten enthält, in der Blockstruktur gespeichert sind. Die Größe eines Datenbankblocks ist keinesfalls a priori festgelegt; sie kann vielmehr beim Anlegen der Datenbank den Gegebenheiten (Anforderungen, Anwendung, Hardware und Betriebssystem) angepasst werden. Sie ist auf jeden Fall ein
124
Datenbank-Architektur
Vielfaches von 1 KB, gängige Werte sind 4, 8 oder 16 KB. Wenn die Datenbank einmal angelegt ist, ist die Datenbankblockgröße nicht mehr änderbar und gilt für den SYSTEM-Tablespace und als Standardwert für alle weiteren Tablespaces. Innerhalb einer Datenbank können jedoch mehrere Blockgrößen verwendet werden, jedoch nicht innerhalb einer Datendatei oder eines Tablespaces. Für die Dateien des Datenbanksystems, die Daten enthalten, gilt, dass ihre Dateigröße ein ganzzahliges Vielfaches ihrer Blockgröße ist. Ein Datenbankblock besteht immer aus zwei logischen Teilen: dem Kopf und dem Inhalt. Beide Teile sind variabel in der Größe, so dass möglichst keine vorgefertigten Beschränkungen wie z.B. Satzzahl pro Block vorhanden sind. Damit sich die beiden Teile beim Wachstum nicht behindern, befindet sich der Kopf am Anfang des Blocks und wächst zum Ende hin; der eigentliche Inhalt beginnt hingegen am Blockende und wächst zum Anfang hin.
Abbildung 3.4: Datendatei und Datenbankblock
3.5
Online-Redolog-Dateien
Die Redolog-Dateien enthalten ein physikalisches Transaktionsprotokoll. Dies ist nicht zu verwechseln mit einem logischen Transaktionsprotokoll, das eine Sequenz von SQL-Kommandos enthalten würde. Alle Änderungen an Datenbankblöcken werden hier protokolliert. Die Protokollierung hat den einfachen Sinn, dass in einem Fehlerfall die logischen Änderungen an der Datenbank durch das nochmalige Durchführen der Blockänderungen wiederhergestellt werden können. Die Eigenschaft der Wiederherstellbarkeit ist eine rudimentäre Anforderung an ein Datenbankmanagementsystem – ohne sie wäre ein produktiver Einsatz nicht möglich. Redolog-Dateien speichern also redo-Informationen des Oracle-Systems, d.h. Informationen, die zum Wiederherstellen (redo) von Blockzuständen notwendig sind – im Gegensatz zu den Undo-Segmenten, die Informationen zum Zurücksetzen (undo) von Blockzuständen speichern. Sie beinhalten ein Transaktionsprotokoll der Datenbankaktivitäten, das im Fehlerfall für die Wiederherstellung der Datenbankkonsistenz nach einem Absturz der Instanz benötigt wird. Als solches enthalten sie Daten zu allen möglichen Blöcken (Daten-, Index- und auch Undo-Blöcken). Notwendig wird das Transaktionsprotokoll durch die asynchrone Arbeitsweise des Database-Writer-Prozesses, der nur in Intervallen oder bei Platzmangel Blöcke aus dem Datenbank-Puffer auf die Platte schreibt. Damit wäre also z.B. bei einem Stromausfall ein Transaktionsverlust vorprogrammiert.
Online-Redolog-Dateien
125
Tritt bei einer Oracle-Instanz durch einen Stromausfall, einen Hardware- oder Softwarefehler ein Abbruch auf, so werden bei einem Wiederanlauf automatisch, durch den System-Monitor(SMON)-Prozess angestoßen, die Transaktionen aus den benötigten Redolog-Dateien nachgefahren. Eine Oracle-Datenbank kennt zwei Typen von Redolog-Dateien: die vom RDBMS ständig zyklisch beschriebenen Online-Redolog-Dateien sowie die (weiter unten beschriebenen) Offline- oder archivierten Redolog-Dateien, die optional (im so genannten Archivelog-Modus) nach dem Schließen von Online-Redolog-Dateien als eine chronologische Folge von durchnummerierten Redolog-Dateikopien entstehen.
3.5.1 Konfiguration Bei der Konfiguration von Redolog-Dateien werden die Bereiche Sicherheit und Performance des Oracle-Systems tangiert. Diese Ziele stehen zunächst im Widerspruch, können aber durch Spiegelung der Redolog-Dateien gut in Einklang gebracht werden. Lage der Redolog-Dateien Für transaktionsorientierte Oracle-Systeme spielt der Durchsatz des Logwriter-Prozesses eine entscheidende Rolle. Bei einem COMMIT-Befehl gilt die Transaktion so lange als nicht beendet, bis alle notwendigen Protokollinformationen in die Redolog-Dateien geschrieben worden sind. Aus Gründen der Performance sollten also die Redolog-Dateien auf schnelle Platten gelegt werden, auf denen ansonsten wenige Aktivitäten stattfinden. Bei extrem hohen Anforderungen sollte auch über Plattenstriping für die Redolog-Dateien nachgedacht werden. Die Trennung der Redolog-Dateien von den Datendateien empfiehlt sich ohnehin aus Sicherheitsaspekten, da ja die Redolog-Dateien im Fehlerfall, bei einem PlattenCrash, zur Wiederherstellung der Datendateien benötigt werden. Anzahl der Redolog-Dateien Eine Oracle-Datenbank benötigt mindestens zwei Gruppen von Redolog-Dateien, zwischen denen der Logwriter-Prozess umschalten kann. Mehr als zwei RedologGruppen zu konfigurieren, kann folgende Gründe haben: 1. Wartezustände auf Checkpoints Eine Redolog-Datei kann erst dann überschrieben werden, wenn sämtliche Blöcke aus dem Database Buffer Cache in der SGA vom Database Writer in die Datendateien geschrieben worden sind, für deren Wiederherstellung bei Ausfall der Instanz die Informationen aus der jeweiligen Redolog-Datei gebraucht werden. Dieser Konsistenzabgleich ist als Checkpoint bekannt. Dauert jetzt bei einem sehr großen Database Buffer Cache und einer hohen Transaktionslast der Checkpoint länger als das Vollschreiben der zweiten Gruppe, ist ein Wartezustand die Folge. In der Alert-Datei der Instanz wird die Meldung Checkpoint not complete protokolliert.
126
Datenbank-Architektur
Da der Checkpoint-Algorithmus die Parallelisierung von Checkpoints erlaubt, kann dieser Wartezustand durch eine höhere Anzahl von Redolog-Gruppen beseitigt werden. 2. Performance des Archivierungsprozesses Die Archivierungsprozesse ARCn sichern voll geschriebene Redolog-Dateien in ein dafür konfiguriertes Verzeichnis, idealerweise auf einer eigenen Platte bzw. einem eigenen Volume. Ist der ARCn-Prozess damit noch nicht fertig, wenn die Datei wieder überschrieben werden soll, so erzeugt das einen Wartezustand. Das kann gerade bei hoher Transaktionslast auftreten. Diese Lastspitzen können über eine größere Anzahl von Redolog-Gruppen abgefangen werden, da es dann entsprechend länger dauert, bis die betreffende Datei wieder überschrieben werden soll, und der ARCH-Prozess damit mehr Zeit zur Verfügung hat, diese zu sichern. Größe der Redolog-Dateien Die Größe der Redolog-Dateien wird aus Performance-Gründen verändert. Immer wenn auf die nächste Redolog-Gruppe umgeschaltet wird, weil die Datei der aktuellen Gruppe zu 100 Prozent gefüllt ist, wird ein Checkpoint initiiert. Während des Checkpoints müssen alle modifizierten Blöcke aus der SGA durch den DBWn-Prozess in die Datendateien geschrieben werden, was bei einer großen SGA bei hoher Transaktionslast zu einer hohen Systemlast führen kann. Eine Reduzierung der Checkpoints führt also zu einer Reduzierung der Systemlast. Werden also die Redolog-Dateien vergrößert, verlängert sich die Zeit zwischen zwei Checkpoints, und die Systemlast sinkt. Allerdings verlängert sich die Zeit beim Wiederanlauf des Oracle-Systems, da z.B. nach einem Stromausfall mehr Transaktionen seit dem letzten Konsistenzzeitpunkt nachgefahren werden müssen. Jedoch ist diese Zeit in der Praxis zu vernachlässigen. Zu dem Wiederanlauf des Rechners kommen dann erfahrungsgemäß einige Minuten Instance-Recovery-Zeit. Die genau benötigte Zeit lässt sich schwer voraussagen; sie ist einerseits abhängig von den Leistungsdaten des Systems, andererseits von der Art der protokollierten Aktionen. In den allermeisten Fällen erweist sich diese Zeit nicht als kritisch. Bei einem Verlust einer Redolog-Gruppe wäre allerdings die Menge der verlorenen Transaktionen größer. Also stellen größere Redolog-Dateien ein höheres Risiko dar. Dieses Risiko kann dadurch minimiert werden, dass man die Redolog-Dateien spiegelt, also Gruppen mit zwei oder drei Mitgliedern (Members) konfiguriert oder die Redolog-Dateien auf gespiegelte Platten legt. Für Systeme mit hoher Transaktionslast sind Redolog-Dateien mit einer Größe von mindestens 100 MB (was mittlerweile dem Standardwert, zumindest für Oracle Managed Files, entspricht) empfehlenswert, bei großen Systemen werden durchaus 500 MB und mehr konfiguriert.
Online-Redolog-Dateien
127
Abbildung 3.5: Redolog-Gruppen und Redolog-Member
Alle Redolog-Gruppen sollten identische Dateigrößen aufweisen. Auch wenn die Datenbank prinzipiell unterschiedliche Redolog-Größen zulässt, führt dies in der Praxis nur zu Problemen und sollte daher vermieden werden. Abhängige Serverparameter Zur Beeinflussung des Checkpoint-Verhaltens der Oracle Instanz gibt es diverse Parameter, die als historisch gewachsene Strukturen betrachtet werden können: log_checkpoint_interval und log_checkpoint_timeout sind die auch schon in früheren Oracle-Versionen eingesetzten Parameter, die harte Checkpoints innerhalb der Befüllung einer Redolog-Datei ausgelöst haben. Die Werte werden für log_checkpoint_interval in 512-B-Blöcken, für log_checkpoint_timeout in Sekunden angegeben. Eine grundsätzliche Konfigurationsempfehlung war früher, Checkpoints innerhalb von Redolog-Dateien zu vermeiden und somit Anzahl und Häufigkeit von Checkpoints durch die Größe der Redolog-Dateien zu steuern. Hierzu setzte man log_checkpoint_interval größer als die Redolog-Datei-Größe und log_checkpoint_timeout auf den Wert 0. Die aktuelle Empfehlung lautet, die Parameter auf den Wert 0 zu setzen oder nicht zu setzen, womit ihre Funktion ausgeschaltet ist. Mit Oracle8i wurde für die Enterprise Edition der Parameter fast_start_io_target eingeführt, der die Anzahl der notwendigen IOs für eine Instanzwiederherstellung beschränken sollte. Der Parameter ist zwar auch noch in Oracle 10g vorhanden, wird aber grundsätzlich nicht mehr empfohlen.
128
Datenbank-Architektur
Die Empfehlung gilt aktuell für den mit Oracle9i eingeführten Parameter fast_start_mttr_target, der eine Vorgabe bezüglich der erlaubten Zeit für eine Instanzwiederherstellung in Sekunden erlaubt (auch hier gilt: für die Enterprise Edition). Wie der zuvor genannte Parameter wird hiermit Fast Start Checkpointing aktiviert. Das bedeutet, dass der Database Writer so viel zusätzliche Schreiblast bekommt, um den nächsten Checkpoint bereits im Vorfeld so weit voranzutreiben, dass die angegebene Zeit für die Instanzwiederherstellung ausreichend ist. In Oracle 10g wurde der zugrunde liegende Algorithmus insofern verbessert, dass Zeiten, in denen IO-Kapazitäten frei sind, bevorzugt für diesen Zweck genutzt werden. Für Systeme mit definierten Anforderungen an Wiederanlaufzeiten im Fehlerfall stellt die Möglichkeit der Zeitvorgabe eine komfortable Realisierung der Anforderungen dar.
3.5.2 Administrationskommandos Im Folgenden werden die wichtigen Kommandos für die Administration der Redolog-Dateien beispielhaft vorgestellt. Für die komplette Syntax sei auf das Handbuch Oracle 10g SQL Reference verwiesen. Die hier vorgestellten Kommandos gelten genauso für Oracle9i und Oracle8i. Zusätzlich können Redolog-Dateien über Oracle Managed Files verwaltet werden. Dabei werden dann die Dateinamen und ev. Größen automatisch vergeben (siehe Kapitel 3.9). Anlegen einer neuen Redolog-Gruppe SQL> ALTER DATABASE ADD LOGFILE GROUP 3 '/disk1/verzeichnis/redo_3_1.log' SIZE 50M;
Der Name der Redolog-Datei sollte die Gruppennummer (hier 3) und die Nummer des Mitglieds einer Gruppe beinhalten (hier 1). Die Dateigröße als Eigenschaft der Redolog-Gruppe sollte angegeben werden, um nicht auf versionsspezifischen Standardwerten zu landen. Hinzufügen eines Mitglieds zu einer Redolog-Gruppe SQL> ALTER DATABASE ADD LOGFILE MEMBER '/disk1/verzeichnis/redo_3_2.log' TO GROUP 3;
Umbenennen von Redolog-Dateien SQL> ALTER DATABASE RENAME FILE '/disk1/verzeichnis/redo_1_1.log' TO '/disk2/verzeichnis_neu/redo_1_1.log’;
Hiermit wird nicht etwa die Redolog-Datei selbst verschoben, sondern lediglich ihr Name in der Kontrolldatei geändert. Voraussetzungen für dieses Kommando sind, dass die Gruppe nicht gerade im Zugriff des Logwriter-Prozesses ist, die Quelldatei identisch mit den Informationen aus v$logfile ist und die Zieldatei existiert, also vorher auf Betriebssystemebene kopiert worden ist.
Online-Redolog-Dateien
129
Löschen eines Mitglieds einer Redolog-Gruppe SQL> ALTER DATABASE DROP LOGFILE MEMBER '/disk1/verzeichnis/redo_3_2.log';
Dieser Befehl löscht den Eintrag aus der Kontrolldatei. Auf Betriebssystemebene muss die Datei zusätzlich gelöscht werden. Bei Oracle Managed Files werden die Dateien automatisch von der Platte gelöscht. Löschen einer Redolog-Gruppe SQL> ALTER DATABASE DROP LOGFILE GROUP 3;
Voraussetzungen sind, dass die jeweilige Gruppe nicht im Zugriff des LogwriterProzesses ist und mindestens zwei Gruppen verbleiben. Auf Betriebssystemebene muss die Datei zusätzlich gelöscht werden. Bei Oracle Managed Files werden die Dateien automatisch von der Platte gelöscht. Initialisieren einer Gruppe SQL> ALTER DATABASE CLEAR UNARCHIVED LOGFILE GROUP 1 UNRECOVERABLE;
Mit diesem Befehl kann eine Redolog-Gruppe oder auch eine einzelne RedologDatei initialisiert werden. Die Wirkung entspricht dem Löschen und Neuanlegen der Gruppe, jedoch funktioniert dieser Befehl auch dann, wenn nur zwei RedologGruppen angelegt wurden. Der Status der Gruppe ist anschließend UNUSED, die Log Sequence Number wird auf 0 zurückgesetzt. Der Zusatz UNARCHIVED erlaubt sogar die Initialisierung, auch wenn die Datenbank im Archivierungsmodus läuft und die Redolog-Datei noch nicht archiviert ist. Die Option UNRECOVERABLE bewirkt, dass eine Initialisierung stattfindet, obwohl Inhalte der Redolog-Datei noch für eine Wiederherstellung der Datenbank benötigt werden. Diese Optionen sollten jedoch nur im äußersten Notfall verwendet werden.
3.5.3 Überwachung von Redolog-Dateien Zur Überwachung der Redolog-Dateien stehen folgende V$-Tabellen zur Verfügung: v$log Die Information listet unter anderem die Größe der Dateien (BYTES), den Status der Archivierung (ARCHIVED) und den Status der Datei (STATUS) auf. Folgende Status sind dabei möglich: – INACTIVE: wird zurzeit nicht benutzt, kann also gelöscht werden, solange mehr als zwei Gruppen übrig bleiben. – ACTIVE: Die Datei wird für ein Instance-Recovery benötigt, kann also nicht gelöscht werden. – UNUSED: Die Datei wurde noch nie benutzt, z.B. nach dem neuen Anlegen. – CURRENT: in dieser Datei wird zurzeit geschrieben.
130
Datenbank-Architektur
v$logfile Neben der Gruppenzugehörigkeit werden in dieser Tabelle auch der Status und die Namen der Redolog-Dateien angezeigt, unter ihnen auch Oracle Managed Files. Um sich die Größe und Lage der Redolog-Dateien anzusehen, muss man einen Join über die Tabellen v$log und v$logfile mit der Spalte GROUP# durchführen, z.B. in der Form: SQL> SELECT v.group#, vl.member, v.bytes, v.status FROM v$log v,v$logfile vl WHERE v.group# = vl.group#; GROUP# MEMBER BYTES STATUS ---------- ----------------------------------- ---------- ---------------1 D:\ORACLE\ORADATA\QJA10G\REDO01.LOG 10485760 INACTIVE 2 D:\ORACLE\ORADATA\QJA10G\REDO02.LOG 10485760 CURRENT 3 D:\ORACLE\ORADATA\QJA10G\REDO03.LOG 10485760 INACTIVE Listing 3.10: Redolog-Informationen
v$loghist und v$log_history In diesen V$-Tabellen werden Informationen über archivierte Redolog-Dateien wie Namen, Zeitstempel und SCN-Nummer verwaltet. Diese Auszüge kommen aus der Redolog-Historie in den Kontrolldateien. Zusätzlich werden sämtliche Redolog-Switches mit Zeitstempel in der Alert-Datei einer Instanz protokolliert. Hier sind auch die Wartezustände vermerkt, die durch Checkpoints oder die Archivierung bedingt sind, meist mit Zeitangaben.
3.5.4 Überlegungen zur Spiegelung von Redolog-Dateien Redolog-Dateien sind die kritischen Dateien einer Oracle-Datenbank im Fehlerfall. Datendateien und Kontrolldateien können wiederhergestellt werden, vorausgesetzt, es existiert eine Sicherung. Redolog-Dateien beinhalten aktuelle Transaktionsinformationen, die insbesondere nach einer Beschädigung an einer Festplatte zur Wiederherstellung der Datendateien benötigt werden. Der Verlust einer kompletten Redolog-Gruppe bedeutet Datenverlust! Aus diesem Grunde ist es für Produktionsdatenbanken erforderlich, die Redolog-Dateien zu spiegeln. Dabei steht zur Auswahl, entweder eine Oracle-seitige Spiegelung einzuschalten (also pro Redolog-Gruppe mindestens zwei Member auf verschiedenen Platten zu konfigurieren) oder die Dateien der Redolog-Gruppen auf betriebssystem- oder hardwareseitig gespiegelte Platten zu legen. Von einer Spiegelung über RAID 5 sollte abgesehen werden, da die benötigte IO-Kapazität durch solche Systeme i.A. nicht gewährleistet werden kann. Fällt ein Spiegel aus, wird die Oracle-Instanz weiterlaufen, der Logwriter-Prozess schreibt in die verbleibende Datei der Gruppe. Bei der Oracle-seitigen Spiegelung hat man den Vorteil, dass der Schreibfehler auf das fehlende Mitglied in der AlertDatei protokolliert wird. Betriebssystem- oder hardwareseitige Spiegelungen sind für den Logwriter-Prozess transparent.
Kontrolldateien
3.6
131
Kontrolldateien
Eine zentrale Aufgabe haben Kontrolldateien: Sie enthalten neben einigen Zeitstempeln und Konsistenzinformationen die physikalische Struktur der OracleDatenbank, d.h. die Namen und Größen aller Daten- und Online-Redolog-Dateien. Für eine Datenbank gibt es zu jedem Zeitpunkt genau eine gültige Version der Kontrolldatei; diese kann gespiegelt betrieben werden. Die Kontrolldateien sind die kleinsten Komponenten (wenige MB) einer OracleDatenbank, haben aber sowohl für die Verfügbarkeit als auch für die Konsistenz der Datenbank eine zentrale Bedeutung, besonders im Wiederherstellungsfall. In einer Kontrolldatei sind Informationen über die Datenbank und alle Dateien abgelegt, die zur Datenbank gehören. Dabei besteht eine Eins-zu-eins-Zuordnung der Kontrolldatei zu einer Datenbank. Wichtige Informationen, die in einer Kontrolldatei gespeichert werden, sind unter anderem: der Name und Erstellungszeitpunkt der Datenbank (v$database) die Namen der zur Datenbank gehörenden Kontroll-, Daten-, Temporär- und Redolog-Dateien mit kompletter Pfadangabe und Statusinformationen wie Offline, Read-only usw. (v$controlfile, v$datafile, v$tempfile, v$logfile, v$log) Informationen über Tablespaces (v$tablespace) Informationen über den Archivierungsstatus (v$archived_logs) Redolog-Historie (v$log_history) Informationen für den Recovery-Manager (v$backup_<xxx>) die aktuelle Log-Sequence-Nummer Checkpoint-Informationen Die Tatsache, dass die Informationen aus den o.a. v$-Views aus der Kontrolldatei kommen, kann leicht überprüft werden, indem man sie im MOUNT-Status einer Instanz abfragt. Die Kontrolldateien sind sowohl beim Starten des Oracle-Systems als auch während des normalen Datenbankbetriebs im Zugriff. Die Aktualisierung der Kontrolldateien erfolgt über die Instanz beim Auftreten eines Checkpoints oder bei Strukturänderungen an der Datenbank. Strukturänderungen der Datenbank sind beispielsweise das Hinzufügen, Umbenennen und Löschen von Datendateien oder Tablespaces, RedologGruppen oder Redolog-Membern. Konsistenzinformationen bezüglich der Datendateien werden redundant in der Kontrolldatei und in den Header der betreffenden Dateien gespeichert und bei Bedarf – z.B. beim Starten der Datenbank – verglichen. Ein Abgleich der Informationen findet darüber hinaus bei einem Checkpoint statt. Zudem speichert der Checkpoint-Prozess in Intervallen von drei Sekunden den Status der Redolog-Dateien in der Kontrolldatei, um parametrierte Grenzen wie z.B. log_checkpoint_interval oder log_checkpoint_timeout abgleichen zu können.
132
Datenbank-Architektur
Diese Konsistenzinformationen bestimmen bei einer Instanzwiederherstellung oder bei einer Medienwiederherstellung, welche Informationen aus RedologDateien oder archivierten Redolog-Dateien nachgefahren werden müssen, um die Datenbank wieder auf einen konsistenten Zustand zu bringen. Sind diese Informationen nicht vollständig vorhanden, muss eine unvollständige Medienwiederherstellung durchgeführt werden, was einen Datenverlust nach sich zieht. Die Kontrolldateien sind somit auch ein wichtiger Bestandteil der Sicherung einer Oracle-Datenbank. Wenn Strukturänderungen wie das Hinzufügen eines neuen Tablespaces oder einer neuen Daten- oder Redolog-Datei durchgeführt werden, sollte anschließend sofort eine Sicherung der Kontrolldatei vorgenommen werden.
3.6.1 Administration der Kontrolldateien Anlegen der Kontrolldateien Die Kontrolldatei wird automatisch beim Anlegen der Datenbank erzeugt. Die Lage der Kontrolldatei wird dabei über den Serverparameter control_files bestimmt. Die Größe wird abhängig vom CREATE DATABASE-Kommando der spezifizierten Obergrenzen errechnet. Die dafür relevanten Parameter sind MAXINSTANCES, MAXLOGFILES, MAXLOGMEMBERS, MAXLOGHISTORY und MAXDATAFILES. Hier ist anzuraten, die Parameter mit Reserven zu versehen. Ist die hier definierte Obergrenze überschritten, so können keine weiteren Dateien des entsprechenden Typs an die Datenbank angehängt werden. Dieses Problem ist dann nur über das Anlegen einer neuen Kontrolldatei zu lösen, was man in der Praxis jedoch vermeiden sollte. Spiegelung der Kontrolldateien Die Wichtigkeit der Kontrolldateien, sowohl für den laufenden Betrieb als auch für den Wiederanlauf des Oracle-Systems, insbesondere bei der Wiederherstellung der Datenbank, ist im vorangehenden Abschnitt beschrieben worden. Aus diesem Grunde ist es sehr empfehlenswert, die Kontrolldateien zu spiegeln. Auch hier stehen datenbank-, betriebssystem- und hardwareseitige Spiegelung zur Auswahl. Im Folgenden wird das Verfahren zur Einrichtung einer datenbankseitigen Spiegelung beschrieben (Pfadangaben für Unix): Der aktuelle Eintrag in der Parameterdatei laute beispielsweise: control_files = '/oradata1/PDWH10G/control01.ctl'
Zunächst wird der Eintrag geändert auf: control_files = '/oradata1/PDWH10G/control01.ctl', '/oradata2/PDWH10G/control02.ctl'
Dies geschieht entweder manuell bei Verwendung einer herkömmlichen Parameterdatei oder – bei Verwendung einer Serverparameterdatei – über folgendes Kommando:
Kontrolldateien
133
SQL> ALTER SYSTEM SET CONTROL_FILES = '/oradata1/PDWH10G/control01.ctl', '/oradata2/PDWH10G/control02.ctl' SCOPE = SPFILE;
Anschließend wird die Instanz heruntergefahren und die Kontrolldatei auf Betriebssystemebene kopiert: $ cp /oradata1/PDWH10G/control01.ctl /oradata2/PDWH10G/control02.ctl
Zum Schluss wird die Instanz wieder hochgefahren. Es ist unbedingt zu beachten, dass die Kontrolldateien nur bei gestoppter Instanz kopiert werden dürfen, da ansonsten die Versionsstände der Dateien differieren und zu einem Fehler beim Starten des Oracle-Systems führen. Umbenennen oder Verlagern der Kontrolldateien Für das Umbenennen oder Verlagern der Kontrolldateien gilt das gleiche Verfahren wie bei der Erstellung einer Spiegelung. Auch hier ist unbedingt die Reihenfolge des Stoppens, der Umbenennung und des Startens einzuhalten. Sichern und Erzeugen von Kontrolldateien Eine Kontrolldatei kann während des laufenden Betriebes durch folgendes Kommando gesichert werden: SQL> ALTER DATABASE BACKUP CONTROLFILE TO '/orabackup/PDWH10G/control_bck.ctl';
Bei Verlust der Kontrolldatei einer Datenbank kann diese durch ein CREATE CONTROLFILE-Kommando wieder aufgebaut werden. Im Kommando müssen alle Dateien angegeben werden, die zur Datenbank gehören, sowohl alle Redolog- als auch alle Datendateien. Da bei der Erstellung eines solchen Skripts Fehler vorprogrammiert sind, existiert die Möglichkeit des automatischen Generierens. SQL> ALTER DATABASE BACKUP CONTROLFILE TO TRACE;
Die daraus resultierende Trace-Datei wird in das Verzeichnis geschrieben, das als user_dump_dest definiert ist. Die Trace-Datei enthält das Startup-Kommando und das CREATE CONTROLFILE-Kommando, inklusive Kommentierung der einzelnen Schritte. Dieses Skript kann auch dann genutzt werden, wenn durch zu klein gewählte Einstellungen beim Anlegen der Datenbank – die Klauseln MAXDATAFILES und MAXLOGFILES – strukturelle Erweiterungen nicht mehr möglich sind. Das Skript kann editiert werden, wobei man dann höhere MAX-Werte einträgt. Das Erzeugen einer Kontrolldatei ist jedoch immer ein Vorgang, der große Sorgfalt erfordert und für den das Oracle-System gestoppt werden muss. In der Oracle-Dokumentation wird angeraten, sowohl vor als auch nach der Ausführung des CREATE CONTROLFILE-Kommandos eine Sicherung zu machen.
134
Datenbank-Architektur
Beispiel eines CREATE CONTROLFILE-Kommandos: STARTUP NOMOUNT CREATE CONTROLFILE REUSE DATABASE "PDWH10G" ARCHIVELOG MAXLOGFILES 32 MAXLOGMEMBERS 3 MAXDATAFILES 254 MAXINSTANCES 1 MAXLOGHISTORY 454 LOGFILE GROUP 1 '/oradata1/PDWH10G/redo_1_1.log' GROUP 2 '/oradata1/PDWH10G/redo_2_1.log' GROUP 3 '/oradata1/PDWH10G/redo_3_1.log' DATAFILE '/oradata1/PDWH10G/system01.dbf', '/oradata1/PDWH10G/sysaux01.dbf', '/oradata1/PDWH10G/undotbs01.dbf', '/oradata1/PDWH10G/users01.dbf', '/oradata1/PDWH10G/tools01.dbf', '/oradata1/PDWH10G/indx01.dbf' CHARACTER SET WE8ISO8859P15 ;
NORESETLOGS
SIZE 50M, SIZE 50M, SIZE 50M
Kontrolldateien und Oracle Managed Files Die Kontrolldateien können auch als Oracle Managed Files angelegt werden. Das bedeutet, dass nicht durch den Serverparameter control_files die Namen bestimmt werden, sondern dass das Oracle-System beim Anlegen der Datenbank eigene eindeutige Dateinamen generiert. Die Lage der Kontrolldateien wird dann über den Serverparameter db_create_online_log_dest_n = /platte/pfad
bestimmt. Dieser Parameter bestimmt darüber hinaus die Lage der Online-RedologDateien. Für die Spiegelung müssen dann entsprechend zwei oder mehr Destinationen angegeben werden. Bei Verwendung einer Parameterdatei alten Stils (init.ora-Datei) müssen die generierten Dateinamen über die View v$controlfile ermittelt und anschließend über den Parameter control_files eingetragen werden. Bei Verwendung einer Serverparameterdatei entfällt diese Maßnahme.
Parameterdateien
3.7
135
Parameterdateien
Die Parameterdatei enthält sämtliche Serverparameter für einen Oracle-Server. Hieraus werden beim Systemstart die Konfiguration und das Verhalten der Instanz bestimmt. Unter anderem enthält die Parameterdatei den oder die Namen der Kontrolldateien. Seit Oracle9i gibt es sie in zwei Varianten. Herkömmliche Parameterdatei (PFILE bzw. init.ora) Zum Begriff Parameterdatei sind zwei Anmerkungen zu machen: 1. Der tatsächliche Name der Parameterdatei ist in den meisten Fällen anders als init.ora. Meist ist der Name der Oracle-Instanz (zum Begriff der Instanz siehe weiter oben) enthalten wie in initPDWH10G.ora; er kann aber auch frei gewählt werden. Beim Hochstarten der Datenbanken wird – wenn nichts anderes angegeben wird – standardmäßig die Datei mit dem Namen init.ora im Verzeichnis \database (für MS-Windows) bzw. /dbs (für andere Plattformen) benutzt, daher findet man die Parameterdatei häufig unter diesem Pfad. 2. Die Start- oder Serverparameter einer Oracle-Instanz heißen in der Oracle-Anwendergemeinde »init.ora-Parameter«, da sie traditionell in der »init.ora-Datei« gespeichert werden. Da die Speicherung der Parameter in der init.ora-Datei nur noch eine von vielen Möglichkeiten ist, wird in diesem Buch die Bezeichnung Serverparameter vorgezogen. Serverparameterdatei Die Konfiguration einer Instanz über eine herkömmliche Parameterdatei ist problematisch, wenn Start- und Stoppvorgänge in einer verteilten Rechnerumgebung vorgenommen werden. Das liegt daran, dass das Client-Werkzeug, das den STARTUPBefehl ausführt, die Parameterdatei liest. Da die Datei jedoch normalerweise auf dem Server gespeichert ist, muss diese vom Client entweder über das Netzwerk gelesen werden oder eine Kopie auf dem Client existieren. Beide Möglichkeiten sind fehleranfällig. Seit Oracle9i besteht die Möglichkeit, alternativ zur herkömmlichen Parameterdatei eine so genannte Serverparameterdatei zu nutzen. Diese wird in einem Binärformat auf dem Server gespeichert und kann aus einer bestehenden herkömmlichen Parameterdatei erzeugt werden. Falls eine Serverparameterdatei existiert, wird diese anstelle der herkömmlichen Parameterdatei zur Konfiguration beim Instanzstart benutzt. Der Inhalt der Serverparameterdatei wird mit Hilfe von ALTER SYSTEMBefehlen modifiziert. Die Serverparameterdatei wird beim STARTUP-Kommando stets auf der Serverseite im Verzeichnis $ORACLE_HOME/dbs (auf Unix) bzw. %ORACLE_HOME%\database (auf MSWindows) unter dem Namen spfile.ora gesucht.
136
Datenbank-Architektur
Achtung: Auch wenn eine Serverparameterdatei auf den ersten Blick bequem im Texteditor manuell editiert werden kann, stellt sich auf den zweiten Blick heraus, dass sie Prüfsummen enthält. Nach einer manuellen Veränderung ist die Serverparameterdatei daher meistens unbrauchbar und wird beim Versuch, die Instanz zu starten, abgelehnt. Stattdessen kann über die Kommandos SQL> CREATE SPFILE='/pfad/auf/server/spfileXYZ.ora' FROM PFILE ='/pfad/auf/client/initXYZ.ora';
bzw. SQL> CREATE PFILE ='/pfad/auf/client/initXYZ.ora' FROM SPFILE='/pfad/auf/server/spfileXYZ.ora';
zwischen einer herkömmlichen Parameterdatei und einer Serverparameterdatei umgewandelt werden. Am einfachsten kann dieser Befehl mit den Standardvorgaben verwendet werden. Der Befehl SQL> CREATE SPFILE FROM PFILE;
erstellt die Datei spfile.ora im Standardverzeichnis ($ORACLE_HOME/dbs bzw. %ORACLE_HOME%\database), wenn diese noch nicht existiert bzw. wenn die Datenbank nicht mit dieser Datei hochgefahren wurde. Ansonsten wird der Befehl abgelehnt. SQL> CREATE PFILE FROM SPFILE;
Hiermit wird ebenfalls im Standardverzeichnis die Datei init.ora erstellt. Allerdings sollten Sie hierbei aufpassen, da eine ältere Version ohne Rücksicht überschrieben wird. Den Trick, mit CREATE PFILE FROM SPFILE eine temporäre herkömmliche Parameterdatei zu erzeugen, diese zu editieren und dann mit CREATE SPFILE FROM PFILE vor dem STARTUP wieder eine Serverparameterdatei zu erzeugen, benötigt man u.a. dann, wenn man einen Parameter ganz austragen will oder sich ein Fehler eingeschlichen hat, mit dem der STARTUP nicht mehr möglich ist – das ALTER SYSTEM SET-Kommando mit SCOPE = SPFILE funktioniert nämlich ausschließlich bei hochgefahrener Instanz.
3.8
Block-Change-Tracking-Datei
Neben den Redologs, die grundsätzlich gepflegt werden, sowie den Flashback-Logs, die optional eingeschaltet werden können, gibt es einen weiteren Mechanismus, um Änderungen der Datenbank zu protokollieren. Der Hintergrund beim so genannten Block Change Tracking ist es, inkrementelle Sicherungsstrategien zu erleichtern. Mit dem mitgelieferten Werkzeug RMAN (Recovery Manager) kann eine OracleDatenbank aufbauend auf einem initialen vollständigen Backup jeweils inkrementell gesichert werden, es werden also nur die Änderungen seit dem letzten Backup gesichert (siehe Kapitel 10). Dies funktioniert insbesondere bei Datenbanken mit geringem bis mäßigen Änderungsvolumen sehr gut. Bis Oracle9i musste nichtsdestoweniger zur Erstellung des inkrementellen Backups der gesamte Datenbankinhalt gelesen werden, um alle seit dem letzten Backup geänderten Blöcke zu finden.
Block-Change-Tracking-Datei
137
Mit Oracle 10g ist die Möglichkeit geschaffen worden, alle Blockänderungen von vornherein mitzuprotokollieren. Im Gegensatz zu den Redologs geht es hierbei nicht darum, die geänderten Daten selbst zu protokollieren und im Recovery-Fall nachspielen zu können, sondern es genügt – unabhängig von der Anzahl und Art der Änderungen eines Blocks –, lediglich ein Flag zu pflegen, das anzeigt, dass der Block geändert wurde. Dabei dürfen natürlich auch Einfügungen durch Direct-Loads, die in den Redolog-Dateien u.U. nicht protokolliert werden, für das Backup nicht verloren gehen. Aus diesen Anforderungen heraus erklärt sich, dass ein weiterer, eigenständiger Logging-Mechanismus, nämlich das Block Change Tracking, geschaffen wurde. Die binäre Log-Datei enthält Flags, die für jeden 32 KB-Block der Datenbank anzeigen, ob der Block geändert wurde (die Granularität beträgt unabhängig von den tatsächlichen Oracle-Blockgrößen stets 32 KB). Daher sind der Protokollierungs-Overhead und der Umfang der anfallenden Logging-Daten minimal. Alle Log-Daten einer Datenbank werden in einer einzigen Block-Change-Tracking-Datei abgespeichert, deren Größe ca. 1/30000 der Gesamtgröße aller Datendateien beträgt (je 32 KB Daten werden auf ein Bit abgebildet, außerdem werden bis zu 8 Bitmaps zurückliegender Backups gepflegt), aufgerundet auf volle 10 MB sowie auf 320 KB pro Datendatei. Für Datenbanken bis 300 GB beträgt die Größe dieser Log-Datei also lediglich 10 MB, bis 600 GB Datenbankgröße 20 MB etc. Bei vielen, kleinen Datendateien kann sie wegen der erwähnten Aufrundung etwas größer werden. Bei mehreren Redolog-Threads (in RAC-Umgebungen) ist die so ermittelte Größe noch mit der Anzahl der aktiven Threads zu multiplizieren. Das Block Change Tracking kann im laufenden Betrieb unter Angabe der LoggingDatei eingeschaltet werden: SQL> ALTER DATABASE ENABLE BLOCK CHANGE TRACKING USING FILE '/disk1/verzeichnis/block_changes.chg';
Verwendet man Oracle Managed Files, empfiehlt es sich, die USING-Klausel wegzulassen. Der Zielort für die Block-Change-Tracking-Datei ergibt sich dann aus den Serverparametern db_create_file_dest und db_unique_name, als: //changetracking Abgesehen von der Möglichkeit, die Log-Datei zu verschieben, ist die Verwaltung der Datei ansonsten vollständig automatisiert. Auch die Nutzung der Datei durch RMAN im Rahmen inkrementeller Sicherungen geschieht automatisch. Über die Spalte status der View v$block_change_tracking kann abgefragt werden, ob Block Change Tracking zurzeit aktiviert ist. Die eigentliche Protokollierung wird durch den CTWR-Hintergrundprozess geleistet, der bei Redolog-Schreibvorgängen vom LGWR-Prozess angestoßen wird. Beim inkrementellen Backup liest RMAN nur noch diejenigen Blöcke, die laut Tracking-Datei geändert wurden. Dies kann auch über die Spalte used_change_tracking der View v$backup_datafile nachvollzogen werden. Die Tracking-Datei selbst ist nicht Bestandteil der Sicherung. Achtung: Inkrementelle Backups mit RMAN – mit oder ohne Block Change Tracking – sind nur mit der Enterprise Edition der Oracle 10g-Datenbank möglich! Außerdem sollte Block Change Tracking erst ab dem Patch-Level 10.1.0.3 verwendet werden, da die Funktionalität zuvor durch verschiedene Software-Bugs deutlich eingeschränkt war.
138
3.9
Datenbank-Architektur
Physikalisches Layout
Das physikalische Layout der Datenbank entscheidet sowohl über die Performance der Datenbank als auch über Administrierbarkeit und Übersichtlichkeit. In vielen Fällen wird der Standard verwendet – ein lokales Dateisystem. Unter MS-Windows sind NTFS, unter Unix diverse Derivate wie Reiser-FS unter Linux Beispiele hierfür. Eine grundsätzliche Empfehlung ist, immer Logging-Dateisysteme für den Betrieb von Datenbanken zu wählen, da diese gegenüber Systemabstürzen wesentlich stabiler und nach Systemabstürzen deutlich schneller wieder verfügbar sind. Also: unter MS-Windows »Finger weg von FAT«! Es gibt zwei Gründe, kein lokales Dateisystem zu verwenden: Performance und der Einsatz von RAC. Die Performance-Frage bezieht sich darauf, dass ein Dateisystem grundsätzlich mit einem Cache im RAM arbeitet. Dieser wird zwar von Oracle grundsätzlich nicht genutzt – zumindest alle Schreiboperationen arbeiten mit write through cache –, er muss jedoch trotzdem verwaltet werden und nimmt einen nicht unerheblichen Teil des RAM in Anspruch. Weicht man z.B. auf Raw Devices aus, so entfällt der Dateisystem-Cache komplett, was per se zu einem besseren IO-Durchsatz führt. Der Dateisystem-Cache ist auch der Grund dafür, dass ein lokales Dateisystem nicht für RAC-Konfigurationen verwendet werden kann – es ist nun einmal für einen Rechner lokal und damit in diesem Moment für die anderen nicht nutzbar.4 RAC setzt aber den gleichberechtigten, gleichartigen Zugriff für alle Rechner voraus.
3.9.1 Dateisystem Oracle gibt im Rahmen der so genannten Optimal Flexible Architecture (OFA) bestimmte Empfehlungen hinsichtlich der Speicherung von Datendateien. Diese Empfehlungen haben sich (teilweise in leicht abgewandelter Form) in der Praxis als sehr sinnvoll herausgestellt: Alle Datenbankdateien außer Parameterdatei und Passwortdatei sollten auf einem anderen physikalischen Datenträger gespeichert werden als die OracleSoftware Für Unix: Die Mountpoints für die Datenbankdateien sind von der Form /<mp>, wobei <mp> für einen beliebigen, kurzen String steht und eine laufende Nummer darstellt. Typische Mountpoints sind beispielsweise /u01, /u02 … oder /disk01, /disk02 … Für MS-Windows: Die Mountpoints für die Datenbankdateien sind von der Form X:\oracle, wobei X für einen Laufwerksbuchstaben steht. Typische Mountpoints sind beispielsweise D:\oracle, E:\oracle etc.
4
Die Verwendung von NFS-Filesystemen ist nur in Ausnahmefällen mit spezieller Hardware erlaubt (z.B. Network Applicance oder kurz NetApp).
Physikalisches Layout
139
Unterhalb eines Mountpoints befindet sich ein Verzeichnis oradata und darunter ein Verzeichnis mit dem Datenbanknamen (Serverparameter db_name bzw. db_unique_name für Oracle 10g-Datenbanken). Dies ist das Verzeichnis für die Datenbankdateien, beispielsweise /u01/oradata/PDWH10G für eine Datenbank mit dem Namen PDWH10G. Redolog- und Archivelog-Dateien sollten sich auf einem anderen physikalischen Datenträger als die Datendateien befinden, damit im Fall eines Medienfehlers des Datenträgers mit den Datendateien eine Wiederherstellung mit Hilfe der Log-Dateien möglich ist. Wird die Kontrolldatei gespiegelt, sollten sich die verschiedenen Kontrolldateien auf unterschiedlichen physikalischen Datenträgern befinden, damit im Fall eines Medienfehlers nicht alle Kontrolldateien beschädigt sind. Zwecks besserer Unterscheidbarkeit sollten für Datenbankdateien die folgenden Dateiendungen verwendet werden: – .dbf für Datendateien (auch für System-, SysAux- und Undo-Tablespaces), – .tmp für Temporärdateien (Temporär-Tablespaces) – .log für Online-Redolog-Dateien – .arc für archivierte Redolog-Dateien (einstellbar über den Serverparameter log_archive_format) – .ctl für Kontrolldateien (einstellbar über den Serverparameter control_files) – .bct für Block-Change-Tracing-Dateien (einstellbar bei der Aktivierung des Block Change Trackings) – .flb für Flashback-Logs (werden automatisch erstellt und verwaltet) Daten- und Temporärdateien sollten im Dateinamen den Namen des Tablespaces sowie eine zweistellige fortlaufende Nummer enthalten, z.B. system01.dbf, temp01.tmp etc. Online-Redolog-Dateien sollten das Wort »redo« sowie die Gruppen- und Member-Nummer enthalten, also beispielsweise redo_02_1.log für den ersten Member der zweiten Redolog-Gruppe. Werden ausschließlich Hardware- oder RAIDSpiegelungen benutzt, kann die Member-Nummer auch weggelassen werden. Archivierte Redolog-Dateien sollten den Datenbanknamen (Serverparameter db_name bzw. db_unique_name für Oracle 10g-Datenbanken), die so genannte LogSequence-Number sowie die Nummer des Redolog-Threads enthalten. Dies wird über die Einstellung des Serverparameters log_archive_format erreicht. Für Oracle 10g-Datenbanken sollte außerdem unbedingt die Resetlogs-ID mit angegeben werden, um ein Recovery zu vereinfachen. Empfehlenswert ist hier beispielsweise für eine Datenbank mit dem Namen PDWH10G der Wert: log_archive_format = PDWH10G_%r_%t_%s.arc.
140
Datenbank-Architektur
Oracle Managed Files Seit Oracle9i kann die Verwaltung von Datenbankdateien auf Wunsch auch weitestgehend der Datenbank überlassen werden. Zu diesem Zweck müssen Standardpfade für neue Datenbankdateien konfiguriert werden. Anschließend können bei der Erstellung von Tablespaces, beim Hinzufügen von Daten-, Temporär- oder Redolog-Dateien oder auch bei der Erstellung einer neuen Datenbank die Klauseln, die sich auf Dateinamen und Größen beziehen, einfach weggelassen werden. Zum Beispiel: SQL> SQL> SQL> SQL>
CREATE TABLESPACE users; ALTER TABLESPACE users ADD DATAFILE; ALTER DATABASE ADD LOGFILE GROUP 4; CREATE DATABASE;
Listing 3.11: Listing 3.1: Beispiele für Oracle Managed Files
Für die verschiedenen Arten von Datenbankdateien können unterschiedliche Pfade konfiguriert werden. Dabei spielen folgende Serverparameter eine Rolle: Der Parameter db_create_file_dest gibt ein Basisverzeichnis für Daten- und Temporärdateien an. Die Parameter db_create_online_log_dest_ ( = 1, 2, 3, 4, 5) geben bis zu fünf Basisverzeichnisse für Redolog-Gruppen und Kontrolldateien an. Die angegebenen Pfade sollten auf jeweils unterschiedlichen physikalischen Datenträgern und auf einem anderen Datenträger als db_create_file_dest liegen. Hintergrund ist, dass die einzelnen Member (Spiegel) einer Redolog-Gruppe sowie die Spiegel der Kontrolldatei entsprechend auf die angegebenen Pfade verteilt werden. Der Parameter db_recovery_file_dest ist erst ab Oracle 10g definiert und gibt ein Basisverzeichnis für Flashback-Logs und archivierte Redolog-Dateien an. In Oracle9i werden die entsprechenden Dateien als Oracle Managed Files direkt in den beschriebenen Basisverzeichnissen abgespeichert. In Oracle 10g hat man etwas mehr Ordnung hereingebracht. In dem Basisverzeichnis wird zunächst ein Unterverzeichnis mit dem Datenbanknamen angelegt (Serverparameter db_unique_name), hierin wird ein weiteres Unterverzeichnis gemäß dem Dateityp (z.B. onlinelog für die Online-Redolog-Dateien) angelegt. Der letzte Schritt entspricht zwar formal nicht den OFA-Regeln, bringt aber jedenfalls noch etwas mehr Übersichtlichkeit. Abbildung 3.6 zeigt noch einmal zusammenfassend die Speicherung von Datenbankdateien als Oracle Managed Files in Oracle 10g. Der grau unterlegte Bereich gilt für Oracle9i.
Physikalisches Layout
141
Abbildung 3.6: Speicherorte und Dateiendungen für Oracle –Managed Files
Neben den beschriebenen Standardpfaden ist auch die Namensgebung für Oracle – Managed Files festgelegt. Diese Dateien haben stets Namen der Form o1_mf__.<endung>. Dabei steht <endung> für eine der aufgeführten Dateiendungen, ist eine Zeichenkette, die einerseits eine eindeutige Beziehung zu dem zugrunde liegenden Objekt schaffen, andererseits den Dateinamen auch eindeutig machen soll. Für Datendateien ist beispielsweise von der Form _, wobei der auf acht Zeichen abgeschnittene Name des Tablespaces und eine eindeutige achtstellige Zeichenkombination darstellt. z.B.: SQL> CREATE TABLESPACE daten_big; SQL> SELECT file_name FROM dba_data_files WHERE tablespace_name = 'DATEN_BIG'; FILE_NAME -----------------------------------------------------------D:\ORACLE\ORADATA\PS10\DATAFILE\O1_MF_DATEN_BI_1GBKDX9R_.DBF
142
Datenbank-Architektur
Nach der Erstellung können OMF wie andere Dateien auch behandelt werden, insbesondere können sie umbenannt und verschoben werden. Für den Status als OMF ist nicht der Pfad, sondern ausschließlich der Dateiname relevant. Jede Datei mit einem Dateinamen der Form o1_mf_*_.<endung> wird von Oracle als OMF identifiziert. Das explizite Anlegen einer solchen Datei z.B. als Datendatei oder RedologDatei ist nicht erlaubt und wird mit einer Fehlermeldung quittiert, z.B.: SQL> CREATE TABLESPACE daten_big DATAFILE 'D:\ORACLE\ORADATA\PS10\O1_MF_DATEN_BI_1GBKDX9R_.DBF'; CREATE TABLESPACE daten_big * FEHLER in Zeile 1: ORA-01276: Datei D:\ORACLE\ORADATA\PS10\O1_MF_DATEN_BI_1GBKDX9R_.DBF kann nicht hinzugefügt werden. Datei hat Name von Oracle Managed Files.
Ein nachträgliches Umbenennen einer Datendatei in eine OMF-Datei und auch ein nachträgliches Verschieben einer OMF-Datei in ein anderes Verzeichnis ist jedoch möglich, z.B.: SQL> ALTER TABLESPACE daten_big OFFLINE; Tablespace wurde geändert. SQL> -- Verschieben der Datendatei auf Betriebssystemebene SQL> ALTER DATABASE RENAME FILE 'D:\ORACLE\ORADATA\PS10\DATAFILE\O1_MF_DATEN_BI_1GBLCKON_.DBF' TO 'D:\ORACLE\ORADATA\PS10\O1_MF_DATEN_BI_1GBLCKON_.DBF';
Letztlich ist jedoch die entscheidende Frage, worin die Vorteile von Oracle Managed Files besteht und wie man diese Funktionalität am besten einsetzen sollte. OMF vereinfachen die Erstellung und Erweiterung von Tablespaces und Redolog-Gruppen. Setzt man dies konsequent ein, werden sämtliche Datenbankdateien außer Parameter- und Passwortdatei automatisch erzeugt und benannt. Dies ist vor allem für Test- und Entwicklungsumgebungen ein Vorteil. In produktiven Umgebungen ist die automatische Erstellung von Daten- und Temporärdateien nur sinnvoll, wenn es einen einzigen Mountpoint gibt, der über die darunter liegende Hardware eine I/O-Parallelisierung durchführt. Liegen dagegen mehrere Mountpoints vor bzw. wird die I/O-Verteilung eher manuell durch geschicktes Verteilen der Tablespaces über die Mountpoints durchgeführt, kommen OMF dafür nicht in Frage. Das versehentliche Erstellen einer Datendatei in einem nicht dafür vorgesehenen Verzeichnis ist ausgeschlossen. Beim Löschen eines Tablespaces oder einer Redolog-Gruppe werden die zugehörigen Dateien auf Betriebssystemebene automatisch gelöscht. Das versehentliche Löschen einer falschen Datei ist dadurch ausgeschlossen. Für Daten- und Temporärdateien gibt es diese Möglichkeit allerdings bereits durch die Klausel INCLUDING CONTENTS AND DATAFILES des DROP TABLESPACE-Kommandos. Außerdem kommt das Löschen eines Tablespaces im produktiven Betrieb nicht häufig vor, wohl aber in Test- oder Entwicklungsumgebungen.
Physikalisches Layout
143
SQL-Skripte, die Tablespace-Definitionen enthalten, können plattformunabhängig geschrieben werden. Lediglich die genannten Serverparameter müssen zuvor plattformabhängig gesetzt werden. Sie verhindern häufig fruchtlose Diskussionen über geeignete Namensgebungen für Datenbankdateien. Zusammenfassend lässt sich sagen, dass OMF für Test- und Entwicklungsumgebungen eine gute Wahl darstellen sowie für Produktionsumgebungen, die über ein leistungsfähiges SAN-Storage verfügen, das dem DBA Fragen bzgl. I/O-Verteilung abnimmt. Ggf. sollte trotzdem eine SIZE-Klausel mit angegeben werden (Standardgröße für Daten-, Temporär- und Redolog-Dateien ist 100MB), auf jeden Fall sollte im Rahmen der AUTOEXTEND-Klausel eine Maximalgröße gesetzt werden, da OMF sonst mit unbegrenztem Wachstum erstellt werden. Für Oracle9i muss unbedingt auch die Erweiterungsgröße (NEXT-Klausel) vom Standardwert (ein Block bei Oracle9i, 100 MB bei Oracle 10g) auf einen sinnvollen Wert geändert werden, also z.B.: SQL> CREATE TABLESPACE users DATAFILE SIZE 1000M AUTOEXTEND ON NEXT 100M MAXSIZE 5000M; SQL> ALTER TABLESPACE users ADD DATAFILE SIZE 1000M AUTOEXTEND ON NEXT 100M MAXSIZE 5000M;
3.9.2 Cluster-Dateisystem Cluster-Dateisysteme werden meist vom Systemhersteller als Zusatzoption für Cluster-Systeme angeboten; für Linux existiert das Projekt Oracle Cluster File System im Rahmen des Oracle Technology Networks, das unter GNU General Public License (GPL) veröffentlicht wird. Cluster-Dateisysteme werden wie lokale Dateisysteme in den Verzeichnisbaum integriert, mit dem Unterschied, dass dies auf mehreren Rechnern gleichzeitig passieren kann. Damit können sie für RAC-Konfigurationen verwendet werden. Dadurch dass bei Cluster-Dateisystemen im Normalfall wiederum DateisystemCaches vorhanden sind, sind sie in den meisten Fällen langsamer als Raw Devices; allerdings sind die Vorzüge bei der Administrierbarkeit nicht zu unterschätzen. Bei einigen Cluster-Dateisystemen ist es möglich, die Installation der Oracle Software im Cluster-Dateisystem durchzuführen. Damit wird der Installationsaufwand minimiert, z.B. auch für neue Knoten, die ins Cluster integriert werden sollen, allerdings zum Preis einer weniger flexiblen Konfiguration. Für Umgebungen mit Forderungen für absolut kleine Auszeiten bei Wartungsarbeiten ist eine lokale Installation auf jedem einzelnen Knoten vorzuziehen. Dieses Konzept wird vom Univeral Installer ebenfalls komfortabel unterstützt. Ansonsten ist über Cluster-Dateisysteme wenig Allgemeines zu sagen – dazu sind die einzelnen Lösungen zu systemspezifisch.
144
Datenbank-Architektur
3.9.3 Raw Devices Raw Devices sind eine Spezialität von Unix-Systemen und seit langer Zeit die Alternative zu Dateisystemen. Übrigens bieten viele Systeme mittlerweile einen Logical Volume-Manager an, der wesentlich mehr Komfort für Raw Devices bietet als das reine Betriebssystem. Mit einem Logical Volume-Manager lassen sich Logical Volumes erzeugen, für die praktisch alle Aussagen über Raw Devices ebenfalls zutreffen. Bei einem normalen Filesystem, wie es unter Unix und Linux in diversen Versionen zur Verfügung steht, wird ein physikalischer Plattenbereich, ein so genanntes Device, entsprechend formatiert, z.B. mit dem Befehl newfs. Dieses Filesystem wird dann als Mountpoint angeschlossen und kann jetzt von jedem, der die Berechtigung dazu hat, mit Dateien gefüllt werden. Ein Buffercache im Memory sorgt dafür, dass die wichtigsten Daten sowie die Dateisystemstruktur immer im Hauptspeicher bleiben und somit eine optimale Performance gewährleistet ist. Wenn man sich die Oracle-Datenbankstruktur ansieht, stellt man fest, dass Oracle genauso funktioniert: Mit dem Befehl CREATE TABLESPACE … DATAFILE … wird ein entsprechender Bereich formatiert (in Oracle-Blöcken), und über die SGA wird ein Buffercache im Memory zur Verfügung gestellt. Also stellt sich die Frage: Wofür braucht man noch ein Filesystem? Ganz im Gegenteil, bei Schreiboperationen muss verhindert werden, dass die Daten im Betriebssystemcache hängen bleiben. Somit ist dieser für Oracle fast wertlos. Also ist es unter Umständen sinnvoller, die Oracle-Datendateien direkt auf die Raw Devices zu platzieren und damit den Overhead des Betriebssystems zu eliminieren. Das wird jedoch mit einer Einschränkung in der Flexibilität erkauft. Raw Devices haben eine bestimmte Größe, die, wenn überhaupt, nur mit Betriebssystemkommandos geändert werden kann. Je Raw Device kann außerdem nur genau eine Oracle-Datei benutzt werden, so dass von vornherein klar sein muss, wie groß die Dateien werden. Ein AUTOEXTEND der Datendatei ist also nicht möglich. Außerdem ist dem Betriebssystem oft nicht bekannt, dass die Dateien in Benutzung sind, somit kann jederzeit mit dem Befehl newfs ein Filesystem auf das Raw Device angelegt und damit die Datenbank zerstört werden. An dieser Stelle empfehlen sich Logical Volumes, deren Namen man bei der Erstellung bestimmen kann. Hier sollte man für Oracle Logical Volumes Standards wie lora__xxx benutzen. Ein weiterer gerne genutzter Trick ist, die Raw Devices nicht direkt als Datenbankdateien zu verwenden, sondern ein Verzeichnis zu erstellen, das symbolische Links auf die Raw Devices enthält. Die Namen der symbolischen Links können dann wieder sprechend bezüglich ihrer Bedeutung in der Datenbank sein. Die symbolischen Links (inklusive des vollständigen Pfads) werden dann als Namen für die Datenbankdateien verwendet. Mit einem Listing des Verzeichnisses hat der Administrator nun eine einfache Möglichkeit, die verwendeten Raw Devices abzufragen. Obwohl Raw Devices grundsätzlich schnellere IOs erlauben als Dateisysteme, sollten sie nicht ohne Vorüberlegungen eingesetzt werden. Die Administration einer Oracle-Datenbank mit Raw Devices ist um einiges komplexer als bei der Verwendung von normalen Dateien. Weiterhin werden die Vorteile im IO-Bereich oft gar nicht bemerkt, da z.B. alle DBW0-IOs asynchron zu den SQL-Befehlen im Hintergrund laufen. Solange das IO-System nicht überlastet ist, sind bei den Anwendungen keine verbesserten Antwortzeiten messbar. Den größten messbaren Vorteil
Physikalisches Layout
145
erzielt man oft bei der Verwendung von Raw Devices für Redolog-Member bei Systemen mit hoher Transaktionslast, da COMMIT-Befehle synchron mit IOs des LGWRProzesses laufen.
3.9.4 Automatic Storage Management (ASM) Mit Oracle 10g führt Oracle ein eigenes Filesystem (ASM, Automatic Storage Management) ein, das unabhängig vom Betriebssystem (z.Z. Unix und MS-Windows) die optimale Implementierung für den Betrieb von Oracle-Datenbanken darstellen soll. Neben der Möglichkeit der Mehrfachspiegelung werden die Filesysteme über alle verfügbaren Devices gestriped und entsprechen damit der von Oracle seit längerem vertretenen These S.A.M.E (Stripe and Mirror Everything). Ein paar Worte zur Historie: Oracle hat sich im Umfeld Oracle Parallel Server und Real Application Clusters in der Vergangenheit schwer getan, die Storages zu verwalten. Zunächst wurden nur Raw Devices unterstützt, was dazu führte, dass nur mit fest vorgegebenen Dateigrößen gearbeitet werden konnte. Mit Version 8i wurde dann auf einigen Plattformen (z.B. AIX) das von den Betriebssytemherstellern entwickelte Global File System unterstützt. Leider war hier das Problem »auf einigen Plattformen«. Mit Version 9i hat Oracle dann das Oracle Cluster File System (OCFS), also eine eigene Implementierung des Global File Systems eingeführt. Dieses ist betriebssystemunabhängig und kann als separates Produkt eingesetzt werden, die Verzeichnisse sind aber z.B. unter MS-Windows als normale Dateisysteme zu erkennen, und somit besteht die Gefahr – wie wir sie schon erlebt haben – , dass diese Verzeichnisse durch Unachtsamkeit zerstört und damit die Datenbank korrumpiert wird. Außerdem steht OCFS nur für den Betrieb von Real Application Clusters zur Verfügung. Mit Version 10g wird jetzt mit ASM ein unabhängiges Produkt geschaffen, das für alle Oracle-Datenbanken zur Verfügung steht und für das Betriebssystem unsichtbar ist. Funktionalität ASM besteht aus einer eigenen Instanz, in der die Disk-Devices verwaltet werden. Eine Oracle-Datenbank nimmt über den ebenfalls in Oracle 10g neu eingeführten Oracle Cluster Synchronization Service (OCSS) eine Verbindung zur ASM-Instanz auf und erhält über diesen die entsprechenden Ressourcen, die vorher eingerichtet worden sind. Intern werden diese Ressourcen wie bei einem normalen Filesystem in Verzeichnissen verwaltet. Dabei werden die Devices speziell formatiert und stehen somit dem Betriebssystem nicht mehr zur Verfügung. Die Gefahr einer unbedachten Formatierung ist dadurch minimiert. Da es sich hierbei um eine interne Kommunikation handelt, muss unter MS-Windows der Parameter SQLNET.AUTHENTICATION_ SERVICES= (NTS) in der Datei sqlnet.ora gesetzt sein. Das Zusammenspiel von Datenbank- und ASM-Instanz über den OCSS-Daemon hat den Nachteil, wenn die ASM-Instanz oder der OCSSD Prozess abstürzt, werden die beteiligten Datenbanken ebenfalls beendet. Die ASM-Instanz wird standardmäßig über die ORACLE_SID »+ASM« angegeben. Folgende Parameter sind dabei notwendig:
146
Datenbank-Architektur
instance_type
='ASM'
asm_diskgroups
='ORA_ASM'
Nähere Informationen zu den Instanzparametern erhalten Sie im Kapitel 4.4. Aufbauen einer Oracle-Datenbank mit ASM Um eine ASM-Instanz aufzubauen, werden unformatierte Devices benötigt. Wenn ein Unix- bzw. Linux-Betriebssystem verwendet wird, reicht es, wenn die Devices dem Oracle-Benutzer und der Gruppe gehören. Außerdem darf hier der erste Block der physikalischen Platte nicht genutzt werden. Zum Löschen der ASM-Informationen müssen die ersten Blöcke jeder Partition überschrieben werden, dies geschieht z.B. mit dem Befehl: dd if=/dev/zero of=/dev/rdsk/c3t0d0s4 bs=8192 count=100 Listing 3.12: Löschen der ASM-Informationen unter Unix
Unter Windows müssen die Partitionen vorhanden, dürfen jedoch nicht mit Betriebssystemmitteln formatiert worden sein. Bevor sie als Diskgruppen benutzt werden können, müssen sie mit dem Werkzeug asmtool (Kommandozeile) oder asmtoolg (grafische Oberfläche) vorformatiert (stamp) werden. Diese Partitionen stehen jetzt für das Betriebssystem nicht mehr zur Verfügung. Um sie wieder »normal« nutzbar zu machen, müssen Sie wiederum das ASM-Tool aufrufen und die Stempel löschen. Das folgende Bild zeigt das Tools asmtoolg mit der Anzeige der möglichen Partitionen und deren Größe.
Abbildung 3.7: asmtoolg
Sobald die Partitionen für ASM genutzt werden, haben sie zusätzlich einen ASM Link Name, der sich aus »ORCLDISK«, dem Präfix und einer eindeutigen Nummer zusammensetzt.
Physikalisches Layout
147
Abbildung 3.8: ASM Link Name
Bei der Verwendung des Database Configuration Assistants (DBCA) für die Erstellung einer Datenbank können Sie Automatic Storage Management als Speicheroption auswählen.
Abbildung 3.9: ASM-Installation über DBCA
Sollte es hier noch keine entsprechende ASM-Instanz geben, wird diese jetzt automatisch angelegt und hochgefahren, dafür können Sie in einem weiteren Schritt das SYS-Passwort und die Serverparameter angeben. Als Nächstes können dann die Diskgruppen angelegt bzw. verwaltet werden.
148
Datenbank-Architektur
Abbildung 3.10: Erstellen einer Diskgruppe
Folgende Parameter müssen angegeben werden: Name der Diskgruppe (hier ora_asm) Redundanz, hier sind folgende Optionen möglich: – Hoch: dreifache Spiegelung – Normal: einfache Spiegelung – Extern: keine Spiegelung Die möglichen Devices (Kandidaten). Dabei sollt ein Vielfaches der gewählten Redundanz an Devices zur Verfügung stehen, da ASM sonnst auf der gleichen Platte spiegelt (es ist theoretisch möglich, eine dreifache Spiegelung mit nur einer Diskgruppe durchzuführen). Eine Größe für Striping kann an dieser Stelle nicht angegeben werden, es gibt für die Verwendung von ASM nur zwei Größen: FINE mit 128 KB und COARSE mit 1 MB. Wenn an dieser Stelle die Devices nicht angezeigt werden, kann das unterschiedliche Gründe haben, einige davon sind: Unter MS-Windows wurden die Devices nicht mit dem asmtool vorformatiert. Unter Unix stimmen die Berechtigungen (Oracle-Benutzer und -Gruppe) nicht. Der Pfad, unter dem die Devices gesucht werden sollen (Serverparameter asm_disk_string), ist gesetzt, zeigt aber auf einen anderen Bereich).
Physikalisches Layout
149
Sind alle Eingaben korrekt, wird als Nächstes die Diskgruppe angelegt, und im DBCA werden die verfügbaren Diskgruppen angezeigt.
Abbildung 3.11: Konfigurierte Diskgruppe
Unschönerweise sind die Größen (Größe und Frei) nicht entsprechend der Redundanz, sondern als Summe der verfügbaren Devices angegeben; in diesem Fall also ca. 70 GB anstelle der tatsächlich zur Verfügung stehenden 35 GB. Als Speicherort für die Datendateien werden jetzt Oracle Managed Files mit dem Namen der ASM-Instanz angeboten (+ORA_ASM). Die weitere Vorgehensweise für die Konfiguration der Datenbank entspricht der für Oracle Managed Files. ASM-Layout Bei einer Standardinstallation werden alle Komponenten der Datenbank im ASMFilesystem abgelegt. Dazu gehören: Datendateien Kontrolldateien Online-Redolog-Dateien Temporäre Dateien Parameterdateien Flashback-Logs Backup-Sets Archivierte Redolog-Dateien
150
Datenbank-Architektur
Diese werden in den zugehörigen Unterverzeichnissen, die automatisch angelegt werden, abgespeichert. Die gesamte Speicherung erfolgt als Oracle Managed Files (OMF), kann aber zusätzlich mit eigenen Namen und Verzeichnissen erweitert werden. Wenn keine speziellen Einstellungen über Templates vorgenommen werden, sind die Kontroll- und Online-Redolog-Dateien mit 128 KB Stripegröße (Fine) eingestellt, alle anderen Bereiche mit 1 MB (Coarse). Eine fertige mit ASM-verwaltete Datenbank sieht also z.B. wie folgt aus: SQL> SELECT tablespace_name, file_name, bytes/1024/1024 MByte FROM dba_data_files; TABLESPACE_NAME FILE_NAME MB ---------------- ---------------------------------------- ------SYSTEM +ORAASM1/sunasm/datafile/system.264.1 300 UNDOTBS1 +ORAASM1/sunasm/datafile/undotbs1.265.1 500 SYSAUX +ORAASM1/sunasm/datafile/sysaux.266.1 230 USERS +ORAASM1/sunasm/datafile/users.268.1 5 DEMO +ORAASM1/sunasm/datafile/demo.270.1 1000 SQL> SELECT name FROM v$controlfile; NAME --------------------------------------------+ORAASM1/sunasm/controlfile/current.256.1 +ORAASM1/sunasm/controlfile/current.257.1 Listing 3.13: Mit ASM verwaltete Datenbank
Diese Information kommt wie üblich aus der Datenbank (in diesem Beispiel heißt diese SUNASM. Um die gleichen Daten auch in der ASM-Instanz darstellen zu können, bedarf es eines etwas umfangreicheren SQL-Befehls: SELECT '+'||dg.name||'/'||sid.name||'/'||typ.name||'/'||datei.name Filename, round(info.bytes/1024/1024) MByte FROM v$asm_diskgroup dg, v$asm_alias sid, v$asm_alias typ, v$asm_alias datei, v$asm_file info WHERE sid.group_number = dg.group_number AND typ.group_number = dg.group_number AND datei.group_number = dg.group_number AND sid.reference_index = typ.parent_index AND typ.reference_index = datei.parent_index AND datei.file_number = info.file_number;
Physikalisches Layout
151
FILENAME MBYTE ----------------------------------------------------------- ----+ORA_ASM1/SUNASM/CONTROLFILE/Current.256.565036357 2 +ORA_ASM1/SUNASM/ONLINELOG/group_1.258.565036359 20 +ORA_ASM1/SUNASM/ONLINELOG/group_2.259.565036359 20 +ORA_ASM1/SUNASM/ONLINELOG/group_3.260.565036361 20 +ORA_ASM1/SUNASM/ONLINELOG/group_4.261.565036363 20 +ORA_ASM1/SUNASM/DATAFILE/SYSTEM.262.565036365 210 +ORA_ASM1/SUNASM/DATAFILE/INDX.268.565036827 100 +ORA_ASM1/SUNASM/DATAFILE/UTILS.267.565036827 10 +ORA_ASM1/SUNASM/DATAFILE/TSUNDO.263.565036381 100 +ORA_ASM1/SUNASM/DATAFILE/SYSAUX.264.565036385 200 +ORA_ASM1/SUNASM/DATAFILE/DATA.266.565036397 100 +ORA_ASM1/SUNASM/TEMPFILE/TEMP.265.565036397 50 +ORA_ASM/SUNASM/PARAMETERFILE/spfile.269.565036399 0 +ORA_ASM/SUNASM/FLASHBACK/log_1.270.565036406 8 +ORA_ASM/ARCHIVELOG/2004_06_23/thread_1_seq_50.271.565036415 9 +ORA_ASM/ARCHIVELOG/2004_06_23/thread_1_seq_51.272.565036416 0 Listing 3.14: Datenbankdateien aus ASM-Sicht
Manuelle ASM-Konfiguration Natürlich kann eine ASM-Instanz auch manuell aufgesetzt werden. Dafür muss zunächst, ähnlich wie beim Anlegen einer Datenbank, eine leere Instanz hochgefahren und anschließend müssen die Diskgruppen erzeugt werden. Als Beispiel wird folgende Initialisierungsdatei mit dem Namen init+ASM.ora im $ORACLE_HOME/dbs Verzeichnis erstellt. *.instance_type ='ASM' *.asm_diskgroups ='ORA_ASM' *.background_dump_dest ='/oracle/admin/+ASM/bdump' *.core_dump_dest ='/oracle/admin/+ASM/cdump' *.large_pool_size =12M *.remote_login_passwordfile ='EXCLUSIVE' *.user_dump_dest = '/oracle/admin/+ASM/udump' Listing 3.15: Initialisierungsdatei der ASM-Instanz
Als Nächstes wird die Datenbank gestartet: % set ORACLE_SID=+ASM % sqlplus / as sysdba SQL> startup Listing 3.16: Starten der ASM-Instanz
Jetzt können die Diskgruppen mit dem Befehl CREATE DISKGROUP angelegt werden. SQL> CREATE DISKGROUP ora_asm NORMAL DISK '\\.\ORCLDISKDATA1', '\\.\ORCLDISKDATA2'; Listing 3.17: Anlegen einer Diskgruppe
152
Datenbank-Architektur
Neben dem Befehl CREATE DISKGROUP gibt es nur noch die Befehle ALTER DISKGROUP und DROP DISKGROUP; insofern eine überschaubare Anzahl von Befehlen für die Verwaltung von ASM-Instanzen. Dennoch ist die Verwendung des DBCA der manuellen Erstellung vorzuziehen, da dort alle verfügbaren Devices mit der entsprechenden Größe automatisch angezeigt werden. Verwalten von Tablespaces bzw. Datendateien über ASM Die Verwaltung von Tablespaces über ASM entspricht der von Oracle Managed Files. Das bedeutet, Sie geben in der Regel keinen Dateinamen an, wenn Sie den Tablespace anlegen. Beim Löschen desselben werden dann die zugehörigen Datendateien automatisch gelöscht. SQL> CREATE TABLESPACE blub DATAFILE SIZE 100M; Listing 3.18: Anlegen eines Tablespaces SQL>DROP TABLESPACE blub; Listing 3.19: Löschen des Tablespaces
Wenn Sie jedoch explizit einen Namen für die Datendatei angeben, werden in der ASM-Instanz zwei Einträge generiert, der eine mit der ASM-eigenen Namensgebung und ein zweiter Eintrag (wie ein Link) mit Ihrem gewählten Namen. Beim Löschen des Tablespaces müssen Sie nachfolgend beide Einträge für die Datendateien mit dem Befehl ALTER DISKGROUP separat löschen. Das folgende Beispiel verdeutlicht dies: SQL> CREATE TABLESPACE blub DATAFILE '+ORA_ASM/SUNASM/DATAFILE/blub01.dbf' SIZE 100M; SQL> DROP TABLESPACE blub; SQL> ALTER DISKGROUP ora_asm DROP FILE '+ORA_ASM/SUNASM/DATAFILE/blub01.dbf'; SQL> ALTER DISKGROUP ora_asm DROP FILE '+ORA_ASM/SUNASM/DATAFILE/blub01.dbf' SQL> ALTER DISKGROUP ora_asm DROP FILE '+ORA_ASM/SUNASM/DATAFILE/BLUB.288.565038087' Listing 3.20: Manuelles Anlegen und Löschen eines Tablespaces
Über den Bereich ADMINISTRATION und SPEICHERUNG kann im Enterprise Manager der Menüpunkt PLATTENGRUPPEN ausgewählt werden, mit dem man sich an einer ASM-Instanz anmelden kann. Hier kann man sich dann z.B. die Konfiguration und Platzbelegung sowie Performance-Informationen ansehen.
Ältere Funktionen
153
Abbildung 3.12: ASM-Darstellung im Oracle Enterprise Manager
Allerdings sollten Sie auch hier bei der Angabe der Größen bedenken, dass die Redundanz nicht berücksichtigt ist, der maximal verfügbare Platz also im obigen Fall nicht 20 GB, sondern nur 10 GB beträgt.
3.10
Ältere Funktionen
3.10.1 Dictionary-Managed Tablespaces In den Datenbankversionen bis einschließlich Oracle 8.0 wurden alle Informationen zu Datenbankobjekten – insbesondere auch für die Verwaltung der Tablespaces – im Data Dictionary gespeichert. Das bedeutet, dass eine Erweiterung von Tabellen oder Indizes um neue Extents oder die Freigabe von Extents mit dem Befehl TRUNCATE zusätzliche rekursive Operationen im Kontext des Data Dictionarys durchführen. Die entsprechenden Änderungen in der Extent-Verwaltung erzeugen damit zusätzliche Rollback- und Redolog-Information. Aus diesem Grund kann die Data-Dictionary-Verwaltung bei umfangreichen Operationen wie zum Beispiel dem Laden großer Tabellen oder der Erstellung von Indizes zu einem Performance-Engpass führen. Mit Oracle Version 7.3 konnte der Temporär-Tablespace aus dieser Verwaltung herausgetrennt werden, wodurch sich Sortierungen und auch die generelle Verwaltung beschleunigen ließen. Mit der Version 8.1 wurde dieser Schritt durch die Einführung von Locally-Managed-Tablespaces konsequent weitergeführt, um mit der Version 9 dann die Möglichkeit zu schaffen, Tablespaces auf unterschiedliche Anforderungen (freie Definition der Oracle-Blockgröße pro Tablespace) anzupassen. Die Tablespaces des alten Typs sollten spätestens mit der Version Oracle 10g nicht mehr benutzt werden. Eine Migration bestehender DM-Tablespaces erfordert zunächst eine Abschätzung darüber, ob die Migration online, d.h. im laufenden Betrieb, durchgeführt werden muss oder ob eine hinreichend lange Auszeit möglich ist.
154
Datenbank-Architektur
Ist eine entsprechende Auszeit möglich, kann innerhalb der bestehenden Datenbank ein neuer LM-Tablespace angelegt werden, in den über Kommandos der Form ALTER TABLE … MOVE TABLESPACE newts die Tabellen dieses Tablespaces verschoben werden. Indizes können einfach in einem neuen LM-Tablespace neu aufgebaut werden; dies geht sogar im laufenden Betrieb über den Befehl ALTER INDEX … REBUILD TABLESPACE newts ONLINE. Ist keine entsprechende Auszeit möglich, kann auch mit den in Oracle und von Drittherstellern zur Verfügung stehenden Reorganisationsmethoden (z.B. dbms_redefinition) gearbeitet werden. Hierbei werden die Tabellen im laufenden Betrieb reorganisiert. Je nachdem, ob nur ein Tablespace oder die gesamte Datenbank betroffen ist, muss alternativ darüber nachgedacht werden, eine neue Datenbank aufzubauen und diese aus der aktuellen Datenbank zu füllen. Um die Zeitdauer hierbei zu minimieren, gibt es Software, wie z.B. SharePlex von der Firma Quest Software, die hierbei unterstützen kann. Das in der Datenbank enthaltene Package dbms_space_admin bietet im Rahmen der Prozedur tablespace_migrate_to_local scheinbar eine weitere einfache Möglichkeit, einen DM-Tablespace direkt in einen LM-Tablespace zu migrieren. Der Tablespace wird dabei lediglich umetikettiert, und die Extent-Bitmap wird hinzugefügt. Die Migration ist im laufenden Betrieb möglich, lediglich umfangreiche Lade-Operationen, die zur Reservierung neuer Extents führen, werden blockiert. Dennoch ist diese Variante in den meisten Fällen nicht praxistauglich, da sie nur eine Umwandlung in einen LM-Tablespace mit einheitlicher Extent-Größe (UNIFORM SIZE) zulässt, wobei als Extent-Größe der größte gemeinsame Teiler aller im DM-Tablespace vorhandenen Extent-Größen genommen wird. Dies liegt meistens sehr nahe an der Oracle-Blockgröße und ist somit viel zu klein. Nur für den Fall, dass der DM-Tablespace mit einer MINIMUM SIZE-Storage-Option konfiguriert war, kann die Migration zu einem guten Ergebnis kommen.
3.10.2 Rollback-Segmente Bis Oracle8i musste die Undo-Verwaltung auf manuellem Wege durchgeführt werden. Bei Erstellung der Datenbank oder unmittelbar danach wurde eine Anzahl Rollback-Segmente erzeugt. Diese manuell erzeugten Rollback-Segmente sind von den automatisch erzeugten Undo-Segmenten (siehe Kapitel 3.3.5) zu unterscheiden. Die manuelle Erstellung geschieht durch Kommandos der Form: SQL> CREATE ROLLBACK SEGMENT r01 TABLESPACE rbs;
Der Tablespace rbs ist dabei ein ganz normaler Tablespace. Wesentliche Nachteile dieser Art der Undo-Verwaltung sind: Das Anlegen, die Bestimmung einer geeigneten Größe sowie das Löschen von Rollback-Segmenten muss manuell durch den DBA geschehen Insbesondere muss ein geeigneter Wert für den so genannten OPTIMAL-Parameter gefunden werden.
Ältere Funktionen
155
Um Fehlermeldungen der Art ORA-01555 (Snapshot too old) möglichst zu unterdrücken, müssen Anzahl, Größe und OPTIMAL-Parameter der Rollback-Segmente sorgfältig austariert werden. Eine Transaktion kann sich nicht über mehrere Rollback-Segmente erstrecken. Für sehr umfangreiche Transaktionen im Rahmen von Batch-Verarbeitungen muss ein dediziertes Rollback-Segment angelegt und in den Skripten kodiert werden. Die ab Oracle9i eingeführten Flashback-Funktionen sind mit Rollback-Segmenten nicht nutzbar. Es ist daher sehr zu empfehlen, ab Oracle9i die automatische Undo-Verwaltung zu benutzen. Die Migration von manueller zu automatischer Undo-Verwaltung ist relativ einfach. Eine kurze Auszeit wird benötigt, da die Datenbank einmal durchgestartet werden muss. Folgendes Verfahren kann dafür genutzt werden (dabei wird davon ausgegangen, dass eine Serverparameterdatei benutzt wird; andernfalls müssen die Serverparameter durch Editieren der Parameterdatei geändert werden): Zunächst sollte ein Undo-Tablespace angelegt werden, z.B.: SQL> CREATE UNDO TABLESPACE undotbs DATAFILE '…' SIZE 1000M AUTOEXTEND ON NEXT 100M MAXSIZE 5000M;
Für den nächsten Neustart der Instanz wird die automatische Undo-Verwaltung eingestellt. Der Parameter undo_retention gibt die Zeit in Sekunden an, für die Undo-Informationen aufbewahrt werden sollen, um Lesekonsistenz für Abfragen zu gewährleisten. Der Parameter undo_tablespace enthält den Namen des soeben erstellten Tablespaces. Mit undo_management wird jetzt auf die automatische Undo-Verwaltung umgeschaltet. SQL> SQL> SQL> SQL> SQL>
ALTER SYSTEM SET ALTER SYSTEM SET ALTER SYSTEM SET -- den folgenden ALTER SYSTEM SET
undo_management=AUTO SCOPE=SPFILE; undo_tablespace=undotbs SCOPE=SPFILE; undo_retention=1800 SCOPE=SPFILE; Befehl nur unter Oracle9i undo_suppress_errors=TRUE SCOPE=SPFILE;
Nach dem nächsten Neustart der Instanz arbeitet die Datenbank mit automatischer Undo-Verwaltung. Der ursprüngliche Rollback Tablespace kann jetzt gelöscht werden. Außerdem sollten Sie jetzt auf jeden Fall ein Backup Ihrer Datenbank und der Parameterdatei durchführen.
Instanz-Verwaltung Die zentralen Befehle für die Instanz-Verwaltung sollen in diesem Abschnitt vorgestellt werden. Hierzu zählen sicherlich STARTUP und SHUTDOWN mit den entsprechenden Parametern, um ein Oracle-System zu starten und zu stoppen. Dazu müssen aber die passenden Werkzeuge unter bestimmten Voraussetzungen verwendet werden, die hier auch kurz dargestellt werden. Die Instanz-Verwaltung wird sich zudem auch immer auf die Datenbank beziehen, die mit einer Instanz gemountet oder geöffnet ist. Daher ist in diesem Abschnitt auch das ALTER-DATABASE-Kommando mit zwei Optionen zu finden. Um Parametrierungen der Instanz zu ändern, an die Instanz angemeldete Prozesse zu verwalten, Zugriffe zu sperren oder freizugeben und den Wechsel des Red-Log zu initiieren, steht das ALTER-SYSTEM-Kommando zur Verfügung. Bestimmte Teilbereiche der Instanz können im laufenden Betrieb manuell oder auch automatisch neu skaliert werden, um auf unterschiedliche Lastprofilen im Tagesverlauf abzustellen. Diese Technik wird ebenfalls vorgestellt. Abschließend werden noch Checkpoints behandelt.
4.1
Werkzeuge und Voraussetzungen
Das bekannteste Werkzeug zur Administration eines Oracle-Systems ist wohl SQL*Plus. Der früher ebenfalls verwendete Server-Manager wird bereits seit der Version Oracle9i nicht mehr mit ausgeliefert und wird daher an dieser Stelle nicht behandelt. Voraussetzung für eine Reihe von Administrationskommandos wie STARTUP, SHUTDOWN, ARCHIVE usw. ist die privilegierte Anmeldung mit CONNECT / (username/password) AS SYSDBA (SYSOPER). In vielen Skripten wird auch noch CONNECT INTERNAL zu finden sein, was nur noch aus Kompatibilitätsgründen unterstützt wird, aber bereits seit Oracle9i nicht mehr verwendet werden kann. Um ein CONNECT / AS SYSDBA ausführen zu können, muss der Betriebssystembenutzer über das Betriebssystem privilegiert worden sein. Unter Unix wird das durch die Zugehörigkeit zur Gruppe dba, unter MS-Windows durch die Zugehörigkeit zur Gruppe ora_dba realisiert. Meldet man sich mit username/password an, ist ein entsprechender Eintrag in der Passwortdatei von Oracle Voraussetzung. Auf die Passwortdatei wird in den Kapiteln 3 und 9 eingegangen. Seit SQL*Plus 8.1 wird das CONNECT / AS SYSDBA unterstützt, so dass SQL*Plus den Server-Manager als Administrationswerkzeug auf Server-Ebene abgelöst hat. Es müssen also unter Oracle8i existierende Skripte, die den Server-Manager aufrufen, auf die Benutzung von SQL*Plus umgestellt werden.
158
Instanz-Verwaltung
Daneben gibt es für die Remote-Administration von Instanzen und Datenbanken den Enterprise Manager, der in einem eigenen Kapitel behandelt wird, und Werkzeuge von Fremdherstellern, welche die Administration über grafische Oberflächen und Menüführungen erleichtern. Im Folgenden werden die Befehle für SQL*Plus vorgestellt, die zur Administration von Instanz und Datenbank notwendig sind.
4.1.1 Startup Ein Oracle-System wird grundsätzlich in drei Phasen gestartet. Die Phasen werden als NOMOUNT, MOUNT und OPEN bezeichnet. Im Folgenden wird hierzu das startup-Kommando vorgestellt, Wie bereits erwähnt, ist eine privilegierte Anmeldung an das Oracle-System mit connect / as sysdba Voraussetzung. Syntax: STARTUP[FORCE][RESTRICT][PFILE=filename] [OPEN [READ ONLY | READ WRITE]] | [MOUNT] | [NOMOUNT]
NOMOUNT In der ersten Phase, der NOMOUNT-Phase, wird die Instanz gestartet. Das bedeutet, dass in dieser Phase die SGA als Hauptspeicherstruktur angelegt und die Hintergrundprozesse gestartet werden. Wie groß die SGA ist und welche Hintergrundprozesse gestartet werden, ist von der Parametrierung der Instanz abhängig, die über Einträge in der Datei init<sid>.ora oder in einem SPFile vorgenommen wird. In der NOMOUNT-Phase wird die init<sid>.ora oder spfile<sid>.ora gelesen, und die Parameter werden interpretiert. In Abschnitt 4.2 wird näher darauf eingegangen. Oracle versucht permanent, so viele Parameter wie möglich dynamisch änderbar zu implementieren. Beispielsweise können ab Oracle9i die Bereiche der SGA dynamisch verändert werden, wobei die Vergrößerung eines Bereichs zu Lasten eines anderen fällt. Auch darauf wird im Folgenden genauer eingegangen. In der NOMOUNT-Phase läuft die Instanz ohne eine Verbindung zur Datenbank. Zu diesem Zeitpunkt können die Kommandos CREATE DATABASE und CREATE CONTROLFILE abgesetzt werden. Auch kann bereits auf einige V$-Tabellen zugegriffen werden. V$-Tabellen sind »virtuelle« Tabellen, die SGA-Strukturen abbilden und auf Inhalte der Kontrolldateien zugreifen. Durch den Initialisierungsparameter control_files in der Parameterdatei sind die Anzahl und die Lage der Kontrolldateien bekannt. MOUNT MOUNT ist die zweite Phase, in der die Kontrolldateien geöffnet werden. Damit wird
die Verbindung der Instanz zur Datenbank hergestellt. Die Kontrolldatei wird üblicherweise über Oracle-Mechanismen gespiegelt. In der MOUNT-Phase werden die gespiegelten Dateien geöffnet und miteinander verglichen. Nur wenn alle Spiegel identisch sind, wird die MOUNT-Phase erfolgreich beendet, und die Kontrolldateien sind geöffnet. Damit sind sämtliche Verweise auf die Redo-Log-Dateien und die Datendateien mit den dazugehörigen Konsistenzinformationen bekannt.
Werkzeuge und Voraussetzungen
159
In der MOUNT-Phase können Dateien umbenannt werden. Bei der Umbenennung werden die neuen Namen in die geöffneten Kontrolldateien eingetragen und ersetzen die alten Einträge. Ebenso muss die Instanz in den MOUNT-Status gebracht werden, wenn eine Wiederherstellung der kompletten Datenbank durchgeführt werden muss. Die Konsistenzinformationen aus den Kontrolldateien werden dann für die Bestimmung der Dateien und des Zielpunkts des Recovery benötigt. OPEN Wird beim Kommando startup keine Phase spezifiziert, so ist OPEN die Voreinstellung. In diesem Fall werden also automatisch alle drei Phasen durchlaufen. In der OPEN-Phase werden die Redo-Log-Dateien und die Datendateien, die in den Kontrolldateien verzeichnet sind, geöffnet, die Konsistenzinformationen werden mit den Informationen in den Dateiköpfen verglichen. Stimmen die Informationen überein, sind die geöffneten Dateien für den Betrieb verfügbar. In dieser Phase wird die Notwendigkeit eines Crash Recoverys, z.B. nach einem Stromausfall, erkannt und automatisch durchgeführt. Werden neben den Informationen aus den RedoLog-Dateien (Online Redolog Files) auch noch Daten aus den archivierten Redo-LogDateien benötigt, so wird die OPEN-Phase mit einer entsprechenden Fehlermeldung abbrechen. In diesem Fall muss in der MOUNT-Phase die Wiederherstellung der Datenbank durchgeführt werden, oder sie muss ohne die beschädigten Dateien geöffnet werden. Diese Punkte werden in Kapitel 10 (Wiederherstellungstechniken) eingehend behandelt. OPEN READ ONLY Der Parameter OPEN mit dem Zusatz READ ONLY öffnet die Datenbank im Read-onlyModus, d.h., es ist ausschließlich lesender Zugriff erlaubt. Auch das Anlegen oder Ändern von Datenbank-Objekten, z.B. Benutzern, ist nicht möglich, da dies Änderungen in Data-Dictionary-Tabellen implizieren würde. RESTRICTED Der Zusatz RESTRICTED beim Öffnen der Datenbank bewirkt, dass zwar alle Datendateien geöffnet werden und das Oracle-System damit voll verfügbar ist, der Zugriff jedoch nur Administratoren oder Benutzern erlaubt ist, die das Oracle-Systemprivileg RESTRICTED SESSION besitzen. Dieser Zustand der Datenbank ist dann interessant, wenn Aktivitäten durchgeführt werden müssen, die eine geöffnete Datenbank voraussetzen, bei denen aber Zugriffe von Anwendern unerwünscht sind. Ein Beispiel dafür ist die Reorganisation von Tabellen. FORCE Das Zusatz FORCE fasst die Einzelbefehle SHUTDOWN ABORT (s. nächster Abschnitt) und das jeweilige STARTUP zusammen. Dieser Befehl findet typischerweise seine Anwendung, wenn ein Oracle-System nach einem Systemabsturz, aus welchen Gründen auch immer, wieder gestartet werden soll, aber noch Fragmente der abgestürzten Instanz vorhanden sind und das Starten verhindern.
160
Instanz-Verwaltung
4.1.2 Shutdown Genau wie das Starten des Oracle-Systems läuft das Stoppen in drei Phasen ab. Die Phasen des Shutdown heißen CLOSE und DISMOUNT, danach wird die Instanz terminiert, d.h., die Hintergrundprozesse werden gestoppt, und der Speicherbereich der SGA wird freigegeben. Hierbei ist ebenfalls ein CONNECT / AS SYSDBA (SYSOPER) Voraussetzung. Syntax: SHUTDOWN [NORMAL] [IMMEDIATE] [TRANSACTIONAL] [ABORT]
NORMAL NORMAL ist die Voreinstellung beim Shutdown. In diesem Fall wird mit dem Stoppen
des Oracle-Systems so lange gewartet, bis sich alle Benutzer abgemeldet haben, neue Anmeldungen an die Instanz werden jedoch nicht mehr erlaubt. Als Erstes wird ein Checkpoint im fast mode (siehe Abschnitt 4.2.1) initialisiert, damit alle modifizierten Datenbankblöcke durch den Database-Writer-Prozess in die Datendateien geschrieben werden. Danach wird die Datenbank, d.h. die Daten- und Redo-Log-Dateien, geschlossen (CLOSE), anschließend werden die Kontrolldateien aktualisiert und geschlossen (DISMOUNT). Abschließend werden alle Hintergrundprozesse beendet und die SGA wird freigegeben. Die Datenbank befindet sich dann in einem konsistenten Zustand und kann beispielsweise gesichert werden. Das SHUTDOWN NORMAL wird jedoch in der Praxis selten eingesetzt, da man sich nicht darauf verlassen kann, dass sich alle Anwender abmelden. Wenn Agents des Enterprise Managers gestartet sind, so sind diese permanent angemeldet und verhindern damit ein Stoppen des Oracle-Systems. Entweder müssen die Anwender per Skript abgemeldet und die Agenten gestoppt werden, oder man verwendet eine der beiden folgenden Optionen. IMMEDIATE Ein SHUTDOWN IMMEDIATE funktioniert genauso wie das SHUTDOWN NORMAL, mit dem Unterschied, dass nicht auf das Abmelden der Benutzer gewartet wird. Der Hintergrundprozess PMON terminiert alle angemeldeten Datenbankprozesse und rollt eventuell offene Transaktionen zurück. Hierbei wird auf die Beendigung der aktuell laufenden Anweisungen gewartet, neue Befehle werden nicht mehr ausgeführt. So kann auf die Beendigung eines Update-Befehls gewartet werden, der anschließende COMMIT-Befehl wird aber nicht mehr akzeptiert. Dann folgen Checkpoint, Close, Dismount und die Beendigung der Instanz. Da der Hintergrundprozess PMON alle offenen Transaktionen zurückgerollt hat, ist auch in diesem Fall die Datenbank in einem konsistenten Zustand und kann gesichert werden.
Werkzeuge und Voraussetzungen
161
TRANSACTIONAL Im Gegensatz zum SHUTDOWN IMMEDIATE wird auf die Beendigung von Transaktionen, nicht von Befehlen, gewartet. Neue Transaktionen können aber nicht mehr gestartet werden. In der Praxis besteht jedoch die Gefahr, dass bei einer Online-Anwendung eine Transaktion noch aktiv ist, ein COMMIT jedoch nicht mehr abgesetzt wird. In diesem Fall würde durch eine automatisierte Sicherungsprozedur das Oracle-System nicht gestoppt werden können. In früheren Oracle-Versionen existierte für das SHUTDOWN TRANSACTIONAL eine Zeitangabe in Sekunden, nach der trotz laufender Transaktionen ein Shutdown durchgeführt wurde. Diese Angabe ist zwar syntaktisch noch möglich, wird aber nicht mehr ausgewertet. ABORT Mit SHUTDOWN ABORT wird ein absoluter Nothalt des Oracle-Systems durchgeführt. SHUTDOWN ABORT beendet sofort die Hintergrundprozesse und gibt die SGA frei. Es wird kein Checkpoint mehr ausgeführt, offene Transaktionen werden nicht zurückgerollt, Datendateien Redolog-Dateien und Kontrolldateien werden nicht geschlossen. Der daraus resultierende Zustand der Datenbank ist inkonsistent. Das bedeutet, dass beim nachfolgenden STARTUP ein Instance Recovery durchgeführt werden muss. Eine solche Datenbank sollte man nicht als Grundlage einer Offline-Sicherung verwenden. Dieses Kommando ist vielmehr dafür vorgesehen, die »Reste« einer abgestürzten Instanz zu beseitigen. Beendet sich ein Oracle-Hintergrundprozess durch einen Fehler, so werden auch alle anderen Hintergrundprozesse heruntergefahren. Auf Unix-Systemen kann in solchen Fällen unter dem Verzeichnis $ORACLE_HOME/dbs noch eine Datei namens lk<sid> zu finden sein, die als Sperrdatei für die Hintergrundprozesse der betreffenden Instanz dient. Beim versuchten Neustart wird dann die Meldung ausgegeben, dass die Instanz bereits gestartet ist, ein SHUTDOWN bringt wiederum die Meldung, dass die Instanz nicht gestartet ist. Ein solcher Zustand wird mit SHUTDOWN ABORT beseitigt. SHUTDOWN ABORT wird implizit auch durch das Kommando STARTUP FORCE durchge-
führt.
4.1.3 Alter Database Einige Einstellungen von Instanz und Datenbank lassen sich nicht im STARTUPKommando spezifizieren, sondern nur über das ALTER DATABASE-Kommando. RENAME GLOBAL_NAME Globale Namen von Datenbanken sind Voraussetzung für verteilte Datenbanksysteme. In einer verteilten Umgebung, also bei Server-Server-Konfigurationen, muss jeder Datenbank ein im System eindeutiger Name zugeordnet sein. Dieser globale Datenbankname kann über ALTER DATABASE RENAME GLOBAL_NAME TO my.global.name geändert werden. Per Default ergibt sich der globale Datenbankname aus den beiden Initialisierungsparametern ..
162
Instanz-Verwaltung
In verteilten Datenbankumgebungen wird üblicherweise der globale Name einer Datenbank im entsprechenden Datenbank-Link verwendet. Wird der globale Name umbenannt, so müssen die Administratoren derjenigen Datenbanken informiert werden, in denen Verweise in Datenbank-Links auf die umbenannte Datenbank existieren, damit diese entsprechend angepasst werden können. CHARACTER SET/NATIONAL CHARACTER SET Das Character Set und das National Character Set einer Datenbank werden beim Anlegen der Datenbank angegeben und sind danach fest. Alle Zeichen, die in die Datenbank geschrieben werden, werden im Datenbankzeichensatz abgelegt. Über das Kommando ALTER DATABASE CHARACTER SET charset kann der Datenbankzeichensatz geändert werden, aber nur unter der Voraussetzung, dass der neue Zeichensatz eine Obermenge des alten Zeichensatzes ist. So kann eine Datenbank, die mit dem Zeichensatz US7ASCII angelegt worden ist, über den Befehl ALTER DATABASE CHARACTER SET WE8ISO8859P1 auf den Zeichensatz WE8ISO8859P1 umgestellt werden. Auch eine Umstellung auf zum Beispiel den Zeichensatz UTF8 wird unterstützt, eine Konvertierung der bereits abgelegten Zeichen wird automatisch durchgeführt. Eine Auflistung aller möglichen Konvertierungen findet sich in der Dokumentation Oracle 10g Globalization Support Guide.
4.1.4 Alter System Eine weitere Gruppe von Instanz-Verwaltungsbefehlen wird über das Kommando ALTER SYSTEM angestoßen. Es werden hier nicht alle Optionen aufgeführt, sondern nur die, die für die Instanz-Verwaltung interessant wird. Für die komplette Syntax des Befehls sei auf die Dokumentation Oracle 10g SQL Reference verwiesen. ENABLE/DISABLE RESTRICTED SESSION Mit dem Befehl ALTER SYSTEM ENABLE RESTRICTED SESSION kann der Administrator den Zugang zur Datenbank für den »normalen Benutzer« sperren. Das ist immer dann sinnvoll, wenn Aktivitäten durchgeführt werden müssen, die zwar eine geöffnete Datenbank voraussetzen, aber keine Benutzeraktivitäten zulassen. Ein Beispiel hierfür ist die Reorganisation einer Tabelle. KILL SESSION Mit ALTER SYSTEM KILL SESSION 'sid,serial#' können Benutzerprozesse des Datenbanksystems gestoppt werden. Dieser Befehl bewirkt, dass noch laufende wichtige Aktivitäten, wie das Warten auf Antwort bei einer verteilten Transaktion oder ein Rollback, noch bearbeitet werden, dann der PMON-Prozess die Verbindung beendet und die betreffende Session als killed markiert. Ist die Verbindung nach einem Wartezustand tatsächlich beendet, geht der Status in dead über. Mit dem Zusatz IMMEDIATE wird sofort ein Rollback offener Transaktionen durchgeführt, und alle Sperren werden aufgehoben. Die SID und SERIAL#, die als Parameter angegeben werden müssen, können aus der virtuellen Tabelle v$session abgelesen werden.
Werkzeuge und Voraussetzungen
163
Beispiel: SQL> SELECT username,sid,serial# FROM v$session WHERE username='SCHWANKE'; USERNAME SID SERIAL# ------------------------------ ---------- ---------SCHWANKE 13 4 SQL> ALTER SYSTEM KILL SESSION '13,4'; System altered. SQL> SELECT username,sid,status FROM v$session WHERE username='SCOTT'; USERNAME SID STATUS ------------------------------ ---------- -------SCHWANKE 13 KILLED Listing 4.1: Kill Session
DISCONNECT SESSION Der Befehl ALTER SYSTEM DISCONNECT SESSION ´sid,serial#´ arbeitet grundsätzlich so wie der KILL SESSION-Befehl. In diesem Fall wird der Server-Prozess terminiert. Der Zusatz POST_TRANSACTION bewirkt, dass auf die Beendigung offener Transaktionen gewartet wird. Der Status des Prozesses ist in dieser Zeit inactive. Mit dem Zusatz IMMEDIATE wird der gleiche Effekt wie beim Kommando ALTER SYSTEM KILL SESSION 'SID,SERIAL#' IMMEDIATE erreicht. FLUSH SHARED_POOL ALTER SYSTEM FLUSH SHARED_POOL räumt in der SGA den Shared Pool auf, den Bereich, in dem Data-Dictionary-Informationen und Shared SQL und PL/SQL liegen. Durch das Aufräumen dieses Bereichs wird Speicherplatz von nicht mehr verwendeten Befehlen freigegeben und damit der Zugriff im Shared SQL-Bereich verbessert.
Dies kann benutzt werden, um bei einer starken Fragmentierung des Shared Pools einige Bereiche freizugeben. Speicher für Objekte, die gerade benutzt oder ausgeführt werden, sowie so genannte »fixierte Objekte« (mittels DBMS_SHARED_POOL.KEEP) wird allerdings nicht freigegeben. Auch findet keinerlei Defragmentierung des Shared Pools statt. Außerdem ist zu beachten, viele SQL-Kommandos nun erneut »geparst« werden müssen, was insbesondere bei komplexen Statements zu deutlichen Performance-Reduktionen unmittelbar nach dem Aufräumvorgang führt. FLUSH BUFFER_CACHE Leert den Buffer-Cache der SGA. Dies ist für Entwicklung- und Testumgebungen gedacht, um Performance-Messungen einzelner Statements besser vergleichen zu können. Da im Rahmen von Autotracing (siehe Kapitel 11) jedoch ohnehin die Gesamtzahl gelesener Blöcke (unabhängig von Caching-Effekten) geliefert wird und in einer produktiven Umgebung letztlich die Performance mit Cache entscheidet, ist die Bedeutung dieses Kommandos eher gering.
164
Instanz-Verwaltung
SWITCH LOGFILE Im normalen Betrieb wird der Wechsel der Redo-Log-Dateien dann ausgeführt, wenn die gerade benutzte Datei gefüllt ist. Soll explizit ein Wechsel ausgeführt werden, wird dazu der Befehl ALTER SYSTEM SWITCH LOGFILE benutzt. Dieser Befehl wird dann gebraucht, wenn an einer Redo-Log-Gruppe gearbeitet werden muss, die gerade den Status current hat und dadurch Aktivitäten nicht erlaubt. Auch bei konventionellen Online-Backup-Prozeduren findet dieses Kommando seine Anwendung. SUSPEND/RESUME Mit dem Befehl ALTER SYSTEM SUSPEND werden alle I/O-Aktivitäten des Oracle-Systems auf Datendateien, Redo-Log-Dateien und Kontrolldateien angehalten. Mit ALTER SYSTEM RESUME werden sie wieder eingeschaltet. Diese Kommandos bieten eine Erweiterung zu Backup-Verfahren, bei denen Plattenspiegelungen aufgelöst werden (s.u.).
4.2
Parametrierung
Eine Oracle-Instanz lässt sich in der Version 10g mit über 250 Parametern einstellen. Diese Parameter werden, wie vorher schon beschrieben, immer beim STARTUP in der NOMOUNT-Phase ausgelesen. Es gibt zwei Möglichkeiten, diese Parameter zu spezifizieren: In einer Serverparameterdatei (SPFile). Diese muss im Dateisystem des Servers liegen. Der SPFile hat den Namen SPFILE<sid>.ora und befindet sich auf UnixSystemen unter $ORACLE_HOME/dbs, auf MS-Windows unter %ORACLE_HOME%\database. Vorteilhaft ist bei dieser Variante, dass die Initialisierungsparameter an zentraler Stelle liegen und insbesondere die Datenbank problemlos von einem entfernten Client aus gestartet werden kann. In einer herkömmlichen Parameterdatei. Diese heißt standardmäßig init<sid>.ora und muss im Dateisystem des SQL*Plus-Clients liegen. Der genaue Ort sowie Dateiname kann über die PFILE-Klausel des STARTUP-Kommandos mitgegeben werden, standardmäßig wird auch hier im Verzeichnis $ORACLE_HOME/ dbs bei Unix-Systemen bzw. %ORACLE_HOME%\database auf MS-Windows gesucht. Ein typisches Problem hierbei ist, dass sich die Datenbank zwar von jedem Client aus herunterfahren lässt, das Starten aber eine dezentrale Parameterdatei (beim Client) erfordert. Die wichtigsten Parameter, die nachträglich nicht oder nur schwer änderbar sind, wurden bereits vorgestellt. Die eingestellten Parameter einer Instanz lassen sich über die virtuelle Tabelle v$parameter abfragen. Feld
Beschreibung
num
Nummer des Parameters
name
Name des Parameters
type
Parametertyp (String, Number, Boolean)
Tabelle 4.1: Die virtuelle Tabelle V$PARAMETER
Parametrierung
165
Feld
Beschreibung
value
Aktueller Wert des Parameters
isdefault
TRUE oder FALSE, zeigt an, ob es der Standardwert ist.
isses_modifiable
TRUE oder FALSE, zeigt an, ob über ALTER SESSION veränderbar.
issys_modifiable
IMMEDIATE kann über ALTER SYSTEM verändert werden. DEFERRED ist nur für neue Anmeldungen gültig. FALSE kann nicht über ALTER SYSTEM verändert werden.
ismodified
MODIFIED zeigt Änderungen über ALTER SESSION an.
isadjusted
TRUE oder FALSE zeigt an, ob der Parameter automatisch vom Datenbanksystem auf einen gültigen Wert korrigiert wurde.
isdeprecated
Zeigt an, ob der Parameter veraltet ist. Solche Parameter sind nur aus Kompatibilitätsgründen noch vorhanden und sollten, wenn möglich, nicht benutzt werden.
description
Beschreibung des Parameters
SYS_MODIFIED zeigt Änderung über ALTER SYSTEM an.
Tabelle 4.1: Die virtuelle Tabelle V$PARAMETER (Forts.)
Die Initialisierungsdatei wird, wie vorher schon beschrieben, immer beim STARTUP in der NOMOUNT-Phase ausgelesen. Dies führte in älteren Oracle-Versionen dazu, dass Parameteränderungen nur nach dem Neustart der Instanz erkannt wurden. Mit neueren Oracle-Versionen werden jedoch immer mehr Parameter zur Laufzeit der Instanz änderbar. Da eine Besprechung aller Parameter den Rahmen an dieser Stelle sprengen würde, sei hier auf die Oracle-Dokumentation verwiesen. Die komplette Beschreibung aller Parameter ist in der Dokumentation Oracle 10g Database Reference zu finden. Zu jedem Parameter ist dort zu finden, ob er generell änderbar ist, ob er für einen bestimmten Prozess oder für das gesamte System zu Laufzeit geändert werden kann, welche Bereiche gültig sind und wie seine Standardeinstellung ist. Für Parameteränderungen, die auf Systemebene möglich sind, wird der Befehl ALTER SYSTEM SET parameter=wert;
verwendet. Wichtig ist hierbei, dass solche Anpassungen im laufenden Betrieb bei Verwendung einer Parameterdatei nicht in diese übertragen werden und somit nach einem erneuten Start der Datenbank verloren sind, sofern sie nicht manuell nachgetragen werden. Bei Verwendung eines SPFiles hingegen erfolgt automatisch eine Synchronisation zwischen laufendem System und SPFile. Ist dies unerwünscht oder – wie im Falle statischer Parameter – nicht möglich, kann der Wirkungsbereich auf das laufende System oder das SPFile alleine beschränkt werden: ALTER SYSTEM SET parameter=wert [SCOPE=MEMORY|SPFILE|BOTH];
166
Instanz-Verwaltung
4.2.1 Checkpoints Ein Checkpoint ist ein notwendiger Mechanismus, um die Konsistenz der Datenbank zu garantieren. Bedingt wird dieses durch die asynchrone Arbeitsweise des Database-Writer-Prozesses, der in der SGA modifizierte Blöcke nicht sofort auf die Platte zurückschreibt. Zwar wird dieses Problem durch den Log Writer und die Redo-Log-Dateien gelöst, jedoch werden die im Falle eines Absturzes der OracleInstanz benötigten Informationen in den Redo-Log-Dateien zyklisch wieder überschrieben. In diesem Fall ist es unverzichtbar, diejenigen Blöcke aus der SGA auf die Platte zurückzuschreiben, die aufgrund der überschriebenen Informationen nicht wiederhergestellt werden könnten. Genau dieses wird durch einen Checkpoint gewährleistet. Ein anderes Ereignis für das Auslösen eines Checkpoints ist ein Schließen von Dateien wie zum Beispiel beim SHUTDOWN eines Oracle-Systems. Auch in diesem Fall sollen vor einem Schließen der Dateien alle modifizierten Daten auf die Festplatten zurückgeschrieben werden. Außerdem kann ein Checkpoint zur Bildung eines Synchronisationszeitpunktes verwendet werden, wie es bei einem konventionellen Online-Backup notwendig ist. Folgende Ereignisse und Befehle lösen Checkpoints aus: Wechsel der Redolog-Dateien
SHUTDOWN NORMAL / IMMEDIATE / TRANSACTIONAL ALTER SYSTEM CHECKPOINT ALTER SYSTEM SWITCH LOGFILE ALTER TABLESPACE BEGIN BACKUP ALTER TABLESPACE OFFLINE NORMAL / TEMPORARY
Ist ein Checkpoint durch die genannten Ereignisse oder Befehle initiiert worden, so ist es Aufgabe des Database Writers, modifizierte Blöcke aus dem Database-BufferCache der SGA auf die Festplatten zurückzuschreiben. Die Dauer eines Checkpoints ist also von der Größe des Database-Buffer-Caches in Verbindung mit der Transaktionsaktivität abhängig. Ein Checkpoint, der durch den Wechsel einer Redo-Log-Datei ausgelöst wird, soll den normalen Betrieb des Datenbanksystems möglichst wenig beeinträchtigen, kann dafür aber etwas länger dauern. Man spricht hier von einem Checkpoint im normal mode. Wird ein Oracle-System heruntergefahren, so soll dies möglichst schnell geschehen. Zudem muss sich der Database Writer nicht mehr um »normale Transaktionen« kümmern, sondern kann sich nur um das Schreiben der modifizierten Blöcke kümmern, schreibt also den Checkpoint im fast mode. Die Beendigung eines Checkpoints wird im Kopf jeder einzelnen Datenbankdatei und in den Kontrolldateien mit der zum Zeitpunkt des Checkpoints aktuellen System Change Number (SCN) protokolliert. Diese Aufgabe wird durch den Checkpoint-Prozess CKPT wahrgenommen.
Parametrierung
167
Problematisch werden kann das Schreiben von Checkpoints während Zeiten hoher Transaktionslast. Wenn durch mehrfaches Umschalten der Redo-Log-Gruppe wieder auf eine Redo-Log-Gruppe umgeschaltet werden soll, deren Checkpoint noch nicht beendet ist, kommt es zu einem datenbankweiten Wartezustand, bis der Checkpoint geschrieben ist. Genau diese Situation gilt es zu vermeiden. Man findet eine Protokollierung dieser Wartezustände in der Alert-Datei der Instanz mit der Meldung checkpoint not complete. Zur Vermeidung der Wartezustände gibt es drei Möglichkeiten: Eine Vergrößerung der Redo-Log-Dateien führt zu einer Reduktion der Anzahl der Checkpoints. Durch das Anlegen zusätzlicher Redo-Log-Gruppen können mehr Checkpoints parallel laufen. Anders formuliert: Es dauert länger, bis wieder auf eine bestimmte Redo-Log-Gruppe umgeschaltet wird. Durch Setzen des Initialisierungsparameters log_checkpoint_interval auf einen von 0 verschiedenen Wert wird bereits vor dem eigentlichen Log-Switch mit dem Schreiben des Checkpoints begonnen (inkrementeller Checkpoint), beim Log-Switch müssen dann maximal so viele Betriebssystemblöcke geschrieben werden wie durch den Parameter gesetzt. Der gesetzte Wert sollte also kleiner sein als die Größe der Redo-Log-Dateien in Betriebssystemblöcken. Ähnliche Effekte lassen sich über die Parameter log_checkpoint_timeout und fast_start_mttr_target erreichen.
4.2.2 Dynamische SGA Bis auf den Log-Buffer sind alle Komponenten der SGA (Buffer-Cache, Shared Pool, Large Pool etc.) dynamisch, d.h., ihre Größe kann im laufenden Betrieb angepasst werden. Dies geschieht einfach durch ein entsprechendes ALTER SYSTEM-Kommando, z.B. SQL> ALTER SYSTEM SET db_cache_size=500M;
Voraussetzung hierfür ist natürlich, dass überhaupt genügend Speicherplatz verfügbar ist. Eine harte Obergrenze für die Gesamtgröße der SGA ist durch den Parameter SGA_MAX_SIZE gegeben. Wenn nicht von vornherein alle SGA-Komponenten entsprechend den physikalischen Limits (Hauptspeichermenge) des Servers dimensioniert sind, sollte dieser Parameter explizit gesetzt werden, da er ansonsten implizit einfach auf die Gesamtgröße aller Komponenten beim Instanzstart gesetzt wird und eine nachträgliche Erhöhung im laufenden Betrieb nicht möglich ist. Die kleinste Speichereinheit, die zwischen den SGA-Komponenten bewegt werden kann, ist eine Granule. Für SGA-Größen unter 1 GB beträgt die Granulengröße 4 MB. Die Größe kann auch direkt abgefragt werden: SQL> SELECT bytes FROM v$sgainfo WHERE name = 'Granule Size';
Mit Oracle 10g stehen zwei Modi zur Verwaltung der SGA zur Verfügung.
168
Instanz-Verwaltung
Manuelle SGA-Verwaltung In der Standardeinstellung befindet sich Oracle 10g in diesem Modus. Die manuelle Verwaltung wird durch Setzen des Initialisierungsparameters SGA_TARGET auf 0 ausgewählt. Im manuellen Modus müssen sämtliche Operationen zur SGA-Verwaltung explizit durch den DBA vorgenommen werden. Soll eine Komponente vergrößert werden, muss ggf. eine andere Komponente zuvor verkleinert werden. Häufig auftretende Verwaltungsaufgaben können als Datenbank-Jobs über den Scheduler (siehe Kapitel 6) programmiert werden, beispielsweise: Vor dem Starten von Batch-Jobs oder Reports in Data-Warehouse-Umgebungen ist es meistens günstig, den Buffer-Cache möglichst großzügig zu dimensionieren. Vor dem Beginn eines Backups mittels RMAN sollte der Large Pool entsprechend dimensioniert werden. Nach einer typischen Laufzeit für diese Tasks plus Zeitreserve muss außerdem der Zustand für den produktiven Betrieb wiederhergestellt werden. Automatische SGA-Verwaltung Der Parameter SGA_TARGET kann jederzeit auf einen von 0 verschiedenen Wert gesetzt werden (Anzahl Bytes, evtl. mit Suffix K, M, G). Dadurch wird die automatische SGAVerwaltung aktiviert. Dieser Modus bietet zum einen den Vorteil, dass vor einer Vergrößerung einer Komponente ggf. automatisch andere Komponenten verkleinert werden. Zum anderen werden bestimmte Operationen vollautomatisch durchgeführt. Voraussetzung für diesen Modus ist, dass der Parameter STATISTICS_LEVEL auf TYPICAL (Default) oder ALL gesetzt ist. Durch SGA_TARGET wird die Gesamtgröße der Instanz angegeben. In der Praxis sollte dieser Wert mit dem Wert von SGA_MAX_SIZE identisch sein. Die herkömmlichen Parameter DB_CACHE_SIZE, SHARED_POOL_SIZE etc. können, aber müssen nicht verwendet werden (zur Bedeutung dieser Parameter bei automatischer SGA-Verwaltung siehe unten). Im Gegensatz zu älteren Oracle-Versionen umfasst der durch SGA_TARGET gegebene Wert die Gesamtgröße der Instanz inklusive »fixed SGA«. Dadurch ist eine exakte Kontrolle über die endgültige Größe der SGA gegeben. Einige Komponenten können in diesem Modus automatisch vom System angepasst werden, nämlich der Buffer-Cache (nur der Default-Buffer-Cache) sowie Shared Pool, Java Pool und Large Pool. Nicht angepasst werden demnach der Keep und Recycle Pool sowie alle Buffer Pools, die nicht der Standardblockgröße entsprechen. Für die automatische Anpassung werden u.a. so genannte Advisories genutzt, konkret sind dies die Performance-Views V$DB_CACHE_ADVICE, V$SHARED_POOL_ADVICE und V$JAVA_POOL_ADVICE. Diese geben für alternative Größen der entsprechenden Komponente (zwischen 10% und 200% der aktuellen Größe) an, welche Performance-
Parametrierung
169
Auswirkungen eine entsprechende Dimensionierung der betreffenden Komponente auf das System hätte, z.B. die Trefferrate im Buffer-Cache für einen doppelt so großen Buffer-Cache. Das Verfahren, nach dem die automatische Anpassung läuft, ist nicht im Einzelnen dokumentiert. Für das Release 10.1.0 kann jedoch Folgendes festgehalten werden: Lediglich Default-Buffer-Cache, Shared Pool, Java Pool und Large Pool werden von der automatischen Anpassung berücksichtigt. Das macht das Verfahren vor allem für kleinere Systeme mit einer SGA-Größe von wenigen hundert MB interessant, da bei großen System praktisch keine Konkurrenz zwischen Shared Pool und Java Pool einerseits sowie Buffer-Cache andererseits besteht. Eine Vergrößerung des Shared Pools bzw. des Java Pools zulasten des Buffer-Cache findet statt, wenn ein entsprechender Mehrwert durch die Advisories angezeigt wird. Diese Situation tritt vor allem dann auf, wenn Batch-Jobs und Reports beendet sind und das Tagesgeschäft wieder anläuft. Die Anpassung geschieht allerdings sehr langsam. Alle fünf Minuten werden eine oder wenige Granulen transferiert. Für ressourcenintensive Abfragen, wie sie in Batch-Jobs oder Reports vorkommen, ist dieser Mechanismus daher zu träge. Auch hier bilden lediglich Systeme mit wenig Hauptspeicher eine Ausnahme. Eine moderate Verkürzung dieses Reaktionsintervalls kann durch Setzen des versteckten Parameters _memory_broker_stat_interval auf eine Anzahl Sekunden erreicht werden (Default ist 300). Eine Vergrößerung des Buffer Cache zulasten des Shared Pools oder Java Pools ist in der Standardeinstellung nicht möglich! Dies ist darauf zurückzuführen, dass die beiden Pools häufig fragmentiert sind und daher gar nicht mehr verkleinert werden können. Eine automatische Defragmentierung der Pools ist auch nicht eingebaut, der Shared Pool kann aber zumindest manuell »aufgeräumt« werden (siehe Abschnitt 4.1.4). Auch hier ist der einzige Ausweg das Setzen eines versteckten Parameters (_memory_broker_shrink_heaps auf 1; Default ist 0). Das Fragmentierungsproblem ist damit aber dennoch nicht gelöst. Durch Setzen der herkömmlichen Parameter DB_CACHE_SIZE, SHARED_POOL_SIZE etc. werden Untergrenzen für die entsprechenden Komponenten spezifiziert. Wichtig ist, dass dadurch offenbar gleichzeitig auch Obergrenzen für die anderen Komponenten gesetzt werden. Insbesondere für den Buffer-Cache sollte dies auch genutzt werden, um eine zu starke Einengung durch die beiden Pools zu verhindern. Freigegebener Platz im Large Pool (z.B. nach Abschluss eines RMAN-Backups) wird schnellstmöglich, d.h. beim nächsten Granulen-Transfer, an den BufferCache übertragen. Abschätzungen, wie lange das Backup benötigt, um rechtzeitig wieder auf die Tagesgeschäftkonfiguration zurückzuschalten, sind also nicht mehr notwendig. Dies ist eindeutig ein Vorteil. Die Übertragung von BufferCache an den Large Pool vor Beginn des Backups läuft aber nicht automatisch, sondern muss weiterhin per Job verdrahtet werden.
170
Instanz-Verwaltung
Überwachung Alle manuellen oder automatischen Speichertransfers werden in der View V$SGA_ RESIZE_OPS festgehalten. Die aktuellen Größen stehen über die View V$SGA_ DYNAMIC_COMPONENTS bereit. SQL> SELECT component, current_size 2 FROM v$sga_dynamic_components; COMPONENT CURRENT_SIZE ------------------------------ -----------shared pool 201326592 large pool 16777216 java pool 104857600 streams pool 0 DEFAULT buffer cache 104857600 KEEP buffer cache 0 RECYCLE buffer cache 0 DEFAULT 2K buffer cache 0 DEFAULT 8K buffer cache 0 DEFAULT 16K buffer cache 104857600 DEFAULT 32K buffer cache 0 OSM Buffer Cache 0
Der Hintergrundprozess MMON ist für die automatische SGA-Verwaltung zuständig. Falls für die Instanzparametrierung ein SPFile benutzt wird, werden beim Herunterfahren der Datenbank die aktuellen Größen der SGA-Komponenten über die Parameter __DB_CACHE_SIZE, __SHARED_POOL_SIZE etc. im SPFile abgelegt. Nach einem Instance-Crash und anschließendem Wiederanstarten schließt das System daher nahtlos an das vorherige Lastprofil an.
4.3
Oracle Cluster Synchronization Service Daemon
Dieser Prozess (ocss) wird nach einer Oracle 10g-Installation automatisch installiert und gestartet. Leider schlägt der Start unter Windows auch bei der Version 10.1.0.3 fehl, da hier ein entsprechender Eintrag fehlt.
Abbildung 4.1: OCSS-Fehlermeldung
Der Fehler kann sehr einfach mit folgendem Befehl behoben werden: "clscfg -local -o %ORACLE_HOME% -l NA"
Damit kann der Prozess gestartet und benutzt werden.
ASM-Instanzen
171
Dieser Prozess ist notwendig für die Kommunikation zwischen Instanzen, also z.B. für eine Real Application Cluster-Datenbank, bei der mehrere Instanzen auf eine gemeinsame Datenbank zugreifen. Des Weiteren wird der Prozess für die Kommunikation einer Oracle-Instanz mit einer ASM-Instanz benötigt. Wenn Sie also kein ASM und kein RAC verwenden, können Sie den Prozess stoppen. Unter Unix gestaltet sich dies allerdings etwas umständlicher. Wer gehofft hat, dass man mit dem schönen Befehl kill –9 weiterkommt, wird enttäuscht, da der Prozess automatisch nachgestartet wird. Je nach Plattform finden Sie einen Eintrag in der Datei /etc/inittab oder eine Datei init.cssd im Verzeichnis /etc/rc3.d.
Mit dem Befehl /etc/init.d/init.cssd stop wird der Prozess endgültig beendet.
4.4
ASM-Instanzen
Die Verwaltung von ASM-Instanzen ist recht simpel. Neben dem wichtigsten Parameter instance_type = ASM gibt es nur noch wenige Einstellungsmöglichkeiten. Hierzu gehören: asm_diskgroups: die Liste der von dieser Instanz verwalteten ASM-Gruppen asm_diskstring: eine mögliche Einschränkung der Disks, die für die ASM-Konfiguration zur Verfügung stehen soll. Wenn dieser Parameter nicht gesetzt ist, werden alle Disks angeboten. background_dump_dest: Wie üblich, das Verzeichnis für die Logs der Hintergrundprozesse core_dump_dest: das Verzeichnis für die, hoffentlich nie auftretenden, CoreDumps user_dump_dest: Verzeichnis für Dumps von Benutzerprozessen remote_login_passwordfile: die Möglichkeit, die ASM-Instanzzugriffe über ein Kennwort zu schützen. large_pool_size: die Größe des Caches der ASM-Instanz. Hier reichen in der Regel 20 MByte aus. Diese Parameter werden, wie bei einer Datenbankinstanz, über ein SPFILE verwaltet. Das Starten der Instanz erfolgt wie oben dargestellt mit dem Befehl STARTUP; vor einer Konfiguration in den Zustand NOMOUNT und mit einer bestehenden ASMGruppe in den MOUNT-Status. Ein Öffnen ist nicht erforderlich. Das Herunterfahren der Instanz wird mit dem Befehl SHUTDOWN durchgeführt. Es sollte aber beachtet werden, dass mit dem Stoppen der ASM-Instanz alle zugehörigen Datenbanken ebenfalls beendet werden, sofern diese mit ASM arbeiten.
172
4.5
Instanz-Verwaltung
Ältere Versionen
Mit der Version 9i wurde die Server-Parameterdatei (SPFILE) eingeführt. Zusätzlich gibt es aber wie bisher die Möglichkeit, die Parameter über eine Initialisierungsdatei, kurz init.ora zu verwalten. Der Vorteil dieser Datei ist, dass sie direkt editierbar ist und als Textdatei die Möglichkeit bietet, umfangreiche Kommentare (z.B. alte Werte) zu speichern. Dem steht der Nachteil gegenüber, dass die Parameter nicht dynamisch anpassbar sind.
Datenbankobjekte 5.1
Namenskonventionen
Die generellen Namenskonventionen für eine Datenbank haben wir bereits in Kapitel 3.1 besprochen. Ähnliche Vorgaben gelten auch für die Datenbankobjekte. Bei diesen gibt es einen zusätzlichen Punkt, der bei der Datenbank selbst unter Umständen eine eher untergeordnete Rolle spielt. Aus den Objektnamen sollte sich der Kontext der Anwendung erschließen lassen (z.B. personen für eine Tabelle, die personenbezogene Daten enthält). Allerdings gibt es in den Unternehmen und auch in diversen Dokumentationen eine Vielzahl von Regelungen, die mehr oder weniger sinnvoll sind, so dass wir hier nicht näher in eine Diskussion einsteigen wollen. Eines sei allerdings noch gesagt. Es gibt Regelungen, in denen der Name eines Objektes auch den Objekttyp enthält, z.B. t_personen für die Personentabelle, v_personen für die View und s_personen für ein Synonym. Bei solchen Benennungsmethoden sollten Sie bedenken, dass die Flexibilität, welche die Oracle-Datenbank in Bezug auf eine Anwendung mit sich bringt, hierdurch verloren geht. Für eine Anwendung ist es egal, ob auf eine Tabelle oder ein Synonym zugegriffen wird, in Teilen (SELECT) gilt dies auch für Views. Die oben beschriebene Namenskonvention macht aber gerade diese Möglichkeit zunichte. Spätestens beim ersten Release-Wechsel werden Sie feststellen, dass die Regeln entweder behindern oder Sie diese nicht mehr einhalten können. Also sollten Sie von vornherein auf derartige Restriktionen verzichten. Jedes heute gebräuchliche Werkzeug ist in der Lage, Ihnen genau darzustellen, um was für einen Objekttyp es sich handelt, auch wenn dieser keine entsprechende Kennzeichnung enthält. Grundregeln Folgende Regeln existieren für die Namensgebung von Objekten in der Datenbank: 1. Namen sind bis zu 30 Byte lang. (Ausnahme: Datenbank-Links bis zu 128 Byte) 2. Namen dürfen keine Anführungsstriche enthalten. 3. Groß-/Kleinschreibung wird bei Namen nicht unterschieden. 4. Namen müssen mit einem alphabetischen Zeichen des Datenbankzeichensatzes anfangen. 5. Namen können ausschließlich alphanumerische Zeichen sowie die Zeichen »_$#« enthalten; Namen von Datenbank-Links zusätzlich ».@«. 6. Reservierte Wörter dürfen nicht verwendet werden. 7. dual darf nicht verwendet werden. 8. Auch nicht reservierte Wörter, die aber eine Bedeutung im Oracle-Umfeld haben (z.B. DIMENSION oder SEGMENT), dürfen nicht verwendet werden.
174
Datenbankobjekte
9. Zwei Objekte im gleichen Namensraum (d.h. Schema) dürfen nicht den gleichen Namen haben. Ausnahme sind Synonyme. 10.Die Spalten einer Tabelle bzw. einer View müssen alle unterschiedliche Namen haben. Spalten verschiedener Tabellen oder Views können gleich lautende Namen haben. 11.Prozeduren oder Funktionen innerhalb eines Packages können gleich lautende Namen haben, falls sie eine unterschiedliche Anzahl von Argumenten oder Argumente verschiedenen Typs haben. 12.Namen können in doppelten Anführungszeichen geschrieben werden (Maskierung). In diesem Fall treffen die Regeln 3 bis 8 nicht zu. Allgemeine Empfehlungen Neben den eigentlichen Regeln sind aber folgende Überlegungen wichtig, um Namen für Datenbankobjekte zu finden: Namen sollten lesbar und ausführlich sein. Die 30 Zeichen können ruhigen Gewissens ausgenutzt werden. Aussagekräftige Namen erhöhen die Lesbarkeit von SQL-Befehlen und Programmen erheblich. Passend zu den Voreinstellungen vieler Design-Werkzeuge sollten Tabellennamen im Plural definiert werden. (Entitäten werden meist im Singular definiert.) Spaltennamen für Spalten mit identischer Bedeutung sollten im gesamten Schema konsistent benannt werden. Somit können sowohl Beziehungen zwischen Tabellen als auch Sachverhalte klar umschrieben werden. Die Objekte sollten möglichst nicht maskiert werden. Das gilt speziell, wenn man Tabellen von anderen Datenhaltungssystemen wie z.B. Access übernimmt, da hier Groß- und Kleinschreibung sowie Leerzeichen des Öfteren vorkommen. Zwar ist es in der Oracle-Datenbank möglich, solche Objekte anzulegen, Sie werden aber bei vielen Werkzeugen auf Probleme in der Handhabung solcher Objekte haben. Eine Spalte, die den Preis eines Produktes in Euro angibt, sollte ruhig preis_in_euro genannt werden. Eine solche Spalte lediglich preis zu nennen, kann verwirrend sein (man denke nur an die Euro-Umstellung). Sollte die Währung in einer eigenen Spalte waehrung_id gekennzeichnet sein (wobei dies natürlich einen Fremdschlüssel in einer Tabelle waehrungen repräsentiert), so kann der Spaltenname z.B. preis_in_ waehrung sein. An dieser Stelle empfehlen wir, für deutsche Namen mit Umlauten ae, oe und ue einzusetzen, obwohl auch Namen wie währungen möglich sind (dies auch ohne doppelte Anführungszeichen). Solche Namen können aber Probleme bereiten, z.B. wenn Sie bei der Programmierung in Oracle-fremden Produkten verwendet werden.
Datenobjekte
5.2
175
Datenobjekte
Die Analyse der Anforderungen und die daran anschließende Entwicklung eines konzeptionellen Datenmodells sind bekanntlich systemneutral, d.h. unabhängig von dem eingesetzten Datenbanksystem. Anders verhält es sich dagegen bei der Umsetzung des konzeptionellen Modells in das physische Datenmodell. Hierbei sind die technischen Möglichkeiten des Zielsystems – in unserem Fall der OracleDatenbank – mit den funktionalen und operationalen Anforderungen der betreffenden Anwendung in Einklang zu bringen. Die folgenden Abschnitte behandeln vor diesem Hintergrund die verschiedenen technischen Möglichkeiten, Datenobjekte (Entitäten) in einer Oracle-Datenbank zu implementieren, und die mit diesen Möglichkeiten verbundenen Auswirkungen im Hinblick auf die Zugriffe und die Verwaltbarkeit der betreffenden Objekte. Ziel ist es dabei, die zur Verfügung stehenden Organisationsformen von Tabellen geschickt für die Optimierung von Zugriffen und Verwaltungsoperationen zu nutzen. Die Zeiten, in denen Entitäten einzig in Form von Heap-Tabellen oder Clustern implementiert werden konnten, sind lange vorbei. Mittlerweile existieren weitergehende Möglichkeiten der physischen Organisation, die – bei sinnvoller Nutzung – wesentlich zur Optimierung von Anwendungen und zur Vereinfachung der Administration beitragen können. Diese Organisationsformen sind im Einzelnen: die »klassischen« in Heap-Form organisierten Tabellen, die Daten unsortiert speichern partitionierte Tabellen, die physisch unabhängige Partitionen zu einer »logischen« Tabelle zusammenfassen indexorganisierte Tabellen, deren Daten über B*Baumstrukturen organisiert sind externe Tabellen, die auf externe, in Dateiform abgelegte Daten zugreifen temporäre Tabellen, die Daten für die Dauer einer Transaktion oder Session speichern im Cluster abgelegte Tabellen, deren Daten in Abhängigkeit von Cluster-Schlüsseln physisch gespeichert werden Objekttabellen, deren Datensätze über Objektbezeichner referenzierbar sind und welche die Einbettung von geschachtelten Tabellen (Nested Tables) erlauben Diese Organisationsformen werden mit ihren Besonderheiten in den folgenden Abschnitten im Detail besprochen.
176
Datenbankobjekte
5.2.1 Datentypen Alle Datenobjekte, die im Folgenden beschrieben werden, bestehen – bei allen Unterschieden in der physischen Speicherung – logisch gesehen aus beliebig vielen Zeilen mit einer festen Spaltenstruktur. Jede Spalte ist von einem bestimmten Datentyp, wobei in den allermeisten Fällen die eingebauten Oracle-Datentypen verwendet werden, die in diesem Abschnitt kurz beschrieben und untereinander verglichen werden sollen. In der objektrelationalen Welt können weitere, benutzerdefinierte Datentypen Verwendung finden. Davon wird in Abschnitt 5.2.8 berichtet. Die Standarddatentypen Einige Datentypen sind seit vielen Jahren und Versionen in der Oracle-Datenbank enthalten. Die Benutzung dieser Datentypen ist zu empfehlen, wenn nicht starke Argumente dagegen sprechen, da Bugs oder sonstige »Kinderkrankheiten« eher unwahrscheinlich sind und sie außerdem von allen Tools und Schnittstellen verstanden und unterstützt werden. Dazu gehören: VARCHAR2(n) und NVARCHAR2(n) für Zeichenketten bis zu 4000 Byte Länge. VARCHAR2 speichert Strings im Datenbank-Zeichensatz (CHARACTER SET-Klausel beim CREATE DATABASE-Kommando), NVARCHAR2 im Alternativ-Zeichensatz (NATIONAL CHARACTER SET-Klausel). Diese Datentypen haben beim Speicherverbrauch Vorteile gegenüber CHAR und NCHAR (s.u.). Auch die Typen VARCHAR und NVARCHAR (also ohne das Suffix »2«) sollten nicht benutzt werden (dies ist ein entscheidender Unterschied zu ANSI-SQL und muss bei Portierungen von Skripten für Fremddatenbanken berücksichtigt werden). Zu erwähnen ist noch, dass bei Zeichensätzen mit variabler Kodierungslänge (z.B. UTF8) oder fixen Kodierungslängen von mehr als einem Byte (z.B. AL16UTF16) Stringlänge und Byte-Zahl nicht identisch sind. Dies muss bei der Dimensionierung des Datentyps berücksichtigt werden. Der Platzverbrauch entspricht der Byte-Größe der konkreten Zeichenkette. CHAR(n) und NCHAR(n) speichern Zeichenketten der fixen Länge n Bytes (maximal 2000 Byte). Diese sollten daher auch nur benutzt werden, wenn die Zeichenkettenlänge einer Spalte für die gesamte Lebensdauer der Tabelle garantiert feststeht, z.B. für eine Spalte geschlecht = m | f. Werte einer Spalte vom Typ CHAR(n) belegen immer n Bytes. Das Einfügen längerer Zeichenketten liefert eine Fehlermeldung, kürzere Zeichenketten werden rechts mit Leerzeichen aufgefüllt. Beim Vergleich mit anderen CHAR- oder NCHAR-Feldern oder String-Konstanten wird der kürzere der beiden Operanden rechts mit Leerzeichen aufgefüllt und anschließend verglichen. In der Praxis ist daher nur CHAR(1) zu empfehlen, in allen anderen Fällen sollte stattdessen VARCHAR2(n) benutzt werden. NUMBER zur Speicherung von Zahlen. Im Hinblick auf Speicherplatz kann ruhigen Gewissens NUMBER ohne Dimensionierung verwendet werden. Der tatsächliche Speicherplatzverbrauch ergibt sich allein aus der Größe der konkret abgespeicherten Zahl. Soll der Wertebereich allerdings im Sinne einer Integritätsbedingung eingeschränkt werden, ist eine Dimensionierung à la NUMBER(10) oder NUMBER(8,2) besser und performanter als ein entsprechender CHECK-Constraint.
Datenobjekte
177
DATE für das Ablegen von Datumswerten und Zeitstempeln. Leider ist keine genauere Speicherung als auf Sekunden-Granularität möglich. Datumsarithmetik ist – etwas umständlich – durch Addieren oder Subtrahieren von Zahlen möglich, die als Anzahl Tage (oder entsprechende Bruchteile eines Tages) interpretiert werden. Der Platzverbrauch ist konstant 7 Byte. Für internationale Unternehmen taucht außerdem bisweilen als Problem auf, dass unterschiedliche Zeitzonen nicht berücksichtigt werden; es ist Aufgabe des Clients bzw. der Anwendung, die Ortszeit in eine Standardzeit (z.B. GMT) zu transformieren (siehe auch Kapitel 8.3). RAW(n) dient der Abspeicherung von Zeichenketten, die nicht gemäß der NLSEinstellung von Client und Datenbank transformiert, sondern in jedem Fall unverändert übertragen werden sollen. Dieser Datentyp ist für die Speicherung von Binärdaten oder Byte-Ketten zu empfehlen. Die Maximallänge beträgt 2000 Byte. Der Speicherbedarf entspricht der Byte-Größe der konkreten Byte-Kette (RAW ist also das Pendant zu VARCHAR2, einen Datentyp VARRAW gibt es nicht). CLOB, NCLOB und BLOB für Zeichenketten, die länger als 4000 Byte sind (Character Large Objects) sowie für umfangreiche Binärdaten (Binary Large Objects). Die Maximalgröße der abzuspeichernden Objekte ist jeweils (2^32 – 1) Oracle-Blöcke. Im Gegensatz zum Datentyp LONG (siehe unten) kann eine Tabelle mehrere LOBSpalten enthalten. Für jede LOB-Spalte kann ein eigenes so genanntes LOB-Segment in einem dedizierten Tablespace zur Speicherung der LOB-Werte angegeben werden (LOB-Klausel beim CREATE TABLE-Kommando). Über die Klausel ENABLE STORAGE IN ROW kann konfiguriert werden, dass LOB-Werte bis ca. 4 KB Länge in der Tabelle selbst gehalten werden, um das zusätzliche Lesen des LOB-Segments einzusparen. LOBs können über das Package dbms_lob abschnittweise geladen und manipuliert werden, die Byte-Größe der Abschnitte lässt sich über die CHUNK-Klausel einstellen (ein Vielfaches der Oracle-Blockgröße, maximal 32K). BFILE als Pointer auf eine externe Datei. Diese bilden die Alternative zu den erwähnten LOB-Varianten, wenn die Speicherung nicht in der Datenbank, sondern im Dateisystem erfolgen soll. Die eingebaute SQL-Funktion BFILENAME stellt eine Verknüpfung zwischen einer BFILE-Tabellenspalte und einer Datei her, Dateioperationen sind über das Package dbms_lob verfügbar. Neuere Datentypen In den Oracle-Versionen 9i und 10g sind einige Datentypen neu hinzugekommen. Diese sind zwar auf den ersten Blick redundant, da sie ebenfalls der Abspeicherung von Datumswerten und Zahlen dienen. Sie haben dennoch ihre Berechtigung, wie im Folgenden beschrieben wird: TIMESTAMP und INTERVAL dienen der Speicherung von Datumswerten und Zeitdauern. Im Gegensatz zu DATE braucht man hier nicht mehr mit winzigen Tagesbruchteilen zu arbeiten, um Datumsarithmetik durchzuführen, sondern kann die Sekunden, Minuten etc. direkt angeben. Dadurch werden auch Rundungsfehler vermieden. Zum Beispiel: SYSTIMESTAMP + INTERVAL '0:30' MINUTE TO SECOND statt SYSDATE + 1 / 24 / 60 / 2
178
Datenbankobjekte
Außerdem können Sekunden mit bis zu neun Nachkommastellen Genauigkeit gespeichert werden. Bei TIMESTAMP ist auch eine automatische Umrechnung entsprechend der Zeitzone des Clients möglich (TIMESTAMP WITH LOCAL TIME ZONE), was für internationale Unternehmen mit Clients in unterschiedlichen Zeitzonen eine erhebliche Vereinfachung bedeutet. Beide Datentypen entsprechen dem ANSI-SQL-Standard. Da sie bereits mit der Version 9i eingeführt wurden, ist mittlerweile auch eine Unterstützung durch die meisten Tools gegeben. BINARY_FLOAT und BINARY_DOUBLE können zur Speicherung von Fließkommazahlen nach dem IEEE 754-Standard verwendet werden. Die Vorteile sind hier die sehr kompakte Speicherung (4 bzw. 8 Byte) sowie die Möglichkeit, arithmetische Operationen extrem schnell direkt mit Maschinenbefehlen durchzuführen. Diese Datentypen gibt es erst seit Oracle 10g, so dass einige Tools sie noch nicht unterstützen. Außerdem können durch die Speicherung der Mantisse als Binärzahl unerwartete Rundungseffekte auftreten. Nicht empfohlene Datentypen Spalten vom Typ LONG bzw. LONG RAW können Zeichenketten bzw. Byteketten bis zu 2 GB Größe aufnehmen. Jedoch wird dieser Datentyp seit langem nur noch aus Kompatibilitätsgründen gepflegt und unterliegt zahlreichen Einschränkungen. So ist beispielsweise die Reorganisation oder das Verschieben einer Tabelle mit LONG-Spalte sehr aufwändig. Die meisten fortgeschrittenen Funktionalitäten arbeiten nicht mit Tabellen zusammen, die eine LONG-Spalte enthalten. Daher sollte statt LONG immer einer der LOB-Datentypen verwendet werden (s.o.). Bestehende LONG-Datentypen sollten entsprechend migriert werden. Dass Oracle selbst im Data Dictionary weiterhin an zahlreichen Stellen den Typ LONG einsetzt, ist schlicht unverständlich. VARCHAR(n) und NVARCHAR(n) (also ohne das Suffix »2«) sind bis einschließlich Oracle 10g mit den Datentypen VARCHAR2 und NVARCHAR2 äquivalent. Dies wird aber für die Zukunft seitens Oracle nicht garantiert. Die Benutzung dieser Datentypen wird von Oracle zurzeit nicht empfohlen. Werden CREATE-Skripte von anderen Datenbanken mit ANSI-SQL-Datentypen (z.B. DB2) benutzt, werden die ANSI-Datentypen [NATIONAL] CHARACTER VARYING konsequenterweise auch in [N]VARCHAR2 übersetzt. Der Datentyp UROWID kann zur Speicherung von ROWIDs, also von physischen Datensatzadressen verwendet werden. Die persistente Speicherung solcher Adressen ist aber gefährlich, da sich im Rahmen eines Neuaufbaus bzw. einer Reorganisation einer Tabelle alle Satzadressen ändern. Auch bei Replikationen zwischen eigenständigen Datenbanken kommt es zu Problemen, da die Satzadressen auf Quell- und Zieldatenbank unterschiedlich sind.
Datenobjekte
179
5.2.2 Tabellen Heap-organisierte Tabellen sind die »klassischen« Datenbanktabellen von OracleSystemen. Sie speichern ihnen zugewiesene Datensätze unsortiert in einem beliebigen, für Insert-Operationen zur Verfügung stehenden Oracle-Block. Bei einer neu angelegten, leeren Tabelle bedeutet dies, dass die Daten in der Reihenfolge der Insert-Operationen nacheinander – im Anschluss an den Header-Block – in die Blöcke des betreffenden Datensegmentes geschrieben werden. Im fortgeschrittenen Zustand der Tabelle, nachdem auch Delete- und Update-Operationen die Tabelle verändert haben, werden Datenblöcke, die für Insert-Operationen zur Verfügung stehen, über so genannte Freilisten oder Bitstrukturen (ASSM) verwaltet. Aufeinander folgende Insert-Operationen werden dadurch nicht zwangsläufig in physisch aufeinander folgende Blöcke geschrieben, sondern können beliebig verstreut werden. Der jeweilige »Höchststand« der Füllung wird durch die so genannte Hochwassermarke (High Water Mark) gekennzeichnet. Blöcke, die sich jenseits der Hochwassermarke befinden, haben demnach noch nie Datensätze für die betreffende Tabelle enthalten. Der Zugriff auf heap-organisierte Tabellen erfolgt entweder durch das vollständige Lesen der Tabelle (Full Table Scan) oder über eine vorgegebene Satzadresse. Beim vollständigen Lesen werden alle Blöcke vom Beginn des Segmentes bis zur Hochwassermarke gelesen. Bei dynamischen Tabellen mit einem hohen Anteil an Delete-Operationen kann dies bedeuten, dass entsprechend viele leere Blöcke gelesen werden müssen – ein typischer Fall für eine Reorganisation der betreffenden Tabelle. Der Zugriff über Satzadressen (Rowids) erfolgt dagegen gezielt auf bestimmte Blöcke in bestimmten, über Dateinummern identifizierten Dateien. Die Hochwassermarke und die »Datenlöcher« spielen in diesen Fällen keine Rolle. Die Satzadressen selbst werden in der Regel über entsprechende Indexzugriffe vom System ermittelt. Die Indizes werden in separaten Segmenten aufgebaut. Für aufwändig indizierte Tabellen kann der für Indizes benötigte Speicherplatz dem der Tabelle nahe kommen oder ihn gar überschreiten. Heap-organisierte Tabellen sind gut geeignet für Datenobjekte, die keine besonderen Anforderungen an die Menge der Daten, deren physische Speichersequenz oder deren Indizierung stellen. Heap-Tabellen sind darüber hinaus eine gute Standardlösung für den Fall, dass die genauen Anforderungen an die Speicherung nicht bekannt sind. Für größere Datenmengen eignen sich u.U. partitionierte Tabellen (s.u.) besser. Da die Partitionierungsoption aber immer noch eine kostenpflichtige Erweiterung der Enterprise Edition ist, werden für die meisten Datenbanken fast ausschließlich heap-organisierte Tabellen eingesetzt. Im folgenden Beispiel wird die Heap-Tabelle kunde mit den Attributen kdnr (Schlüssel), kname und kadresse erstellt. Die organization-Klausel ist dabei optional: CREATE TABLE kdnr kname kadresse ) ORGANIZATION
kunde ( NUMBER CONSTRAINT kunde_pk PRIMARY KEY, VARCHAR2(100), VARCHAR2(500) HEAP;
Listing 5.1: Erstellung einer heap-organisierten Tabelle
180
Datenbankobjekte
5.2.3 Partitionierte Tabellen Partitionierte Tabellen bieten die Möglichkeit, Datensätze nach vorgegebenen Verteilungskriterien physikalisch unabhängig, d.h. in separaten Tablespaces mit unterschiedlich Speicherparametern, zu speichern und diese Partitionen separat zu verwalten. Aus Sicht der Anwendung sind alle Daten über den Namen der partitionierten Tabellen les- und schreibbar, der Optimizer dagegen kennt die physikalische Aufteilung der Tabelle und ist in der Lage, entsprechende Zugriffspfade zu generieren. Die zu einer partitionierten Tabelle gehörenden Indizes lassen sich ebenso partitionieren – nach eigenständigen oder identischen Kriterien wie die Tabelle selbst. Durch die Aufteilung der Daten in »kleinere« Partitionssegmente kann grundsätzlich eine bessere Verwaltbarkeit und ein effizienterer Aufbau der Indizes erreicht werden. Die Optimierung von Zugriffen ist prinzipiell durch folgende Merkmale gegeben: Partitionen stellen eine im Vergleich zum übergeordneten logischen Objekt kleinere Einheit dar. Table-Scan-Operationen können – in Abhängigkeit von der betreffenden WHERE-Klausel – davon profitieren, indem sie bestimmte Partitionen operational ausklammern. Index-Bäume können – da sie partitionsspezifisch aufgebaut werden – flacher ausfallen, d.h., weniger Ebenen benötigen. Hierdurch können die EA-Operationen bei den Zugriffen minimiert werden. Bestimmte Tabellenoperationen, wie z.B. Joins, lassen sich parallel zwischen einzelnen Partitionen ausführen. Vereinfachte und verkürzte Verwaltungsroutinen sind prinzipiell möglich, weil: Partitionen einzeln hinzugefügt, gelöscht und aufgeteilt werden können. der Austausch der Daten zwischen Tabellen und Partitionen über sehr effiziente Switch-Operationen durchgeführt werden kann. Diese Vorteile sind prinzipiell möglich, ob sie jedoch konkret genutzt werden können, ist im Einzelfall durch eine sorgfältige Analyse zu ermitteln, bevor mit der Implementierung dieses Merkmals begonnen wird! Diese Analyse sollte die folgenden Kriterien berücksichtigen: 1. Die Priorisierung der Optimierungsziele. Wird mehr Wert auf eine effizientere Verwaltung oder auf die Optimierung der Zugriffe gelegt? 2. Die Größe der Objekte. Eine Tabelle mit wenigen tausend Zeilen ist mit Sicherheit nicht für die Partitionierung geeignet, eine mit vielen Millionen schon eher.
Datenobjekte
181
3. Die Art der Zugriffe. Indexzugriffe auf die betreffenden Objekte, die über die entsprechenden Satzadressen (Rowids) nur wenige Zeilen selektieren, wie sie im so genannten OLTP-Betrieb1 typisch sind, profitieren in der Regel wenig oder gar nicht von einer Partitionierung. Batch-Zugriffe, die Scans auf große Bereiche der Tabellen durchführen, profitieren dagegen von den kompakteren Partitionsbereichen und eventuell auch von flacheren Indexstrukturen. 4. Die Art der Verwaltung bzw. die DML-Charakteristik: Rolling Window-Anwendungen2, die Daten periodisch löschen und hinzufügen, sind vor allem dann geeignete Kandidaten, wenn die Partitionierungskriterien der Tabellen sich mit den Löschzyklen direkt oder indirekt3 synchronisieren lassen. Modifikationen der Partitionsstrukturen, wie z.B. das Löschen einer Partition, können dagegen die Reorganisation bestimmter Indizes notwendig machen und wirken aus diesem Grunde dem Ziel der Verwaltungsoptimierung entgegen. Eine Partitionierung kann erst dann empfohlen werden, wenn alle zu einer Priorisierung passenden Kriterien erfüllt werden. Für wirklich große Tabellen, d.h. Tabellen im Gigabyte-Bereich, sollte die Partitionierung auf jeden Fall in Erwägung gezogen werden. Typen der Partitionierung Es stehen mehrere unterschiedliche Partitionierungsmethoden zur Verfügung: Range-Partitioning Die Kriterien für die Partitionierung werden bei diesem Modell durch fest definierte Wertebereiche einer oder mehrerer Spalten vergeben. Für jede Partition wird über eine entsprechende Values-Klausel der begrenzende Spaltenwert vorgegeben, z.B. VALUES LESS THAN (2000). Auf diese Weise lässt sich auch von außen unmittelbar nachvollziehen, welche Daten in welcher Partition gespeichert sind: Wurde beispielsweise eine Partitionierung nach Jahren und Monaten durchgeführt, d.h., für jeden Monat jedes Jahres eine Partition aufgebaut, lassen sich Löschungen eines bestimmten Monats in einem bestimmten Jahr sehr einfach über das Löschen der betreffenden Partition realisieren. Gleichermaßen kann der Optimizer bei lesenden Bereichszugriffen bestimmte Partitionen »ausklammern« und die Zugriffe auf einzelne Partitionen beschränken. Diese Partitionierung ist überall dort angebracht, wo aufgrund der Tabellenstruktur und der Spaltenwerte »natürliche« Partitionierungskriterien vorliegen, die darüber hinaus auch annäherungsweise eine Gleichverteilung der Daten garantieren können.
1 2 3
OLTP steht für OnLine Transaction Processing und wird – im Gegensatz zum Batch-Betrieb – durch kleine Online-Transaktionen charakterisiert. Rolling Window = ein »Fenster« aktiv vorgehaltener Daten, z.B. Aufträge, die vom Tagesdatum aus zwei zurückliegende Jahre vorgehalten werden. Direkte Synchronisierung: Das Partitionierungskriterium fällt mit der Einheit Zyklus zusammen, z.B. Monat, Vierteljahr. Indirekte Synchronisierung: Die Einheiten fallen nicht zusammen, können aber zur Übereinstimmung gebracht werden, z.B. Tage gegenüber Monaten.
182
Datenbankobjekte
Hash-Partitioning Bei der Hash-Partitionierung übernimmt eine interne Hash-Funktion die Zuordnung einer Tabellenzeile zu einer Partition. Dies geschieht – wie auch bei der Range-Partitionierung – in Abhängigkeit von einer oder mehreren Partitionierungsspalten. Aufgrund der internen Hash-Funktion ist es jedoch für das Programm nicht absehbar, in welcher Partition ein vorgegebener Spaltenwert gespeichert wird. Daher wird hier während der Definition nur die Anzahl der gewünschten Partitionen vorgegeben. Das Löschen von Monatsdaten analog dem obigen Beispiel könnte daher in diesem Falle nicht über das Löschen der Partition realisiert werden. Beim Zugriff kann man dann von der Partitionierung profitieren, wenn mehrere Tabellen mit dem gleichen Schlüssel partitioniert wurden (Partition Join, siehe Kapitel 15). Auf der anderen Seite bietet die Hash-Partitionierung dort Vorteile, wo keine »natürlichen« Partitionierungskriterien vorliegen oder diese nur eine sehr ungleiche Verteilung der Daten aufweisen könnten. Um eine möglichst homogene Verteilung der Datensätze auf die einzelnen Partitionen zu gewährleisten, ist es darüber hinaus empfehlenswert, nur Spalten mit möglichst hoher Selektivität – eindeutige oder nahezu eindeutige Werte – als Kriterium auszuwählen. List-Partitioning Im Gegensatz zur Range-Partitionierung werden bei der List-Partitionierung keine festen Wertebereiche, sondern explizite, möglicherweise diskontinuierliche Werte als Kriterium vorgegeben. Aus diesem Grunde ist diese Methode überall dort empfehlenswert, wo keine natürlichen Wertebereiche vorliegen, trotzdem aber die Kontrolle über die Zuordnung von Spaltenwert und Partition erhalten bleiben soll, um beispielsweise das Löschen von Daten zu erleichtern. Derzeit lässt sich bei der List-Partitionierung – im Gegensatz zu den vorangehenden Methoden – nur eine einzige Spalte als Partitionierungskriterium definieren. Die Abgrenzung der einzelnen Partitionen wird – wie auch bei der Range-Partitionierung – über eine VALUES-Klausel erreicht. Composite-Partitioning Die Composite-Partitionierung stellt eine Kombination der oben genannten Methoden dar. Hierbei wird in erster Instanz eine Range-Partitionierung durchgeführt, innerhalb jeder Range-Partition werden dann in zweiter Instanz Subpartitionen nach der Hash-Methode oder nach der List-Methode angelegt. Jede Subpartition ist hierbei speichertechnisch unabhängig, d.h., sie kann mit eigenen Speicherparametern ausgestattet sein. Die Composite-Partitionierung ist vor allem für die Parallelisierung von DMLund Join-Operationen auf der Ebene der Subpartitionen interessant. Folgendes Beispiel soll dies kurz erläutern: Eine gedachte Tabelle auftrag sei auf Jahresund Monatsbasis range-partitioniert; die zugeordnete Tabelle kunden – wegen des fehlenden »natürlichen« Kriteriums – auf Basis der Kundennummer Hashpartitioniert. Beide Tabellen sind also – was die Kriterien ihrer Partitionierung betrifft – inkompatibel. Werden nun für die Tabelle auftrag Subpartitionen auf Basis der auch in ihr enthaltenen Kundennummer angelegt, entstehen »kompatible« Partitionen, für die sich parallele Join-Operationen für die einzelnen Partitionen durchführen lassen.
Datenobjekte
183
5.2.4 Indexorganisierte Tabellen (IOT) Indexorganisierte Tabellen speichern ihre Daten – sortiert nach dem Primärschlüssel – in Form eines B*-Indexbaumes. Im Gegensatz zu normalen B*-Indexbäumen enthalten die B*-Bäume von IOT-Tabellen jedoch auch Spalten, die nicht zu dem Tabellenschlüssel gehören. Es ist darüber hinaus möglich, bestimmte Spalten, die nicht zum Schlüssel gehören, »auszulagern«, d.h., außerhalb des B*-Baumes in einem separaten Segment – dem Überlaufbereich – zu speichern. Auf diese Weise können die Datensätze in den Blättern des Baumes kurz gehalten und dadurch der Baum kompakter aufgebaut werden. Es lassen sich auch so genannte Sekundärindizes für IOT-Tabellen definieren, um Zugriffe, die nicht über die Primärschlüsselspalten erfolgen, zu optimieren. Diese Sekundärindizes enthalten logische Satzadressen für den Zugriff auf den Indexbaum. Da Einträge in Indexbäumen durch INSERT- und UPDATE-Operationen und damit verbundenen Split-Operationen auf den Indexblättern möglicherweise verschoben werden, können Zugriffe über logische Satzadressen fehlschlagen. In diesen Fällen ist dann eine zusätzliche Scan-Operation über den Primärschlüssel notwendig, um den betreffenden Datensatz zu lesen. Im folgenden Beispiel wird die indexorganisierte Tabelle artikelpreis mit den Schlüsselspalten artnr, von_datum und bis_datum angelegt. Die Spalten kommentar und rabattliste werden dabei – sofern der Schwellenwert von 10 % pro Block und Datensatz überschritten wird – in einen Überlaufbereich ausgelagert, der sich im Tablespace ts_over befindet: CREATE TABLE artikelpreis( artnr VARCHAR2(20), von_datum DATE, bis_datum DATE, preis_euro NUMBER(6,2), kommentar VARCHAR2(2000), rabattliste NUMBER(4), CONSTRAINT pk_artikelpreis, PRIMARY KEY(artnr, von_datum, bis_datum) ) ORGANIZATION INDEX TABLESPACE ts_data PCTTHRESHOLD 10 INCLUDING preis_euro OVERFLOW TABLESPACE ts_over; Listing 5.2: Index-organized Table
Im nächsten Beispiel wird der Sekundärindex i$artpreis_rab für die Spalte rabattliste angelegt: CREATE INDEX i$artpreis_rab ON artikelpreis(rabattliste); Listing 5.3: Zusätzlicher Index auf IOT
Wie normale Indizes, so lassen sich auch indexorganisierte Tabellen zusätzlich komprimieren. Bei der Komprimierung werden die Spalten des Primärschlüssels in Präfix- und Suffixbereiche aufgeteilt und die wiederholt auftretenden Werte der Präfixe innerhalb eines Blockes unterdrückt. Durch die Komprimierung wird eine Verkürzung der Datensätze in den Blättern des Indexbaumes erreicht, die den Index kompakter und damit für EA-Operationen effizienter machen.
184
Datenbankobjekte
Im folgenden Beispiel wird die oben beschriebene Tabelle artikelpreis mit einer Komprimierung auf der ersten Schlüsselspalte artnr angelegt. Dementsprechend werden redundante Artikelnummern innerhalb eines Indexblattes unterdrückt: CREATE TABLE artikelpreis ( artnr VARCHAR2(20), von_datum DATE, bis_datum DATE, preis_euro NUMBER(6,2), kommentar VARCHAR2(2000), rabattliste NUMBER(4), CONSTRAINT pk_artikelpreis PRIMARY KEY(artnr, von_datum, bis_datum) ) ORGANIZATION INDEX COMPRESS 1 TABLESPACE ts_data PCTTHRESHOLD 10 INCLUDING preis_euro OVERFLOW TABLESPACE ts_over; Listing 5.4: IOT mit Komprimierung
Indexorganisierte Tabellen sind sehr gut geeignet für die Umsetzung aller Datenobjekte, die einen großen Teil ihres Informationsgehaltes aus den Schlüsselspalten beziehen. Hierbei schlägt vor allem die Einsparung von Speicherplatz zu Buche, da keine separaten Segmente für Tabellen und Indizes angelegt werden müssen. Mögliche Kandidaten sind z.B. so genannte Intersection-Tabellen, die n:m-Relationen4 des Datenmodells auflösen, und große Referenztabellen, die nur wenige Spalten enthalten, die nicht zum Schlüssel gehören.
5.2.5 Temporäre Tabellen Der Terminus »temporäre Tabellen« (Temporary Tables) ist etwas irreführend: Was an temporären Tabellen »flüchtig« ist, sind ihre Daten, keineswegs jedoch ihre im Data Dictionary definierte Struktur. Einmal angelegt sind sie – entsprechende Privilegien vorausgesetzt – für alle Benutzer sichtbar und benutzbar. Die Daten, die sie speichern, werden jedoch am Ende jeder Transaktion oder am Ende der betreffenden Session automatisch gelöscht. Sie sind grundsätzlich – auch nach einer COMMITOperation – nur für die gerade aktive Session sichtbar. Physisch speichern temporäre Tabellen ihre Daten in dem temporären Tablespace des anlegenden Benutzers, und dies auch erst zum Zeitpunkt der betreffenden Insert-Operation. Aus diesem Grunde führt die Verwendung der TABLESPACE-Klausel bei temporären Tabellen zu Fehlern. Sie können beliebig indiziert, über Views – auch zusammen mit regulären Tabellen – referenziert und mit Triggern belegt werden. DML-Operationen auf ihren Daten erzeugen nur Redo-Log-Informationen für ein eventuelles Rollback, nicht jedoch für die geänderten Datenblöcke.
4
Jedes A bezieht sich auf ein oder mehrere B, und umgekehrt kann sich jedes B auf ein oder mehrere A beziehen.
Datenobjekte
185
Im folgenden Beispiel wird die temporäre Tabelle load erzeugt, deren Daten bis zum Ende jeder Session erhalten bleiben sollen. CREATE GLOBAL TEMPORARY TABLE load ( startdate DATE, enddate DATE, class CHAR(20) ) ON COMMIT PRESERVE ROWS; Listing 5.5: Erstellen einer temporären Tabelle
Zum Einfügen und Selektieren von Daten werden herkömmliche SELECT- und INSERT-Befehle benutzt. Indizes werden über den CREATE INDEX-Befehl – ohne TABLESPACE- und STORAGE-Klausel – erzeugt, setzen allerdings voraus, dass die betreffende Tabelle in allen aktuell angemeldeten Sessions vollständig leer ist. CREATE INDEX tidxload ON load(class) * FEHLER in Zeile 1: ORA-14452: Versuch, einen Index auf einer schon verwendeten temporären Tabelle zu erstellen, zu ändern oder zu löschen Listing 5.6: Fehler bei der Indexerstellung einer IOT
Temporäre Tabellen sind sehr gut für die Zwischenspeicherung und spätere Konsolidierung von Daten geeignet. Beliebig viele Anwendungen mit gleichen Anforderungen an temporäre Speicherstrukturen können sich jeweils eine temporäre Tabelle teilen, ohne Bezeichner für die Identifizierung der eigenen Daten mitzuführen. Die Daten können dabei intern entstehen und intern weiterverarbeitet werden oder in einem ersten Schritt von externen Ressourcen geladen und dann intern konsolidiert werden. Durch das reduzierte Redo-Log-Volumen können temporäre Tabellen im Kontext großer Datenmengen verwendet werden. Ein weiterer Vorteil ist dadurch gegeben, dass sie ihren Speicherplatz nicht permanent in Form eines eigenen Segmentes anlegen, sondern diesen – beim Vorhandensein von Daten – aus dem Speichervolumen des temporären Tablespace beanspruchen. Leider ist es nicht möglich, parallele Abfragen oder parallele DML-Operationen auf Temporär-Tabellen auszuführen, außerdem können sie nicht partitioniert werden.
5.2.6 Externe Tabellen Seit der Version 9i ist es möglich, externe, im Dateisystem abgelegte Daten mit Hilfe von »externen« Tabellen so in die Datenbank zu integrieren, dass ihr lesender Zugriff über normale SQL-Befehle durchgeführt werden kann. UPDATE-, INSERT- und DELETE-Operationen sowie das Anlegen von Indizes sind dagegen in diesem Kontext nicht möglich. Die externen Daten können jedoch mit Hilfe von Funktionen und Ausdrücken beliebig abgefragt, in Views integriert, über Synonyme referenziert oder nach Spalten sortiert werden.
186
Datenbankobjekte
Externe Tabellen werden im Data Dictionary hinsichtlich ihrer Spaltenstruktur, der Lokation ihrer externen Daten sowie der für das Lesen der Daten notwendigen Formatmaske definiert. Der Zugriff auf die externen Daten erfolgt schließlich über einen in die Datenbank integrierten Treiber. Um mit externen Tabellen arbeiten zu können, muss zunächst einmal ein Directory-Objekt angelegt werden. Dies ist lediglich ein Alias-Name für ein Dateisystemverzeichnis auf dem Datenbankserver (siehe Abschnitt 5.7). Im folgenden Beispiel wird dem Datenbankverzeichnis dat_dir das externe Verzeichnis /home/oracle zugeordnet: CREATE OR REPLACE DIRECTORY dat_dir AS '/home/oracle'; Listing 5.7: Create Directory
Der Benutzer, der die externe Tabelle anlegen will, muss als Nächstes in der Datenbank Leserechte für dieses neue Datenbankverzeichnis erhalten: GRANT READ ON DIRECTORY dat_dir TO patrick;
Sollen die Zugriffe auf die externen Daten in einer Log-Tabelle protokolliert oder Formatverletzungen in eine Bad-Datei geschrieben werden, sind darüber hinaus Schreibrechte für das Verzeichnis zu vergeben: GRANT WRITE ON DIRECTORY dat_dir TO patrick;
Im nächsten Schritt kann dann die externe Tabelle – in diesem Fall neue_auftraege – definiert werden: CREATE TABLE neue_auftraege ( aufnr NUMBER (10), kdnr NUMBER (10), aufdatum DATE ) ORGANIZATION EXTERNAL ( TYPE ORACLE_LOADER DEFAULT DIRECTORY dat_dir ACCESS PARAMETERS ( RECORDS DELIMITED BY NEWLINE BADFILE dat_dir:'auftrag%p.bad' LOGFILE dat_dir:'auftrag%p.log' FIELDS TERMINATED BY "," OPTIONALLY ENCLOSED BY "'" ( "AUFNR" FLOAT EXTERNAL NULLIF "AUFNR"=BLANKS, "KDNR" FLOAT EXTERNAL NULLIF "KDNR"=BLANKS, "AUFDATUM" DATE "ddmmyyyyhh24miss" NULLIF "AUFDATUM"=BLANKS ) ) LOCATION ('neue_auftragsdaten.dat') ) PARALLEL 5 REJECT LIMIT UNLIMITED; Listing 5.8: Erstellung einer externen Tabelle
Datenobjekte
187
In diesem Beispiel wird die externe Tabelle neue_auftraege mit den Spalten aufnr, kdnr und aufdatum angelegt. Die zugrunde liegende Datei wird in der LOCATION-Klausel angegeben. Die Zeilen der Tabelle sollen sich aus den Zeilen dieser Datei ergeben (NEWLINE-Klausel); die Felder sind entsprechend durch Kommata getrennt gespeichert. Auf die Datei wird in diesem Fall über den Treiber ORACLE_LOADER – siehe die TYPE-Klausel – zugegriffen. Die Datei neue_auftragsdaten.dat kann durchaus mehr als die hier angegebenen »Spalten« enthalten, entsprechende, weiterführende Einträge werden ignoriert. Für den Fall, dass die »Spaltenwerte« der Datei sich nicht im Rahmen der definierten Datentypen und -längen – hier NUMBER(4) und VARCHAR2(10) – darstellen lassen, wird eine Fehlerdatei geschrieben – siehe die BADFILE-Klausel. In diesem Beispiel wird der Name der Datei mit der Prozessnummer des betreffenden Serverprozesses (Substitutionsvariable %p) qualifiziert. Jeder Zugriff wird darüber hinaus in einer Log-Datei – LOGFILE-Klausel – protokolliert. Zugriffe werden über die gewohnte SQL-Syntax generiert, die Selektion von Rowids ist jedoch – aus nahe liegenden Gründen – nicht möglich. Die PARALLEL-Klausel sorgt für eine Parallelisierung der Zugriffe, was jedoch nur für große Datenmengen Laufzeitvorteile mit sich bringt. Neben der Methode des Ladens über den Oracle Loader, die schon in Oracle9i möglich war, gibt es bei Oracle 10g auch die Möglichkeit, die Funktion des Data Pump für das Ein- und Auslesen der Daten zu nutzen (TYPE ORACLE_DATAPUMP). Damit ist es erstmals möglich, Daten über externe Tabellen zu entladen. Im Gegensatz zum Loader handelt es sich bei der Ausgabe allerdings um ein internes Oracle-Format, d.h., die Daten können auch nur über Data Pump weiter verarbeitet werden. Das folgende Beispiel erzeugt ein Dump-File (neue_auftragsdaten.dmp) als externe Tabelle. Durch den Befehl CREATE TABLE AS SELECT entfallen auf der Quellseite die Spaltenangaben. CREATE TABLE auftraege_ext ORGANIZATION EXTERNAL ( TYPE ORACLE_DATAPUMP DEFAULT DIRECTORY pump_dir ACCESS PARAMETERS ( LOGFILE 'auftraege.log') LOCATION ('auftragsdaten.dmp' )) AS SELECT aufnr, kdnr, aufdatum FROM demo.auftraege Listing 5.9: Externe Tabelle mit Data Pump erstellen
Mit einem SELECT-Befehl kann jetzt wie üblich auf diese externe Tabelle zugegriffen werden. Diese Methode bietet sich überall dort an, wo Tabelleninhalte in regelmäßigen Abständen zwischen Systemen transferiert werden müssen. Die erstellte Datei (auftragsdaten.dmp) kann allerdings nicht überschrieben werden, d.h., nach der Übertragung sollten Sie die Dump-Datei löschen und mit dem oben angegebenen Befehl bei Bedarf wieder neu anlegen. DML-Befehle sind bei externen Tabellen generell nicht möglich. Weitere Informationen über die Benutzung von Data Pump erhalten Sie in Kapitel 10.6.
188
Datenbankobjekte
Beachten sollten Sie außerdem, dass bei der Verwendung von externen Tabellen und der Angabe einer Log-Datei (LOGFILE) jeder Zugriff protokolliert wird. Wenn also eine größere Anzahl Benutzer auf die Daten zugreift, sollten Sie ohne LogDatei (NOLOGFILE) arbeiten. Externe Tabellen sind vor allem dort interessant, wo externe Daten konsolidiert und geladen werden müssen. Die Dateien können auf diese Weise direkt aus der Datenbank heraus – z.B. im Kontext von PL/SQL-Prozeduren – selektiert, die Daten über SQL-Funktionen entsprechend verdichtet, an Parameter- oder Referenztabellen gejoint und in interne Tabellen übernommen werden. Der aufwändige Aufruf von separaten Werkzeugen, wie z.B. SQL*Loader, ist damit in vielen Fällen nicht mehr notwendig. Ebenso ist es möglich, die der externen Tabelle zugeordneten Datendateien durch gleichnamige zu ersetzen. Dadurch kann der Datenbestand komplett ausgetauscht werden, ohne die Definition der externen Tabelle in der Datenbank ändern zu müssen.
5.2.7 Cluster In diesem Kapitel geht es nicht um Hardware-Cluster, sondern um eine spezielle Form der Speicherung von Daten. Daher sollten Sie, wenn Sie sich mit jemandem über »Cluster« unterhalten, frühzeitig abklären, was damit gemeint ist! In Clustern abgelegte Tabellen speichern Daten in Abhängigkeit von ClusterSchlüsseln in für diese Cluster-Schlüssel ausgewiesenen Datenblöcken. Teilen mehrere Tabellen einen Cluster-Schlüssel, können sie gemeinsam in einem Cluster angelegt werden. Entsprechend werden Datensätze mit gleichen Cluster-Schlüsseln gemeinschaftlich gespeichert. Die Zuordnung von Cluster-Schlüsseln zu Datenblöcken und der Zugriff auf diese Sätze wird über zwei unterschiedliche Verfahren – durch Indizierung und HashAlgorithmen – geregelt. Dementsprechend sprechen wir von Index-Clustern oder Hash-Clustern. Index-Cluster Bei Index-Clustern übernimmt ein B*-Index, der so genannte Cluster-Index, die Reservierung einzelner Blöcke für bestimmte Cluster-Schlüssel. Da der Index im Kontext der INSERT-Operationen gefüllt wird, erfolgt die Reservierung der Blöcke in der Reihenfolge, wie die INSERT-Operationen der Cluster-Schlüssel von den Programmen durchgeführt werden. Die Hochwassermarke wird bei leeren Index-Clustern – wie auch bei Heap-Tabellen – synchron zu den Insert-Operationen verschoben.
Datenobjekte
189
Im folgenden Beispiel wird der Index-Cluster testcl mit den Tabellen kunde und auftrag angelegt: CREATE CLUSTER kd_auftraege (kdnr NUMBER) INDEX; CREATE INDEX i$kd_auftraege ON CLUSTER kd_auftraege; CREATE TABLE kunden ( kdnr NUMBER, nachname VARCHAR2(100), vorname VARCHAR2(100) ) CLUSTER kd_auftraege (kdnr); CREATE TABLE auftraege ( aufnr NUMBER, kdnr NUMBER, aufdatum DATE ) CLUSTER kd_auftraege (kdnr); Listing 5.10: Index-Cluster
Hash-Cluster Beim Hash-Cluster ist die Reihenfolge der INSERT-Operationen nicht relevant für die Zuordnung der Datenblöcke zu den Cluster-Schlüsseln. Hier bestimmt eine HashFunktion den Block, in dem ein Cluster-Schlüssel zu speichern ist. Die Hash-Funktion gibt in der Regel den Blockversatz relativ zum Beginn des betreffenden Segmentes an. Damit nicht mehrere Cluster-Schlüssel einen Datenblock teilen, muss beim Anlegen eines Hash-Clusters die erwartete maximale Anzahl von ClusterSchlüsseln möglichst präzise angegeben werden. Diese Schlüsselanzahl bestimmt direkt die Anzahl der Blöcke, die unterhalb der Hochwassermarke bereitgehalten werden müssen – unabhängig davon, ob Daten eingefügt wurden oder nicht. Insert-Operationen bewegen daher nur dann die Hochwassermarke, wenn ein Blocküberlauf stattfindet. Im folgenden Beispiel wird der Hash-Cluster testclh mit den Tabellen kundeh und auftragh angelegt. Es werden 1.000 Cluster-Schlüssel erwartet. Entsprechend werden 1.000 Blöcke initialisiert. Die Hash-Funktion arbeitet – spezifiziert durch die hash is-Klausel – auf Basis der numerischen Spalte kdnr: CREATE CLUSTER kd_auftraege (kdnr NUMBER) HASHKEYS 1000 HASH IS kdnr; CREATE TABLE kunden ( kdnr NUMBER, nachname VARCHAR2(100), vorname VARCHAR2(100) ) CLUSTER kd_auftraege (kdnr); CREATE TABLE auftraege ( aufnr NUMBER, kdnr NUMBER, aufdatum DATE ) CLUSTER kd_auftraege (kdnr); Listing 5.11: Hash-Cluster
190
Datenbankobjekte
Cluster-Implementierungen sind keine Standardlösungen, sie sollten sorgfältig geplant werden. Generell können sie die folgenden Vorteile bieten: »Physische Joins« durch die Speicherung mehrerer Tabellen in einem Cluster, sofern der Cluster-Schlüssel identisch mit dem Join-Schlüssel ist. Adressierung der Datensätze im Hash-Cluster ohne Vorhandensein eines Index »sortierte« Speicherung der Datensätze Diesen Vorteilen steht jedoch eine Reihe von Nachteilen gegenüber: Für den Fall, dass nur eine der im Cluster abgelegten Tabellen gelesen wird, kommt es zu einer erhöhten Anzahl an Blockzugriffen. Nur partiell gefüllte Hash-Cluster führen ebenfalls zu einer erhöhten Anzahl von Blockzugriffen. Ungenügende Füllung von Cluster-Blöcken bei »geringem« Datenvolumen pro Cluster-Schlüssel; umgekehrt Verkettung von Cluster-Blöcken (Überlauf) bei »großem« Datenvolumen pro Cluster-Schlüssel; nicht einschätzbare Wirkungen bei »schwankendem« Datenvolumen pro Cluster-Schlüssel. Die Eindeutigkeit kann nur über zusätzliche Indizes sichergestellt werden, die zusätzlichen Speicherplatz kosten. Ineffiziente Segmentgrößen bei Hash-Clustern, wenn die Anzahl der ClusterSchlüssel nicht bekannt ist oder falsch eingeschätzt wurde. Die Hash-Funktion kann nur für Gleichheitsoperatoren genutzt werden. Cluster können nicht repliziert und partitioniert werden. Diese Überlegungen machen deutlich, dass Cluster-Implementierungen nur selten zum Einsatz kommen dürften.
5.2.8 Objekttypen und Kollektoren Seit der Version 8.0 des Oracle-Datenbanksystems steht eine Reihe objektrelationaler Merkmale zur Verfügung. Die Liste dieser Merkmale wurde unter Oracle8i und – vor allem – unter Oracle9i erweitert, so dass nun eine beachtliche Bandbreite objektorientierter Techniken – inklusive der Vererbung und Polymorphie – für Designimplementierungen zur Verfügung stehen. Eine ausführliche Besprechung dieser Merkmale liegt außerhalb der Ziele dieser Publikation. Auf den folgenden Seiten soll jedoch ein kurzer Überblick über die Möglichkeiten gegeben werden, konzeptionelle Vorgaben in Oracle 10g umzusetzen. Objekttypen Objekttypen sind die Grundbausteine der objektorientierten Welt. Sie werden im Kontext von Oracle auch als »benutzerdefinierte Datentypen« (user-defined Datatypes) bezeichnet. Objekttypen bestehen ihrerseits aus Attributen und Methoden. Attribute sind entweder skalare Datentypen, wie z.B. NUMBER und VARCHAR2, Referenzen oder andere benutzerdefinierte Datentypen. Methoden (Member Functions) sind Prozeduren oder Funktionen, die relevante Abläufe für die Objekte des betreffenden
Datenobjekte
191
Typs abbilden. Methoden können in PL/SQL oder Java codiert und als solche in der Datenbank gespeichert werden. Methoden, die in anderen Sprachen – z.B. C – realisiert wurden, werden dagegen extern gehalten, sind aber über gespeicherte Prozeduren ansprechbar. Neben den vom Benutzer frei definierbaren Methoden gibt es vordefinierte Methoden: Konstruktoren (Constructor Methods) dienen dem Anlegen und Ändern von Objekten eines Typs und heißen so wie der Objekttyp selbst. Objekttypen sind sehr gut geeignet, wieder verwendbare Attributgruppen mit für sie relevanten Prozedurabläufen zu definieren und in unterschiedlichen – relationalen wie objektrelationalen – Schemakontexten einzusetzen. Im folgenden Beispiel wird der Objekttyp adresse angelegt, der aus den Attributen strasse, postfach, plz , ort und land besteht. CREATE OR REPLACE TYPE adresse AS OBJECT ( strasse VARCHAR2(50), postfach VARCHAR2(20), plz VARCHAR2(20), ort VARCHAR2(50), land VARCHAR2(50) ); Listing 5.12: Objekttyp
Einmal definiert, lassen sich Objekttypen als Spaltenobjekte (Column Object) oder Zeilenobjekte (Row Object) verwenden. Spaltenobjekte Objekttypen, die als Attribute in anderen Objekttypen oder in relationalen Tabellen verwendet werden, bezeichnet man als Spaltenobjekte. Auf diese Weise lassen sich Objekttypen als »Attributgruppen« beliebig oft einsetzen. Im folgenden Beispiel wird die relationale Tabelle firma angelegt, die – neben zwei skalaren Attributen – den Objekttyp adresse verwendet: CREATE TABLE firma ( id INTEGER CONSTRAINT pk_firma PRIMARY KEY, name VARCHAR2(100), anschrift adresse ); Listing 5.13: Erstellen einer Tabelle mit Objekttypen
INSERT-Operationen für diese Tabelle müssen den – mit dem Objekttyp automatisch vordefinierten – Konstruktor adresse verwenden: INSERT INTO firma VALUES (1,'Database Consult', adresse(NULL,NULL,'83676','Jachenau',NULL) ); Listing 5.14: Einfügen in eine Tabelle mit Objekttypen
192
Datenbankobjekte
Für den Zugriff auf einzelne skalare Attribute des Objekttyps adresse ist der Attributname der implementierenden Tabelle und der des Objekttyps anzugeben. Im folgenden Beispiel werden entsprechend nur der Firmenname und Ort selektiert: SELECT f.name, f.anschrift.ort FROM firma f;
Die – für relationale Begriffe – ungewohnte Syntax lässt sich nötigenfalls durch eine View kaschieren: CREATE VIEW firma_view AS SELECT f.name name , f.anschrift.ort ort FROM firma f; SELECT name, ort FROM firma_view; Listing 5.15: View auf eine objektrelationale Tabelle
Spaltenobjekte liegen auch dann vor, wenn Objekttypen in anderen Objekttypen verwendet werden. Der Objekttyp person verfährt so: CREATE OR REPLACE TYPE person AS OBJECT( vorname VARCHAR2(30), nachname VARCHAR2(30), anschrift adresse );
Objekttabellen und Zeilenobjekte Objekttypen, die vollständige Zeilen in Objekttabellen definieren, werden als Zeilenobjekte bezeichnet. Zeilenobjekte lassen sich aus Objekttypen heraus referenzieren. Im folgenden Beispiel wird die Objekttabelle personen auf der Basis des Objekttyps person angelegt: CREATE TABLE personen OF person OBJECT IDENTIFIER IS SYSTEM GENERATED;
Die in Objekttabellen gespeicherten Objekte werden über Objektbezeichner (Object Identifier) referenziert. Standardmäßig legt Oracle – wie in diesem Beispiel (... IDENTIFIER IS SYSTEM GENERATED ...) – eine interne OID-Spalte in der Länge von 16 Byte für die interne Referenzierung der Objekte an. Alternativ lässt sich auch der Primärschlüssel einer Tabelle hierzu einsetzen (… IDENTIFIER IS PRIMARY KEY ...), der jedoch nicht – wie der generierte Bezeichner – eine globale Eindeutigkeit garantiert und ggf. auch mehr Speicherplatz benötigt. Auch im Falle der Objekttabellen werden die Attributwerte über Konstruktoren eingefügt: INSERT INTO personen VALUES ('Otto','Müller', adresse(NULL,NULL,'PLZ','Ort',NULL) );
Zeilenobjekte lassen sich über ihre Objektbezeichner referenzieren. Im nächsten Beispiel wird zunächst der Objekttyp auftrag angelegt, dessen Attribut auftraggeber den Objekttyp person referenziert:
Datenobjekte
193
CREATE OR REPLACE TYPE auftrag AS OBJECT ( aufnr INTEGER, datum DATE, auftraggeber REF person, kommentar VARCHAR2(500) );
Im zweiten Schritt wird nun die Objekttabelle auftraege auf der Basis des Typs auftrag angelegt: CREATE TABLE auftraege OF auftrag;
Damit das Attribut auftraggeber der Objekttabelle auftraege nicht alle möglichen Tabellenimplementierungen des Objekttyps person referenziert, wird der Gültigkeitsbereich dieses Attributes in der Tabelle auftraege im folgenden Beispiel auf die Objekte der Objekttabelle personen beschränkt. Mit anderen Worten: Das Attribut auftraggeber der Tabelle auftraege referenziert nur Datensätze aus der Tabelle personen: ALTER TABLE auftraege ADD(SCOPE FOR (auftraggeber) IS personen);
Durch die Einschränkung des Gültigkeitsbereiches über die SCOPE-Klausel wird auch die interne Speicherung des betreffenden Attributes optimiert! Einschränkungen sollten daher nach Möglichkeit durchgeführt werden. Für das Einfügen von Personenreferenzen in die neue Tabelle ist der REF-Operator zuständig, der, wie das Beispiel zeigt, über einen eindeutigen (!) Zugriff auf die Tabelle personen den Objektbezeichner zuordnet: INSERT SELECT FROM WHERE AND
INTO auftraege 12345, SYSDATE, REF(p), 'Kommentar' personen p p.nachname = 'Müller' p.vorname = 'Otto';
Beim Selektieren der Auftragsdaten ist die Syntax – dank der Möglichkeit der impliziten Dereferenzierung – einfacher. Für diese Dereferenzierung muss auf jeden Fall ein Alias-Name angegeben werden: SELECT a.aufnr, a.auftraggeber.nachname, a.auftraggeber.vorname FROM auftraege a /
Kollektionen Kollektionen lassen sich als Behältnis für mehrere gleichartige Objekte begreifen. Es stehen zwei unterschiedliche Typen von Kollektionen bereit: Varrays – sind geordnete Kollektionen von Elementen gleichen Datentyps, deren maximale Anzahl bei der Definition festgelegt wird und nicht überschritten werden kann. Einzelne Elemente von Varray-Kollektionen können darüber hinaus nicht beliebig gelöscht und eingefügt werden. Varrays können als Datentypen für Attribute relationaler Tabellen oder für Attribute von Objekttypen verwendet werden.
194
Datenbankobjekte
Nested Tables – sind ungeordnete Kollektionen von Elementen gleichen Datentyps, die nicht in ihrer Maximalzahl festgelegt werden und aus nur einem Attribut bestehen. Das Attribut einer geschachtelten Tabelle ist entweder ein skalarer Datentyp oder ein Objekttyp. Geschachtelte Tabellen werden – wie auch Varrays – als Datentypen für Attribute relationaler Tabellen oder für Attribute von Objekttypen verwendet. Im folgenden Beispiel wird das Varray telnummern angelegt, das die Speicherung von maximal zehn Telefonnummern pro Objektinstanz gestattet: CREATE OR REPLACE TYPE telnummern AS VARRAY(10) OF VARCHAR2(20);
Dieses Varray kann nun in dem Objekttyp pers_tel verwendet werden: CREATE OR REPLACE TYPE pers_tel AS OBJECT ( personenangabe person, telefon telnummern ); Listing 5.16: Objekttabelle mit VARRAY
pers_tel kann dann – wie oben beschrieben – weiterverwendet werden. Zum Einfü-
gen von Varray-Attributen stehen ebenfalls vordefinierte Konstruktoren bereit: in diesem Fall z.B. telnummern('nr1', 'nr2'). Im nächsten Beispiel wird der Objekttyp auftragsposition angelegt, der dann im Folgenden für die geschachtelte Tabelle auftragspositionen benutzt wird. CREATE OR REPLACE TYPE auftragsposition AS OBJECT (posnr INTEGER, anzahl INTEGER, prodid VARCHAR2(20)); CREATE OR REPLACE TYPE auftragspositionen AS TABLE OF auftragsposition /
Der tabellarische Objekttyp auftragspositionen kann nun in einen weiteren Objekttyp auftraege_pos integriert werden: CREATE OR REPLACE TYPE auftraege_pos AS OBJECT (auftragkopf auftrag, pos_tab auftragspositionen);
Schließlich wird dieser Objekttyp dazu benutzt, die endgültige Objekttabelle auftraege_positionen mit der geschachtelten Tabelle pos_tab_table anzulegen: CREATE TABLE auftraege_positionen OF auftraege_pos NESTED TABLE pos_tab STORE AS pos_tab_table ( (PRIMARY KEY(NESTED_TABLE_ID,posnr)) ORGANIZATION INDEX COMPRESS) RETURN AS LOCATOR; Listing 5.17: Objekttabelle mit Nested Table
Die Kopplung der Haupttabelle mit der geschachtelten Tabelle wird über die interne Spalte nested_table_id gewährleistet. Für den Fall, dass die geschachtelte Tabelle – wie in diesem Fall – einen Primärschlüssel enthält, kann sie als IOT angelegt und der Indexbaum zusätzlich komprimiert werden. Die Speicherung als Index hat die Sortierung der Daten (Clustering) mit der nested_table_id als Präfix zur
Indexstrukturen
195
Folge. Durch die Komprimierung wird die Wiederholung gleicher Werte von nested_table_id unterdrückt und die Tabelle dadurch kompakter. Statt der gesamten Daten wird ferner nur ein Locator für den Zugriff zurückgegeben, was besonders bei geschachtelten Tabellen mit vielen Elementen empfehlenswert ist. Das Füllen der Objekttabelle auftraege_positionen geschieht in zwei Phasen: Zunächst wird ein Auftragskopfsatz über Konstruktoren mit einer leeren Referenz in die geschachtelte Tabelle eingefügt: INSERT INTO auftraege_positionen VALUES (auftrag(123,SYSDATE,NULL,NULL),auftragspositionen());
In der zweiten Phase wird mit Hilfe des TABLE-Ausdrucks die geschachtelte Tabelle für den Auftrag 123 mit einem Element gefüllt: INSERT INTO TABLE( SELECT a.pos_tab FROM auftraege_positionen a WHERE a.auftragkopf.aufnr = 123) VALUES(1,3,222); Listing 5.18: Einfügen in eine nested Table
5.3
Indexstrukturen
Indizes sind für relationale Datenbanksysteme aus verschiedenen Gründen unerlässlich: Auf der einen Seite helfen sie – richtig aufgebaut – bei der Optimierung von Zugriffen, auf der anderen Seite können sie – als so genannter Unique Index – eindeutige Wertemengen garantieren. Für den Datenbankadministrator wie auch den Anwendungsentwickler gruppieren sich unterschiedliche Aufgabenbereiche um die Welt der Indizes: 1. Im Zuge der Datenmodellierung gilt es, geeignete Attribute für die Indizierung auszusuchen. 2. Wird das physikalische Modell aufgesetzt, müssen den Indexkandidaten konkrete Indizes bzw. Indextypen zugewiesen werden. 3. Die Indizes des physikalischen Modells werden dann mit geeigneten StorageKlauseln (z.B. Tablespace) angelegt. 4. Im laufenden Betrieb schließlich müssen die Indizes überwacht und bei Bedarf reorganisiert werden. Gleichfalls kann es notwendig sein, konkrete Zugriffspläne einzelner SQL-Befehle zu generieren, hinsichtlich ihrer Indexnutzung zu analysieren und – falls notwendig – die Indexstrukturen zu optimieren. Das vorliegende Kapitel beschäftigt sich vornehmlich mit Punkt 2 der oben angeführten Aufgabenliste, nämlich der Umsetzung einer Indexanforderung in einen konkreten Index eines bestimmten Indextyps. In Oracle 10g steht uns eine Reihe unterschiedlicher Indextypen zur Verfügung. Neben den »klassischen« B*Bäumen können wir u.a. Bitmap-Indizes, Reverse Key-Indizes oder funktionale Indizes anlegen. Die genaue Kenntnis dieser einzelnen Indextypen und ihrer Charakteristika ist für eine optimale Indeximplementierung mindestens genauso wichtig wie die Entscheidung darüber, welche Attribute welcher Tabellen in welcher Gruppierung indiziert werden sollen.
196
Datenbankobjekte
5.3.1 Allgemeine Regeln Indizes lassen sich im Kontext von Tabellen und Clustern anlegen. Vorhandene Indizes werden durch INSERT, UPDATE oder DELETE-Befehle automatisch verändert, was bei einer großen Zahl von Indizes und entsprechendem DML-Aufkommen messbare Folgen haben kann. Über die Nutzung von Indizes für konkrete SQLZugriffe entscheidet der Optimizer, beeinflusst durch die Syntax des betreffenden SQL-Befehls, vorhandene Statistiken oder konkrete Anweisungen (Hints). Indizes lassen sich eindeutig (unique) oder nicht eindeutig (non-unique) anlegen. Es können sowohl einzelne Spalten als auch Spaltengruppen indiziert werden. Im letzteren Fall handelt es sich um zusammengesetzte Indizes (concatenated Index, composite Index). Die maximale Anzahl von Spalten, die in zusammengesetzten Indizes gruppiert werden können, liegt – abhängig vom Indextyp – zwischen 30 und 32. Wichtig ist beim Aufbau von zusammengesetzten Indizes vor allem die Reihenfolge der Spalten, entscheidet sie doch über die Nutzung seitens des Optimizers5. Indizes lassen sich technisch in beliebiger Anzahl für jede Tabelle erzeugen, solange sich die Kombination der Spalten für jeden Index unterscheidet. Demnach sind mehrere Indizes auf einer Spalte oder einer Spaltengruppe mit gleichen Spalten in gleicher Reihenfolge nicht möglich. Indizes sind logisch wie physisch von den Tabellen, auf die sie sich beziehen, in dem Sinne unabhängig, als sie angelegt, gelöscht oder reorganisiert werden können, ohne dass Programme ihre Funktionsfähigkeit verlieren. Die einzige Auswirkung kann die Beeinflussung der Laufzeit von Zugriffen sein. Indizes verwalten ihre Daten in sortierten Listen. Die sortierten Listen der Schlüssel werden dabei auf einzelne Oracle-Blöcke, die so genannten Indexblätter (Leaf Node) verteilt. Zeiger auf die Endpunkte dieser Indexblätter werden in einem Indexbaum in so genannten Indexzweigen (Branch Node) zusammengefasst, die den schnellen Zugriff auf konkrete Schlüsselwerte garantieren.
Abbildung 5.1: Struktur eines Indexbaums 5
Zusammengesetzte Indizes können in der Regel nur genutzt werden, wenn alle oder die führenden Spalten spezifiziert werden.
Indexstrukturen
197
Die oben abgebildete Grundstruktur wird im Rahmen eines Segments für jeden Index, unabhängig von seinem Typ, aufgebaut. Die Art, in welchem Format und in welcher Sortierung die Daten in den Indexblättern gespeichert werden, ist dagegen unterschiedlich und hängt von dem verwendeten Indextyp ab. Suchvorgänge in Indizes beginnen bei dem so genannten Wurzelblock (Root Block) und gelangen über die »Zweige« des Indexbaumes zu den »Blättern«, über die schließlich die Satzadresse (Rowid) des gesuchten Schlüsselwertes ermittelt wird. Der Zugriff auf den gewünschten Datensatz erfolgt dann über die ermittelte Adresse. Da die Blätter von Indexbäumen auch untereinander durch Pointer verbunden sind, lassen sich Bereichszugriffe (Range Scans) ohne erneuten Einstieg über die Wurzel realisieren. Prinzipiell können Indizes nur dann vom Optimizer genutzt werden, wenn die betreffende SQL-Anweisung Prädikate enthält, welche die indizierten Spalten referenzieren. Bei zusammengesetzten Indizes müssen dies in der Regel alle oder zumindest die führenden Spalten sein. Eine Ausnahme ist der so genannte SkipScan, der die führende Spalte überspringen kann, wenn diese nur wenige unterschiedliche Werte (geringe Kardinalität) aufweist. Die Indexnutzung ist darüber hinaus abhängig vom verwendeten Operator: Mit Ausnahme von Ungleich-Operatoren und Like-Operatoren, die führende Platzhalter haben, sind alle Operatoren für Indexzugriffe geeignet. Enthält die SQL-Anweisung mehrere indizierte Prädikate, kann der Optimizer die betreffenden Indizes für den Zugriff mischen (merge). Indizes werden als Segmente in Oracle-Datenbanken verwaltet und gespeichert. Als solche lassen sie sich – unabhängig von der ihnen zugeordneten Tabelle – mit eigenen Storage-Klauseln und in separaten Tablespaces organisieren. In den folgenden Abschnitten werden die Besonderheiten der einzelnen Indextypen vorgestellt.
5.3.2 B*Tree Index B*Indizes sind die »klassischen« Indizes in Oracle-Datenbanken. Im folgenden Beispiel wird ein nicht eindeutiger B*Index mit Namen idx_ang_name für die Spalte name der Tabelle angestellte aufgebaut. CREATE INDEX idx_ang_name ON angestellte (name);
Für den Aufbau dieses Index werden die Spaltenwerte von name sortiert. Jeder Name wird zusammen mit der ihm zugehörigen Satzadresse (Rowid) in den Indexblättern gespeichert. Über die Blätter wird dann der restliche Indexbaum erzeugt. Da die Syntax keine Storage-Klausel enthält, wird das Indexsegment in diesem Fall im DefaultTablespace des betreffenden Schemabenutzers angelegt. B*Indizes enthalten keine NULL-Werte, es sei denn, es handelt sich um zusammengesetzte Indizes. D.h., Abfragen mit IS NULL-Klauseln können einen solchen Index in der Regel nicht benutzen. Im zweiten Beispiel wird ein zusammengesetzter Index erzeugt, der an erster Stelle die Abteilungsnummer und an zweiter den Namen setzt. CREATE INDEX idx_ang_abtname ON angestellte (abtnr, name) TABLESPACE indx;
198
Datenbankobjekte
B*Indizes lassen sich wie folgt charakterisieren: Sie zeigen – im Gegensatz zu den weiter unten beschriebenen Bitmap-Indizes – ein gutes, weil die Gleichzeitigkeit von Transaktionen förderndes Sperrverhalten. Sperren werden hier auf der Basis einzelner Einträge durchgeführt und verursachen dadurch keine unnötigen Wartezustände bei gleichzeitig operierenden Transaktionen. Ihr Speicherbedarf ist auf der anderen Seite größer als der von Bitmap-Indizes. Dies führt zu höheren »Kosten« beim Zugriff, da mehr Indexblöcke gelesen werden müssen. Durch den höheren Speicherbedarf sind Mischoperationen (Merge) mit B*Indizes aufwändiger als bei Bitmap-Indizes. Zur Vermeidung unnötiger Mischoperationen kann statt einzelner Indizes ein zusammengesetzter Index angelegt werden. Aufgrund der oben beschriebenen Charakteristika sind B*Indizes überall dort einsetzbar, wo die folgenden Kriterien zutreffend sind: Die betreffenden Spalten werden in Prädikaten referenziert und vom Optimizer als Zugriffspfad akzeptiert. Die Spalten werden prinzipiell über DML-Befehle verändert (Sperrverhalten). Die Referenzierung der Spalten in den Prädikaten erfolgt in direkter Form, d.h., die Spalten werden dort nicht über Funktionen und Ausdrücke verändert. Zu Recht sind aus diesen Gründen B*Indizes die Oracle-Indizes, die in den meisten Fällen zum Einsatz kommen können.
5.3.3 Bitmap-Index Im Gegensatz zu B*Indizes speichern Bitmap-Indizes ihre Schlüssel nicht mit den zugehörigen Satzadressen, sondern in Form von Bitmaps. Zu jedem Spaltenwert der Tabelle enthält der Bitmap-Index eine logische Bitmap. Diese Bitmap enthält in ihrem Kopf eine Start- und Schlussadresse, gefolgt von der eigentlichen Bitmap, bei der jede Bitposition einem Satz der zugeordneten Tabelle entspricht. Enthält der betreffende Datensatz den der Bitmap zugeordneten Spaltenwert, steht das Bit auf 1, ansonsten auf 0. Die Umrechnung einer Bitposition in eine Satzadresse erfolgt mit Hilfe der Kopfdaten und eines – gedachten – Rasters. Das Raster jeder Bitmap einer Tabelle ergibt sich aus der maximalen Anzahl von Datensätzen pro Block. Diese Anzahl wiederum wird beim Aufbau des Bitmap-Index aus der minimalen Satzlänge errechnet. Logische Bitmaps werden bei der Speicherung in physische Bitmaps aufgeteilt, wobei maximal zwei physische Bitmaps in einem Oracle-Block Platz finden. Um den Speicherbedarf weiter zu optimieren, werden aufeinander folgende Nullen in den Bitmaps komprimiert.
Indexstrukturen
199
Die folgende Abbildung zeigt den Aufbau einer Bitmap.
Abbildung 5.2: Struktur einer Bitmap
Auf die physischen Bitmaps eines Bitmap-Index wird über eine Baumstruktur – vergleichbar einem B*Index – zugegriffen. Im folgenden Beispiel wird der nicht eindeutige Bitmap-Index bidx_ang_dat für die Spalte einstelldatum der Tabelle angestellte aufgebaut: CREATE BITMAP INDEX bidx_anrede ON kunden(anrede);
Auch dieser Index wird – wegen der fehlenden Storage-Klausel – im Default-Tablespace des betreffenden Schemas angelegt. Der Speicherplatz, der für die Sortierung der Daten und den Aufbau der Bitmaps notwendig ist, wird in der Regel im Rahmen der dynamischen PGA-Verwaltung (pga_aggregate_target bzw. workarea_size_policy) verwaltet. Alternativ kann er über den Serverparameter create_bitmap_area_size eingestellt werden, dessen Standardwert 8 MByte beträgt. Eine weitere Optimierung der Bitmap-Indizes lässt sich über die Festlegung der maximalen Anzahl von Datensätzen pro Oracle-Block erreichen: ALTER TABLE kunden MINIMIZE RECORDS_PER_BLOCK;
Dieser Befehl sorgt dafür, dass die maximale Anzahl von Datensätzen pro Block für die betreffende Tabelle festgeschrieben wird und zukünftige INSERT-Operationen diese vorgegebene Marke nicht überschreiten. Auf diese Weise müssen die Bitmaps nicht auf der Basis der theoretisch maximal möglichen Blockfüllung kalkuliert werden, sondern können auf Basis der konkret vorgefundenen Anzahl von Datensätzen pro Block angegeben werden. Der Befehl kann nur dann abgesetzt werden, wenn die Tabelle bereits Datensätze, aber noch keinen Bitmap-Index enthält. Im Gegensatz zu B*Indizes werden in Bitmap-Indizes auch Null-Werte erfasst, d.h., ein Prädikat mit einer IS NULL-Klausel kann über den Index aufgelöst werden. Bitmap-Indizes können – wie B*Indizes – auch als zusammengesetzte Indizes angelegt werden. Eindeutige Bitmap-Indizes dagegen sind nicht erlaubt. Bitmap-Indizes werden grundsätzlich nur über den statistischen Optimizer genutzt; sie existieren nicht für den regelbasierten Optimizer. Der folgende Zugriffsplan6 verdeutlicht die Nutzung eines Bitmap-Indexes für den Zugriff auf Nullwerte: 6
Der Plan wurde in SQL*Plus über den Befehl Set Autotrace On generiert.
200
Datenbankobjekte
SELECT * FROM kunden WHERE anrede IS NULL; Execution Plan ---------------------------------------------------------0 SELECT STATEMENT Optimizer=ALL_ROWS (Cost=1 Card=1 Bytes=63) 1 0 TABLE ACCESS (BY INDEX ROWID) OF 'KUNDEN' (TABLE) (Cost=1 Card=1 Bytes=63) 2 1 BITMAP CONVERSION (TO ROWIDS) 3 2 BITMAP INDEX (SINGLE VALUE) OF 'BIDX_ANREDE' (INDEX (BITMAP)) Listing 5.19: Bitmap-Index-Ausführungsplan
Die Operation BITMAP-INDEX (SINGLE VALUE) sucht gezielt die Bitmap für den Wert NULL. Mit Hilfe von BITMAP CONVERSION wird die Umrechnung in eine Satzadresse vorgenommen, die dann den Zugriff steuert. Bitmap-Indizes lassen sich zusammenfassend wie folgt charakterisieren: Bitmap-Indizes werden extrem kompakt gespeichert. Aufgrund dessen sind die Kosten für Zugriffe auf diese Indizes sehr gering. Die Bitmaps einer Tabelle lassen sich – unabhängig davon, ob sie unterschiedliche Werte einer Spalte oder unterschiedliche Spalten repräsentieren – sehr effizient mischen. Auf diese Weise können Prädikate, die über AND oder OR miteinander verknüpft sind oder die über IN- oder BETWEEN-Operatoren verfügen, effizient abgearbeitet werden. Der »Ausweg« über verknüpfte Bitmap-Indizes, obwohl möglich, ist nur selten notwendig. Da sich maximal nur zwei physische Bitmaps einen Block teilen, können – abhängig von der Blockgröße und der Komprimierung – Hunderte bis Tausende von Datensätzen in einer Bitmap referenziert werden. Bei relativ kleinen Tabellen mit hoher Kardinalität, die pro distinktivem Spaltenwert nur wenige Datensätze aufweisen, werden daher die physischen Bitmaps sehr schlecht genutzt. Der Speichervorteil gegenüber B*Indizes ist in diesem Fall nicht sehr signifikant. Bei Änderungen von Spalten, die über Bitmap-Indizes indiziert wurden, wird ein so genanntes Bitmap-Index-Fragment gesperrt. Davon sind unter Umständen alle Zeilen betroffen, die den gleichen Wert der Bitmap-Spalte enthalten. Die oben beschriebenen Merkmale verdeutlichen, dass die Nutzung von BitmapIndizes sehr große Vorteile, aber auch erhebliche Probleme nach sich ziehen kann! Der Einsatz von Bitmap-Indizes sollte aus diesem Grunde wohl überlegt werden. Optimale Bedingungen für Bitmap-Indizes sind gegeben, wenn: die betreffenden Spalten nicht oder nur äußerst selten und dann von streng seriell ablaufenden Transaktionen geändert werden die Kardinalität der Spalten eher gering ist die Tabellen »viele« Datensätze enthalten Zugriffe existieren, deren Prädikate diese Spalten verwenden auf der Tabelle mehrere Bitmap-Indizes existieren und sich dadurch Vorteile durch die gleichzeitige Verwendung ergeben
Indexstrukturen
201
Bitmap-Indizes dürfen in keinem Fall – wegen des oben beschriebenen Sperrverhaltens – für Spalten angelegt werden, die gleichzeitig von vielen Transaktionen verändert werden! Bei massenhaften INSERT- oder UPDATE-Operationen kann es in einigen Fällen vorkommen, dass Bitmap-Indizes überproportional schnell wachsen. In solchen Fällen ist entweder eine regelmäßige Neuorganisation7 oder das Löschen vor und Neuanlegen nach den betreffenden Operationen sinnvoll.
5.3.4 Bitmap-Join-Index Bitmap-Join-Indizes sind Bitmap-Indizes, die eine Tabelle in Bezug auf Spaltenwerte anderer Tabellen indizieren. Diese anderen Tabellen sind Tabellen, die über Fremdschlüssel mit der indizierten Tabelle verbunden sind. Auf diese Weise lassen sich Join-Operationen im Index vorbereiten. Für die Join-Operationen sind dementsprechend keine Zugriffe auf die Fremdschlüsseltabellen mehr notwendig; alle WHERE-Klauseln können vielmehr über den betreffenden Bitmap-Join-Index aufgelöst werden.
Abbildung 5.3: Speicherstrukturen von Bitmap-Join-Indizes
7
ALTER INDEX ... REBUILD;
202
Datenbankobjekte
Ein Beispiel soll dies verdeutlichen: Eine zentrale, partitionierte Faktentabelle namens sales8 enthält Verkaufszahlen zu Produkten. Die Tabelle sales ist neben den Produkten (products) mit weiteren Dimensionen wie z.B. Datumsangaben (times) verbunden. Eine Abfrage soll die Umsatzzahlen des Produktes »Linen Big Shirt« für das Kalenderjahr 2004 wie folgt ermitteln: SELECT FROM WHERE AND AND AND
SUM(amount_sold) sales s , times t, products p t.time_id = s.time_id p.prod_id = s.prod_id t.calendar_year = 2004 p.prod_name = 'Linen Big Shirt';
Ohne Aufbau eines Bitmap-Join-Index könnte diese Abfrage wie folgt optimiert werden9 (für den Fall, dass außer den Primärschlüsseln der Dimensionen keine weiteren Indizes angelegt wurden): Execution Plan -------------------------------------------------------------0 SELECT STATEMENT Optimizer=CHOOSE (Cost=1160 Card=1 Bytes=84 1 0 SORT (AGGREGATE) 2 1 HASH JOIN (Cost=1160 Card=102 Bytes=8568) 3 2 TABLE ACCESS (FULL) OF 'PRODUCTS' (Cost=65 Card=100 Bytes=3100) 4 2 HASH JOIN (Cost=1095 Card=10163 Bytes=538639) 5 4 TABLE ACCESS (FULL) OF 'TIMES' (Cost=6 Card=15 Bytes=300) 6 4 PARTITION RANGE (ITERATOR) 7 6 TABLE ACCESS (FULL) OF 'SALES' (Cost=1089 Card=1016271 Bytes=33536943)
Der Zugriffsplan zeigt klar, dass neben sales auch die Tabellen times und products zur Auflösung der Join-Operation gelesen werden müssen. Zur Optimierung dieser Abfrage wird nun ein Bitmap-Join-Index für die Tabelle sales angelegt, der die Spalten prod_name der Tabelle products und calendar_year von times enthält: CREATE BITMAP INDEX bj_index ON sales (products.prod_name, times.calendar_year) FROM sales,times,products WHERE products.prod_id = sales.prod_id AND times.time_id = sales.time_id LOCAL COMPUTE STATISTICS;
Da die Tabelle sales partitioniert wurde, muss auch der Bitmap-Join-Index lokal partitioniert angelegt werden. Das Syntaxbeispiel zeigt die minimale Syntax ohne explizite Benennung der einzelnen Partitionsnamen. Während des Index-Aufbaus werden sofort Statistiken generiert.
8 9
Die Beispieltabellen dieses Abschnitts sind dem Oracle Demo-Schema Sales History entlehnt, das jeder Installation beigefügt ist. Die Ausgabe wurde über den Befehl SET AUTOTRACE ON in Sql*Plus erzeugt.
Indexstrukturen
203
Durch diesen Index wird der Zugriffsplan der oben angegebenen Abfrage wie folgt geändert: Execution Plan ---------------------------------------------------------0 SELECT STATEMENT Optimizer=CHOOSE (Cost=37 Card=1 Bytes=33) 1 0 SORT (AGGREGATE) 2 1 PARTITION RANGE (ALL) 3 2 TABLE ACCESS (BY LOCAL INDEX ROWID) OF 'SALES' (Cost=37 Card=1016271 Bytes=33536943) 4 5
3 4
BITMAP CONVERSION (TO ROWIDS) BITMAP-INDEX (SINGLE VALUE) OF 'BJ_INDEX'
Der Plan zeigt, dass die Umsatzzahlen für das genannte Produkt nun nur durch Zugriff auf die Tabelle sales über den neuen Index generiert werden können. Die Zugriffe auf products und times sind nicht mehr notwendig, da der Bitmap-JoinIndex alle referenzierten Spaltenwerte enthält. Derzeit10 ist es noch nicht möglich, funktionale Bitmap-Join-Indizes oder BitmapJoin-Indizes für indexorganisierte Tabellen zu erstellen. Informationen zu Bitmap-Join-Indizes enthalten die Views user_indexes Index_type = 'BITMAP' AND Join_Index = 'YES' – sowie user_ind_columns.
–
Das vorangehende Beispiel hat gezeigt, dass Bitmap-Join-Indizes ideal geeignet sind, um Star-Abfragen – wie sie z.B. im Umfeld von Data-Warehouses auftreten – zu optimieren. Für sie gelten darüber hinaus die gleichen Merkmale, die bereits im Abschnitt 5.3.3 für Bitmap-Indizes erwähnt wurden. Hier ist vor allem die Tatsache zu erwähnen, dass bei Änderungen auf Dimensionsschlüsseln – in unserem Beispiel time_id und product_id – Sperren im Kontext von Bitmap-Bereichen aufgebaut werden11.
5.3.5 Function-based Index Funktionsbasierte Indizes (function-based Index) werden im Kontext von Funktionen oder Ausdrücken angelegt, die sich auf Spalten der betreffenden Tabelle beziehen. Hierbei werden die von der betreffenden Funktion oder die von dem Ausdruck zurückgegebenen Werte indiziert. Die indizierten Funktionen können sowohl vordefinierte SQL-Funktionen als auch vom Benutzer selbst erstellte Funktionen sein. Das folgende Beispiel erzeugt den zusammengesetzten funktionsbasierten Index fidx_name der Tabelle kunden für die SQL-Funktion UPPER auf den Spalten kd_nachname und kd_vorname: CREATE INDEX fidx_name ON angestellte (UPPER(kd_nachname),UPPER(kd_vorname));
10 Oracle 10g Version 10.1.0.3 11 Bei Bitmap-Join-Indizes werden – im Gegensatz zu Bitmap-Indizes – mehr als zwei physische Bitmaps in einem Oracle-Block gespeichert.
204
Datenbankobjekte
Für den Aufbau eines funktionsbasierten Index ist das Systemprivileg QUERY REWRITE erforderlich, außerdem muss für die Datenbank oder zumindest für die Session der Parameter query_rewrite_enabled = TRUE eingestellt werden. ALTER SESSION SET QUERY_REWRITE_ENABLED=TRUE;
Abfragen, welche die SQL-Funktion UPPER nutzen, werden danach über den funktionalen Index ausgeführt: SELECT * FROM kunden WHERE UPPER(kd_nachname) = 'AHRENDS' AND UPPER(kd_vorname) = 'GERD'; Execution Plan ---------------------------------------------------------0 SELECT STATEMENT Optimizer=ALL_ROWS (Cost=2 Card=5 Bytes=315) 1 0 TABLE ACCESS (BY INDEX ROWID) OF 'KUNDEN' (TABLE) (Cost=2 Card=5 Bytes=315) 2 1 INDEX (RANGE SCAN) OF 'FIDX_NAME' (INDEX) (Cost=1 Card=1)
Funktionsbasierte Indizes können als B*Index oder Bitmap-Index angelegt werden, als B*Index sind sie auch als Reverse Index definierbar. Informationen können über die View user_indexes abgerufen werden. Die Spalte index_type enthält entsprechende Angaben: FUNCTION-BASED NORMAL oder FUNCTION-BASED NORMAL/REV sowie FUNCTION-BASED BITMAP. Die dem Index zugeordneten Funktionen enthält die View user_ind_expressions. Die View user_ind_columns weist für funktionale Indizes nur eine Pseudospalte – z.B. SYS_NC000010$ – auf. Funktionale Indizes bieten überall dort Vorteile, wo Funktionen oder Ausdrücke in WHERE-Klauseln Verwendung finden und diese Prädikate genügend Selektivität für
Indexzugriffe bieten. Normale Indizes sind für diese Prädikate nicht einsetzbar. Zu beachten ist bei funktionalen Indizes, dass damit natürlich genau eine Funktion benutzt werden kann. Die oben genannte Funktion UPPER führt bei der Abfrage dazu, dass der Index benutzt wird, die alternative Funktion LOWER hingegen würde keinen Indexzugriff ermöglichen.
5.3.6 Partitionierte Indizes Ebenso wie Tabellen können auch Indizes partitioniert werden. Es ist grundsätzlich möglich, partitionierte Indizes für partitionierte wie auch nicht partitionierte Tabellen anzulegen. Ebenso ist es möglich, partitionierte Tabellen mit nicht partitionierten Indizes zu versehen. Mit bestimmten Einschränkungen12 können sowohl B*- als auch Bitmap-Indizes für die Partitionierung verwendet werden. Die Auswahl geeigneter Spalten, aber auch geeigneter Indextypen erfordert bei partitionierten Tabellen mindestens die gleiche Aufmerksamkeit wie bei nicht partitionierten.
12 Nicht partitionierte Tabellen können nicht mit partitionierten Bitmap-Indizes versehen werden; Bitmap-Indizes auf partitionierten Tabellen müssen nach gleichen Kriterien wie die zugeordnete Tabelle partitioniert sein (Equipartitionierung).
Indexstrukturen
205
Indextypen Bei partitionierten Indizes werden zwei Eigenschaftspaare unterschieden, deren Elemente in unterschiedlichen Kombinationen miteinander auftreten und entsprechende Indextypen definieren können. Die Elemente des ersten Paares beziehen sich auf die Kriterien der Partitionierung. Es sind: Lokale Indizes Partitionierte Indizes sind immer dann lokal, wenn sie die gleichen Partitionierungskriterien – Partitionen und Subpartitionen – wie die ihnen zugeordnete Tabelle aufweisen (equipartitioniert). Operationen auf den Partitionen der Tabelle – wie z.B. aufteilen, löschen, lesen – können 1:1 auf den entsprechenden Index übertragen werden, unabhängig davon, ob die Tabelle range- oder hash-partitioniert wurde. Aus diesem Grunde wird ein lokaler Index transparent zu allen Operationen auf der partitionierten Tabelle mitgeführt. Lokale Indizes können auch eindeutig sein, sofern die Partitionierungsspalten eine Untermenge der Indexspalten darstellen. Auf diese Weise ist es möglich, die Eindeutigkeit im Rahmen einer Partition und damit über die gesamte Tabelle sicherzustellen. Globale Indizes Man spricht von einem globalen Index, wenn der Index eigene, von der zugeordneten Tabelle unabhängige Partitionierungskriterien aufweist. Diese Kriterien werden stets auf Basis der Range-Partitionierung definiert. Operationen auf den Partitionen der zugeordneten Tabelle können hier nicht direkt auf den Index übertragen werden. Das Löschen einer einzigen Tabellenpartition beispielsweise kann den gesamten globalen Index betreffen, Zugriffe auf eine Tabellenpartition können mehrere Indexpartitionen umfassen und umgekehrt. Aus diesem Grunde werden globale Indizes nach bestimmten administrativen Eingriffen – z.B. dem Löschen oder Splitten von Partitionen – ungültig und müssen reorganisiert werden. Die Elemente des zweiten Attributpaares beziehen sich auf die Rollen der Indexspalten. Es sind: Prefixed Indizes sind prefixed, wenn die für die Partitionierung des Index verantwortlichen Spalten selbst auch indiziert sind: Ein Index X ist prefixed, wenn die indizierte Spalte C1 auch die Grundlage für die Partitionierung bildet. Nonprefixed Indizes sind nonprefixed, wenn die für die Partitionierung verantwortlichen Spalten selbst nicht indiziert werden: Ein Index Y ist nonprefixed, wenn er die Spalte C1 indiziert, jedoch nach den Werten der Spalte C2 partitioniert wird. Die oben genannten Eigenschaftspaare können nun in den folgenden drei Kombinationen auftreten und entsprechende Indizes definieren. Die Eigenschaften ergeben sich entsprechend durch die Zusammenstellung der oben genannten Elemente:
206
Datenbankobjekte
Local prefixed Index Ein Index wird als local prefixed bezeichnet, wenn er in Bezug auf die zugeordnete Tabelle equipartitioniert ist und die Partitionierungsspalte oder -spalten an führender Position enthält. Es spielt dabei keine Rolle, ob die Tabelle range-, hash- oder composite-partitioniert wurde. Ein Beispiel soll dies verdeutlichen: Gegeben sei die Tabelle x mit den Spalten c1, c2 und c3. Sie wird auf Basis der Spalte c2 range-partitioniert. Der Index i1 ist local prefixed, wenn er für die Spalte c2 definiert und in der gleichen Weise wie x partitioniert wird. Der Index i2, der zwar wie x partitioniert wird, aber aus den Spalten c3 und c2 besteht, ist nicht local prefixed, weil er die Partitionierungsspalte der Tabelle – c2 – nicht an führender Position enthält. Local prefixed Indizes haben eine Reihe von erwähnenswerten Vorteilen: – Sie unterstützen die Unabhängigkeit von Partitionen, weil sie beim Hinzufügen, Löschen und Aufteilen von Partitionen transparent zu der betreffenden Tabelle angepasst werden und keinen Neuaufbau (rebuild) erfordern. – Sie können als eindeutige Indizes angelegt werden. – Der Optimizer kann die Zugriffe auf identische Index- und Tabellenpartitionen abstimmen. – Recovery-Aktionen – vollständig oder unvollständig – sind ohne zusätzlichen Verwaltungsaufwand für die Indizes durchführbar. Local prefixed Indizes zählen daher zu den am häufigsten eingesetzten Typen. Local nonprefixed Index Ein Index, der in gleicher Weise wie die zugrunde liegende Tabelle partitioniert ist, jedoch die für die Partitionierung verantwortliche Spalte selbst nicht oder nicht an führender Position indiziert, wird als local nonprefixed bezeichnet. Der oben beschriebene Index i2 auf den Spalten c3 und c2 ist ein Local nonprefixed Index. Ebenso ist ein Index i3, der nur die Spalte c3 indiziert, aber wie die Tabelle x nach c2 partitioniert ist, ebenfalls local nonprefixed. Local nonprefixed Indizes haben aufgrund des Attributes LOCAL und der damit verbundenen Equipartitionierung die bereits besprochenen Vorteile bei der Verwaltung der zugeordneten Tabelle. Sie sind aus diesem Grunde überall dort sinnvoll, wo Zugriffe ohne die jeweiligen Partitionierungsspalten durchgeführt werden sollen, ohne die oben erwähnten Vorteile bei der Verwaltung der Tabellen und Indizes zu verlieren – beispielsweise beim Zugriff auf eine partitionierte Tabelle auftrag über Kundennummern unabhängig von dem Auftragsdatum. Diesen Vorteilen stehen jedoch einige Nachteile gegenüber: – Local nonprefixed Indizes können nur dann als unique definiert werden, wenn die Partitionierungsspalten eine Untermenge der Indexspalten bilden. – Zugriffe sind – wegen der fehlenden Equipartitionierung – aufwändiger als über prefixed Indizes, denn Schlüsselwerte können in mehreren Partitionen vorkommen.
Indexstrukturen
207
Global prefixed Index Ein Index wird als global prefixed bezeichnet, wenn er nach anderen Kriterien als der zugrunde liegenden Tabelle partitioniert ist, die für die Partitionierung verantwortliche Spalte jedoch mit indiziert ist. Die Partitionierung bei Global prefixed Indizes darf jedoch nur vom Typ Range sein, die Tabelle, auf die er sich bezieht, kann dagegen jede Art von Partitionierung enthalten. Auch hierzu ein kurzes Beispiel: Gegeben sei wieder die Tabelle x, die – immer noch – aus den Spalten c1, c2 und c3 besteht und auf Basis von c2 partitioniert ist. Der Index i4, der die Spalten c3 und c1 von x indiziert und nach c3 partitioniert ist, wird als global prefixed bezeichnet. Global prefixed Indizes haben wenige Vorteile – z.B. die mögliche Eindeutigkeit –, dagegen eine Reihe von gravierenden Nachteilen: – Administrative Eingriffe wie z.B. das Löschen, Hinzufügen und Splitten von Partitionen haben – wegen der unterschiedlichen Partitionierung – in der Regel Auswirkungen auf sämtliche Indexpartitionen und erfordern daher die anschließende explizite Reorganisation der globalen Indizes! – Unvollständige Recovery-Aktionen der Tabelle erfordern den kompletten Neuaufbau aller globalen Indizes. – Satzadressen einer Indexpartition können auf mehrere oder alle Partitionen der zugeordneten Tabelle verweisen. Syntaxbeispiele Im Folgenden finden sich einige syntaktische Beispiele für den Aufbau der oben besprochenen Indexvarianten. Im ersten Beispiel wird der lokale Index pidx_verkauf1 angelegt, der, genau wie seine Basistabelle verkauf, range-partitioniert ist. Er enthält alle Partitionierungsspalten dieser Tabelle. Partitionsnamen werden in diesem Beispiel explizit vergeben, wie auch die betreffenden Tablespaces. Eine VALUES-Klausel ist wegen der Equipartitionierung nicht zulässig. CREATE INDEX pidx_verkauf1 ON verkauf(verkjahr, verkmonat,verktag) LOCAL (PARTITION vi1 TABLESPACE tsi1, PARTITION vi2 TABLESPACE tsi2, PARTITION vi3 TABLESPACE tsi3, PARTITION vi4 TABLESPACE tsi4); Listing 5.20: Equipartitionierter Index
Im zweiten Beispiel wird für die indexorganisierte Tabelle verkauf_iot, die nach den Spalten verkjahr, verkmonat und verktag partitioniert ist, der lokale Sekundärindex pidx_verkauf_iot1 angelegt. Da er nur die Spalten verkmonat und verktag enthält und nicht alle Partitionierungsspalten an führender Position, handelt es sich um einen Local nonprefixed Index.
208
Datenbankobjekte
CREATE INDEX pidx_verkauf_iot1 ON VERKAUF_IOT(VERKMONAT, VERKTAG) LOCAL (PARTITION vi1 TABLESPACE tsi1, PARTITION vi2 TABLESPACE tsi2, PARTITION vi3 TABLESPACE tsi3, PARTITION vi4 TABLESPACE tsi4); Listing 5.21: Local nonprefixed Index
Die kürzeste mögliche Form der Syntax zeigt das folgende Beispiel. Für die Tabelle auftrag, die nach dem Auftragsdatum und – als Subpartition – nach der Produktnummer partitioniert ist, wird der lokale nonprefixed Index pidx_auftrag3 angelegt. Dieser Index ist wie auch die Tabelle in vier Hauptpartitionen mit jeweils acht Subpartitionen aufgeteilt. Da jegliche Speicherparameter zu Partitionen fehlen, werden die Indexpartitionen so benannt wie die der Tabelle und im Default-Tablespace des betreffenden Schemas gespeichert. CREATE INDEX pidx_auftrag3 ON auftrag(prodnr) LOCAL;
Bei der composite-partitionierten Tabelle auftrag soll die Vergabe eindeutiger Auftragsnummern sichergestellt werden. Aus diesem Grunde wird ein eindeutiger, partitionierter Index für die Spalte anrede geplant. Ein lokaler eindeutiger Index müsste – neben der Spalte anrede – aus den Partitionierungsspalten aufdatum (Hauptpartitionen) und prodnr (Subpartitionen) bestehen und könnte daher keine eindeutigen Auftragsnummern garantieren. Deshalb wird im folgenden Beispiel ein eindeutiger, range-partitionierter Global prefixed Index angelegt13, der nach anrede partitioniert werden muss. CREATE UNIQUE INDEX puidx_auftrag ON auftrag(anrede) GLOBAL PARTITION BY RANGE (anrede) (PARTITION p1 VALUES LESS THAN(1000), PARTITION p2 VALUES LESS THAN(2000), PARTITION p3 VALUES LESS THAN (MAXVALUE) ); Listing 5.22: Global prefixed Index
Metadaten Informationen zu partitionierten Indizes sind über die folgenden Views abrufbar: user_indexes – enthält allgemeine Informationen und globale Statistiken (Filterung der partitionierten Indizes über die Where-Klausel partitioned = 'YES'). user_part_indexes – enthält Informationen zum Typ der Partitionierung und des Index, die für alle Partitionen gültigen Speicherparameter und die Anzahl der Partitionen. user_ind_partitions – enthält Informationen zu den einzelnen Hauptpartitionen, d.h. Namen, Partitionierungskriterien, Speicherparametern und Statistiken.
13 Als Alternative käme hier auch ein nicht partitionierter, eindeutiger Index in Frage.
Indexstrukturen
209
user_ind_subpartitions – enthält entsprechend die Namen, Speicherparameter und Statistiken für Subpartitionen. user_ind_columns – enthält die Namen und Reihenfolge der Indexspalten für partitionierte wie auch nicht partitionierte Indizes. Es versteht sich, dass die oben genannten Views auch in den dba- und all-»Familien« definiert sind.
5.3.7 Komprimierung von Indizes Bei der komprimierten Speicherung von Indizes wird jeder Schlüsselwert in ein Präfix und ein Suffix aufgeteilt. Präfixe, die in der Regel redundant vorkommen, werden pro Indexblatt nur einmal gespeichert; Suffixe verweisen auf die Präfixe ihres Blattes und sind pro Blatt mehrfach vorhanden. Auf diese Weise lässt sich die Speichergröße von Indizes reduzieren, und damit lassen sich die Zugriffe optimieren. Standardmäßig wird das Präfix bei einem n-fach zusammengesetzten nicht eindeutigen Index aus n Spalten gebildet, für eindeutige Indizes aus n–1 Spalten. Das folgende Beispiel zeigt den Aufbau eines zusammengesetzten, nicht eindeutigen Index für die Spalten gehalt und kommission der Tabelle angestellte: CREATE INDEX idx_ang_com ON angestellte (gehalt, kommission) COMPRESS;
Die folgende Abfrage gibt die Eigenschaften des neuen Index aus: SELECT index_name, index_type, compression, prefix_length FROM user_indexes WHERE index_name = 'IDX_ANG_COM'; INDEX_NAME INDEX_TYPE COMPRESS PREFIX_LENGTH --------------- ----------------------- -------- ------------IDX_ANG_COM NORMAL ENABLED 2 Listing 5.23: Compressed Index
Das Präfix wird hier von beiden Spalten – gehalt und kommission – gebildet, im Suffix werden in diesem Fall die Satzadressen (rowid) gespeichert. Der Speicherbedarf dieses Index gegenüber einem identischen ohne Komprimierung betrug etwa 30%.14 Die Länge von Präfixen kann aber auch explizit definiert werden. Im folgenden Beispiel wird die Anzahl der Spalten des Präfix – hier nur die führende Spalte gehalt – in der COMPRESS-Klausel angegeben: CREATE INDEX idx_ang_com ON angestellte (gehalt, kommission) COMPRESS 1;
Es versteht sich, dass der Speicherbedarf bei sinkender Komprimierungsrate steigt.
14 Die Tabelle Angestellte bestand aus 29.000 Einträgen; die Indexgrößen betrugen 550 KByte (nicht komprimiert) und 300 KByte (komprimiert).
210
Datenbankobjekte
Komprimierte Indizes empfehlen sich überall dort, wo großer Wert auf kompakte Speicherung gelegt wird, Bitmap-Indizes jedoch aufgrund konkurrierender DMLAktivitäten nicht angebracht sind. Für die Rekonstruktion der Schlüsselwerte aus Präfixen und Suffixen ist ein geringfügiger Anstieg der CPU-Zeiten in Kauf zu nehmen.
5.3.8 Reverse Key-Indizes B*Indizes lassen sich auch als Reverse Key-Indizes aufbauen. In diesem Fall werden die Schlüsselwerte in den Indexblättern in umgekehrter Bit-Reihenfolge abgespeichert. Im folgenden Beispiel wird der Index idxr_ang_abt als Reverse Key-Index für die Spalte abt_nr der Tabelle angestellte angelegt: CREATE INDEX idxr_ang_abt ON angestellte (abt_nr) REVERSE;
Durch die umgekehrte Speicherung der Zeichenketten werden Schlüssel, die normalerweise in einem Indexblatt zusammengefasst würden, auf unterschiedliche Blätter verteilt. Das Gleiche gilt auch für DML-Operationen, die diese Schlüsselwerte verändern. Reverse Key-Indizes können also helfen, IO-Operationen besser auf die Indexblätter zu verteilen. Interessant sind Reverse Key-Indizes auch für Indexspalten, die chronologisch mit wachsenden Spaltenwerten gefüllt werden, also z.B. ein Erfassungsdatum oder eine Auftragsnummer, die aus einer Sequenz generiert wird. Bedingt durch den Mechanismus, mit dem B*Indizes gepflegt werden, haben solche Indizes nach einer gewissen Zeit einen schlechten Füllgrad (maximal 50%), durch Benutzung eines Reverse Key-Index wird dieses Verhalten beseitigt. Auf der anderen Seite werden aufgrund der umgekehrten Speicherung Wertebereiche, die normalerweise über Range-Zugriffe im Index gelesen werden können, einzeln abgearbeitet. Wenn aber sowieso hauptsächlich Einzelzugriffe auf Datensätze über den Index vorkommen, dann sollte ein Reverse Key-Index in Betracht gezogen werden. Informationen zu Reverse Key-Indizes enthält die View user_indexes unter dem Indextyp NORMAL/REV. Die indizierten Spalten werden über user_ind_columns ausgewiesen.
5.3.9 Weitere Aspekte der Indexverwaltung Parallelisierung Der Aufbau von Indizes kann parallelisiert und dadurch beschleunigt werden. In diesem Fall arbeiten mehrere Prozesse daran, die Basistabelle zu lesen und die Schlüsselwerte zu sortieren. Im folgenden Beispiel wird der Index idx_aufdatum mit zweifacher Parallelisierung angelegt: CREATE INDEX idx_aufdatum ON auftraege (aufdatum) PARALLEL 4; Listing 5.24: Parallele Erstellung eines Index
Indexstrukturen
211
Entsprechende Hintergrundprozesse müssen in diesem Fall vorher vom DBA über die Serverparameter parallel_min_servers und parallel_max_servers konfiguriert worden sein. Die Parallelisierung kann hier sowohl intra- als auch interoperational erfolgen. Dies bedeutet, dass sowohl das Lesen der Tabelle als auch das Sortieren gleichzeitig parallelisiert wird. In unserem Beispiel führt das zur Aktivierung von insgesamt vier Serverprozessen. Die Parallelisierung hat auch Auswirkungen auf die Größe der Segmente, da jeder Serverprozess eigene Extents aufbaut. Online-Aufbau Um die Konsistenz der Index- und Tabellendaten im Mehrbenutzerbetrieb sicherzustellen, wird der Aufbau von Indizes stets von entsprechenden Tabellensperren begleitet. Die Beispiele der vorangehenden Abschnitte fordern aus diesem Grunde stets eine Tabellensperre vom Typ Share Mode für die zu indizierende Tabelle an. Dies kann zu unterschiedlichen Reaktionen führen, abhängig davon, welche Transaktionen gleichzeitig auf der betreffenden Tabelle aktiv sind. Bei offenen UPDATE-, DELETE- oder INSERT-Operationen, die bereits aktive Row Exclusive-Sperren auf Tabellenebene aufgebaut haben, führt dies zu einem Fehler15, da beide Sperrmodi nicht miteinander kompatibel sind. Der gleiche Fehler wird generiert, wenn in umgekehrter Reihenfolge zuerst der Indexaufbau durchgeführt wird und in dieser Zeit UPDATE-, DELETE- oder INSERT-Befehle auf die Tabelle treffen. Um im Mehrbenutzerbetrieb parallel ablaufende Transaktionen weniger zu stören, ist für den Indexaufbau eine Online-Klausel verfügbar: CREATE INDEX idx_ang_abt ON angestellte (abtnr) ONLINE;
Hierbei wird die Basistabelle – in unserem Beispiel angestellte – nur im Row ShareModus gesperrt. Dieser Modus ist mit den meisten anderen Sperrmodi – Row Exclusive, Row Share und Share Row Exclusive – kompatibel. Dies bedeutet, dass der Indexaufbau keine INSERT-, UPDATE und DELETE-Operationen, die Row Exclusive-Sperren aufbauen, behindert. Auch SELECT FOR UPDATE-Befehle sind möglich, da sie Row ShareSperren erzeugen. Der einzig inkompatible Sperrmodus ist Exclusive. Um die Änderungen, die während des Indexaufbaus anfallen, zu protokollieren, erzeugt der Befehl automatisch eine Journaltabelle im Schema des Tabelleneigentümers mit Namen sys_journal_nnnnn, wobei nnnnn ein fünfstelliger, intern generierter, eindeutiger numerischer Bezeichner ist. Die Journaltabelle enthält im Wesentlichen einen numerischen Operationscode und die Adresse des veränderten Datensatzes. Bei partitionierten Tabellen kommt noch eine Partitionsnummer hinzu. Diese Tabelle wird im Share Modus gesperrt, mit den DML-Daten zwischenzeitlicher Transaktionen gefüllt und nach dem fertigen Aufbau des Index genutzt, um die angefallenen Änderungen diesem anzufügen. Die ONLINE-Klausel ist für Bitmap- und Cluster-Indizes nicht nutzbar.
15 ORA-00054: resource busy and acquire with NOWAIT specified
212
Datenbankobjekte
Indexreorganisation Durch häufiges Einfügen und Löschen16 von Indexschlüsseln kann es notwendig werden, Indexbäume zu reorganisieren, um ihre Effizienz wiederherzustellen. Nach der reinen Lehre sind B*Bäume zwar ausgewogen und haben überall die gleiche Höhe, da Oracle Schlüsselwerte in Indizes jedoch nur logisch und nicht physisch löscht, kann der äußerlich ausgewogene Index eine »innere« Schieflage erhalten. Um dies zu erkennen, ist eine Indexanalyse durchzuführen. Die Analyse eines Indexbaumes lässt sich am besten über den ANALYZE-Befehl bewerkstelligen: ANALYZE INDEX i$brev VALIDATE STRUCTURE;
Die Klausel VALIDATE STRUCTURE prüft die Baumstruktur und füllt die Hilfstabelle index_stats mit statistischen Werten. Das folgende Beispiel zeigt den Platzverbrauch sowie die Anzahl und den Umfang von gelöschten Einträgen. Beim Platzverbrauch wird differenziert zwischen der Größe des Segmentes – blocks –, dem in diesem Segment für den Aufbau des B*Baumes benötigten Platz – btree_space – sowie dem innerhalb des Baumes für Einträge verbrauchten Bereich – used_space. NAME HEIGHT BLOCKS BR_BLKS LF_BLKS DEL_LF_ROWS BTREE_SPACE USED_SPACE ----------- ------- ------- ------- ------- ----------- ----------- ---------I$BREV 2 64 1 56 307 455804 377892 DEL_LF_ROWS DEL_LF_ROWS_LEN ----------- --------------307 4298
Indizes mit einem hohen Anteil an gelöschten Schlüsselwerten können durch eine Reorganisation wesentlich kompakter gespeichert werden. Für die Reorganisation von Indizes stehen unterschiedliche Methoden bereit. Im folgenden Beispiel wird der Index i$brev über die REBUILD-Klausel reorganisiert: ALTER INDEX i$brev REBUILD;
REBUILD baut den Index vollständig neu auf, indem auf der Basis des alten Index als
Datenquelle der neue Index erstellt wird und dieser schließlich an die Stelle des alten rückt. Über die REBUILD-Klausel ist es ebenfalls möglich, den Index in einen neuen Tablespace zu verschieben und seine STORAGE-Klausel anzupassen. Die Online-Option kann hier ebenfalls verwendet werden und verändert das Sperrverhalten wie im Abschnitt Online-Aufbau beschrieben. Für die Fälle, in denen der – kurzzeitig – erhöhte Speicherbedarf und die CPU-Belastung der Rebuild-Methode Probleme bereiten, steht die COALESCE-Klausel bereit: ALTER INDEX i$brev COALESCE;
COALESCE zieht benachbarte Blätter eines Indexzweiges zusammen. Auf diese Weise
lassen sich gelöschte Schlüsselwerte kostengünstig ausmustern. Da der Index jedoch nicht vollständig neu aufgebaut wird, kann COALESCE keine Storage-Klauseln und Tablespaces ändern. Kommt es lediglich darauf an, den ungenutzten Speicherplatz eines Indexsegmentes zu reduzieren, kann die DEALLOCATE-Klausel helfen: 16 Da Schlüsselwerte in Indizes sortiert gespeichert werden, werden Update-Operationen als Löschen des alten und Einfügen des neuen Wertes ausgeführt. Es gibt in den Blättern eines Index also keine Updates. (Die Ausnahme sind Bitmaps.)
Constraints
213
ALTER INDEX i$brev DEALLOCATE UNUSED;
Die DEALLOCATE-Klausel bietet keine Reorganisation! Sie lässt lediglich das betreffende Segment bis auf die Hochwassermarke oder einen oberhalb von ihr befindlichen Wert17 schrumpfen. Monitoring Indizes sind nur sinnvoll, wenn sie vom Optimizer genutzt werden können. Um dies festzustellen, lassen sich einerseits die Zugriffspläne einzelner SQL-Befehle generieren, andererseits können Indizes gezielt beobachtet werden. Im folgenden Beispiel wird der Index i$ang_geh für das Monitoring aktiviert: ALTER INDEX i$ang_geh MONITORING USAGE;
Einmal eingeschaltet, kann die Nutzung der betreffenden Indizes über die View v$object_usage angezeigt werden. Man sollte sich hier beim Testen nicht verwirren lassen, es kann einige Stunden dauern, bis die ersten Protokolle in dieser View auftauchen. Das Monitoring wird über die NOMONITORING-Klausel wieder ausgeschaltet. Generell gilt für das Monitoring von Indizes, dass diese Information sehr effektiv erstellt wird, da die Daten nur zyklisch in die entsprechenden Data-DictionaryTabellen geschrieben werden. Das bedeutet zwar, dass bei einem plötzlichen Systemausfall Informationen verloren gehen, da diese jedoch unkritisch sind, ist das zu verschmerzen.
5.4
Constraints
Constraints sind eine grundlegende und sehr nützliche Eigenschaft des relationalen Datenbankmodells. Sie dienen dazu, gewisse Basiseigenschaften von Datenbankobjekten zu garantieren, z.B. deren Eindeutigkeit. Besonders hervorzuheben ist dabei die Tatsache, dass Constraints nicht programmiert werden müssen. Sie sind deklarativ, d.h., sie werden lediglich im Kontext einer Tabelle definiert. Die Verknüpfung von Daten mit Hilfe von Primärschlüssel-Fremdschlüssel-Relationen ist die Basis für ein gut funktionierendes relationales Datenmodell. Dieses basiert auf der grundlegenden Eigenschaft, zusammenhängende Daten nicht durch feste Zeiger (Pointer) darzustellen, sondern durch die Übereinstimmung von Schlüsselfeldern. Dies wiederum ermöglicht die immense Flexibilität bei der Ablage, Indizierung und Abfrage von Daten in relationalen Strukturen. Rein technisch ist es zwar möglich, ein relationales Datenmodell ohne Constraints zu implementieren; allerdings müssen dann sämtliche Prüfungen von den Anwendungen durchgeführt werden. Andererseits führen gute Constraint-Definitionen i.A. dazu, dass Anwendungen einen robusten und datentechnisch sauberen Eindruck machen – weil sie den Ballast der Constraint-Prüfungen zumindest teilweise ablegen und sich auf eine funktionierende Datenbasis verlassen können. Einige grundlegende Constraint-Definitionen sollten daher mit der Entwicklung des Datenmodells einhergehen. 17 Über den Zusatz Keep n, wobei n die Anzahl der Bytes oberhalb der Hochwassermarke angibt.
214
Datenbankobjekte
5.4.1 Constraint-Definitionen Allgemeines Im Folgenden werden die unterschiedlichen Constraints vorgestellt. Jeder definierte Constraint hat einen Namen. Dieser wird entweder vom Benutzer vorgegeben oder beim Anlegen des Constraints vom Datenbanksystem automatisch vergeben. Die automatisch vergebenen Namen lauten i.A. sys_cnnnnn. Es wird unbedingt empfohlen, eigene Namen für Constraints zu vergeben, da andernfalls Administrationsprozeduren schwer lesbar sind. Die Definition eines Constraints erfolgt entweder bei der Deklaration der Spalte (Spalten-Constraint) oder als Zusatz zu den Spaltendefinitionen (Tabellen-Constraint). Constraints, die sich lediglich auf eine einzige Spalte beziehen, kann man mit beiden Varianten deklarieren; die Definition als Spalten-Constraint ist oft übersichtlicher. Bezieht sich ein Constraint auf mehrere Spalten, so ist er ausschließlich als Tabellen-Constraint definierbar. Bei der Implementierung eines Datenmodells empfiehlt es sich, Tabellen- und Constraint-Definitionen in verschiedene Skripte zu trennen. Bei einer späteren Migration hat man dann alle Werkzeuge zur Verfügung, um die erforderlichen Schritte (in etwa: Tabellen aufsetzen, Daten laden, Constraints anlegen) gezielt und kontrolliert auszuführen. NOT NULL Der einfachste Constraint-Typ ist der NOT NULL-Constraint. Hiermit wird für eine Spalte definiert, dass sie auf jeden Fall mit einem Wert besetzt sein muss bzw. dass sie keine NULL-Werte enthalten darf. Hiermit können bereits sehr wirkungsvolle Regeln im Datenbankschema implementiert werden, z.B. dass ein Auftrag immer eine Kundennummer enthalten muss. CREATE TABLE auftraege ( ... kundennr NUMBER(10,0) CONSTRAINT auft_kdnr_nn NOT NULL, ...
Mit den Spalten einer Tabelle, die als NOT NULL deklariert sind, wird ein minimaler Rumpfdatensatz beschrieben, der als sinnvoll angesehen wird. UNIQUE Mit dem UNIQUE-Constraint wird definiert, dass die Werte einer Spalte bzw. einer Kombination von Spalten eindeutig sein müssen. Man spricht auch von einem eindeutigen Schlüssel oder UNIQUE KEY. Eine Tabelle kann beliebig viele eindeutige Schlüssel haben. Zur Abgrenzung von den weiter unten definierten Primärschlüsseln spricht man bei eindeutigen Schlüsseln auch von Sekundärschlüsseln. ALTER TABLE produkte ( CONSTRAINT produkte_prodid_uq UNIQUE (prodid) );
Constraints
215
Die Überprüfung der Eindeutigkeit erfolgt mit Hilfe eines Index. Falls die Spalte bzw. die Spaltenkombination noch nicht indiziert ist, wird beim Anlegen des Constraints automatisch ein eindeutiger Index angelegt, dessen Name identisch zum Namen des Constraints ist. Mit Hilfe der USING INDEX-Klausel können für den Index Speicheroptionen angegeben werden: ALTER TABLE produkte ( CONSTRAINT produkte_prodid_uq UNIQUE (prodid) USING INDEX TABLESPACE appl_idx );
Falls die Spaltenkombination bereits indiziert ist, benutzt Oracle den bestehenden Index zur Constraint-Prüfung. Der bestehende Index muss nicht unbedingt eindeutig sein! Auch mit einem nicht eindeutigen Index kann die Prüfung auf Eindeutigkeit performant erfolgen. PRIMARY KEY Jede Tabelle kann maximal einen Primärschlüssel oder PRIMARY KEY enthalten. Der Primärschlüssel bezeichnet wie ein eindeutiger Schlüssel eine Spalte oder eine Spaltenkombination, die – einzeln oder in Kombination – für die Tabelle eindeutig sein muss. Beim Primärschlüssel ist – im Gegensatz zum eindeutigen Schlüssel – implizit eine NOT NULL-Definition für alle Schlüsselspalten eingeschlossen. CREATE INDEX aufpos_pk ON auftragspositionen (auftr_id, pos_id) TABLESPACE appl_idx;
oder ALTER TABLE auftragspositionen ( CONSTRAINT aufpos_pk PRIMARY KEY (auftr_id, pos_id) );
Zur Primärschlüsselprüfung werden wie bei den eindeutigen Schlüsseln Indizes verwendet. FOREIGN KEY Mit Fremdschlüsseln oder FOREIGN KEY-Constraints werden relationale Tabellen miteinander verknüpft. FOREIGN KEY-Constraints können eine oder mehrere Spalten enthalten. Sie müssen sich stets auf den Primärschlüssel oder ein beliebiges UNIQUEConstraint einer übergeordneten »Master«-Tabelle beziehen. Es versteht sich, dass die Anzahl und die Datentypen der referenzierten wie referenzierenden Spalten zusammenpassen müssen. Im nachfolgenden Beispiel wird der Primärschlüssel der Tabelle auftraege über einen FOREIGN KEY-Constraint der Tabelle auftragspositionen referenziert: ALTER TABLE auftragspositionen ( CONSTRAINT aufpos_fk_auftraege FOREIGN KEY (auftr_id) REFERENCES auftraege );
216
Datenbankobjekte
Soll statt des Primärschlüssels ein Unique-Constraint referenziert werden, so ist dies explizit in Form der betreffenden Spalten anzugeben: ALTER TABLE auftragspositionen ( CONSTRAINT aufpos_fk_auftraege FOREIGN KEY (auftr_id) REFERENCES auftraege (auf_unique) );
Bei DML-Operationen auf der Fremdschlüsseltabelle wird nun immer überprüft, ob der als Fremdschlüssel vorhandene Wert bzw. die Wertekombination als Primärschlüssel vorhanden ist. Im Beispiel heißt das, dass nur dann auftragspositionen angelegt werden können, wenn ein passender auftrag (mit gleicher auftr_id) vorhanden ist. Nicht ganz konform zu den allgemeinen Erwartungen ist die Prüfung mehrspaltiger Fremdschlüssel in Verbindung mit NULL-Werten. Sobald eine Spalte eines mehrspaltigen Fremdschlüssels einen NULL-Wert enthält, werden die restlichen Spalten nicht mehr geprüft. Hierzu ein Bespiel: Tabelle A hat zwei Primärschlüsselspalten a1 und a2, welche die folgenden Werte besitzen: SQL> SELECT * FROM a; A1 A2 ---------- ---------1 2 3 4
Tabelle B besitzt ebenfalls die Spalten a1 und a2, die als Fremdschlüssel zu A definiert werden; dabei sind NULL-Werte erlaubt: SQL> INSERT INTO B VALUES (1, 2) 1 row created. SQL> INSERT INTO B VALUES (3, 4) 1 row created. SQL> INSERT INTO B VALUES (1, 4) * FEHLER in Zeile 1: ORA-02291: Integritäts-Constraint (SYSTEM.SYS_C001782) verletzt - übergeordneter Schlüssel nicht gefunden SQL> INSERT INTO B VALUES (NULL, NULL) 1 row created. SQL> INSERT INTO B VALUES (NULL, 4) 1 row created. SQL> INSERT INTO B VALUES (77, NULL) 1 row created. SQL> COMMIT; Commit complete.
Constraints
217
Beim Durchlesen der o.a. Zeilen sind die Reaktionen des Datenbanksystems größtenteils in Ordnung.; lediglich die Wertekombination (77,NULL) findet oft nicht auf Anhieb das Einverständnis des Betrachters. Allerdings verdeutlicht die angegebene Regel Folgendes: Sobald ein Wert eines mehrspaltigen Fremdschlüssels NULL ist, wird der Rest – hier die 77 – nicht mehr geprüft. Um ein solches Verhalten zu vermeiden, genügt es oft, alle Fremdschlüsselspalten mit einem NOT NULL-Constraint zu belegen. Sollen aber auch NULL-Werte erlaubt sein, hilft zumindest manchmal ein CHECK-Constraint, der nur Wertekombinationen zulässt, bei denen alle Spalten entweder NULL oder NOT NULL sind (s.u.). Ein definierter Fremdschlüssel schränkt die DML-Möglichkeiten sowohl auf der Primär- als auch auf der Fremdschlüsselseite ein. Es können nur solche Befehle verarbeitet werden, deren Ergebnis im Sinne der Fremdschlüsselbedingung korrekt ist. Das heißt, dass nach einem Update auf auftr_id in der Fremdschlüsseltabelle die neue auftr_id auch als Primärschlüssel vorkommen muss. Das Gleiche gilt für Update- und Delete-Befehle auf der Primärschlüsseltabelle. Optional zum Standardverhalten kann für DELETE-Befehle auf der Primärschlüsseltabelle eingestellt werden, dass die zugehörigen Fremdschlüsseldatensätze gelöscht werden sollen (ON DELETE CASCADE) bzw. dass die Fremdschlüssel auf NULL gesetzt werden sollen (ON DELETE SET NULL). Sollen z.B. beim Löschen eines Auftrags alle Auftragspositionen mit gelöscht werden, so lautet obige Fremdschlüsseldefinition wie folgt: ALTER TABLE auftragspositionen ( CONSTRAINT aufpos_ref_auftraege FOREIGN KEY (auftr_id) REFERENCES auftraege ON DELETE CASCADE );
Gibt man keine ON DELETE-Klausel an, so werden Löschbefehle für Primärschlüsseldatensätze, die noch referenziert werden, nicht zugelassen. Eine manuelle Löschroutine muss also immer bei den Fremdschlüsseldatensätzen anfangen und sich zu den Primärschlüsseln »hocharbeiten«. Die ON DELETE-Klausel kann sich zu einem späteren Zeitpunkt jedoch als Problem erweisen, und zwar dann, wenn die Tabellen repliziert werden sollen (siehe Kapitel 13). In diesem Fall können solche Funktionen zu Synchronisierungsproblemen führen. Ein spezieller Diskussionspunkt beim DML-Verhalten ist das Sperrkonzept für Fremdschlüssel. Die wichtigste Information ist, dass praktisch keine Probleme mit Sperren auftreten, wenn Fremdschlüssel indiziert werden. Das passiert hier – im Gegensatz zu den eindeutigen und Primärschlüsseln – nicht automatisch. Falls kein solcher Index existiert, wird bei einem UPDATE oder DELETE auf der Primärschlüsselseite ein Share Lock auf Tabellenebene bei der Fremdschlüsselseite benötigt. Oracle9i und 10g agieren hier ein wenig besser als Oracle8i, da der Share Lock nur für eine kurze Zeit pro betroffenem Datensatz gehalten wird; Oracle8i hält den Share Lock bis zum Transaktionsende. Allerdings ist auch das Oracle 10g-Verhalten problematisch, da der Share Lock auf Tabellenebene inkompatibel zum Exclusive Lock auf Datensatzebene ist. Falls eine große Transaktionslast auf der Fremdschlüsseltabelle existiert, kann es zu längeren Wartezeiten wegen inkompatibler Sperren kommen.
218
Datenbankobjekte
Tipp: Grundsätzlich sollten Fremdschlüssel indiziert werden. Hiermit werden Probleme mit Sperren verhindert. Ein weiterer empfohlener Grundsatz, der in der Anwendung berücksichtigt werden muss, ist, keine UPDATE-Befehle auf eindeutige und Primärschlüsselspalten zuzulassen. Auch bei DDL-Operationen gibt es Einschränkungen für Tabellen mit Fremdschlüsselverknüpfungen: Tabellen, deren eindeutige bzw. Primärschlüssel von anderen Tabellen referenziert werden, können mit dem gängigen DROP TABLE-Befehl nicht gelöscht werden. Mit der Option CASCADE CONSTRAINTS kann der Befehl durchgeführt werden, die referenzierenden Constraints werden dabei entfernt. Die Option ist auch beim DROP TABLESPACE-Befehl vorhanden. DROP TABLE auftraege CASCADE DROP TABLESPACE appl_data -INCLUDING CONTENTS -CASCADE CONSTRAINTS; --
CONSTRAINTS; -- oder: Lösche den ganzen Tablespace sowie alles, was drin ist und alle Fremdschlüssel-Constraints
CHECK Mit dem CHECK-Constraint ist es möglich, frei formulierbare Bedingungen an einen Datensatz zu knüpfen. Die CHECK-Klausel ähnelt der WHERE-Klausel eines SELECTBefehls, ist aber einigen Einschränkungen unterworfen. Der Gebrauch von Unterabfragen, Sequenzen und einigen SQL-Funktionen ist untersagt. Die CHECK-Klausel bezieht sich also immer auf genau einen Datensatz. Ein gutes Beispiel ist ein CHECK-Constraint, der dafür sorgt, dass zwei Spalten entweder beide NULL oder beide NOT NULL sind (s.o.): ALTER TABLE b ADD CONSTRAINT b_chk_fk CHECK (((a1 IS NULL) AND (a2 IS NULL)) OR ((a1 IS NOT NULL) AND (a2 IS NOT NULL)));
Mit den genannten Bedingungen können CHECK-Constraints immer sofort »am Datensatz« überprüft werden. Sie können daher nicht zu Laufzeitproblemen durch weitere Scans in der Datenbank führen.
5.4.2 Constraint-Handhabung Aus- und Einschalten von Constraints Für administrative Operationen, Migrationen und andere Aktivitäten ist es oft notwendig, Constraints temporär zu deaktivieren. Wenn z.B. bei einer Reorganisation die Tabellen neu geladen werden, sind die Fremdschlüssel meist ungültig. Beim Beladen fehlen oft auch die zur Prüfung benötigten Indizes. Das Ausschalten eines Constraints wird mit dem Befehl ALTER TABLE x DISABLE CONSTRAINT x_constraint;
erreicht; das Einschalten entsprechend mit dem Schlüsselwort ENABLE. Zusätzlich kann die Option VALIDATE bzw. NOVALIDATE angegeben werden, wobei VALIDATE beim
Constraints
219
ENABLE und NOVALIDATE beim DISABLE der Standard ist. ENABLE VALIDATE bedeutet, dass beim Einschalten des Constraints auch vorhandene Datensätze geprüft werden; ENABLE NOVALIDATE prüft den Constraint lediglich für nachfolgende DML-Operationen.
Für die Prüfung von eindeutigen bzw. Primärschlüsseln werden Indizes verwendet. Ist die Spaltenkombination beim Einschalten nicht indiziert, so wird ein neuer eindeutiger Index erzeugt; ein vorher angelegter Index kann aber auch zur Überprüfung der Eindeutigkeit herangezogen werden. Der Vorteil eines nicht eindeutigen Index ist, dass dieser beim DISABLE des Constraints nicht entfernt wird. Falls beim Einschalten eines Constraints ein Index angelegt werden muss, können mit der USING INDEX-Klausel hierfür Speicheroptionen (STORAGE-Klausel, TABLESPACE, FREELISTS usw.) angegeben werden. Noch flexibler ist die USING INDEX-Klausel, da hier auch ein bestehender Index mit USING INDEX <schema>.
oder ein komplettes CREATE INDEX-Kommando mit USING INDEX (CREATE INDEX ...)
angegeben werden kann. Seit Oracle9i ist außerdem der Übergang von ENABLE NOVALIDATE zu ENABLE VALIDATE als nicht blockierende Operation implementiert, die auch parallel ausgeführt werden kann. Zum Einschalten von umfangreichen eindeutigen Schlüsseln oder Primärschlüsseln kann idealerweise folgende Kommandofolge verwendet werden: CREATE INDEX <schema>. ... / ALTER TABLE <schema>. ENABLE NOVALIDATE CONSTRAINT / ALTER TABLE <schema>. ENABLE VALIDATE CONSTRAINT USING INDEX <schema>. /
Ein Spezialfall ist das DISABLE VALIDATE-Kommando. Dies wird benötigt, wenn Daten mittels EXCHANGE PARTITION in eine range-partitionierte Tabelle eingefügt werden sollen. Ein vorhandener eindeutiger oder Primärschlüssel wird dann ausgeschaltet, ein eindeutiger Index entfernt, aber die Eigenschaft VALID wird behalten. Beim DISABLE eines eindeutigen oder Primärschlüssel-Constraints kann mit der KEEP INDEX- bzw. DROP INDEX-Option über das Verbleiben des Index, der zur Prüfung des Constraints genutzt wurde, entschieden werden. Eine elementare Eigenschaft des VALIDATE-Prozesses ist die Möglichkeit, ConstraintVerletzungen in einer Ausnahmetabelle zu speichern. Der Hintergrund hierzu ist, dass man beim Fehlschlagen des VALIDATE nicht nur auf eine Fehlermeldung wie ORA-02437: cannot validate (<schema>.) - primary key violated
220
Datenbankobjekte
angewiesen sein sollte – man weiß dann immer noch nicht, welche Datensätze die Bedingung verletzt haben. Die Speicherung in der Ausnahmetabelle erfolgt mit der EXCEPTIONS INTO-Option: ALTER TABLE <schema>. ENABLE VALIDATE CONSTRAINT EXCEPTIONS INTO <exceptions> /
Hierbei bezeichnet <exceptions> eine Tabelle, für die ein Beispiel im Skript $ORACLE_HOME/rdbms/admin/utlexcpt.sql
angegeben ist: CREATE TABLE exceptions( row_id ROWID, owner VARCHAR2(30), table_name VARCHAR2 (30), constraint VARCHAR2 (30) );
Alternativ kann eine beliebige eigene Tabelle verwendet werden; lediglich Spaltennamen und Datentypen müssen identisch zu o.a. Tabelle sein. Nach dem VALIDATE werden alle Datensätze, deren Constraint-Prüfung fehlschlägt, in der Ausnahmetabelle über ihre ROWID identifiziert. Da bei doppelten Schlüsseln für eindeutige oder Primärschlüssel nicht entschieden werden kann, welcher der »falsche« ist, werden in solchen Fällen alle (mindestens zwei!) betroffenen Datensätze eingetragen. RELY-/NORELY-Status Mit Hilfe des RELY-Status kann beim ALTER TABLE MODIFY CONSTRAINT bestimmt werden, dass ein Constraint im NOVALIDATE-Modus für eine Query-Rewrite-Aktion herangezogen wird, obwohl das standardmäßig nicht passiert. RELY wird bei Materialized Views im Zusammenhang mit ausgeschalteten Con-
straints benötigt. Verzögerte Constraint-Prüfung Die Prüfung der Constraints bei DML-Befehlen erfolgt grundsätzlich auf Befehlsebene. Bei INSERT, UPDATE oder DELETE mehrerer Datensätze wird also geduldet, dass es einen nicht constraint-konformen Zwischenstatus geben kann. Solange am Ende eines einzelnen Befehls alle Constraints erfüllt werden, läuft der Befehl ohne Fehlermeldung durch. Diese Eigenschaft kann zwar in Ausnahmefällen nützlich sein – oft wird eine Modifikation der Schlüsselfelder bei einer selbstreferenzierenden Tabelle genannt –, praxisnahe Beispiele hierfür sind aber eher selten. Weitaus wichtiger ist die optionale Möglichkeit, die Constraint-Prüfung auf das Ende der Transaktion zu verschieben. Hierzu gibt es weitaus mehr Beispiele, u.a. viele Fälle von Anwendungen, bei denen im Verlauf einer Transaktion zwischenzeitlich ein nicht constraint-konformer
Constraints
221
Zustand besteht, am Ende einer Transaktion jedoch alles in Ordnung ist. Diese Situation trifft man oft bei der nachträglichen Einführung von Constraints bei bestehenden Anwendungssystemen. Hierzu gibt es die Möglichkeit, eine verzögerte Constraint-Prüfung am Ende einer Transaktion zu aktivieren. Bei der Definition der Constraints hat man zunächst die Möglichkeit, die verzögerte Prüfung zuzulassen oder nicht (DEFERRABLE/NOT DEFERRABLE). Weiterhin kann man bestimmen, ob standardmäßig verzögert geprüft wird oder nicht (INITIALLY DEFERRED/INITIALLY IMMEDIATE). Die Umschaltung auf verzögerte bzw. nicht verzögerte Constraint-Prüfung erfolgt mit einem ALTER SESSION-Befehl: ALTER SESSION SET CONSTRAINTS = [ IMMEDIATE | DEFERRED | DEFAULT ]
Hier ein Beispiel, bei dem ein Primärschlüssel-Constraint verzögert geprüft werden kann: SQL> ALTER TABLE t1 ADD CONSTRAINT t1_pk PRIMARY KEY (i) DEFERRABLE INITIALLY IMMEDIATE; Table altered. SQL> INSERT INTO t1 VALUES (1,'a'); ERROR at line 1: ORA-00001: unique constraint (DIERK.T1_PK) violated SQL> ALTER SESSION SET CONSTRAINTS = DEFERRED; Session altered; SQL> INSERT INTO t1 VALUES (1,'a'); 1 row created. SQL> SELECT * FROM t1; I C ---------- --------------1 x 2 y 3 z 1 a SQL> COMMIT; commit * ERROR at line 1: ORA-02091: transaction rolled back ORA-00001: unique constraint (DIERK.T1_PK) violated Listing 5.25: Deferred Constraint Checking
Mit einem ALTER TABLE-Befehl kann später zwischen INITIALLY IMMEDIATE und INITIALLY DEFERRED gewechselt werden; die prinzipielle Eigenschaft DEFERRABLE oder NOT DEFERRABLE kann ausschließlich beim Anlegen des Constraints angegeben werden. Mit der verzögerten Constraint-Prüfung hat man nunmehr für viele Situationen ein wirkungsvolles Werkzeug zur Hand, u.a. auch für die Einführung von Constraints in replizierten Umgebungen. Interessant ist nun die Frage, warum man nicht automatisch dazu übergeht, Constraints verzögert zu prüfen. Dabei sind, wie immer, verschiedene Aspekte abzuwägen:
222
Datenbankobjekte
Die verzögerte Constraint-Prüfung erfolgt sicher nicht ohne zusätzlichen CPUund Hauptspeicheraufwand. Es sind zwar keine allgemein gültigen Vergleichsfaktoren bekannt; die Alternative der direkten Prüfung in Verbindung mit einer Anwendung, die damit umgehen kann, stellt jedoch sicherlich die schnellere Variante dar. Falls verzögerte Constraint-Prüfungen negativ ausgehen, ist auch der Zusatzaufwand für den Datenbankserver nicht zu unterschätzen. Es entstehen Aufwände im Bereich der Undo-Segmente sowie des Redo-Log sowohl durch die Transaktion als auch durch das Zurückrollen derselben. Generell ist auch die Aufwärtskompatibilität zu älteren Releases wie Oracle7 erwähnenswert: Ohne verzögerte Constraint-Prüfung verhält sich der Datenbankserver identisch zum alten Release. Metadaten Die Views dba_constraints und dba_cons_columns sind zum Monitoring von Constraints vorgesehen. Hier einige ausgewählte Spalten: R_OWNER: Eigentümer der referenzierten Tabelle bei Fremdschlüsseln R_CONSTRAINT_NAME: Name des referenzierten Constraints bei Fremdschlüsseln BAD: YES bedeutet, dass ein Datum mit einem zweistelligen Jahresformat verwendet wird (und somit zu falschen Ergebnissen führen kann). LAST_CHANGE: Datum des letzten ENABLE oder DISABLE CONSTRAINT_TYPE: – P: Primärschlüssel – U: Eindeutiger Schlüssel – R: Fremdschlüssel – C: Check-Constraint – V: View mit Check-Option – O: Read-only-View POSITION: Spaltenposition (wichtig für mehrspaltige Schlüssel) in dba_cons_columns
Views
5.5
223
Views
5.5.1 Standard-Views Views sind virtuelle Tabellen. Ihr Inhalt besteht wie bei Tabellen aus Zeilen und Spalten, liegt aber nicht physisch irgendwo in der Datenbank, sondern wird erst bei Bedarf »on the fly« ermittelt. Die Daten, die eine View beinhaltet, sind von anderen Daten (aus echten Tabellen) abgeleitet. Dennoch können Views in SQLAbfragen wie normale Tabellen behandelt werden. Auch der Inhalt einer View selbst wird durch eine SQL-Abfrage definiert. Diese kann direkt auf echte Tabellen oder selber wiederum auf andere Views Bezug nehmen. Auf diese Weise leitet sich der Inhalt einer View direkt oder indirekt aus einer oder mehreren Basistabellen ab. Unter diesem Aspekt kann eine View auch als benannte Abkürzung für eine SQL-Abfrage gesehen werden. Außer dem Text dieser Abfrage wird praktisch kein weiterer Speicherplatz benötigt. Im Gegensatz zu Tabellen bilden Views also keine Segmente, tauchen also z.B. nicht in dba_segments auf, wohl aber in dba_objects. Natürlich ist Schreibfaulheit nicht der einzige Grund dafür, Views zu benutzen. In den folgenden Abschnitten wird das Thema daher etwas eingehender beleuchtet. Vereinfachung von SQL-Abfragen Komplexe SQL-Abfragen können schnell unleserlich werden. Insbesondere wenn Unterabfragen ([NOT] EXISTS oder [NOT] IN) beteiligt sind, lohnt sich manchmal eine »Auslagerung« der Unterabfrage in eine View. Bei der Anwendungsentwicklung wird das Schreiben und Austesten von SQLAbfragen oft stiefmütterlich behandelt. Performance-Aspekte werden häufig vollständig an die spätere Datenbankadministration »delegiert«. Im produktiven Einsatz zeigen sich dann früher oder später die Mängel, und es muss mit manchmal hohem Aufwand nachgebessert werden, dafür werden Optimizer-Hints und Indexstrukturen nachgepflegt etc. Mit dem nächsten Software-Release und/oder OracleMigration wird das Ganze iteriert. Stammt die Software von einem Drittanbieter, ist es meist nicht möglich, in den Entwicklungsprozess einzugreifen. Wird jedoch auch im eigenen Hause entwickelt, lohnt sich eine Aufgabenteilung: Die Entwickler formulieren schriftlich, welche Abfragen sie brauchen, d.h., welche Daten zurückgegeben werden sollen. Die Datenbanktruppe formuliert entsprechende SQL-Abfragen und stellt für diese, wenn möglich, Views zur Verfügung.
224
Datenbankobjekte
In der Praxis stößt man dabei relativ schnell auf das Problem, dass die meisten Abfragen Bindevariablen beinhalten, Views aber nicht parametriert werden können. Beispielsweise kann folgende Abfrage zur Umsatzbestimmung in einem gegebenen Zeitraum nicht ohne weiteres als View formuliert werden: SQL> SELECT FROM WHERE AND
SUM(ap.anzahl * ap.einzelpreis) AS umsatz auftraege a, aufpositionen ap a.aufnr = ap.aufnr a.aufdatum BETWEEN :b1 AND :b2;
In einigen Fällen lässt sich dieses Problem wie folgt lösen: Vor der eigentlichen Abfrage werden die Parameter in einer temporären Tabelle abgelegt. In der ViewDefinition werden die Bindevariablen durch Unterabfragen auf die temporäre Tabelle ersetzt. Die resultierenden SQL-Kommandos sehen zwar deutlich länglicher aus; da es sich um nichtkorrelierte Unterabfragen handelt, ist die Verarbeitung aber sehr einfach. SQL> CREATE GLOBAL TEMPORARY TABLE param_table ( vname VARCHAR2(20) -- Generische ,param VARCHAR2(20) -- Parametertabelle, ,value_vc VARCHAR2(200) -- wird ,value_num NUMBER -- einmalig ,value_date DATE -- angelegt ) ON COMMIT DELETE ROWS; SQL> CREATE VIEW umsatz_zahlen AS SELECT SUM(ap.anzahl * ap.einzelpreis) AS umsatz FROM auftraege a, aufpositionen ap WHERE a.aufnr = ap.aufnr AND a.aufdatum BETWEEN ( SELECT value_date FROM param_table WHERE vname='ums' AND param='b1') AND ( SELECT value_date FROM param_table WHERE vname='ums' AND param='b2'); SQL> INSERT VALUES SQL> INSERT VALUES
INTO param_table (vname, param, value_date) ('ums', 'b1', sysdate-20); INTO param_table (vname, param, value_date) ('ums', 'b2', sysdate);
SQL> SELECT * from umsatz_zahlen; Listing 5.26: Verknüpfung von View und temporärer Tabelle
Die Parametertabelle kann selbstverständlich für alle Abfragen gemeinsam verwendet werden. Allerdings funktioniert dieser Trick nicht, wenn für eine effiziente Abfragebearbeitung Histogramm-Informationen auf der Spalte aufdatum benötigt werden. Häufig ist es für Benutzer, die Leserechte auf anderen Schemata haben, bequem, eine View zum Lesen der Daten zu definieren. Dabei tritt immer wieder folgende auf den ersten Blick widersprüchliche Situation auf:
Views
225
SQL> CREATE SELECT FROM CREATE VIEW
VIEW alle_kunden AS * appl.kunden; alle_kunden AS SELECT * FROM appl.kunden * FEHLER in Zeile 1: ORA-01031: Unzureichende Berechtigungen SQL> SELECT * FROM appl.kunden; KDNR -----1 2 3
ANRED ----Herr Herr Frau
VORNAME ----------Gerd Gerd Hildegard ...
NACHNAME ----------Müller Müller Dursch
GEBURTST -------03.07.50 15.11.71 22.08.66
Listing 5.27: Rechteproblem mit Views
Obwohl der Benutzer offensichtlich Leserecht auf die betreffende Tabelle hat, kann keine View definiert werden. Der Grund ist, dass das Recht nicht direkt, sondern über eine Rolle (indirektes Recht) an den Benutzer gegeben wurde. Für Abfragen oder DML-Operationen macht dies keinen Unterschied. Innerhalb von Schemaobjekten – also z.B. bei der Definition einer View, analog aber auch bei PL/SQL-Prozeduren oder Triggern – müssen alle benötigten Rechte als direkte Rechte vorhanden sein (der Hintergrund ist, dass Rollen pro Session aktiviert oder deaktiviert werden können, wodurch die View in Sessions ohne Rolle ungültig wäre). In diesem Fall lässt sich das Problem also wie folgt lösen: SQL> GRANT SELECT ON appl.kunden TO demo;
Views aus Security-Gründen Views bieten ein einfaches, allerdings auch beschränktes Sicherheitskonzept. Beispielsweise wird einem Benutzer nicht das Leserecht auf eine bestimmte Tabelle gegeben, sondern das Leserecht auf eine View, die nur diejenigen Sätze der Tabelle zurückliefert, die der Benutzer sehen darf. Der Benutzer sieht sozusagen nur »seinen« Teil der Tabelle. Beispielweise könnte ein Sachbearbeiter für alle Kunden mit Nachnamen von F bis N zuständig sein: SQL> CREATE VIEW kunden_fn AS SELECT * FROM kunden WHERE nachname BETWEEN 'F' AND 'N'; SQL> GRANT SELECT ON kunden_fn TO schwanke; Listing 5.28: View als Sicherheitskonzept
Sollen auch Änderungen auf der Tabelle erlaubt sein, genügt natürlich das reine SELECT-Recht nicht. Hier stehen unterschiedliche Techniken zur Verfügung. Im einfachsten Fall werden zusätzlich UPDATE-, INSERT- oder DELETE-Rechte auf die View vergeben. Dies erlaubt entsprechende DML-Operationen auf den durch die View freigegebenen Teil der Tabelle.
226
Datenbankobjekte
Problematisch ist dabei, dass durch UPDATE- oder DELETE-Kommandos Datensätze in den eigentlich nicht sichtbaren Teil der Tabelle verschoben bzw. eingefügt werden können. Um das zu verhindern, sollten betroffene Views immer mit der Klausel WITH CHECK OPTION angelegt sein. Benutzer mit entsprechenden Rechten auf Views können durch folgende Abfrage ermittelt werden: SQL> SELECT FROM WHERE AND
AND UNION SELECT FROM WHERE AND
AND GRANTEE ---------SCHWANKE SCHWANKE SCHWANKE
grantee, owner, table_name AS view_name, privilege dba_tab_privs p owner = 'APPL' EXISTS ( SELECT 1 FROM dba_views v WHERE v.owner = p.owner AND v.view_name = p.table_name) privilege <> 'SELECT' grantee, owner, table_name AS view_name, privilege dba_col_privs p owner = 'APPL' EXISTS ( SELECT 1 FROM dba_views v WHERE v.owner = p.owner AND v.view_name = p.table_name) privilege <> 'SELECT'; OWNER ---------APPL APPL APPL
VIEW_NAME ---------KUNDEN_FN KUNDEN_FN KUNDEN_FN
PRIVILEGE ---------DELETE INSERT UPDATE
Listing 5.29: Ermitteln von Rechten auf Views
In diesem Fall hätte der Benutzer schwanke DML-Rechte auf die View kunden_fn. Diese sollte daher mittels Check-Option geschützt sein. Die mit Check-Option angelegten Views sowie Read-only-Views werden wie folgt aufgelistet: SQL> SELECT FROM WHERE AND
table_name AS view_name -- alle Views dba_constraints owner = 'APPL' constraint_type IN ('V','O');
VIEW_NAME ---------KUNDEN_FN Listing 5.30: Auflistung von Views
Eine Alternative zur Vergabe von DML-Rechten auf Views ist der Aufbau einer Business-API, die alle Änderungsoperationen in PL/SQL-Aufrufen kapselt. Vorteilhaft ist, dass auch komplexere Plausibilitätsprüfungen eingebaut werden können. Über autonome Transaktionen ist auch ein Logging kritischer Änderungen möglich. Außerdem ist diese Lösung auch für Views möglich, die »non-updateable« sind, also aus technischen Gründen keine DML-Operationen zulassen. In diesem Fall sollten die Views mit der WITH READ ONLY-Klausel definiert werden. Die gesamte
Views
227
Rechtevergabe läuft dann über EXECUTE-Privilegien auf den PL/SQL-Objekten der Business-API. Die Vorteile der beiden Techniken (transparenter Zugriff über normale DML-Kommandos einerseits und flexiblere Sicherheitsmechanismen andererseits) können durch Verwendung so genannter INSTEAD OF-Trigger kombiniert werden. Dabei wird die PL/SQL-Logik in einen Trigger integriert, der die entsprechende Änderungsoperation auslöst. Beispiele für INSTEAD OF-Trigger finden Sie in Abschnitt 5.5.3. Die Views sollten in diesem Fall mit der Check-Option definiert sein (für den Fall, dass ein Trigger versehentlich gelöscht oder deaktiviert wird). Es werden ganz normal DML-Rechte auf die View vergeben. Die Möglichkeit, die sichtbaren Datenmenge durch Views einzuschränken, ist allerdings nicht allzu flexibel. Hat man es mit dynamischen Einschränkungskriterien zu tun, ist jedes Mal eine Neuerzeugung der View notwendig. Auch steigt die Anzahl der notwendigen Views mit der Anzahl der Benutzer rapide an. Der Administrations- und Pflegeaufwand wird entsprechend hoch. Leistungsfähigere und besser skalierbare Sicherheitslösungen bieten beispielsweise die Technologien Fine Grain Access (FGA) bzw. Virtual Private Database (VPD), die in Kapitel 9.8 beschrieben werden. Views zur Datenabstraktion Ein weiterer Grund für die Verwendung von Views ist die Absicherung von Anwendungen oder Tools vor Änderungen des darunter liegenden Datenmodells. Neben dem Security-Aspekt ist dies meist das zentrale Argument für die Integration von Views in eine Business-API. Oracle selbst hat diese Technik konsequent im Rahmen der Data-Dictionary- sowie der V$-Performance-Views eingesetzt. Diese Technik wird auch gerne in Projekten eingesetzt, wenn eine Anpassung oder Reorganisation des Datenmodells durchgeführt werden soll. Dabei wird in zwei Umgebungen parallel gearbeitet. In einer Entwicklungs- und Testumgebung wird die Software an das neue Datenmodell angepasst. Parallel wird auf dem Produktionssystem bereits schrittweise das Datenmodell angepasst und/oder reorganisiert. Über eine Business-API bestehend aus Views und INSTEAD OF-Triggern wird der produktiven Anwendung weiterhin das alte Datenmodell vorgegaukelt. Die eigentliche Umschaltung auf die neue Anwendung kann irgendwann einfach durch Einspielen des neuen Software-Release geschehen. Die Datenbank ist an dieser Stelle bereits vorbereitet. Views und Performance Der unsachgemäße Einsatz von Views kann auch Nachteile mit sich bringen. Insbesondere das Prinzip der Datenabstraktion wird manchmal falsch verstanden, was zu Architekturen führt, in denen über den Basistabellen mehrere Schichten von Views aufgetürmt sind.
228
Datenbankobjekte
Beliebt ist auch eine Argumentation über Wiederverwendung bereits vorhandenen Codes (Code in diesem Fall das SQL-Statement), die seitens der Programmentwicklung gebracht wird. Wird ein Bericht um einige Funktionen erweitert, nutzt man die vorhandenen Views (in denen ja häufig eine Menge Definitionsarbeit steckt) und verknüpft via Joins noch ein, zwei Tabellen oder andere Views dazu. Diese Methodik birgt aber einige Nachteile: Das Ausrechnen des Dateninhalts einer solchen View geschieht in den meisten Fällen sequenziell über mehrere Stufen. Dabei werden in jedem Schritt neue Spalten (aus anderen Tabellen) angeknüpft, ganze Tabellen werden über die SELECTKlausel wieder ausgeblendet, manchmal in einem weiteren Schritt wieder angeknüpft etc. Dies ist prinzipiell aufwändiger als eine View, die von vornherein auf den benötigten Basistabellen aufsetzt. Der Optimizer hat Probleme, solche aufeinander aufbauenden Views in gute Ausführungspläne zu übersetzen. Insbesondere das Verschmelzen von Views und die Weitergabe von Filterbedingungen an unten liegende Views funktioniert längst nicht allen Fällen. Das Resultat sind schlechte Ausführungspläne, die zudem unübersichtlich sind, was den Tuning-Aufwand erhöht. Das Tuning solcher Abfragen und Views mittels Optimizer-Hints ist ebenfalls kritisch. Erfahrungsgemäß ist das Ergebnis solcher Maßnahmen sehr empfindlich gegenüber Änderungen in den Datenvolumen sowie Upgrades auf eine neue Oracle-Version (die interne Arbeitsweise des Optimizers kann sich mit jedem Release ändern). Ein häufiges Nachpflegen der eingebauten Hints wird notwendig. Es sollte daher unbedingt angestrebt werden, nur eine einzige View-Schicht über den Basistabellen zu haben. Wiederverwendung von Code ist zwar im Programmierumfeld eine gute Technik, für SQL-Abfragen im beschriebenen Sinne aber ungeeignet. Auch bei einfachen Views wird man aber nicht immer um Tuning-Maßnahmen herumkommen. Ist der Einbau von Optimizer-Hints geplant, sollten diese aber nicht innerhalb der SELECT-Anweisung der View-Definition untergebracht werden, da man dadurch Abfragen negativ beeinflussen könnte, die diese View ebenfalls verwenden, aber andere WHERE-Klauseln haben. Stattdessen ist hier die Benutzung so genannter globaler Hints anzuraten (für Beispiele siehe Kapitel 11.4). View-Definitionen in Skripten An dieser Stelle sollen noch einige Tipps zum Scripting für Views gegeben werden: Bei einfachen Views ist es bequem, in die SELECT-Liste einfach den * zu schreiben, um alle Spalten der darunter liegenden Tabelle(n) zu übernehmen. Der * wird aber zur Erzeugungszeit der View in eine konkrete Spaltenliste expandiert. Werden die Basistabellen oder Views später um neue Spalten erweitert, werden diese nicht in die darüber liegende View propagiert. Auch ein Rekompilieren der View hilft hier nicht. Sollen die neuen Spalten mit aufgenommen werden, muss die View neu erzeugt werden: CREATE OR REPLACE VIEW ... AS SELECT * ...
Views
229
Die Verwendung der FORCE-Klausel (CREATE FORCE VIEW ...) sorgt für eine höhere Robustheit in Skripten, da ansonsten die Erzeugung der View fehlschlägt, wenn die darunter liegenden Tabellen/Views noch nicht vorhanden sind. Mit der FORCE-Option wird die View erzeugt und ist ggf. noch ungültig. Wenn auf einer Basistabelle ein funktionsbasierter Index neu erzeugt wurde, sollten Views, die direkt oder indirekt auf dieser Tabelle basieren, neu kompiliert werden (ALTER VIEW ... COMPILE). Ein entsprechendes Compile-Skript sollte zur Sicherheit nach den Indexdefinitionen aufgerufen werden.
5.5.2 Materialized Views Dem Vorteil herkömmlicher Views, keinen Speicherplatz zu verbrauchen, steht der Nachteil gegenüber, dass der Inhalt erst einmal berechnet werden muss, was natürlich Ressourcen kostet. Greifen viele Benutzer auf dieselbe View zu, werden diese Berechnungen immer wieder durchgeführt. Insbesondere in Data-Warehouse Umgebungen hat man es meist mit großen Mengen an Rohdaten zu tun, die für Reporting-Zwecke eingeschränkt und verdichtet werden. Hier ist man oft bereit, Speicherplatz zur Verfügung zu stellen, um das Ergebnis einer SQL-Abfrage oder View physikalisch abzuspeichern. Bei der Abfrage einer solchen Materialized View wird der Inhalt nicht »on –the fly« berechnet, sondern einfach aus dem zugehörigen Segment gelesen. Materialized Views sind echte Segmente wie Tabellen auch. Ihre Dateninhalte sind zwar redundant. Im Gegensatz zu einer manuell erstellten Summationstabelle, deren Konsistenz und Aktualität vom Benutzer überwacht und gepflegt werden müssen, ist diese Redundanz aber der Datenbank bekannt und wird automatisch kontrolliert sowie ggf. zur inkrementellen Pflege des View-Inhalts genutzt. Grundsätzlich kann jede View auch materialisiert werden. In der Praxis ist vor allem interessant, wie die Pflege der Materialized Views möglichst ressourcenschonend gestaltet werden kann. Dabei sind zwei grundlegende Fragen zu beantworten: Die fachliche Frage nach den Anforderungen an die Datenaktualität muss gestellt werden. Die Antwort darauf bestimmt das Intervall, in dem eine Aktualisierung (Refresh) der Materialized Views durchgeführt werden muss. Auf technischer Ebene ist zu klären, ob die durch die View bereitgestellten Daten inkrementell aktualisiert werden können. Mit der Version Oracle 10g wird für die technische Realisierung einer Materialized View ein Expertensystem – der so genannte MView-Advisor – mitgeliefert. Durch die Query-Rewrite-Funktionalität (Klausel ENABLE QUERY REWRITE) wird die Existenz einer Materialized View für die Anwendung transparent. SQL-Abfragen brauchen nicht angepasst zu werden, stattdessen prüft der Optimizer, ob zur Beantwortung einer Abfrage eine Materialized View herangezogen werden kann. Details und Beispiele zur Definition und Benutzung von Materialized Views sowie des MView-Advisors finden Sie in Kapitel 15.2.5.
230
Datenbankobjekte
5.5.3 Object-Views Da der relationale Teil des Oracle-Systems auf der Speicherung von Daten in Tabellen sowie der Darstellung von Teilmengen, Verknüpfungen usw. in Views basiert, ist es nicht verwunderlich, dass es im objektrelationalen Bereich ebenfalls Views gibt. Diese sind jedoch insbesondere für die Fälle gedacht, in denen relationale Strukturen z.B. für Entwicklungs- und Testzwecke als objektrelationale Elemente dargestellt werden sollen. Einige Erweiterungen des View-Konzepts helfen dabei, auch komplexe Strukturen abzubilden. Natürlich sind auch Objekttabellen und Views als Basis für Objekt-Views erlaubt. Ein Beispiel, basierend auf den Objekttypen person und telnummern, soll den Ansatz der Objekt-Views erklären. Damit eine Objekt-View erstellt werden kann, die auf relationalen Strukturen basiert, werden zunächst die entsprechenden »flachen« Tabellen personen und telefone benötigt. CREATE TABLE personen (pid NUMBER(5,0), name VARCHAR2(30), vorname VARCHAR2(30), CONSTRAINT personen_pk PRIMARY KEY (pid) ) / CREATE TABLE telefone (pid NUMBER(5,0), nr VARCHAR2(20), CONSTRAINT telefone_ref_personen FOREIGN KEY (pid) REFERENCES personen, CONSTRAINT telefone_pk PRIMARY KEY (nr) ) / Listing 5.31: „Normale“ Tabellen als Basis für Objekt-Views
Für die Tabellen sind einige Constraints definiert worden, so dass ein typisches relationales Modell vorliegt. Mit der folgenden Objekt-View-Definition wird dieses Modell nunmehr in die objektrelationale Welt abgebildet: CREATE OR REPLACE TYPE telnummern_t AS VARRAY(10) OF VARCHAR2(20) / CREATE OR REPLACE TYPE person_t AS OBJECT ( id NUMBER(5,0), vorname VARCHAR2(30), nachname VARCHAR2(30), telnummern telnummern_t) / CREATE VIEW person_v OF person_t WITH OBJECT IDENTIFIER (id) AS
Views
231
SELECT pid, vorname, name, CAST( MULTISET( SELECT nr FROM telefone t WHERE t.pid = p.pid) AS telnummern_t) FROM personen p / Listing 5.32: Erstellen einer Objekt-View
Hierbei ist zunächst zu beachten, dass das CREATE VIEW-Kommando den Zusatz OF erhält, mit dem man, wie bei einer Objekttabelle, einen Objekttyp zuordnet. Für Objekt-Views, die auf relationalen Strukturen basieren, muss ein aus einem oder mehreren Werten zusammengesetzter Objekt-Identifier spezifiziert werden. Hier bietet sich ein Primärschlüssel an. Mit Hilfe der CAST- und MULTISET-Operatoren können Ergebnisse aus Subselects als Collections in die Objektstruktur eingebaut werden. Nunmehr können Werte, die z.B. per INSERT in die Basistabellen geflossen sind, aus der Objekt-View gelesen werden. Problematisch ist jedoch die Manipulation der Objekt-View selbst: Der Versuch, einen passend getypten Datensatz in die ObjektView einzufügen, mündet in einen Fehler, da die künstlichen Schlüsselinformationen für die referenzielle Integrität nicht automatisch erzeugt werden können. Aus diesem Grund wurde zeitgleich zur Einführung der Objekttechnologie in das Oracle-System der Instead-of-Trigger für Views eingeführt. Dieser hängt ebenso wie die bekannten Tabellen-Trigger an den DML-Operationen INSERT, UPDATE und DELETE, mit dem Unterschied, dass er nicht vor bzw. nach der eigentlichen DMLOperation ausgeführt wird, sondern statt der DML-Operation. Ein INSERT-Trigger für die Objekt-View person_v könnte wie folgt aussehen: CREATE OR REPLACE TRIGGER person_v_insert INSTEAD OF INSERT ON person_v FOR EACH ROW BEGIN INSERT INTO personen VALUES (:NEW.id, :NEW.nachname, :NEW.vorname); FOR v_loop IN 1..:NEW.telnummern.COUNT LOOP INSERT INTO telefone VALUES (:NEW.id, :NEW.telnummern(v_loop)); END LOOP; END; / Listing 5.33: Instead-of-Trigger
Hierbei wird das neu einzufügende Objekt in seine Bestandteile zerlegt und mit Hilfe von Schleifenstrukturen auf Master- und Detaildatensätze verteilt. Dadurch, dass die zugrunde liegenden flachen Tabellen mit Primär- und Fremdschlüsseln versehen sind, wird automatisch die logische Konsistenz der Daten gewährleistet.
232
Datenbankobjekte
Mit Hilfe der Objekt-Views können also relationale Strukturen in die Objektwelt abgebildet werden; mit Hilfe der Instead-of-Trigger kann diese Abbildung sogar funktional vollständig sein. Somit können z.B. beim Übergang von einem relationalen zu einem objektrelationalen Datenmodell bereits neue Anwendungen erstellt und auf den bestehenden Daten getestet werden. Ein potenzieller Vorteil bei der Verwendung von Objekt-Views in Client-Software ist die Übertragung des gesamten Objekts in einem Netzwerkzyklus anstelle der Übertragung von einzelnen Zeilen oder Zeilenmengen im relationalen Fall. Hierbei handelt es sich sozusagen um eine Weiterentwicklung des Array-Fetch-Modells der Oracle-Client-Software. Ansonsten sind die Instead-of-Trigger sicherlich auch interessant für andere Anwendungen, da sie keineswegs auf Objekt-Views eingeschränkt sind. Somit ist es möglich, INSERT-Befehle abzufangen und mit den gelieferten Daten etwas ganz anderes zu tun, sie z.B. an eine Advanced Queue übergeben.
5.6
PL/SQL-Objekte
Eine Anwendung besteht nie ausschließlich aus SQL-Skripten, sondern ist in einer so genannten Host-Sprache geschrieben, z.B. C++, Delphi, Java etc. SQL-Kommandos werden an entsprechenden Stellen in den Quellcode eingebunden, entweder durch Prozeduraufrufe oder – komfortabler – als Klartext-Befehle, die von einem Precompiler in Prozeduraufrufe der Host-Sprache übersetzt werden. PL/SQL ist so eine Host-Sprache. Von anderen unterscheidet sie sich im Wesentlichen durch zwei Merkmale: Sowohl der Precompiler als auch die Laufzeitumgebung für PL/SQL sind fester Bestandteil der Oracle Server-Software und in den Oracle-Kernel integriert. Daraus folgt, dass bei der Ausführung eines SQL-Kommandos aus einer Prozedur heraus kein Overhead durch Netzwerk- oder Interprozess-Kommunikation auftritt. Außerdem ist das Zusammenspiel von SQL und PL/SQL auf Codierungsebene verhältnismäßig gut und unkompliziert. Dies reicht so weit, dass die Grenzen zwischen SQL-Engine und PL/SQL-Engine bisweilen regelrecht verwischen. Insbesondere die Datentypen und eingebauten Funktionen beider Umgebungen sind nahezu deckungsgleich. Intern wird aber wie bei jeder anderen Host-Sprache auch konvertiert. Jede Ausführung eines SQL-Kommandos in einer PL/SQLProzedur führt zu einem Kontext-Switch, der CPU-Overhead erzeugt. PL/SQL ist sehr datenbanknah und verfügt über keine grafische Ausgabe und nur sehr begrenzt über die Möglichkeit der Textausgabe. In der Praxis findet daher häufig eine Aufgabenteilung dergestalt statt, dass eine andere Sprache als PL/SQL als Host-Sprache für die Anwendung verwendet wird, aus der heraus SQL-Kommandos ausgeführt und/oder PL/SQL-Konstrukte aufgerufen werden. Auf diese Weise wird die eigentliche Datenbanklogik in PL/SQL formuliert, während der Rest des Quellcodes in einer Drittsprache vorliegt.
PL/SQL-Objekte
233
PL/SQL ist normalerweise eine interpretierte Sprache, d.h., der Quellcode wird nicht in Maschinenbefehle übersetzt, sondern in eine Zwischenschicht – den so genannten M-Code –, der erst zur Laufzeit von der PL/SQL-Engine interpretiert und ausgeführt wird. Die dadurch erreichte Plattformunabhängigkeit des Objektcodes wird durch einen Performance-Nachteil gegenüber kompilierten Sprachen erkauft. Insbesondere bei CPU-intensiven Routinen lohnt es sich daher, Native Compilation oder sogar die Realisierung in einer anderen Programmiersprache in Betracht zu ziehen (siehe unten, Abschnitt Laufzeit-Optimierung). Die Datentypen von PL/SQL entsprechen weitgehend den SQL-Datentypen. Es existieren dennoch einige Abweichungen. Die wichtigste ist, dass der Datentyp VARCHAR2 in PL/SQL bis zu 32767 Zeichen aufnimmt, was bei entsprechenden Funktionsaufrufen in SQL-Kommandos zu Problemen führen kann. Auch der PL/SQLeigene Datentyp BOOLEAN kann leider nicht aus der SQL-Engine heraus angesprochen werden. Remote-Aufrufe von PL/SQL-Routinen auf anderen Datenbanken sind möglich, soweit es einen Datenbank-Link zu der betreffenden Datenbank gibt. Die Ausführung geschieht auf der Remote-Datenbank. Diese Möglichkeit kann natürlich auch ein Sicherheitsproblem darstellen. Auf produktiven Systemen sollte daher kein Benutzer-Account, der über einen Datenbank-Link erreichbar ist, Ausführungsrechte für PL/SQL-Objekte haben, die nicht zur Anwendung gehören. Einige der mitgelieferten PL/SQL-Packages sind unter Security-Aspekten ohnehin kritisch, da sie in einer Standarddatenbank von jedem Benutzer ausführbar sind. Dabei handelt es sich speziell um die Packages utl_file, utl_tcp, utl_http, utl_smtp, dbms_random, dbms_lob, dbms_sql, dbms_sys_sql, dbms_job, dbms_scheduler und owa_util. Der allgemeine Zugriff auf diese Packages sollte verhindert werden, z.B.: SQL> REVOKE EXECUTE ON sys.dbms_job FROM public;
Anschließend können Ausführungsrechte gezielt an einzelne Benutzer vergeben werden. Alle PL/SQL-Objekte können über die View dba_objects abgefragt werden (object_type IN ('FUNCTION','PROCEDURE','PACKAGE','PACKAGE BODY')). Der Quelltext ist über dba_source verfügbar, die Parameterlisten über all_arguments. Komfortabler ist aber die Verwendung geeigneter Tools, z.B. TOAD von Quest, Hora von Keeptool oder im Oracle Enterprise Manager. Genau wie bei Views gilt auch für die Erstellung von PL/SQL-Objekten und Triggern, dass alle benötigten Rechte als direkte Rechte vorhanden sein müssen, die indirekte Erlaubnis über eine Rolle genügt nicht. Debugging Für jedes PL/SQL-Objekt können im M-Code zusätzliche Informationen zu Debugging-Zwecken abgelegt werden (DEBUG-Klausel des ALTER PROCEDURE-Kommandos). Für das eigentliche Debugging sind Ausführungsrechte auf dem Package dbms_debug notwendig. Da dieses normalerweise für alle Benutzer ausführbar ist, stellt es kein Problem dar.
234
Datenbankobjekte
Neu in Oracle 10g ist, dass außerdem das Systemprivileg DEBUG CONNECT SESSION benötigt wird. Für PL/SQL-Objekte in anderen Schemas kommen noch die Systemprivilegien EXECUTE ANY PROCEDURE und DEBUG ANY PROCEDURE hinzu. Debugging ist prinzipiell nicht für solche Objekte möglich, die mit Native Compilation erzeugt, also in Maschinencode übersetzt wurden. Der Kompilierungsmodus sowie das Vorhandensein von Debug-Informationen können aus dem Data Dictionary abgefragt werden: SQL> SELECT name, type, plsql_code_type, plsql_debug FROM dba_plsql_object_settings WHERE owner = 'DEMO'; NAME ---------DEMOPKG DEMOPKG
TYPE --------------PACKAGE PACKAGE BODY
PLSQL_CODE_TYPE --------------INTERPRETED INTERPRETED
PLSQL_DEBUG ----------FALSE FALSE
Listing 5.34: Kompilierungsmodus und Debug überprüfen
Debugging ist für alle Prozeduren und Funktionen (standalone oder als Bestandteil eines Packages) sowie für Trigger möglich. Methoden innerhalb von Objekttypen (erzeugt über den SQL-Befehl CREATE TYPE ...) sind nicht Debug-fähig. Dasselbe gilt für anonyme PL/SQL-Blöcke (DECLARE ... BEGIN ... END), hier muss ggf. eine separate Prozedur mit dem betreffenden Block als Inhalt für das Debugging definiert werden. Das Debugging sollte nach Möglichkeit nicht manuell, sondern tool-gestützt (Quest TOAD, Keeptool Hora, PL/SQL-Developer etc.) durchgeführt werden. Wichtig zu wissen ist, dass das Debugging eine zeitlupenartige Ausführung des entsprechenden PL/SQL-Objekts darstellt. Während eines Debugging-Laufs sind daher das betreffende Objekt sowie alle davon direkt oder indirekt benutzten PL/SQL-Objekte, Tabellen, Views etc. in den Oracle Library-Cache geladen und dort gesperrt. Daher sind »hängende« Debugging-Sessions in einer Entwicklungs- oder Testumgebung ein sehr lästiges Problem. Kompilierungsversuche durch einen Benutzer oder in einer anderen Session führen dazu, dass diese Session ebenfalls hängt. Häufig ist der schnellste Weg, diese Situation aufzulösen, mit Administratorrechten die Debug-Session zu killen (ALTER SYSTEM KILL SESSION ...). In solchen Umgebungen sollte unbedingt die Disziplin angemahnt werden, Debug-Sessions stets sauber zu beenden (jedes Tool hat dafür einfach einen entsprechenden Button, man muss ihn eben nur benutzen ...). Wrapping Der Quellcode eines PL/SQL-Objekts kann geschützt werden, indem man das Objekt verhüllt, neudeutsch wrappt. Dies bedeutet, dass der eigentliche Quellcode durch den M-Code ersetzt wird. Auf diese Weise kann eine Anwendung ausgeliefert werden, ohne Einblick in den Quellcode zu gewähren. Auch über die oben genannte View dba_source ist der Quellcode nicht mehr einsehbar. Die meisten mitgelieferten Oracle-Packages (dbms_*) liegen ausschließlich als M-Code vor.
PL/SQL-Objekte
235
Es ist nicht möglich, ein PL/SQL-Objekt in die Datenbank einzuspielen und nachträglich ein Wrapping durchzuführen. Stattdessen findet das Wrapping der Objektdefinition innerhalb eines Skripts statt, das anschließend eingespielt wird. Im Unterverzeichnis bin innerhalb des Oracle-Homes befindet sich das Tool wrap (wrap.exe unter MS-Windows), das die eigentliche Konvertierung leistet, z.B.: $ wrap iname=create_procs.sql oname=create_procs_wrapped.sql SQL> @create_procs_wrapped.sql Listing 5.35: PL/SQL-Wrapper
Aus dem Originalskript create_procs.sql wird ein neues Skript erzeugt. Sämtliche CREATE-Kommandos für Funktionen, Prozeduren, Packages, Package Bodies, Typen sowie Typ-Bodies werden in den M-Code übersetzt, alle anderen Kommandos bleiben unverändert. Alleine das Skript create_procs_wrapped.sql wird anschließend eingespielt. Da eine Wiederherstellung des Quellcodes aus dem M-Code nicht möglich ist, muss für Updates stets das Originalskript gepflegt und anschließend für die Auslieferung erneut verhüllt werden. Einige wichtige Hinweise zum Wrapping sollen an dieser Stelle noch gegeben werden: In den PL/SQL-Code eingebettete SQL-Kommandos können trotz Wrapping durch SQL-Tracing der Anwendung (siehe Kapitel 11.2) oder durch Inspektion der View v$sql sichtbar gemacht werden. Das Exportieren und Importieren von verhüllten PL/SQL-Objekten mittels Data Pump oder konventionellem Export/Import (siehe Kapitel 10.6) ist problemlos möglich. Die Objekte bleiben dabei verhüllt. Der Quellcode von Triggern kann nicht verhüllt werden. Stattdessen muss eine eigene Prozedur für den Trigger-Quellcode geschrieben und das Wrapping danach durchgeführt werden. Der Trigger ruft anschließend einfach diese Prozedur auf. Passwörter oder sonstige Werte, die als Konstanten oder als Default-Werte für Variablen im Quellcode eingebaut sind, werden durch das Wrapping nicht verschlüsselt, sondern tauchen auch im verhüllten Code im Klartext auf! In solchen Fällen sollte das Passwort stattdessen verschlüsselt in einer entsprechend geschützten Datenbanktabelle oder Betriebssystemdatei gespeichert werden. Über die Packages dbms_obfuscation_toolkit oder dbms_crypto (Letzteres sollte ab der Datenbankversion 10g benutzt werden) stehen verschiedene Ver- und Entschlüsselungsalgorithmen zur Verfügung, u.a. DES, 3DES, AES, MD5 und SHA-1. Die Datenbank, in die ein verhülltes Objekt eingespielt wird, muss von derselben oder einer neueren Version sein als die Datenbank, in der das Wrapping stattfand. Das Einspielen in eine ältere Datenbankversion ist nicht möglich.
236
Datenbankobjekte
Tabellenfunktionen Oracle bietet mit den so genannten Tabellenfunktionen die Möglichkeit, benutzerdefinierte PL/SQL-Funktionen als Datenquellen in SQL-Abfragen einzusetzen. Dies ist auch für administrative Zwecke interessant, da auf diese Weise zum Beispiel Monitoring-Skripte zentral in der Datenbank abgespeichert und gepflegt werden können. Ein entsprechender Report kann dann jederzeit von jedem Client aus abgegriffen werden, ohne dass erst das richtige Skript gesucht werden muss. Der Report wird zeilenweise von einer PL/SQL-Funktion erzeugt. Für eine detaillierte Beschreibung der Benutzung von Tabellenfunktionen wird auf die Oracle-Dokumentation Oracle 10g PL/SQL User’s Guide and Reference sowie Data Cartridge Developer’s Guide verwiesen. Hier soll lediglich ein einfaches Beispiel gegeben werden. SQL> CREATE TYPE report_typ AS TABLE OF VARCHAR2(200); / SQL> CREATE OR REPLACE FUNCTION datenbank_report RETURN report_typ PIPELINED AS CURSOR c1 IS SELECT owner, table_name FROM dba_tables WHERE last_analyzed IS NULL AND owner NOT IN ('SYS','SYSTEM') ORDER BY owner, table_name; BEGIN PIPE ROW ('************************************'); PIPE ROW ('Datenbank-Report ' || TO_CHAR(SYSDATE,'DD.MM.YYYY HH24:MI:SS')); PIPE ROW ('************************************'); PIPE ROW (''); PIPE ROW ('Tabellen ohne Optimizer-Statistiken:'); PIPE ROW ('------------------------------------'); FOR t IN c1 LOOP PIPE ROW (t.owner || '.' || t.table_name); END LOOP; -- weitere Tests PIPE ROW (''); PIPE ROW ('Report-Ende'); RETURN; END; / SQL> SET PAGESIZE 0 SQL> SET LINESIZE 120 SQL> SELECT * FROM TABLE(datenbank_report);
PL/SQL-Objekte
237
************************************ Datenbank-Report 04.03.2005 21:44:36 ************************************ Tabellen ohne Optimizer-Statistiken: -----------------------------------DEMO.AUFPOSITIONEN DEMO.AUFTRAEGE DEMO.KUNDEN DEMO.PRODUKTE Report-Ende 12 Zeilen ausgewählt. Listing 5.36: Table Function
Überwachung kritischer DML-Operationen mit Triggern Der Zugriff auf sensible Daten einer Anwendung wird in den meisten Fällen über Rechtevergaben genau geregelt sein. Änderungen solcher Daten mittels DML-Operationen können außerdem mit Hilfe von Triggern protokolliert werden. Führen solche Änderungen allerdings zu einer Constraint-Verletzung, wird die SQL-Operation und mit ihr die Protokollierung durch den Trigger zurückgerollt. Unter Security-Gesichtspunkten ist es manchmal interessant, gerade diese zurückgewiesenen Änderungen zu protokollieren. Die Lösung dafür liegt in der Verwendung so genannter autonomer Trigger. Dabei wird der Inhalt des Triggers, also die Protokollierung, in einer eigenständigen Transaktion ausgeführt und unabhängig vom Ausgang der auslösenden DML-Operation festgeschrieben. Ein normaler Trigger kann einfach in einen autonomen Trigger verwandelt werden, indem im Deklarationsteil das Compiler-Pragma AUTONOMOUS_TRANSACTION eingefügt wird. Für die Aufträge-Tabelle kann das z.B. wie folgt aussehen: SQL> CREATE OR REPLACE TRIGGER auftraege_protokoll AFTER INSERT ON auftraege FOR EACH ROW DECLARE PRAGMA AUTONOMOUS_TRANSACTION; -- dies ist entscheidend BEGIN INSERT INTO auftraege_log (datum, benutzer, aufnr) VALUES (SYSDATE, USER, :new.aufnr); COMMIT; END; / Listing 5.37: Autonome Transaktion
238
Datenbankobjekte
Problemfälle Bei allen Annehmlichkeiten und Möglichkeiten, welche die Benutzung von PL/SQL mit sich bringt, soll hier auch auf Konstellationen hingewiesen werden, auf welche die Autoren in der Praxis gestoßen sind und die problematisch sein können: In PL/SQL können sehr einfach Hauptspeichertabellen definiert und verwaltet werden (so genannte PL/SQL-Tabellen, Index-by-Tabellen oder Nested-Tabellen). Theoretisch können diese Konstrukte bis zu 2^31, also ca. 2 Mrd. Zeilen enthalten. Dennoch sollte mit diesen Tabellen nicht verschwenderisch umgegangen werden. Der Inhalt wird nämlich komplett im Hauptspeicher gehalten. Es findet keine Auslagerung in Temporär-Segmente statt. Auch Begrenzungen des Hauptspeichers über Serverparameter wie sort_area_size oder pga_aggregate_target spielen in diesem Zusammenhang keine Rolle! Bei vielen parallelen Session multipliziert sich der Gesamtspeicherbedarf entsprechend. Ist nicht genügend Hauptspeicher vorhanden, tritt auf Betriebssystemebene irgendwann massives Paging auf, was natürlich erhebliche Performance-Nachteile mit sich bringt (datenbankseitig manifestiert sich dies in deutlichem Ansteigen der CPU-Zeiten, betriebssystemseitig schafft bei Unix das vmstat-Kommando Klarheit). Im Extremfall hängt sich der Datenbankserver komplett auf. Ist das Kind schon in den Brunnen gefallen, kann durch HauptspeicherAusbau oder Lastverteilung über eine RAC-Datenbank Entlastung geschaffen werden. Der Einsatz von benutzerdefinierten Funktionen in Abfragen anstelle von mengenorientierten Operationen wie Joins und Aggregationen erscheint häufig verlockend, sollte aber nur in Ausnahmefällen wirklich realisiert werden, da er entscheidende Nachteile mit sich bringt. Dies soll an den beiden folgenden Abfragen verdeutlicht werden, die scheinbar dasselbe tun: SQL> CREATE FUNCTION anz_auftraege (i_kdnr IN NUMBER) RETURN NUMBER AS ergebnis NUMBER; BEGIN SELECT COUNT(*) INTO ergebnis FROM auftraege WHERE kdnr = i_kdnr; RETURN ergebnis; END; / SQL> SELECT k.kdnr, COUNT(a.aufnr) AS anz_auftraege FROM kunden k, auftraege a WHERE k.kdnr = a.kdnr (+) GROUP BY k.kdnr; SQL> SELECT kdnr, anz_auftraege(kdnr) AS anz_auftraege FROM kunden; Listing 5.38: Vergleich von Funktion und SQL-Befehl
PL/SQL-Objekte
239
Beide Abfragen ermitteln die Anzahl der Aufträge jedes Kunden. Die zweite Abfrage erscheint übersichtlicher und einfacher lesbar, da auch kein Outer-Join benötigt wird, um Kunden ohne Aufträge zu erfassen. Die Funktion anz_auftraege kann auch in anderen Abfragen wiederverwendet werden, der Join dagegen müsste stets aufs Neue formuliert werden. Leider handelt es sich aber tatsächlich nur um codierungstechnische Vorteile, denen zwei gewichtige Nachteile bei der Ausführung gegenüberstehen: Die Performance der zweiten Abfrage ist fast immer schlechter, da auf prozeduralem Wege so etwas wie ein Nested-Loop-Join erzwungen wird, wohingegen die erste Abfrage von alternativen Join-Methoden des Optimizers wie MergeJoins oder Hash-Joins profitieren kann. Auch alternative Join-Reihenfolgen der beteiligten Tabellen sind in der prozeduralen Variante offenbar nicht möglich. Außerdem müssen für jeden Kunden insgesamt vier so genannte Kontext-Switches zwischen SQL- und PL/SQL-Engine durchgeführt werden, die zusätzlichen CPU-Overhead erzeugen. Werden während der Laufzeit der Abfrage Aufträge geändert, storniert oder neu generiert, gewährleistet die Datenbank bekanntlich Lesekonsistenz durch Rückgriff auf die Undo-Segmente (siehe Kapitel 1.3.1). Weniger bekannt ist die Tatsache, dass bei der zweiten Abfrage keine (!) Lesekonsistenz besteht, da jede einzelne Abfrage der Aufträge-Tabelle ihren eigenen Konsistenz-Zeitpunkt hat. Die zurückgelieferten Auftragsinformationen müssen also weder mit den Kundeninformationen noch untereinander konsistent sein. Dies fällt beim Entwickeln und Testen nicht so schnell auf, da es erst bei gleichzeitigen DML-Operationen akut wird. Ist hier das Kind schon in den Brunnen gefallen, besteht der einzige Ausweg darin, vor der Abfrage über das Kommando SET TRANSACTION READ ONLY einen einzigen Konsistenz-Zeitpunkt für die gesamte Transaktion (die nur aus einer oder aus mehreren Abfragen besteht) festzulegen. Vor der nächsten DML-Operation muss dann ein COMMIT stehen, um den Read-only-Modus wieder zu verlassen. Ohne Eingriffe in den Quellcode ist hier also nichts zu retten. Laufzeit-Optimierung von PL/SQL-Code Vor dem Einsatz von Techniken zur Laufzeit-Verbesserung von PL/SQL-Code sollte eine Performance-Analyse stehen, welche die Frage klärt, wo eigentlich die ganze Laufzeit verbraucht wird: in den SQL-Kommandos oder in PL/SQL-Konstrukten wie Schleifen oder umfangreichen Hauptspeicheroperationen. Hierfür ist der so genannte PL/SQL-Profiler bestens geeignet. Über das mitgelieferte Package dbms_profiler werden Laufzeitstatistiken für die Ausführung von PL/SQL-Objekten gesammelt, die beschreiben, wie viel Zeit in jeder durchlaufenen Quellcodezeile verbracht wird. Einige Anmerkungen zu der Benutzung des Profilers: Um die Messergebnisse nicht zu verfälschen, werden während der Ausführung die Laufzeitstatistiken im Hauptspeicher gepflegt. Erst nach der Ausführung werden die endgültigen Werte in Tabellen geschrieben. Dadurch sind diese Werte tatsächlich sehr verlässlich.
240
Datenbankobjekte
Die Auswertung dieser Tabellen (plsql_profiler_data, plsql_profiler_units und plsql_profiler_runs) geschieht vorzugsweise über ein Tool, um übersichtliche Darstellungen wie z.B. Balken- oder Kuchendiagramme nutzen zu können. Quest TOAD oder der PL/SQL-Developer bieten entsprechende Schnittstellen. Die genannten Tabellen müssen zuvor über das Skript proftab.sql im Verzeichnis $ORACLE_HOME/rdbms/admin erstellt werden. Sie können wahlweise in mehreren Schemata oder in einem zentralen Schema erstellt werden. In letzterem Fall wird über entsprechende Synonyme und Rechtevergaben der Zugriff mehrerer Benutzer geregelt. In den Datenbankversionen bis einschließlich Oracle9i muss außerdem das Package dbms_profiler manuell im Schema SYS erstellt werden (Skript profload.sql). Der erste Aufruf eines PL/SQL-Objekts liefert meist unbrauchbare Laufzeitwerte, da rekursive (interne) SQL-Kommandos die Messungen verfälschen. Dieser Aufruf sollte daher nicht ausgewertet werden. Stellt sich heraus, dass SQL-Kommandos (Abfragen, Cursor-Durchläufe sowie DMLOperationen) den Flaschenhals bilden, sollte mit der Optimierung zunächst dort begonnen werden. SQL-Tracing ist in diesem Fall ein guter Start, um weitere Details und Ansatzpunkte für Tuning-Maßnahmen zu erhalten (siehe Kapitel 11.2). Erst wenn echte PL/SQL-Kommandos den Großteil der Zeit beanspruchen, sollte PL/SQL-Optimierung in Betracht gezogen werden. Betriebssystemseitig bedeutet dies meistens, dass bei wachsender Last zuerst die CPU vor dem I/O-System an ihre Grenzen stößt. Abgesehen von Änderungen am Quellcode gibt es zwei Möglichkeiten, die Performance von PL/SQL-Code zu verbessern: Generierung von optimiertem M-Code: Der PL/SQL-Compiler wird über den Serverparameter plsql_optimize_level angewiesen, bestimmte Techniken anzuwenden. Folgende Werte sind möglich: – 0: entspricht der normalen Kompilierung wie in der Datenbankversion 9i – 1: beinhaltet kleinere Optimierungen, z.B. werden unnötige Berechnungen oder Ausführungen weggelassen – 2: aktiviert weitergehende Techniken, insbesondere »Code Reordering«, also Anpassungen der Reihenfolge der einzelnen Anweisungen. Entgegen der Dokumentation ist die Default-Einstellung dieses Serverparameters nicht 0, sondern 2. Standardmäßig findet also bereits eine Optimierung statt. Kompilieren des M-Codes in Maschinencode (»Native Compilation«): Anstatt des interpretierten M-Codes wird direkt ausführbarer Maschinencode in Form von Shared Libraries (.dll-Dateien unter MS-Windows, .so-Dateien unter Unix) erzeugt. Voraussetzung hierfür ist das Vorhandensein eines von Oracle zertifizierten C-Compilers und Linkers auf dem Datenbankserver (diese Komponenten werden nicht von Oracle ausgeliefert, sondern müssen eigenständig lizenziert und installiert werden). Eine Übersicht lizenzierter Compiler findet sich im Oracle 10g Installation Guide für die jeweilige Plattform sowie auf der Oracle Metalink-Seite. Unter Oracle9i führte die sehr flexible Konfiguration für Native Compilation zu erheblichen Security-Problemen, in Oracle 10g wurde sie daher stark überarbeitet und vereinfacht:
PL/SQL-Objekte
241
Der Serverparameter plsql_code_type = NATIVE | INTERPRETED regelt, ob explizite Kompilierungen mittels CREATE ... oder ALTER ... COMPILE Maschinencode oder MCode erzeugen. Default-Einstellung ist INTERPRETED. Der Parameter kann auch auf Session-Ebene gesetzt werden. Zusammen mit dem Parameter plsql_debug ersetzt er den aus Oracle9i bekannten Parameter plsql_compiler_flags. Letzterer existiert aus Kompatibilitätsgründen noch, sollte aber nicht mehr verwendet werden. Der Kompilierungsmodus jedes PL/SQL-Objekts wird im Data Dictionary abgespeichert (Spalte PLSQL_CODE_TYPE der View dba_plsql_object_settings) und für automatische Neukompilierungen durch Oracle herangezogen (z.B. nach der Änderung einer vom Objekt referenzierten Tabelle). Auch durch SQL-Kommandos der Form ALTER ... COMPILE REUSE SETTINGS kann der aktuelle Kompilierungsmodus beibehalten werden. Achtung: Bei einem Export via Data Pump oder konventionellem Export (siehe Kapitel 10.6) gehen die Informationen über Kompilierungsmodi verloren. Über den Serverparameter plsql_native_library_dir wird das Zielverzeichnis für die Shared Libraries angegeben. Die Shared Libraries werden aber auch im Data Dictionary gespeichert. Ein versehentliches Löschen auf OS-Ebene führt somit nicht mehr wie bei Oracle9i zu einem Laufzeitfehler, sondern die Dateien werden automatisch aus dem Data Dictionary in das Dateisystem zurückgeschrieben. Da die betreffende Tabelle (SYS.NCOMP_DLL$) im SYSTEM-Tablespace liegt, muss dieser ggf. vergrößert werden, bevor eine größere Menge von PL/SQL-Objekten kompiliert wird. Das Shared-Library-Verzeichnis sollte unter dem Verzeichnis angelegt werden, das auch die Datendateien des SYSTEM-Tablespace enthält, und ausschließlich für die Benutzer oracle und root schreibbar sein. Die Datei spnc_commands im Verzeichnis $ORACLE_HOME/plsql enthält den plattformspezifischen Aufruf des C-Compilers bzw. Linkers. In den meisten Fällen braucht diese nicht angepasst zu werden, einzig der Pfad zum Compiler-Programm sollte vor der ersten Kompilierung verifiziert werden. Es versteht sich, dass aus Security-Gründen auch diese Datei höchstens für oracle und root schreibbar sein darf. Trigger-Verwaltung Trigger stellen ein sehr mächtiges Werkzeug dar, da sie komplexe Reaktionen ermöglichen (erst recht in der Form der oben beschriebenen autonomen Trigger). Sie bringen aber auch einen Overhead mit sich. In vielen Systemen treten regelmäßig Massenoperationen wie Batch-Läufe oder Ladeprozesse auf. Dabei sollte überprüft werden, ob wirklich alle Trigger aktiv sein müssen. Häufig lässt sich eine deutliche Beschleunigung des Prozesses erzielen, wenn einige oder alle Trigger vor der Massenoperation deaktiviert und anschließend reaktiviert werden. Entsprechende Befehle dafür sind: SQL> ALTER TRIGGER DISABLE | ENABLE; SQL> ALTER TABLE DISABLE | ENABLE ALL TRIGGERS;
242
Datenbankobjekte
Bei Ladeoperationen über den direkten Pfad mit dem Werkzeug SQL*Loader werden Insert-Trigger der betreffenden Tabellen für die Dauer des Ladelaufs automatisch deaktiviert. In Replikationsumgebungen müssen ebenfalls Vorkehrungen getroffen werden, damit keine Doppel-Ausführungen der Trigger-Aktionen auf der Zieldatenbank auftreten: Bei einer Master-Slave-Replikation werden einfach alle Trigger der Slave-Datenbank deaktiviert. Bei einer Multi-Master-Replikation müssen auf allen Datenbanken die Trigger um WHEN-Klauseln ergänzt werden, die bewirken, dass der Trigger nur feuert, wenn die Änderung nicht durch den Replikationsmechanismus eingebracht wurde, z.B. durch eine Ergänzung der WHEN-Klausel um die Bedingung USER <> 'ReplUser'. Das Replikations-Tool Quest Shareplex bringt beispielsweise Skripte mit, die diese Anpassung automatisch durchführen. Die Views dba_triggers und dba_trigger_cols bieten Informationen über Trigger.
5.7
Directory-Objekte für den Dateizugriff
Häufig ist es notwendig, aus der Datenbank heraus auf Dateien zuzugreifen, sei es lesend im Rahmen von Ladeoperationen, sei es schreibend, z.B. um Daten in einem bestimmten Format zu exportieren. Dafür gibt es mittlerweile eine Reihe von Möglichkeiten; die wichtigsten sind: Das mitgelieferte Package utl_file, das aus PL/SQL-Routinen heraus lesenden und/oder schreibenden Zugriff in beliebigen Ausgestaltungen erlaubt. Der Import und Export von Daten auf dem Datenbank-Server mittels Data Pump (siehe Abschnitt 10.6). Die Definition so genannter »externer Tabellen« (siehe Abschnitt 5.2.6), die lesenden Zugriff auf Data-Pump-Dump-Dateien sowie Dateien in einem SQL*Loader-kompatiblen Format ermöglichen und den Dateiinhalt als Tabelleninhalt präsentieren. Das mitgelieferte Package dbms_file_transfer (neu in der Version 10g), das Dateien über Datenbank-Links hinweg zwischen Datenbankservern kopieren kann (eine Art triviales FTP, wobei der Datenbank-Link als Tunnel verwendet wird). Mit der Version 10.1.0.3 funktioniert dies aber nur für Data-Pump-Dump-Dateien (siehe auch Abschnitt 10.6)! Der Zugriff über einen BFILE-Locator für Tabellenspalten vom Typ BFILE über die eingebaute SQL-Funktion BFILENAME. In allen Fällen geschieht der Zugriff auf das Dateisystem des Datenbankservers durch den Oracle-Serverprozess (nicht zu verwechseln mit einem clientseitigen Dateizugriff durch das Kommandozeilen-Tool SQL*Plus nach einem SPOOL-Kommando). Prinzipielle Voraussetzung ist daher, dass der Betriebssystembenutzer, unter dem der Serverprozess läuft (oracle auf Unix, Lokales System unter MS-Windows) entsprechende Zugriffsrechte hat. Unter Unix lässt sich dies ggf. durch Kommandos wie chown, chgrp und chmod erreichen.
Directory-Objekte für den Dateizugriff
243
Unter MS-Windows stößt man zusätzlich auf das Problem, dass das lokale Systemkonto, unter dem der gesamte Oracle-Prozess standardmäßig läuft, keinerlei Zugriffsrechte auf Netzwerkfreigaben hat. Der Zugriff auf Dateien über Freigaben (z.B. Z:\testdatei.txt oder als UNC-Pfad \\server\freigabe\testdatei.txt) scheitert daher regelmäßig. In diesem Fall müssen der Oracle-Dienst und der TNS-Listener als ein privilegierter Benutzer angemeldet werden. In Windows XP kann diese Anmeldeinformation unter Systemsteuerung Verwaltung Dienste eingestellt werden (siehe Ändern der Anmeldeinformationen für den Oracle-Dienst). Es kann ein beliebiger Benutzer eingetragen werden, der lesend und/oder schreibend auf die Netzwerkfreigabe zugreifen kann.
Abbildung 5.4: Ändern der Anmeldeinformationen für den Oracle-Dienst
Kann der Oracle-Serverprozess auf eine Datei prinzipiell zugreifen, sind als zweite Stufe die Zugriffsrechte der Datenbankbenutzer zu regeln. Bei einer neu aufgesetzten Datenbank hat zunächst kein Datenbankbenutzer Zugriffsrechte auf Dateien. So genannte Directory-Objekte repräsentieren einzelne Dateisystemverzeichnisse innerhalb der Datenbank und bilden sowohl bei der Angabe von Dateipfaden als auch bei der Zugriffskontrolle die Schnittstelle zwischen Dateisystem und Datenbankbenutzern. Lese- und Schreibrechte können also nicht pro Datei, sondern nur pauschal für alle Dateien eines Verzeichnisses gewährt werden. Das Erstellen oder Löschen eines Directory-Objekts hat keine Auswirkung auf die Existenz des betreffenden Dateisystemverzeichnisses, es handelt sich nur um einen Pointer.
244
Datenbankobjekte
Das Erstellen und Löschen von Directory-Objekten ist nur mit den Systemprivilegien CREATE | DROP ANY DIRECTORY möglich. Directory-Objekte sind streng genommen keine Schema-Objekte, da sie nicht zum Schema des erzeugenden Benutzers, sondern immer zum Schema SYS gehören. Ihre Namen müssen daher datenbankweit eindeutig sein. Benutzer mit mindestens einem der oben genannten Systemprivilegien haben pauschal Lese- und Schreibrechte auf alle Directory-Objekte. Einzelne Zugriffsrechte werden über die Objektprivilegien READ und WRITE zugeteilt, z.B.: SQL> CREATE DIRECTORY alertlog_dir AS 'C:\ORACLE\ADMIN\PS10\BDUMP'; SQL> GRANT READ ON DIRECTORY alertlog_dir TO schulung; SQL> GRANT READ, WRITE ON DIRECTORY alertlog_dir TO admin; Listing 5.39: Erstellen von Directories
Die Rechtevergabe bezieht sich stets nur auf das angegebene Verzeichnis, Unterverzeichnisse sind nicht inbegriffen. Beim Zugriff auf eine Datei über einen der oben beschriebenen Wege wird die Datei durch Verzeichnis und Dateiname identifiziert, das Verzeichnis wird dabei nicht direkt, sondern über ein Directory-Objekt mitgegeben, z.B. der Parameter location der Funktion utl_file.fopen, der Parameter directory beim Data-Pump-Export und -Import etc. Der Serverparameter utl_file_dir, der ebenfalls Zugriffsrechte auf Dateien regelt, sollte nicht mehr verwendet werden, da er keine Differenzierung zwischen Lese- und Schreibrechten zulässt, er keine Differenzierung zwischen Datenbanknutzern zulässt, für eine Anpassung ein Neustart der Instanz notwendig ist, zur Pfadangabe trotzdem ein Directory-Objekt benötigt wird. Aus Security-Gründen sollte auf jeden Fall vermieden werden, dass utl_file_dir=* gesetzt ist, da sonst wahlfreier Dateizugriff für alle Benutzer gegeben ist. Informationen über Directory-Objekte finden sich in der View dba_directories (Name und Pfad, die Spalte owner ist immer SYS). Über Schreib- und Leserechte gibt die folgende Abfrage Auskunft: SQL> SELECT
t.grantee, t.privilege, d.directory_name, d.directory_path FROM dba_tab_privs t, dba_directories d WHERE t.owner = d.owner AND t.table_name = d.directory_name ORDER BY t.grantee, d.directory_name, t.privilege;
Listing 5.40: Berechtigungen für Directories
Administrationswerkzeuge In diesem Kapitel werden die Werkzeuge von Oracle und anderen Herstellern aufgeführt, die für die Basisadministration der Datenbank verwendet werden. Dazu gehört natürlich zunächst einmal der Oracle Enterprise Manager, der in der Version 10g komplett neu aufgebaut ist, aber auch das gute alte SQL*Plus, ohne das auch mit der Version 10g eine Oracle-Datenbankinstallation nicht möglich wäre. Exemplarisch werden hier zusätzlich die Produkte TOAD von Quest Software und HORA von Keeptool besprochen, da sie im Bereich Oracle-Administration eine weite Verbreitung haben. Tools, bei denen das Monitoring bzw. die Überwachung der Datenbank im Vordergrund stehen, werden im Kapitel 14 besprochen.
6.1
Oracle Enterprise Manager
Mit Version 7.3 hat Oracle den Enterprise Manager als Werkzeug für alle administrativen Aufgaben einer Oracle-Datenbank eingeführt. Mit der Version 8i wurde das Produkt neu in Java implementiert und als Framework für die Datenbankadministration, aber auch die Verwaltung des Oracle Application Servers angeboten. Durch die Verwendung von Java war es somit erstmals möglich, die Datenbanken auch über Webbrowser zu administrieren. Die ebenfalls mit der Version eingeführte Dreischichten-Architektur erlaubte es außerdem, unterschiedliche Aufgaben in einem speziellen Enterprise Manager Repository zu verwalten und somit speziell für große Unternehmen ein flexibles Werkzeug für Administration, Monitoring und auch Entwicklung zu schaffen. Die neue Enterprise-Manager-Version verabschiedet sich jetzt vom Java-Client und wird nur noch als Webanwendung angeboten. Dabei gibt es zwei unterschiedliche Konfigurationsarten: 1. Enterprise Manager Database Control für die Verwaltung einer einzelnen Datenbank 2. Enterprise Manager Grid Control für die Verwaltung von unterschiedlichen Datenbanken, aber auch anderen Anwendung wie Application Server etc. Während der Enterprise Manager Database Control mit jeder Installation direkt installiert werden kann, muss für das Grid Control zunächst eine eigene Umgebung geschaffen werden. In Kapitel 6.1.1 werden wir daher zunächst die Basisversion beschreiben, bevor wir in Kapitel 6.1.2 auf die recht komplexe Installation und Konfiguration des Enterprise Manger Grid Controls eingehen. Es sei aber an dieser Stelle schon gesagt, dass hier nur die Grundlagen zur Benutzung gelegt werden können, da die Komplexität dieses Werkzeuges die Grenzen des Buches sprengen würde. Da es sich in beiden Fällen um eine Webanwendung handelt, sollten Sie beachten, dass im Normalfall ein Caching der Informationen auf Rechner erfolgt. Für die
246
Administrationswerkzeuge
Benutzung des Enterprise Managers müssen Sie auf jeden Fall die Option »Bei jedem Zugriff auf die Seite nach einer neueren Version suchen« aktivieren. Im Microsoft Internet Explorer finden Sie diese Option unter »Internet-Optionen – Temporäre Internetdateien – Einstellungen«.
Abbildung 6.1: Einstellungen für den Internet Explorer
Ein Vorteil bei der Benutzung eines Webbrowsers besteht darin, dass man die Spracheinstellungen umschalten kann. Dies macht sich der Enterprise Manager zunutze, so dass Sie z.B. zwischen deutscher und englischer Umgebung jederzeit umschalten können. Während der Entstehung des Buches war das von großem Nutzen, da die Fehlersuche mit einer englischen Version im Oracle Metalink wesentlich einfacher ist.
Abbildung 6.2: Umschaltung im Enterprise Manager
Mit »Refresh« bzw. »Aktualisieren« wird dann die neue Einstellung sichtbar.
Oracle Enterprise Manager
247
6.1.1 Enterprise Manager Database Control Wenn Sie eine Datenbank über den Database Configuration Assistant installieren, haben Sie in Schritt 4 die Möglichkeit, die Datenbank für die Verwendung des Enterprise Managers zu konfigurieren (siehe Abbildung 6.3).
Abbildung 6.3: Enterprise-Manager-Konfiguration
In diesem Beispiel sehen Sie auch, dass es hier nicht möglich ist, das Grid Control zu konfigurieren, da kein Agent auf dem Server installiert ist. Zusätzlich können Sie an dieser Stelle eine E-Mail-Benachrichtigung konfigurieren und ein tägliches Backup aktivieren. Beide Optionen sollten jedoch unseres Erachtens erst mit der tatsächlichen Produktionsaufnahme der Datenbank eingerichtet werden – was in der Regel erst nach einigen Tagen, Wochen oder Monaten der Fall sein wird. Im Schritt 9 der Installation können Sie, wie in Abbildung 6.4 dargestellt, dann noch den Tablespace für die Speicherung des Repositorys angeben. Der Tablespace SYSAUX, der, wie bereits erwähnt, zwingend in der Oracle 10g-Datenbank vorhanden sein muss, ist hierfür vorgesehen und sollte auch nicht geändert werden. In diesem Tablespace wird jetzt das Enterprise Manager Repository angelegt. Der hierfür gewählte Benutzer heißt SYSMAN, das Kennwort können Sie in Schritt 5 eingeben.
248
Administrationswerkzeuge
Abbildung 6.4: Enterprise Manager Repository
Nach der Konfiguration und anschließenden Erstellung der Datenbank kann der Enterprise Manager genutzt werden. Dafür existiert unter MS-Windows ein neuer Dienst mit dem Namen OracleDBConsole<SID>. Unter dem Betriebssystem Unix wird der entsprechende Prozess mit folgendem Befehl gestartet: % emctl start dbconsole Listing 6.1: Starten DBConsole unter Unix
Sollte dieser Befehl nicht erfolgreich sein (was unter verschiedenen Linux-Derivaten vorkommen kann), muss die Konfiguration angepasst werden. Hierbei hat sich folgendes Vorgehen als erfolgversprechend erwiesen. 1. Zunächst wird die notwendige Basiskonfiguration neu angelegt. Dies geschieht mit dem Befehl emca –r. Mit diesem Befehl wird die OC4J-Instanz, welche die Grundlage für den Enterprise Manager bildet, neu konfiguriert. Die Option »-r« gibt dabei an, dass das Repository in der Datenbank schon existiert und somit nicht neu angelegt werden muss. Zur Konfiguration sind dann einige Angaben, wie z.B. die Passwörter sowie der Listener-Port (Standard 1521), notwendig. Nach der Beendigung der Konfiguration sollte im ORACLE_HOME ein Verzeichnis in der Form _ existieren. 2. Im Verzeichnis _/sysman/config gibt es eine Datei mit dem Namen emd.properties. In dieser Datei muss jetzt der Eintrag EMD_URL geändert werden, da wahrscheinlich der Port fehlt. Beispiel: http://hllinux1:1830/emd/main.
Oracle Enterprise Manager
249
Danach sollte sich der Prozess problemlos starten lassen. Jede auf dem Server installierte Datenbank benötigt dabei ihre eigene »Database Control«, d.h., je Datenbank gibt es ein Unterverzeichnis im ORACLE_HOME und entsprechende Prozesse mit eigenen Ports. Der Aufruf des Enterprise Managers hängt also im Folgenden von den verwendeten Ports ab. Die Liste der Ports lässt sich am einfachsten aus der Datei portlist.ini im Verzeichnis ORACLE_HOME/install ermitteln. Hier finden Sie z.B. folgende Einträge: Enterprise Manager Console HTTP Port (LINUX10G) = 5500 Enterprise Manager Agent Port (LINUX10G) = 1830 Listing 6.2: Enterprise Manager Portlist
Das bedeutet, dass der Agent für die Datenbank LINUX10G (den Sie u.U. in der Datei emd.properties manuell angegeben haben) den Port 1830 und die Konsole für die Datenbank den Port 5500 benutzt. Vorsicht beim Löschen des Schemas SYSMAN. In diesem Fall wird zwar das Repository gelöscht, einige Einträge bleiben jedoch erhalten und verhindern, dass das Repository neu angelegt werden kann. Es müssen alle Public-Synonyme, die mit MGMT beginnen, das Synonym setemviewusercontext sowie die Rolle mgmt_user manuell gelöscht werden, bevor mit dem Befehl emca (ohne Optionen) ein neues Repository angelegt werden kann. Alternativ kann man folgenden Befehl verwenden: Verzeichnis %ORACLE_HOME%/sysman/admin/emdrep/bin % Repmanager –sys_password <password> -action drop
z.B. in der folgenden Form: Repmanager hllap34 1521 JA10G -sys_password manager -action drop Listing 6.3: Löschen des Repositorys
Dabei wird dann der Benutzername des Repositorys (SYSMAN) und dessen Kennwort abgefragt. Unter MS-Windows gibt es dabei eine unschöne Fehlermeldung, da das Perl-Skript für Unix geschrieben wurde und mit dem Befehl stty das Echo des Kennwortes ausgeschaltet wird, was so aber unter Windows nicht funktioniert. Falls es Sie stört, können Sie in dem Perl-Script emrepmgr.pl die entsprechenden Zeilen auskommentieren. Es hat aber keinen Einfluss auf die Ausführung des Skriptes. In einigen Fällen ist es allerdings passiert, dass der User mgmt_view nicht gelöscht wird. Also kontrollieren Sie am besten, ob es noch Objekte gibt, die mit mgmt beginnen. Mit dem gleichen Befehl, aber der Option create wird das Repository dann neu angelegt. Also z.B.: repmanager hllap34 1521 JA10G -sys_password manager -action create Listing 6.4: Anlegen des Repositorys
250
Administrationswerkzeuge
Leider gibt es dabei einige Ungereimtheiten, d.h., in einigen Fällen ist es vorgekommen, dass der Enterprise Manager anschließend nicht genutzt werden konnte. Als Alternative kann das Repository auch über den Database Configuration Assistant neu installiert werden. Anmeldung an den Enterprise Manager Um mit dem Enterprise Manager arbeiten zu können, wird jetzt ein Browser gestartet und darin die Adresse der Konsole eingetragen. In unserem Beispiel also: http://hllinux1:5000/em
Zunächst meldet man sich dann an die Datenbank an.
Abbildung 6.5: OEM-Anmeldung
Beim ersten Aufruf erhalten Sie anschließend eine Abfrage, welche Optionen (Management Packs) Sie lizenziert haben. Folgende optionalen Pakete sind möglich: Oracle Diagnostic Pack: Hierzu gehört – wie in früheren Versionen – das EventManagement, mit dem es möglich ist, Informationen zu sammeln und bei Bedarf Warnungen oder Alarme per E-Mail zu versenden oder auf der Konsole anzuzeigen. Neu hinzugekommen ist die grafische Implementierung von ADDM (Automatic Database Diagnostic Monitor), den wir in Kapitel 11 (Tuning) in der Basisversion näher beschreiben werden. Dazu noch ein Hinweis: Das Database Diagnostic Pack ist lizenzpflichtig – und damit auch der Punkt ADDM. Die Funktionalität, die dahinter steckt, ist jedoch im Basisumfang der Datenbank enthalten. Das Gleiche gilt auch für das Automatic Workload Repository.
Oracle Enterprise Manager
251
Oracle Tuning Pack: Zu diesem Paket gehören wie in älteren Version Werkzeuge für Anwendungstuning und Reorganisation. Oracle Configuration Pack: Dieses Paket gibt es in der Version 10 erstmals, und es enthält Werkzeuge für die Software-Verteilung und Patch-Installation, aber auch Tools für die Überprüfung der Datenbankkonfiguration. Oracle Change Management Pack: Im Gegensatz zu den bereits genannten Optionen steht dieses Paket nur als Java-Anwendung zur Verfügung und ist daher nicht über den hier besprochenen Enterprise Manager nutzbar. Stattdessen muss der optionale java-basierende Enterprise Manager installiert werden. Dieser ist identisch mit der bereits in Oracle8i und Oracle9i genutzten Version und wird an dieser Stelle nicht weiter betrachtet. Im Unterschied zu älteren Versionen des Enterprise Managers gliedern sich hier die Packages in die Konsole ein, so dass man beim normalen Arbeiten keinen Unterschied zwischen Standardfunktionalität und kostenpflichtigen Packages bemerkt. Sie können die Benutzung der einzelnen Pakete im laufenden Betrieb aber jederzeit ändern. Dafür gehen Sie auf den Menüpunkt »Setup«, den Sie oben und unten auf jeder Enterprise-Manager-Seite finden. Dort befindet sich auf der linken Seite das Untermenü »Management Pack Access«, in dem Sie dann die einzelnen Beschreibungen finden und ein- bzw. ausschalten können. Standardverzeichnis Kommen wir zurück zum Basisumfang des Enterprise Managers. Wenn Sie sich angemeldet haben, gelangen Sie zum STANDARDVERZEICHNIS (Reiter Datenbank). Dieses Fenster ist in unterschiedliche Bereiche unterteilt. Dazu zählen allgemeine Informationen (Name und Status der Datenbank), aktuelle Statistikwerte (CPUVerbrauch oder angemeldete Benutzer), aber auch Informationen über Alarme und durchgeführte Jobs. Bereich Allgemein
Abbildung 6.6: Bereich Allgemein
Neben Informationen über Namen der Datenbank und der Verfügbarkeit können Sie von hier aus die Datenbank stoppen (HERUNTERFAHREN).
252
Administrationswerkzeuge
Abbildung 6.7: Hoch- und Herunterfahren der Datenbank
Der eingetragene Betriebssystembenutzer (johannes) muss auf dem Rechner die Berechtigung Anmelden als Stapelverarbeitungsauftrag haben.
Abbildung 6.8: Hochfahren der Datenbank
Oracle Enterprise Manager
253
Für das Starten der Datenbank sind über den Menüpunkt ERWEITERTE OPTIONEN weitere Optionen möglich.
Abbildung 6.9: Optionen für das Starten der Datenbank
Interessant ist auch der Unterpunkt HOST im Bereich ALLGEMEIN, da hier die wichtigsten Werte des Rechners angezeigt werden – in dieser Form sucht man so etwas auf vielen Systemen vergeblich. Leider sind in anderen Bereichen nur Basiswerte verfügbar, eine Aufgliederung verlangt die Nutzung des Database Diagnostic Packs.
254
Administrationswerkzeuge
Abbildung 6.10: Hostparameter
High Availability Ein weiterer wichtiger Bereich ist HIGH AVAILABILITY, da von diesem Punkt aus die Archivierung und die Flash-Recovery-Area konfiguriert werden kann. Weitere Informationen hierzu finden Sie in Kapitel 10 (Wiederherstellungstechniken).
Abbildung 6.11: High Availability
Oracle Enterprise Manager
255
Alerts Dieser Punkt ist eine entscheidende Bereicherung des neuen Enterprise Managers, da jetzt zum ersten Mal die Informationen aus der Alert-Datei, aber auch aus anderen Bereichen dargestellt werden – ohne das eine zusätzliche Konfiguration notwendig ist. Leider gilt auch hier die Einschränkung, dass nur eine Überschrift angezeigt wird, wer nähere Informationen benötigt – die in diesem Fall sicherlich angebracht sind –, wird auf das Diagnostic Pack verwiesen. Alternativ kann aber natürlich auch in der entsprechenden Datei (z.B. Alert-Log) nachgesehen werden. Einige Meldungen (wie z.B. aus der Kategorie USER AUDIT) sind aber auch selbsterklärend.
Abbildung 6.12: Alarme und Warnungen
Zugehörige Links Die Meldungen werden über Metriken verwaltet. Einige Metriken sind dem Diagnostic Pack vorbehalten, eine ganze Reihe kann aber auch im Standard-Enterprise-Manager verwaltet werden. Im Bereich ZUGEHÖRIGE LINKS kann über den Punkt METRIKEN VERWALTEN die Standardeinstellung verändert werden. Zunächst wird dabei die aktuelle Einstellung angezeigt, über den Menüpunkt SCHWELLENWERTE BEARBEITEN gelangt man dann in die eigentliche Einstellung (siehe Abbildung 6.13). Hier kann dann z.B. die Meldung über Anmeldungen als Benutzer »SYS« ausgeschaltet werden. Ein weiterer Punkt in diesem Bereich ist INHALT VON ALERT LOG, mit dem die gesamte Alert-Datei der Datenbank als Textdatei angezeigt wird. Das kann zum Beispiel als Hilfe dienen, wenn im Bereich ALERT Meldungen der Kategorie ALERT LOG angezeigt werden. Leider dauert der Aufruf dieser Datei sehr lange, so dass es oftmals sinnvoller ist, sich direkt auf dem Rechner anzumelden und die Datei mit einem Standardeditor anzuzeigen.
256
Administrationswerkzeuge
Abbildung 6.13: Schwellenwerte einstellen
Weitere Verzeichnisse Neben dem Standardverzeichnis gibt es das Verzeichnis PERFORMANCE, auf das Sie nur dann einen Zugriff haben, wenn Sie das Diagnostic Pack lizenziert haben. Über das Verzeichnis ADMINISTRATION können Sie alle wesentlichen Teile der Datenbank administrieren. Wir gehen an dieser Stelle nicht weiter auf diesen Bereich ein, da die einzelnen Punkte in entsprechenden Kapiteln ausführlich behandelt werden und es sich hier ja nur um die grafische Repräsentation von SQL-Befehlen handelt. Interessant ist hier eventuell noch der in Abbildung 6.14 dargestellte Menüpunkt STATISTIKEN DER DATENBANKVERWENDUNG im Bereich KONFIGURATIONSVERWALTUNG, da hier alle Datenbankfunktionen und ihre Verwendung dargestellt werden. Gerade bei Audit-Aktionen sind diese Informationen hilfreich. Das letzte Verzeichnis WARTUNG beinhaltet schließlich das Thema Backup und Recovery, Export – Import sowie Reorganisation (siehe auch Kapitel 10). Bei Verwendung des Configuration Management Packs können hier deren wichtigste Funktionen aufgerufen werden.
Oracle Enterprise Manager
257
Abbildung 6.14: Statistiken der Datenbankverwendung
6.1.2 Enterprise Manager Grid Control Der Enterprise Manager Grid Control ist eine Dreischichten-Architektur bestehend aus einer Verwaltungsdatenbank (Grid Control Database), Agenten auf den zu überwachenden Rechnern und den zu verwaltenden Anwendungen, zu denen sowohl das Betriebssystem als auch die einzelnen Datenbanken zählen. Diese Software ist unabhängig von einer Oracle-Datenbank oder einem Application Server und wird somit in allen Komponenten separat installiert. Das bedeutet, dass Sie auf dem Datenbankserver einen Agenten in einem eigenen ORACLE_HOME installieren müssen, der dann die Datenbanken und das Betriebssystem überwacht. Ein Rechner muss für das Grid Control zur Verfügung gestellt werden. Da dieses die Daten aller Agenten auswerten und darstellen muss, ist es anzuraten, diesen Rechner mit mindestens 2 GByte Hauptspeicher auszustatten. Dieser Rechner ist es, auf den sich von jetzt an die Administratoren anmelden, um die einzelnen Datenbanken zu verwalten.
258
Administrationswerkzeuge
Grid-Control-Installation Folgendes Bild zeigt die auswählbaren Komponenten:
Abbildung 6.15: Komponenten des Enterprise Manager Grid Controls
Die in der Abbildung dargestellten Installationsoptionen haben folgenden Inhalt: ENTERPRISE MANAGER 10G GRID CONTROL USING A NEW DATABASE 10.1.0.3 installiert die Grid-Control-Software sowie die komplette Datenbank-Software in der Version Oracle 9.0.1.5. Da diese Version von Oracle nur für den Einsatz von Grid Control unterstützt ist, können wir diese Option nicht empfehlen. ENTERPRISE MANAGER 10G GRID CONTROL USING AN EXISTING DATABASE 10.1.0.3 installiert ebenfalls die Grid-Control-Software. Das Repository wird allerdings in eine bereits existierende Datenbank der Version 9.2.0.4 oder höher installiert. Diese Datenbank muss eine Enterprise-Edition sein und muss laut Dokumentation die Option Label Security installiert und konfiguriert haben. Es gibt allerdings einen Metalink-Eintrag (Doc-Id: 285209.1), laut dem es sich hierbei um einen Dokumentations-Bug handeln soll. ADDITIONAL MANAGEMENT SERVICE 10.1.0.3 installiert ausschließlich die GridControl-Software, ohne das Repository zu erstellen. ADDITIONAL MANAGEMENT AGENT 10.1.0.3 installiert die Agent-Software für die zu überwachenden Datenbanken, Webserver, Application Server und Systeme.
Oracle Enterprise Manager
259
Für die von uns durchgeführten Tests haben wir zunächst die Oracle 10g-Datenbank-Software installiert und darauf eine Datenbank (EM10G) erstellt. Diese benutzen wir als Repository für Grid Control. Für die Repository-Datenbank müssen folgende Initialisierungsparameter gesetzt sein: session_cached_cursors >= 200 aq_tm_processes >= 1 shared_pool_size >= 130 MB Wenn diese Parameter nicht entsprechend gesetzt sind, erhalten Sie eine Fehlermeldung, können aber mit der Installation fortfahren. In der ausgewählten Datenbank werden zwei neue Tablespaces MGMT und MGMT_ECM_DEPOT angelegt. Während der Installation können Sie die Lage der Datendateien angeben.
Abbildung 6.16: Management Repository
In der obigen Abbildung sehen Sie die notwendigen Angaben für die Installation von Grid Control für eine bereits bestehende Datenbank. Aus unerfindlichen Gründen darf der mit der Version 10.1.0.3 erstmals konfigurierte Scheduler-Job für die Sammlung der Systemstatistiken nicht benutzt werden. Sie müssen diesen Job also vor oder während der Installation deaktivieren. SQL> exec dbms_scheduler.disable('SYS.GATHER_STATS_JOB');
260
Administrationswerkzeuge
Leider sind Enterprise Manager Grid Control und Enterprise Manager Database Control nicht kompatibel, so dass Sie eine bereits angelegte Database-Control-Konfiguration (Schema SYSMAN) vorher löschen müssen. Das Gleiche gilt, wenn Sie Grid Control nicht mehr verwenden wollen, sondern zurück zum Database Control wollen. Verwenden Sie dafür das in Kapitel 6.1.1 angegebene Verfahren zum Löschen und Anlegen des Schemas SYSMAN. Bei der Installation unter Linux gab es einige Besonderheiten, die zwar störend, aber nicht kritisch sind. So gab es eine Fehlermeldung, die besagte, dass das Verzeichnis oradata im ORACLE_HOME der Grid-Software nicht existiert. Da die Software gerade neu installiert wird, kann es auch gar nicht existieren. Also muss man von Hand dieses Verzeichnis anlegen und kann dann mit der Installation fortfahren. Benutzt wird dieses Verzeichnis jedoch nur, wenn man die Verzeichnisse der beiden Tablespaces MGMT und MGMT_ECM_DEPOT nicht anpasst. Während der Installation werden weitere Konfigurationsparameter abgefragt. Dazu gehören: Das Passwort des Benutzers SYSMAN, das mindestens fünf Zeichen und eine Zahl enthalten muss Die Konfiguration einer automatischen Benachrichtigung per E-Mail Metalink-Zugriffsdaten für die automatische Verwaltung von Patches Proxy-Informationen, um mit den Agenten oder auch externen Datenbanken (wie z.B. Metalink) über Grid-Control kommunizieren zu können. Anschließend wird zunächst die Grid-Control-Software in dem ausgewählten Verzeichnis installiert. Außerdem wird der Agent in einem separaten Verzeichnis parallel zum ORACLE_HOME der Grid-Control-Software installiert. Das bedeutet, für die Konfiguration inklusive der Oracle-Datenbank-Software werden drei unterschiedliche ORACLE_HOME-Verzeichnisse benötigt: Datenbank: /app/oracle/product/10.1.0/db_1 Grid-Control: /app/oracle/product/10.1.0/grid Agent: /app/oracle/product/10.1.0/agent Der Zugriff auf die Grid-Control Console erfolgt über die folgende HTML-Seite: http://servername:7780/em
WICHTIG: Der Servername muss auf dem Client aufgelöst werden können (Host-Datei oder DNS). Bei der direkten Eingabe der IP-Adresse kann es vorkommen, dass man auf einer falschen Seite landet. Nach der ersten Anmeldung erhalten Sie wie beim Database Control die Aufforderung, die Packages anzugeben, die Sie benutzen bzw. lizenziert haben. Anschließend bekommen Sie die Übersicht über die Systeme, Datenbanken etc. wie in der unten angegebenen Form.
Oracle Enterprise Manager
261
Abbildung 6.17: Enterprise Manager Grid Control
Eine ausführliche Beschreibung des Enterprise Manager Grid Controls würde an dieser Stelle zu weit führen. Da die Funktionsweise allerdings sehr gut beschrieben ist (sogar, wie in der Abbildung zu erkennen, in Deutsch), sollten Sie in der Lage sein, sich im Enterprise Manager schnell zurechtzufinden. Agent-Installation Die Installation eines Agenten für die Verwaltung mit Grid Control ist sehr einfach. Es wird lediglich ein Verzeichnis für die Installation angegeben und dann der Punkt ADDITIONAL MANAGEMENT AGENT 10.1.0.3 ausgewählt. Nach dem Starten des Agenten werden der Host, die Datenbanken, Web- und Application Server automatisch im Grid-Control angezeigt. Wenn Sie anschließend eine neue Datenbank erstellen, können Sie wie im folgenden Bild gezeigt die Verwendung des Agenten konfigurieren.
262
Administrationswerkzeuge
Abbildung 6.18: Datenbank für Grid Control konfigurieren
Administration Zum Schluss einige Bemerkungen zur Administration, d.h. Starten und Stoppen der einzelnen Komponenten. Wichtig ist, dass Sie, speziell auf Unix-Systemen, die Umgebungsvariablen richtig setzen. Wir haben aus diesem Grund die Datei /etc/oratab bzw. /var/opt/oracle/ oratab um die notwendigen Einträge erweitert: oratab EM10G:/app/oracle/product/10.1.0/db_1:N GRID:/app/oracle/product/10.1.0/grid:N AGENT:/app/oracle/product/10.1.0/agent:N % . oraenv ORACLE_SID = [EM10G] ? GRID Listing 6.5: Environment für Grid Control
In diesem Beispiel können wir jetzt zwischen den einzelnen Umgebungen mit dem Befehl oraenv wie dargestellt hin- und herschalten (im Beispiel von der Umgebung der Datenbank EM10G auf die Grid-Control-Software). Mit dem folgenden Befehl werden der Management-Server sowie die OC4J-Instanzen und der Webcache gestoppt und wieder gestartet. Dieser Befehl bietet sich generell an, wenn der Management-Server neu durchgestartet werden soll.
Oracle Enterprise Manager
263
% . oraenv ORACLE_SID = [EM10G] ? GRID % cd $ORACLE_HOME/opmn/bin % ./opmnctl stopall # Stoppen aller Services % ./opmnctl startall # Starten aller Services Listing 6.6: Stoppen und Starten aller Management-Server-Komponenten
Alternativ können die Komponenten über den Befehl emctl auch einzeln verwaltet werden. Da dieser Befehl im Verzeichnis ORACLE_HOME/bin liegt, kann er in der Regel ohne Pfadangabe aufgerufen werden. % emctl status oms Oracle Enterprise Manager 10g Release 10.1.0.3.1 Copyright (c) 1996, 2005 Oracle Corporation. All rights reserved. Oracle Management Server is Up Listing 6.7: Statusabfrage Oracle Management Server
Für die Verwaltung des Agenten müssen die Umgebungsvariablen wieder entsprechend umgestellt werden. Also: % . oraenv ORACLE_SID = [EM10G] ? AGENT % emctl stop agent % emctl start agent Listing 6.8: Stoppen und Starten des Enterprise-Manager-Agenten
Für eine weitergehende Administration des Enterprise Manager Grid Controls empfiehlt sich das Dokument Oracle Enterprise Manager Advanced Configuration (Part No. B12013-03). Anmerkung Die Installation des Enterprise Manager Grid Controls erwies sich während der Entstehung des Buches als überaus schwierig. Eine Installation unter MS-Windows (2000 und XP) ist uns trotz mehrerer Versuche nicht gelungen. Während der Installation gab es immer wieder die Fehlermeldung, dass die Pfadlänge 1023 Zeichen überschritten habe (was bei größeren Installationen mit mehreren unterschiedlichen Oracle Software-Versionen natürlich keine Seltenheit ist). Schlussendlich setzte aber der KONFIGURATIONSASSISTENT FÜR JAVA-SICHERHEIT (engl.: Java Security Configuration Assistant) der Installation ein Ende. Diesbezügliche Anfragen bei Oracle blieben leider ohne Erfolg. Generell kann hier nur nochmals darauf hingewiesen werden, sich exakt an die Vorgaben zu halten, d.h., alle Voraussetzungen zu prüfen. Nur so lassen sich tagelange Tests vermeiden. Außerdem hatten wir sowohl mit dem Database Control als auch mit dem Grid Control Probleme, den Status der Datenbanken abzufragen. Nach Stoppen und Starten des Management-Servers bzw. der Konsole wurde als Status der Datenbank immer wieder »Heruntergefahren« gemeldet, obwohl Datenbanken und Agenten liefen.
264
Administrationswerkzeuge
.
Tipp: Wenn unter Unix die Datenbank-Software und der Management-Server wie oben dargestellt installiert werden (also drei ORACLE_HOME-Verzeichnisse), kann es vorkommen, dass der Oracle Net-Listener-Prozess sehr viel Last erzeugt. Dies ist darauf zurückzuführen, dass der Universal Installer sowohl für die DatenbankSoftware als auch für die Grid-Control-Software die gleichen Ports für den Notification Server (ONS) konfiguriert hat. Als Lösung sollte in dem entsprechenden Verzeichnis der Datenbank-Software (z.B. /app/oracle/product/10.1.0/db_1/grid/opmn/conf) die Datei ons.config umbenannt werden. Danach kann der Listener einmal durchgestartet werden und läuft wieder normal.
6.2
Scheduler
Mit einem Scheduler ist man in der Lage, regelmäßig anfallende Aufgaben automatisiert auszuführen. In der Datenbank findet man diese Möglichkeit auch – neben Möglichkeiten der Betriebssysteme sowie spezieller Software. Bei den Betriebssystemen sind unter Unix die cron-Funktionalität, unter Windows so genannte at-Jobs bekannt. In vielen Umgebungen werden diese Scheduler auch genutzt, um Datenbankaufgaben zu starten. Mit dem Scheduler in der Datenbank gibt es hierzu eine Alternative. Ob und wann es Sinn macht, den Scheduler in der Datenbank zu benutzen, verschieben wir auf den letzten Abschnitt dieses Unterkapitels, nachdem die Funktionsweise und Möglichkeiten des Schedulers erklärt worden sind. Um die grundsätzliche Verwirrung ein bisschen zu steigern, gibt es bei Oracle 10g zwei unterschiedliche Scheduler: den mit Oracle7 eingeführten »alten« Scheduler sowie einen neu entwickelten 10g-Scheduler. Beide Scheduler können parallel betrieben werden. Somit ist es möglich, »alte« Jobs, die bei einer Migration übrig geblieben sind, weiter mit dem alten Scheduler zu betreiben, gleichzeitig jedoch neue Jobs direkt im neuen Scheduler aufzusetzen.
6.2.1 Alter Scheduler Der alte Scheduler wird über ein mitgeliefertes PL/SQL-Modul dbms_job gesteuert. Hiermit können Jobs eingestellt, geändert und gelöscht werden. Hierzu ein Beispiel: VAR j NUMBER EXECUTE dbms_job.submit (job => :j, what => dbms_lock.sleep(10);', next_date => sysdate, interval => 'sysdate + 1/24') COMMIT /
Scheduler
265
Hiermit wird ein neuer Job eingestellt, der über den OUT-Parameter JOB eine eindeutige systemgenerierte Jobnummer zugewiesen bekommt. Für praktisch alle Aufrufe des dbms_job-Packages gilt, dass sie letztendlich Einträge in den Jobverwaltungstabellen machen, die durch COMMIT bestätigt werden müssen. In den dbms_job-Prozeduren selbst ist kein COMMIT eingebaut – es müssen also alle Aufrufe explizit COMMITed werden! In den weiteren Beispielen ist das COMMIT nicht immer mit aufgeführt. Über die Jobnummer kann der eben eingerichtete Job in der View dba_jobs wieder gefunden werden. Der zugehörige Datensatz sieht wie folgt aus:
Abbildung 6.19: Datensatz aus dba_jobs
Unter what kann nachgeschaut werden, was der Job tut (in diesem Fall zehn Sekunden warten). Es handelt sich hierbei um PL/SQL-Prozeduraufrufe bzw. anonyme PL/ SQL-Blöcke. Das abschließende Semikolon ist hierbei unerlässlich! Im Übrigen empfiehlt es sich, längere Blöcke als Prozedur zu definieren und diese dann als Job auszuführen – schon alleine deshalb, weil man Verarbeitungslogik möglichst nicht in Scheduler-Definitionen verpacken sollte. Für Prozeduraufrufe können Parameter angegeben werden; allerdings sind IN OUT- und OUT-Parameter nicht erlaubt. Wichtig
266
Administrationswerkzeuge
ist, dass alle Privilegien, die einem Benutzer über Rollen zugewiesen sind, innerhalb von Jobs nicht zur Verfügung stehen – genau wie bei PL/SQL Prozeduren, Packages usw. Im obigen Beispiel benötigt der Benutzer SYSTEM das direkte EXECUTE-Privileg des Packages sys.dbms_lock – das Recht EXECUTE ANY PROCEDURE aus der Rolle dba zieht in diesem Fall nicht! Die letzte an dieser Stelle genannte Einschränkung für Jobs ist die folgende: Innerhalb der Jobs können keine Datenbank-Links genutzt werden, die ohne CONNECT TO- und IDENTIFIED BY-Klauseln definiert sind. Normalerweise werden diese Informationen aus dem aktuellen Sitzungskontext genommen und an die entfernte Datenbank weitergeleitet. Da bei der Jobausführung dieser Sitzungskontext nicht vorhanden ist, funktionieren solche Datenbank-Links innerhalb von Jobs eben nicht. Alle _user-Felder der View haben den Inhalt SYSTEM; dies spiegelt wider, dass der Job (wie in diesem Fall geschehen) unter SYSTEM angelegt worden ist und auch unter dieser Benutzerkennung läuft. Die DATE-Felder last_date, this_date und next_date geben an, wann der Job zuletzt gestartet (und ohne Fehler beendet) worden ist, wann er für die aktuelle Ausführung gestartet worden ist und wann er das nächste Mal gestartet wird. Da in vielen Umgebungen das Anzeigeformat für DATE-Felder NLS_DATE_FORMAT nur das Datum und keine Zeiten beinhaltet, zeigt die View Stunden, Minuten und Sekunden zusätzlich in den _sec-Feldern an. In der obigen Anzeige stand NLS_DATE_FORMAT auf DD.MM.YYYY HH24:MI:SS, so dass die zusätzliche Anzeige nicht nötig ist. Wichtig ist der Inhalt von interval: Hier wird eine Funktion vom Typ DATE erwartet. Sie wird immer genau dann ausgeführt, wenn der Job seine Ausführung beendet, und berechnet dann den Zeitpunkt der nächsten Ausführung (und wird damit in next_date eingetragen). Ist interval nicht gefüllt (NULL), so erfolgt die Ausführung des Jobs nur einmal. Im Beispiel wird auf das aktuelle Datum der Wert 1/24 addiert – mit dem Zusatzwissen, dass DATE-Funktionen bei Oracle mit der Einheit Tag rechnen, ist klar, dass der Job jeweils nach einer Stunde neu ausgeführt wird. In der Spalte nls_env werden alle NLS-Einstellungen (Sprache, Datumsformat, Sortierreihenfolgen usw.) der Sitzung festgehalten, die den Job eingestellt haben. Diese Einstellungen werden auch jeweils für die ausführende Sitzung (im Hintergrundprozess) verwendet. Voraussetzung für die Ausführung von Jobs ist das Setzen des Serverparameters job_queue_processes auf einen von 0 unterschiedlichen Wert. Hierdurch wird der Hintergrundprozess CJQ0 (Central Job Queue Coordinator) permanent gestartet. Dieser startet bei Bedarf Jobprozesse Jnnn, maximal die im Serverparameter angegebene Anzahl. Diese Prozesse führen die Jobs selbst aus. Da die Jnnn-Prozesse zu den Hintergrundprozessen gehören, schreiben sie ihre TraceDateien in das entsprechende Verzeichnis (Serverparameter background_dump_ dest). Sobald bei der Ausführung eines Jobs auf oberster Ebene1 Fehler auftauchen, werden diese in der Trace-Datei protokolliert. In der View dba_jobs werden Fehler nur durch den Zähler failures angezeigt. Hiermit wird die Anzahl der Fehler seit der letzten erfolgreichen Ausführung angezeigt. 1
Da es sich um PL/SQL-Code handelt, können natürlich Fehler auftauchen, die über einen Exception Handler abgefangen werden. Diese werden nicht nach außen weitergegeben und somit auch nicht als Fehler gewertet.
Scheduler
267
Mit jeder fehlerhaften Ausführung wird demnach failures hochgezählt; zusätzlich wird next_date auf einen etwas späteren Zeitpunkt gesetzt. Dabei werden die Abstände zum nächsten Ausführungsversuch mit höheren failures-Werten immer länger – wohl in der Hoffnung, dass die abgelaufene Zeit die »Wunden« heilt und zu einer fehlerfreien Ausführung führt ... Nach 16 fehlerhaften Versuchen bekommt der Job den Status Broken (Feld broken auf Y, next_date auf 1. Januar 4000). Es wird dann nicht mehr versucht, den Job auszuführen. Eine weitere Möglichkeit, einen Job auf BROKEN zu setzen, ist der Aufruf einer entsprechenden Prozedur: EXECUTE dbms_job.broken (job => 3, broken => TRUE)
Mit der Prozedur dbms_job.broken kann ein Job auch wieder zurückgesetzt werden, z.B. wenn man das Problem gelöst hat, das zum Fehlverhalten des Jobs geführt hat. Als weiteren Parameter erlaubt die Prozedur deshalb auch ein next_date: EXECUTE dbms_job.broken (job => 3, broken => FALSE, next_date => SYSDATE)
Mit dem Aufruf EXECUTE dbms_job.run(job => 3)
besteht die Möglichkeit, einen Job unabhängig von Broken-Status und next_date sofort auszuführen. Die Ausführung erfolgt allerdings in der aktuellen Sitzung (d.h. nicht innerhalb eines Jnnn-Prozesses!). Dies kann z.B. für Tests sehr nützlich sein; die Blockierung der aktuellen Sitzung ist jedoch gerade bei Jobs mit langen Ausführungszeiten eher unpraktisch. Nach einer erfolgreichen Ausführung wird der Broken-Status aufgehoben und das next_date laut interval neu gesetzt. Die Ausführung des Jobs ist übrigens ausschließlich unter dem Benutzer, der den Job angelegt hat, möglich.
6.2.2 Neuer Scheduler Wie so oft, wenn neue Funktionen in das Oracle DBMS eingeführt werden, sind diese so komplex, dass eine einfache Erweiterung der »alten« Strukturen nicht reicht. Auch in diesem Fall ist ein kompletter neuer Scheduler implementiert worden – und damit auch die bisher verwendeten Jobs weiterlaufen, ist der »alte« Scheduler zunächst komplett erhalten geblieben. Der Grund für den Parallelbetrieb beider Scheduler dürfte sein, dass es keinen einfachen Weg gibt, alte Jobs automatisch zu migrieren, da z.B. die Einstellung der Ausführungszeiten anders funktioniert als beim alten Scheduler. Außerdem gibt es weiterhin Komponenten, die Jobs für den alten Scheduler erstellen, z.B. Materialized Views mit automatischem Refresh oder der Enterprise Manager 10g Database Control (EMD_MAINTENANCE.EXECUTE_EM_DBMS_JOB_PROCS(); unter dem Benutzer SYSMAN).
268
Administrationswerkzeuge
Es ist damit zu rechnen, dass beide Scheduler für zwei oder mehr Oracle-Versionen parallel betrieben werden können. Nach einer Übergangsphase, in welcher der alte Scheduler nur noch über undokumentierte Serverparameter erreichbar sein wird, wird er dann ganz verschwinden ... Warum ein neuer Scheduler? Diese Frage ist berechtigt, da der alte Scheduler ja nach wie vor funktioniert und dies i.A. auch sehr verlässlich tut. Allerdings gibt es Anforderungen an ein Scheduler-System, die mit dem alten Scheduler nicht vereinbar sind, z.B.: Spezifikation der Laufzeiten: Natürlich ist mit dem next_date-Mechanismus und der Oracle DATE-Arithmetik praktisch alles an Laufzeitmustern abbildbar. Allerdings ist es manchmal schon kompliziert, einfache Dinge wie »alle 10 Minuten«, »jede Stunde außer von 23 bis 2 Uhr« usw. hinzuschreiben. Berechtigungen: Jobs können nur vom Ersteller ausgeführt werden. Dies ist insbesondere beim Testen bzw. »Wiederanlaufenlassen« von einer DBA-Konsole aus unangenehm, wenn nicht alle Jobs über den DBA-Account laufen. Logging: Im alten Scheduler sind immer nur Informationen über die letzte Ausführung vorhanden. In den Trace-Dateien der Jobprozesse finden sich Fehlermeldungen bei nicht erfolgreichen Versuchen. In der View dba_scheduler_job_log sind nunmehr Informationen über alle Ausführungen (erfolgreiche und nicht erfolgreiche!) vorhanden – bis diese in der Regel nach drei Wochen gelöscht werden. Prioritäten: Ganz neu ist die Einbindung von Ressource Consumer Groups über die Jobklasse und somit die Zuordnung von Prioritäten. Weiterhin kann über den instance-Parameter ein Job einer speziellen RAC-Instanz zugeordnet werden. Im neuen Scheduler geschieht die Zuordnung über Dienstnamen (in der Jobklasse), was eine größere Flexibilität ermöglicht, z.B. die Zuordnung zu mehreren Instanzen. Dies sind nur einige »Anforderungen« an den Neuen – nunmehr ist klar, dass der neue Scheduler noch viel mehr in die Richtung »Professionelles Job-Management« geht als der Alte. Betrachten wir also die Möglichkeiten von vorne: Zunächst einmal ist der Job im neuen Scheduler wesentlich modularer aufgebaut als im Alten. Hier wurden die Task, das Zeitverhalten usw. für jeden Job einzeln festgelegt. Im neuen Scheduler gibt es diese Möglichkeit auch (man legt einen Job an); man kann jedoch auf vorbereitete Definitionen von Zeitplänen (Schedules) und Programmen zurückgreifen. Dies macht z.B. Sinn, wenn man einen bestimmten Zeitplan (etwa: alle fünf Minuten) für diverse Jobs benötigt. Voraussetzungen Der neue Scheduler ist unabhängig von der Einstellung von Serverparametern wie job_queue_processes einsatzfähig. Dabei wird der Central Job Queue Coordinator CJQ0
bei Bedarf gestartet – wenn er nicht sowieso für die Verarbeitung von alten Jobs gestartet ist – und übernimmt die Steuerung weiterer Jobprozesse Jnnn. Die Maximalzahl der für den neuen Scheduler gleichzeitig gestarteten Jobs kann mit dem globa-
Scheduler
269
len Scheduler-Attribut max_job_slave_processes gesetzt werden.2 Standardmäßig ist dies auf NULL gesetzt, d.h. CJQ0 bestimmt abhängig von Maschinenauslastung und der Anzahl zu verarbeitender Jobs die Anzahl der notwendigen Jobprozesse. Weiterhin muss bei Windows-Systemen der Dienst OracleJobScheduler<SID> gestartet sein, damit externe Programme gestartet werden können. Für interne Programme (PL/SQL-Prozeduren und Blöcke) ist dies nicht notwendig. Bei Unix-Systemen müssen u.U. Berechtigungen für das ausführbare Programm extjob geändert werden. Es empfiehlt sich grundsätzlich, bei neuen Releases oder Patch-Sets auf Informationen zu diesem Thema gesondert zu achten. Programme, Schedules und Jobs Der neue Scheduler erlaubt den strukturierten Aufbau von Jobs. Es werden nicht mehr unbedingt alle vorhandenen Informationen in einen einzigen Aufruf (wie bei dbms_job.submit) verpackt, sondern es besteht die Möglichkeit, Programme, Schedules und Jobs getrennt zu definieren. Programme Dabei definiert man mit einem Programm zunächst eine mögliche auszuführende Arbeitseinheit. Neu ist, dass bei den Programmen der program_type angegeben wird. Hierbei hat man die Auswahl aus PLSQL_BLOCK, STORED_PROCEDURE und EXECUTABLE. Hierbei ist bei PLSQL_BLOCK in etwa das gemeint, was der alte Scheduler im what-Parameter erlaubt hat. Im Falle von STORED_PROCEDURE gibt man lediglich den Aufruf der Prozedur an und spart sich zunächst das Semikolon. Wirklich neu ist der Typ EXECUTABLE, womit man tatsächlich ein Programm (ausführbares Programm oder Skript) auf Betriebssystemebene aufrufen kann. Zunächst
ein
Beispiel
für
die
Definition
eines
Programms
vom
Typ
STORED_PROCEDURE: EXEC dbms_scheduler.create_program (program_name => 'SP', program_type => 'stored_procedure', program_action => 'job_sp', enabled => TRUE, comments => 'Just a test...')
Definierte Programme können in der View dba_scheduler_programs angezeigt werden. Für Programme vom Typ STORED_PROCEDURE und EXECUTABLE können Argumente fest definiert werden. Hierzu gibt es einen eigenen Satz an Definitions- und Übergabeprozeduren im Package dbms_scheduler. Im angegebenen Beispiel wird das Programmattribut enabled auf TRUE gesetzt. Damit ist das Programm sofort einsetzbar. Wird das Attribut nicht angegeben, wird FALSE angenommen. Dies gilt auch für Schedules und Jobs. Zum Aktivieren kann die Prozedur dbms_scheduler.enable genutzt werden.
2
Das Setzen von globalen Scheduler-Attributen wird weiter unten noch genauer behandelt.
270
Administrationswerkzeuge
Schedules Ebenfalls getrennt vom eigentlichen Job können Schedules definiert werden. Der Schedule steht für ein Ausführungszeitschema. Zunächst auch hierzu ein Beispiel: EXEC dbms_scheduler.create_schedule (schedule_name => 'M_SCHED', repeat_interval => 'FREQ=MINUTELY;BYSECOND=0', comments => 'Will it Work?')
Zur Abfrage der Schedules dient die View dba_scheduler_schedules. Jeder, der bereits einige Jobs mit Hilfe des alten Schedulers implementiert hat, wird wohl beim Anblick des repeat_interval-Parameters erleichtert aufatmen: Die interval-Funktion des alten Schedulers erlaubte zwar durch den Zugriff auf die komplette DATE-Arithmetik des Oracle-Kerns die Berechnung praktisch beliebiger Intervalle, die Lesbarkeit der resultierenden Ausdrücke war jedoch nicht immer gegeben. Zum Vergleich die beiden Ausdrücke für »genau zu jeder Viertelstunde«: Alter Scheduler: trunc(sysdate, 'HH24') + ((trunc(to_char(sysdate, 'MI') / 15) + 1) * 15) / (24 * 60)
Neuer Scheduler: FREQ=HOURLY;BYMINUTE=0,15,30,45;BYSECOND=0
Der repeat_interval-Parameter kann entweder mit einem kalendarischen Ausdruck oder einer PL/SQL-Funktion gesetzt werden. Das o.a. Beispiel für viertelstündlich dokumentiert bereits die Struktur sowie die Lesbarkeit der kalendarischen Ausdrücke. Ein kalendarischer Ausdruck besteht aus einer FREQ-Klausel, einer optionalen INTERVAL-Klausel sowie optional einer oder mehreren BY-Klauseln. Die FREQ-Klausel legt die Ausführungsfrequenz auf die Werte YEARLY, MONTHLY, WEEKLY, DAILY, HOURLY, MINUTELY oder SECONDLY fest. Die INTERVAL-Klausel legt fest, wie viele Einheiten der FREQ-Klausel zwischen zwei Ausführungen vergehen sollen. Die BY-Klausel(n) legt (legen) weitere Details für die gewählte Frequenz fest. Es gibt die Varianten BYMONTH, BYWEEKNO, BYYEARDAY, BYMONTHDAY, BYDAY, BYHOUR, BYMINUTE sowie BYSECOND. BY-Klauseln können Wertelisten enthalten. Somit kann die Frequenz »alle 10 Minuten« z.B. mit folgenden Varianten dargestellt werden: FREQ=MINUTELY;INTERVAL=10 FREQ=HOURLY;BYMINUTE=0,10,20,30,40,50
Für undefinierte obere Grenzen von BY-Klauseln können negantive Werte eingesetzt werden, z.B. BYMONTHDAY=-1 für den letzten Tag im Monat. Weitere Details zu kalendarischen Ausdrücken können z.B. dem Handbuch »PL/ SQL Packages and Types« entnommen werden.
Scheduler
271
PL/SQL-Funktionen als Alternative zum kalendarischen Ausdruck zur Definition von repeat_interval müssen als Ergebnistyp DATE oder TIMESTAMP liefern. Falls durch repeat_interval keine Zeitzone definiert wird, wird diese vom Wert der Variablen start_date übernommen. Falls start_date ebenfalls keine Zeitzone definiert, wird sie vom globalen Scheduler-Attribut default_timezone übernommen.3 Globale Scheduler-Attribute können mit Hilfe der Prozedur dbms_scheduler.set_scheduler_attribute gesetzt und mit der Prozedur dbms_scheduler.get_scheduler_attribute oder der View dba_scheduler_global_attribute abgefragt werden (obwohl Letztere im Handbuch »Oracle Database Reference« nicht definiert ist). Jobs Nachdem Schedule und Programm definiert sind, kann man zur Definition des Jobs übergehen. Im einfachsten Fall werden hierbei ein Programm und ein Schedule verknüpft: EXEC dbms_scheduler.create_job (job_name => 'LS_JOB', program_name => 'LS', schedule_name => 'M_SCHED', enabled => TRUE)
Man kann die Definition von Programmen und Schedules weglassen und die JobArgumente job_type, job_action, start_date und repeat_interval direkt setzen. Im Sinne einer Strukturierung der Jobs ist dies jedoch nicht empfehlenswert. Übersicht über Jobs erlangt man durch Abfragen der View dba_scheduler_jobs. Ähnlich wie beim alten Scheduler findet man Dinge wie last_start_date, next_run_date, nls_env und einige weitere Informationen. Anstelle der Gesamtlaufzeit aller Runs findet man die last_run_duration für die Laufzeit der letzten Ausführung. Zusätzliche Informationen über jeden einzelnen Start eines Jobs findet man in den Views dba_scheduler_job_log und dba_scheduler_job_run_details. Diese beiden Views ersparen z.B. bei der Problemanalyse das lästige Suchen nach und in Tracefiles der Jobprozesse. Setzen von Attributen Attribute für Programme, Schedules und Jobs werden zunächst beim Erzeugen gesetzt, die meisten stehen dann auf ihrem Standardwert. Zum Ändern der Attribute wird die Prozedur dbms_scheduler.set_attribute(, , )
genutzt. Die Attribute sind in den dba_scheduler-Views sofort sichtbar; allerdings wirken sie sich nicht mehr auf bereits laufende Ausführungen aus. Die Liste der möglichen Attribute ist sehr lang und kann im Handbuch »PL/SQL Packages and Types« nachgeschlagen werden. 3
Das erwähnte globale Scheduler-Attribut default_timezone ist bei einer neu kreierten Datenbank zunächst nicht gesetzt. Es wird dringend empfohlen, dies z.B. mit EXEC dbms_scheduler.set_scheduler_attribute ('default_timezone', 'Europe/Berlin') zu setzen. Nach einem Neustart der Instanz funktioniert dann – meist – alles wie erwartet.
272
Administrationswerkzeuge
Fehlerbehandlung Der neue Scheduler unterscheidet im Gegensatz zum alten Scheduler Scheduled Runs und Retries. Scheduled Runs beziehen sich grundsätzlich auf das mit repeat_interval festgelegte Ausführungsschema. Wenn einer der Scheduled Runs einen Fehler verursacht, wird dieser bis zu sechs Mal erneut gestartet (Retry), falls das Jobattribut restartable auf TRUE gesetzt ist (was standardmäßig der Fall ist). Dabei findet der erste Retry eine Sekunde nach dem Ende des Scheduled Runs statt, die Wartezeit für weitere Retries ist jeweils um den Faktor zehn länger. Falls ein Retry erfolgreich ist, alle sechs Retries abgeschlossen sind und zu Fehlern geführt haben oder der Ausführungszeitpunkt des nächsten Retrys nach dem Ausführungszeitpunkt des nächsten Scheduled Runs liegt, werden keine Retries mehr gestartet. Damit wird der aktuelle Scheduled Run als beendet gewertet und der run_count in dba_scheduler_jobs um eins erhöht. Wenn alle sechs Retries zu Fehlern führen, wird auch failure_count um eins erhöht. In der View dba_scheduler_job_log werden Scheduled Runs im Feld operation als RUN gekennzeichnet, Retries als RETRY_RUN. Details zur Fehlerursache findet man in der View dba_scheduler_job_run_details. Diese Views sind zunächst nicht destruktiv, d.h., man findet Informationen über alle möglichen Ausführungen (und -versuche) auch nachträglich in den Views. Das Jobattribut max_failures kann auf einen Wert zwischen eins und 1.000.000 gesetzt werden (Standard ist NULL) und führt dazu, dass der Job auf DISABLED gesetzt wird, falls die angegebene Anzahl von aufeinander folgenden Scheduled Runs zu Fehlern führen. Der Jobstatus (state) wechselt von SCHEDULED auf BROKEN. Achtung! Falls das Jobattribut auto_drop auf TRUE steht (Standard!), wird der Job beim Erreichen von max_failures aus der Jobtabelle gelöscht! Jobklassen, Fenster und Fenstergruppen Jobklassen Mit Hilfe von Jobklassen können einige übergeordnete Parameter gesetzt werden. Dabei gelten die Parameter für alle Jobs, die der Jobklasse zugeordnet sind, d.h., die Jobklasse ist wiederum ein Attribut der einzelnen Jobs. Folgende Parameter sind vorhanden: Durch die Zuordnung einer resource_consumer_group können z.B. Prioritäten von Jobs untereinander bzw. im Verhältnis zum Gesamtsystem geregelt werden. Durch die Benennung eines service werden Jobs ausschließlich auf der oder den Instanzen ausgeführt, die den benannten service in ihrem Serverparameter service_names gesetzt haben. Damit ist es z.B. möglich, Jobs in einer RAC-Umgebung einzelnen Instanzen oder Instanzgruppen zuzuordnen. Der logging_level kann zwischen OFF, RUNS und FULL ausgewählt werden. Dies hat Einfluss darauf, ob kein Logging, lediglich Logging für Ausführungen oder
Scheduler
273
für Ausführungen sowie Änderungsoperationen (Enable, Disable, Setzen von Attributen usw.) erfolgt. Die Aufbewahrungsfrist für Log-Informationen (Standard: 30 Tage) wird mit log_history auf eine Anzahl von 1 bis 999 Tagen gesetzt. Es gibt eine Standard-Jobklasse default_job_class, der alle Jobs standardmäßig zugeordnet werden. Dabei ist der logging_level auf RUNS eingestellt, die anderen Parameter sind mit NULL vorbesetzt. Eine weitere Jobklasse auto_tasks_job_class ist grundsätzlich vorhanden. Diese unterscheidet sich von der default_job_class nur dadurch, dass die resource_ consumer_group mit auto_task_consumer_group voreingestellt ist. Fenster und Fenstergruppen Die Definition von Fenstern und Fenstergruppen ermöglicht grundsätzlich zwei Dinge: 1. Die Aktivierung von verschiedenen Ressourcenplänen zu unterschiedlichen Zeitpunkten im Zusammenspiel mit den Konsumentengruppen der Jobklassen 2. Die Definition von Ausführungszeitfenstern bzw. Gruppen solcher Zeitfenster für Jobs, die ausschließlich zu bestimmten Zeiten laufen sollen Zur Verdeutlichung betrachten wir einen der vordefinierten Jobs im neuen Scheduler, den gather_stats_job. Dieser Job ist für das automatische Sammeln von Statistiken für Datenbankobjekte mit der Prozedur dbms_stats.gather_database_stats_ job_proc verantwortlich und ist im Schema sys untergebracht. Er ist weiterhin der Jobklasse auto_tasks_job_class und der Fenstergruppe maintenance_window_group zugeordnet. Diese Fenstergruppe enthält die Fenster weeknight_window, das an Wochentagen jeweils um 22:00 Uhr beginnt und 8 Stunden dauert, und weekend_ window, das Samstags um 0:00 Uhr beginnt und zwei Tage dauert. Durch diese Zuordnung läuft der Statistikjob nachts bzw. am Wochenende genau im beschriebenen Fenster. Dadurch, dass der Job das Attribut stop_on_window_close auf TRUE gesetzt hat, wird der Job abgebrochen, sobald das Fenster (jeweils nach der o.a. Dauer) geschlossen wird. Berechtigungen Im Gegensatz zur sehr rudimentären Berechtigungsverwaltung des alten Schedulers (EXECUTE-Privileg auf dbms_job reicht zum Anlegen und Administrieren von Jobs; jeder Benutzer kann ausschließlich auf seine eigenen Jobs zugreifen) bietet der neue Scheduler einige zusätzliche Möglichkeiten in diesem Bereich an. Systemprivilegien und Rollen Zunächst gibt es einige Systemprivilegien, die das Arbeiten mit dem Scheduler ermöglichen. CREATE JOB erlaubt das Anlegen von Programmen, Schedules und Jobs im eigenen Schema. Wie bei vielen anderen Privilegien erlaubt das verwandte CREATE ANY JOB
diese Aktionen in beliebigen anderen Schemata.
274
Administrationswerkzeuge
Die Privilegien EXECUTE ANY PROGRAM und EXECUTE ANY CLASS erlauben die Erstellung von Jobs mit Bezug auf beliebige Programme bzw. Jobklassen anderer Schemata. Das Privileg MANAGE SCHEDULER erlaubt weiterhin, Jobklassen, Fenster und Fenstergruppen zu definieren, deren Attribute zu ändern sowie über die entsprechenden Views Informationen zu sehen. Die Rolle scheduler_admin enthält die o.a. Systemprivilegien (jeweils WITH ADMIN OPTION). Die Rolle selber ist in der Rolle dba enthalten. Objektprivilegien Wie bei Prozeduren kann gezielt ein EXECUTE-Privileg auf Programmen und Jobklassen vergeben werden. Dadurch kann im berechtigten fremden Schema ein Job mit Bezug auf das Programm bzw. ein beliebiges Programm der Jobklasse erstellt werden. Mit dem ALTER-Privileg kann für Programme, Schedules und Jobs die Erlaubnis zur Administration vergeben werden. Für Programme, Schedules, Jobs und Jobklassen kann weiterhin das ALL-Privileg vergeben werden, das noch umfassender ist. Migration und Ausblick Bei der Bewertung des neuen Schedulers tritt natürlich auch die Frage der Migration auf. Falls man bereits eine komplexe Job-Umgebung mit dem alten Scheduler betreibt, stellt sich natürlich auch die Frage nach einer automatisierten Übernahme der alten Jobs. Hierbei sollten folgende Argumente beachtet und abgewägt werden: Automatisch erstellte Jobs, z.B. zum Refresh von Materialized Views, sollten zunächst nicht migriert werden, da eine Modifikation der Refresh-Parameter der Materialized Views beim Versuch, den alten Job automatisch zu ändern, ins Leere greifen würde. Beim alten Scheduler sind häufig sehr komplexe next_date-Klauseln zu finden, da geplante Auszeiten und sonstige Unregelmäßigkeiten durch keinen anderen Mechanismus abgefangen werden können. Beim Übergang auf den neuen Scheduler sollten hierfür Mechanismen wie kalendarische Ausdrücke, Fenster und Fenstergruppen eingesetzt werden. Dies ist jedoch kaum automatisiert zu machen, sondern erfordert eine »intelligente« Migration – leider auf manuellem Weg. Zunächst wird also ein Mischbetrieb mit altem und neuem Scheduler in Frage kommen, da es bei einigen Jobs noch keinen Sinn macht, diese zum neuen Scheduler zu migrieren. Ein wesentliches neues Feature des Schedulers ist die Möglichkeit, Programme auf Betriebssystemebene zu starten und somit z.B. die Datenbanksicherung mit einem Recovery-Manager-Skript in die Datenbank selbst zu integrieren. Für das nächste Release wurde von Oracle u.a. die Fähigkeit versprochen, Verknüpfungen für Jobs definieren zu können, wie z.B. »Job 3 startet, wenn Job 1 und Job 2 fehlerfrei abgearbeitet sind«. Anwender, die eine Migration ihrer Datenbankjobs von größeren Jobkontrollsystemen auf den neuen Scheduler in Erwägung ziehen, vermissen dies in den allermeisten Fällen.
Weitere Werkzeuge
275
Weiterhin gibt es offensichtliche Lücken, die noch ergänzt werden müssen. Die View dba_scheduler_jobs enthält das Feld max_run_duration, das nach der Beschreibung im Handbuch »Oracle Reference« nicht etwa die längste bis jetzt aufgetretene Laufzeit eines Jobs enthält, sondern eine Vorgabe, wie lange der Job maximal laufen darf. Dies ist durchaus eine interessante Möglichkeit – allerdings fehlt ein Weg, dieses Feld zu besetzen.
6.3
Weitere Werkzeuge
Neben den von Oracle mitgelieferten Werkzeugen haben sich auf dem Markt viele Tools für die Arbeit mit der Oracle-Datenbank etabliert. Aus dieser Liste greifen wir uns exemplarisch zwei sehr verbreitete Werkzeuge heraus: TOAD von Quest Software Inc. (www.quest.com) und Hora von KeepTool GmbH (www.keeptool.com). Beide Tools werden oft dort eingesetzt, wo es darum geht, schnell auf die OracleDatenbanken zugreifen zu können, ohne zusätzliche Software auf dem Server installieren zu müssen. Beide Produkte können nur auf MS-Windows-Rechnern betrieben werden und brauchen einen Oracle-Client für die Kommunikation zur Datenbank. Zunächst gehen wir noch kurz auf das alt bewährte SQL*Plus ein.
6.3.1 SQL*Plus Dieses Tool gibt es seit Oracle Version 6 und wird von vielen Administratoren immer noch vielseitig eingesetzt. Zum allgemeinen Verständnis: SQL*Plus ist nicht die SQL-Sprache von Oracle, sondern ein Kommandozeilen-Editor, um SQL an die Oracle-Datenbank zu senden. Das »Plus« steht hierbei für einige zusätzliche Befehle, die über den Standard-SQL-Umfang hinausgehen. Dazu gehören unter anderem einige einfache Formatierungen (Zeilen und Seitenlängen, Titel und Nummerierung) und für die Verwaltung der Datenbank. So kann z.B. mit SQL*Plus die Datenbank gestartet und gestoppt oder die Archivierung aktiviert werden. Da die Standardeinstellungen in der Regel unzureichend sind, empfiehlt es sich, die Datei glogin.sql anzupassen (Verzeichnis: $ORACLE_HOME/sqlplus/admin), in der z.B. die Zeilen- und Seitenlänge festgelegt werden können. Weitere anwenderspezifische Anpassungen können in der Datei login.sql vorgenommen werden. Die Lage dieser Datei wird über die Umgebungsvariable SQLPATH bestimmt, wobei hier eine Liste von Pfaden durch Doppelpunkt getrennt angegeben werden kann. Im Folgenden ein Beispiel für glogin.sql oder login.sql: set set set set
pagesize 66 linesize 100 echo on timing on
Listing 6.9: Beispiel für login.sql
276
Administrationswerkzeuge
Mit den oben angegebenen Einträgen wird die Seitenlänge (pagesize) auf 66 Zeilen und die Zeilenlänge (linesize) auf 100 Zeichen geändert. Außerdem wird jeder Befehl vor der Ausführung noch einmal ausgegeben (set echo on) und die Ausführungsdauer zum Schluss angezeigt (set timing on). SQL*Plus wird ebenfalls oft für das Tuning von SQL-Befehlen eingesetzt. Dabei wird der SQL-Befehl über SQL*Plus ausgeführt, und statt (oder zusätzlich zum) Ergebnis werden der Ausführungsplan sowie Informationen über die verarbeiteten Blöcke angegeben. Nähere Informationen hierzu finden Sie in Kapitel 11. Als Erweiterung zum SQL*Plus gibt es den iSQL*Plus, wobei auf dem Server eine J2EE-Instanz gestartet werden muss. Anschließend kann über einen Internet Explorer in der Regel über Port 5560 auf die Anwendung zugegriffen werden. Ansonsten unterscheidet sich die Verwendung nur unwesentlich von der des SQL*Plus.
6.3.2 TOAD Das Produkt TOAD steht für Tool for Oracle Application Development und wurde ursprünglich als Freeware für die Entwicklung von PL/SQL-Programmen angeboten. Quest Software Inc. hat das Tool 1999 samt Entwickler gekauft und vertreibt es heute in unterschiedlichen Konfigurationen für den klassischen Entwicklerbereich, aber auch als Werkzeug für Datenbankadministratoren. Daneben gibt es eine große »Gemeinde« unter www.toadsoft.com, über die auch weiterhin eine Freeware zur Verfügung steht4. Die aktuelle Version (8.5) unterstützt die wesentlichen neuen Funktionen von Oracle 10g wie z.B. den neuen Scheduler. Es gibt im TOAD eine Reihe von Tools, die im Wesentlichen die Aufgabe haben, SQL-Befehle zu erstellen und die Ergebnisse in einem oder mehreren Ergebnisfenstern (so genannten Grids) darzustellen. Diese Ergebnismengen können dann komfortabel z.B. als Excel-Datei oder Tabellenblatt abgespeichert werden. Für Entwickler und Anwender ist die Möglichkeit, sich für jedes Datenbankobjekt oder ein gesamtes Schema ein Skript erstellen zu lassen, sicherlich eine wichtige Funktion. Ergänzt wird das Produkt durch die grafische Modellierung von SQL-Befehlen im SQL-Modeler und die Darstellung von Abhängigkeiten im ER-Diagrammer. In der Abbildung 6.20 ist der SCHEMA BROWSER mit der Option »SAVE GRID CONTENTS« dargestellt. Neben der Abspeicherung als Excel-Datei ist sicherlich auch die Möglichkeit, die Daten als SQL-Loader oder »Insert-Befehl« abzuspeichern, interessant. Neben diesen Standardfunktionalitäten gibt es bereits in der Basisversion einige Tools für die Administration von Datenbanken. Unter anderem gehört der in Abbildung 6.21 gezeigte Session Browser dazu, der die Überwachung von SessionInformationen einer Datenbank ermöglicht.
4
Die Version ist allerdings sehr eingeschränkt und veraltet, so dass derzeit der Zugriff auf Oracle 10g-Datenbanken nur bedingt möglich ist.
Weitere Werkzeuge
Abbildung 6.20: TOAD Schema Browser
Abbildung 6.21: Session Browser
277
278
Administrationswerkzeuge
Durch Zusatzmodule kann der TOAD für unterschiedliche Benutzerkreise erweitert werden. Hier bietet sich das DBA-Modul an, mit dem z.B. Tablespaces und Datafiles verwaltet werden können. Außerdem ist hierin der LogMiner als grafische Oberfläche integriert, so dass es relativ einfach ist, Informationen aus den RedologDateien auszulesen.
6.3.3 Hora Das Werkzeug Hora wird von der Firma Keep Tool5 in Berlin hergestellt. Es ist als Clientanwendung auf allen gängigen Windows-Plattformen ab Windows 95 verfügbar und wendet sich gleichermaßen an Datenbankadministratoren wie Anwendungsentwickler. Hervorzuheben sind an dieser Stelle die kompakten, übersichtlichen Navigationsmöglichkeiten, die alle wesentlichen Funktionsbereiche des Alltagsgeschäftes abdecken. Über thematisch gegliederte »Pages« lassen sich zusammengehörige Menüs aufrufen, die ihrerseits wieder mehrdimensionale Navigationsmöglichkeiten eröffnen. Eine Favoritenseite erlaubt die individuelle Zusammenstellung von einzelnen Menüpunkten. Die Abbildung 6.22 zeigt das Tabellenmenü der Standardseite mit Spalteninformationen und – davon abhängig – zugehörigen Constraints. Die oberen TabReiter ermöglichen die Navigation in unterschiedlichen Kontexten eines Tabellenoder View-Objektes.
Abbildung 6.22: Standardseite von Hora 5
www.keeptool.com
Weitere Werkzeuge
279
Die Anforderungen der Datenbankverwalter werden über die DBA-Seite mit ihren Untermenüs abgedeckt. Neben einer Performance-Anzeige mit Diagrammen der wichtigsten Metriken werden Menüs zu den Funktionsbereichen Tablespaces, Benutzerverwaltung, Sessions, Datenbank, Redolog, Auditing und Data Dictionary angeboten. Die Abbildung 6.23 zeigt den Bereich »SESSIONS« mit Informationen zu einzelnen Sessions, wie z.B. den aktuellen SQL-Befehlen, Locking und Statistiken.
Abbildung 6.23: Sessionmonitor von Hora
Aktionen, die über Menüs generiert werden, können optional vor der Ausführung in SQL-Form angezeigt und bei Bedarf modifiziert werden. Ein separater SQLBereich kann zur Ablage von eigenen SQL-Skripten genutzt werden. Dieses SQLRepository kann in der Windows Registry oder direkt im Filesystem gespeichert werden.
280
Administrationswerkzeuge
Mehrere aktive Datenbankverbindungen lassen sich in jeweils eigenen Fenstern anzeigen. Hora wird ergänzt durch weitere Werkzeuge, die folgende Funktionsbereiche abdecken: Debugging von PL/SQL-Code Generierung von HTML-Dokumenten zur Dokumentation der betreffenden Datenbank SQL-Editor ER-Diagrammer zur Darstellung von Tabellen und ihren Relationen Generierung von DDL-Befehlen mit umfangreichen Filtermöglichkeiten Neben diesen vorgestellten Werkzeugen gibt es viele andere, die sicherlich erwähnenswert wären. Wir haben uns in der Kürze auf die beschränkt, die wir selber in Projekten eingesetzt – und an die wir uns gewöhnt haben.
Zugriff auf die Datenbank 7.1
Oracle Net
Oracle Net ist eine Softwareschicht, die für den transparenten Zugriff von praktisch beliebigen Clients auf Oracle-Datenbanken sorgt. Mittlerweile gibt es diverse Varianten der Oracle Net-Implementierung – als installierter Oracle Client, als Emulation eines solchen Clients mit Hilfe von Java in der Thin JDBC-Schnittstelle oder als eine Sammlung von dynamischen Laufzeitbibliotheken namens Instant Client. Lediglich in einer 3-Schichten-Architektur kommt Oracle Net auf dem Client-Rechner nicht mehr vor. Hierbei kommt meist Oracle Net oder JDBC auf dem Applikationsserver (in der mittleren Schicht) zum Einsatz. Die umfassende Darstellung der Oracle Net-Architektur ist sehr umfangreich und abstrakt. Der hier gewählte Ansatz zur Darstellung von Oracle Net ist pragmatischer Natur: Die Beschreibung der Architektur, der Oracle Net-Komponenten sowie ihrer Konfiguration wird ineinander verschachtelt vorgenommen, so dass die wichtigen Zusammenhänge deutlich werden. Auf eine vollständige Architekturbeschreibung wird daher verzichtet.
7.1.1 Architektur und Konfiguration Die allgemeine Diskussion von Anwendungsarchitekturen (also Client/Server, 3Schicht-Architektur usw.) würde den Rahmen dieses Buches sprengen. Zur Erläuterung der Oracle Net-Architektur betrachten wir aus Richtung der Datenbank das nächste Stück Software, das am anderen Ende der Netzwerkverbindung sichtbar ist, und nennen dies Client. In den meisten Fällen wird auf dem Client auch eine Oracle-Installation durchgeführt. Hierbei werden die jeweils passenden Schnittstellen für die geplanten Anwendungen ausgewählt: OCI und OCCI für Anwendungen, die mit C bzw. C++ programmiert wurden, ODBC für die »traditionelle« MS-kompatible Schnittstelle, Oracle Provider for OLE DB und Oracle Data Provider for .Net für modernere MS-konforme Programme, Oracle Objects for OLE als Oracle-Alternative auf der MS-Plattform, JDBC OCI für Java-Programme usw. Zumindest fast alle Schnittstellen haben als Gemeinsamkeit, dass Oracle Net als Basis für Verbindungen zum Oracle Server dient und im Rahmen des Oracle Clients installiert und konfiguriert sein muss. Thin JDBC ist die eine Ausnahme im JavaUmfeld, die als Komponente z.B. in Applets enthalten ist und somit auf Rechnern laufen kann und muss, die keine Oracle Client-Installation besitzen. Die andere Ausnahme ist der Instant Client, der einerseits nicht mit dem Universal Installer installiert werden muss und andererseits ohne Konfigurationsdateien auskommt (und hierzu die Easy Connect-Methode verwendet).
282
Zugriff auf die Datenbank
Instanzen und Dienste An dieser Stelle dürfte als bekannt vorausgesetzt werden können, dass eine OracleInstanz einen Namen – die ORACLE_SID – besitzt, der sie zumindest auf einem Rechner eindeutig identifiziert. In älteren Oracle-Versionen (Oracle8 und älter) wurde der Instanzname als einziges Kriterium, eine bestimmte Instanz zu adressieren, genutzt. Dies hat sich jedoch aus diversen Gründen als unpraktisch herausgestellt: In RACUmgebungen musste man z.B. in früheren Oracle Net-Versionen die Instanzen identisch benennen, da man zwar eine Liste von Netzwerkadressen, etwa für LoadBalancing-Zwecke, angeben konnte, aber nur einen Wert für die ORACLE_SID. Ein Cluster, in dem alle Instanzen gleich heißen, ist jedoch für den Administrator nicht einfach zu verwalten ... Aus diesem Grund wird hier etwas näher auf Oracle-Dienstnamen eingegangen. Dienste innerhalb der Datenbank sind ein dynamisches und daher äußerst flexibles Gebilde, um den Verbindungsaufbau zu einer Instanz zu gestalten. Grundsätzlich gilt, dass es zwei vordefinierte Dienstnamen (SYS$USERS und SYS$BACKGROUND) sowie einen aus den Werten der Systemparameter db_name und db_domain zusammengesetzten Dienstnamen (.) gibt. Mit dem Systemparameter service_names kann die Liste der aktiven Dienstnamen modifiziert werden, wobei die vordefinierten Dienstnamen immer aktiv sind; sie müssen also nicht in der Liste auftauchen. service_names ist dynamisch auf Systemebene veränderbar (d.h. mit ALTER SYSTEM online veränderbar). Vorsicht ist durch die Tatsache geboten, dass immer die komplette Liste der aktiven Dienste geändert wird, d.h. durch den Befehl ALTER SYSTEM SET service_names = 'NEWSERVICE.HOME.COM' SCOPE = MEMORY;
wird nicht etwa der Dienst NEWSERVICE.HOME.COM zusätzlich aktiviert, sondern anstelle der vorher aktiven Liste der Dienste. Zusätzliche Flexibilität liefert das PL/SQL-Modul dbms_service. Zunächst muss man sich daran gewöhnen, dass ein Dienst innerhalb des Moduls zwei Namen hat: den Dienstnamen, der innerhalb des gesamten Moduls verwendet wird, und den Netzwerknamen, so wie er im Zusammenhang mit Oracle Net verwendet wird. Dabei hat der Dienstname eine Maximallänge von 64 Zeichen, der Netzwerkname bis zu 512 Zeichen. Es hat sich bewährt, falls es irgendwie möglich ist, beide Namen gleich zu lassen (und bitte immer mit Domäne!). Der Netzwerkname kommt lediglich beim Anlegen eines Dienstes vor und wird damit dem Dienstnamen zugeordnet: EXECUTE dbms_service.create_service ( service_name => 'NEWSERVICE.HOME.COM', network_name => 'NEWSERVICE.HOME.COM')
Damit steht der Dienst jedoch noch nicht zur Verfügung. Erst durch das Starten des Dienstes kann auf ihn zugegriffen werden: EXECUTE dbms_service.start_service – ( service_name => 'NEWSERVICE.HOME.COM', instance_name => 'SID1')
Oracle Net
283
Die Angabe von instance_name ist optional und ermöglicht, den Dienst in einer bestimmten Instanz eines RAC-Clusters zu starten. Dies eröffnet später die Möglichkeit, bestimmte Verbindungen gezielt auf einzelne bzw. Gruppen von RACInstanzen zu leiten. Mit der Prozedur dbms_service.stop_service (mit gleichen Parametern wie beim Start) können Dienste ebenfalls wieder gestoppt werden. Auf der aktuellen Instanz (diejenige im RAC, bei der man angemeldet ist) können mit dem Aufruf EXECUTE dbms_service.disconnect_session ( service_name => 'NEWSERVICE.HOME.COM')
alle zu einem Dienst gehörenden Sitzungen beendet werden. Um einen Überblick zu bekommen, welche Sitzungen hiervon betroffen sein werden, enthält die View v$session die Spalte service_name. Zu guter Letzt können Dienste mit dbms_service.delete_service wieder gelöscht werden. Im Data Dictionary sind einige hilfreiche Views zur Administration von Diensten enthalten: all_services bzw. dba_services bieten wie v$services einen Überblick über alle vorhandenen Dienste; v$active_services verrät, welche davon zurzeit aktiv sind. Oracle Net-Architektur Die Client-Server-Architektur der Oracle Database zeichnet sich im Normalfall dadurch aus, dass ein Programm beliebiger Art (der Client) mit einem ihm eigens zugewiesenen (dedicated) Prozess des Oracle Servers kommuniziert, der zur entsprechenden Instanz gehört. Dieses Modell wird deshalb – im Gegensatz zur SharedServer-Architektur, die weiter unten behandelt wird – auch als Dedicated-ServerArchitektur bezeichnet. Schematisch sieht dies wie folgt aus:
Abbildung 7.1: Oracle Net-Architektur
284
Zugriff auf die Datenbank
Der Client nutzt als Aufrufschnittstelle zum Server das Oracle Call Interface OCI; der Server Oracle Program Interface OPI. Im Allgemeinen antwortet der Server auf einen Aufruf aus dem OCI mit einem Aufruf des OPI. Dies erfolgt im Normalfall synchron, d.h., der Client ist blockiert, bis die Antwort des Servers eingetroffen ist. Die Schichten TTC (Two Task Common), TNS (Transparent Network Substrate) und Protocol Support gehören zu Oracle Net. Mit »Netzwerk« sind die unter dem Protocol Support liegenden Schichten der Netzwerkschichten (layer) zusammengefasst. Die Architektur basiert auf dem ISO/OSI 7-Schichten-Modell. In der folgenden Abbildung sind die sieben Schichten des Standardmodells den Oracle Net-Schichten zugeordnet:
Abbildung 7.2: ISO/OSI 7-Schichten-Modell und Oracle Net
Die TTC-Schicht ist für die Konvertierung von Zeichensätzen und Datenformaten zuständig. TNS ist die Hauptkomponente von Oracle Net und für korrekten Aufbau und Verwaltung von Verbindungen zwischen Client und Server verantwortlich. TNS wird manchmal auch als Net Foundation Layer bezeichnet. Innerhalb von TNS sind u.a. Dienste zur Namensauflösung sowie Sicherheitsfunktionen untergebracht. Mit Protocol Support sind letztendlich die Interfaces in die verschiedenen Protokolle gemeint, die Oracle Net unterstützt. Dies sind: TCP/IP, TCP/IP mit SSL, Named Pipes und SDP.1 In der Thin JDBC-Schnittstelle sind alle Oracle Net-Schichten in Java implementiert; JavaNet entspricht im Wesentlichen TNS. Als Protokoll wird ausschließlich TCP/IP unterstützt. Verbindungsaufbau durch den Listener Eine zentrale Aufgabe des TNS ist der Verbindungsaufbau. Da diese Phase zwingend notwendig für eine Verbindung zwischen Client und Server ist, sollte deren Funktionsweise von großem Interesse sein.
1
Oracle Net ist also kein Netzwerkprotokoll! Auf dieses Gerücht stößt man immer wieder ...
Oracle Net
285
Auf der Serverseite ist der Listener für den Verbindungsaufbau zuständig. Dies ist ein eigenständiger, insbesondere von jeglicher Instanz unabhängiger Prozess, der mit der Aufgabe beschäftigt ist, auf mindestens einem Netzwerk-Endpunkt zu »horchen«. Mit Netzwerk-Endpunkt ist im Falle von TCP/IP ein Port einer Schnittstelle bzw. IP-Adresse gemeint. Die Beziehung zwischen Instanzen und Listenern ist eine oft diskutierte Frage. Grundsätzlich sind alle denkbaren Konstellationen möglich, z.B. Jede Instanz hat ein eigenes ORACLE_HOME und einen eigenen Listener. Jede Instanz hat ein eigenes ORACLE_HOME; es gibt aber nur einen einzigen Listener. Es gibt mehrere ORACLE_HOMEs mit unterschiedlich vielen Instanzen und einem Listener pro ORACLE_HOME. Es gibt ein ORACLE_HOME mit vielen Instanzen und einem Listener. Man sollte lediglich beachten, dass man für den Fall, dass ein Listener Verbindungen für Instanzen aus verschiedenen ORACLE_HOMEs aufbaut, grundsätzlich den »neuesten« Listener nehmen sollte – in den allermeisten Fällen ist er entsprechend abwärtskompatibel, so dass ältere Versionen unterstützt werden, und er ist dann in der Lage, für die Instanzen der neueren Oracle-Versionen auch deren Oracle Net Features zu nutzen. Insbesondere gilt für Oracle 10g, dass der Listener zwingend eine 10.1er-Versionsnummer haben muss – ältere Listener können keine Verbindungen zu Oracle 10gInstanzen aufbauen.2
Abbildung 7.3: Der Oracle Net Listener
2
Mit früheren Versionen war dies durchaus möglich; ein Listener mit Version 8.1 kann durchaus zu Instanzen mit Version 9.x Verbindungen aufbauen.
286
Zugriff auf die Datenbank
Ein Client, der den Netzwerk-Endpunkt des Listeners kennen muss, wendet sich unter Angabe seiner Kontaktdaten mit einer Verbindungsanfrage beim Listener. Wenn alle Kontaktdaten zu einer der vom Listener gehörenden Instanzen passen, startet der Listener bei eben dieser Instanz einen Dedicated-Server-Prozess. Im Normalfall wird die Verbindungsanfrage des Clients an den Serverprozess übergeben, so dass dieser im nächsten Schritt dem Client antwortet und die Verbindung somit bereits aufgebaut ist. Diese vom Listener bevorzugte Methode wird auch als direct hand-off bezeichnet. Alternativ hierzu ist auch ein Redirect möglich, bei dem der Listener die Kontaktdaten des von ihm aufgebauten Serverprozesses an den Client übergibt. Hierbei ist die Verbindung zwischen Client und Serverprozess erst einen Schritt später aufgebaut. Die tatsächlich verwendete Methode hängt vom Betriebssystem und der Netzwerkkonfiguration ab – genauen Aufschluss liefert hier wohl nur ein Netzwerktrace. Die Basiskonfiguration Zu einer Basiskonfiguration gehören mindestens ein Server und ein Client. Diese besitzen jeweils eine oder mehrere Konfigurationsdateien. Im Normalfall befinden sich alle Oracle Net-Konfigurationsdateien im Verzeichnis $ORACLE_HOME/network/ admin. Falls man die Konfiguration für verschiedene Installationen getrennt durchführen möchte, z.B. weil man in verschiedenen Umgebungen arbeitet, ist dies so richtig; oft wird aber eine Speicherung an einer zentralen Stelle gewünscht, die nicht unter dem Installationsverzeichnis $ORACLE_HOME liegt. Als Alternative kann man z.B. $ORACLE_BASE/network/admin verwenden. Dies hat zwei Vorteile: 1. Bei mehreren ORACLE_HOMEs muss die Konfiguration nur einmal durchgeführt werden; redundante Speicherorte werden vermieden. 2. Beim Löschen eines Installationsverzeichnisses gehen keine Konfigurationsdaten verloren. Damit die Oracle-Software (Client und Server) in einem anderen als dem Standardverzeichnis nach Oracle Net-Konfigurationsdateien sucht, muss die Variable TNS_ADMIN auf das gewünschte Verzeichnis gesetzt werden.3 Falls TNS_ADMIN gesetzt ist, die Konfigurationsdateien aber nicht vorhanden sind, werden sie dennoch im Standardverzeichnis $ORACLE_HOME/network/admin gesucht. Die Konfiguration wird meist beim Server begonnen. Hier wird mindestens ein Listener konfiguriert. Hierzu wird mindestens die Datei listener.ora, oft auch sqlnet.ora benötigt. Die Datei sqlnet.ora sollte auf der Serverseite im Falle eines MS-Windows Servers mindestens die Zeile SQLNET.AUTHENTICATION_SERVICES = (NTS)
3
Unter Unix gibt es alternativ die Möglichkeit, mit Links zu arbeiten. Da es hier und dort Werkzeuge (oder Versionen von Werkzeugen ...) gibt, die auf $TNS_ADMIN nicht reagieren, ist diese Möglichkeit auch in Betracht zu ziehen.
Oracle Net
287
enthalten. Dies hat zwar nichts mit der Netzwerkkonfiguration zu tun; falls der Eintrag nicht da ist, kann jedoch die lokale Anmeldung AS SYSDBA ohne Passwort (für Mitglieder der Windows-Gruppe ORA_DBA) nicht genutzt werden. Als Beispielprotokoll verwenden wir zunächst das Protokoll TCP/IP, da dies bei den meisten Installationen verwendet wird. Eine einfache Listener-Konfiguration in der Datei listener.ora sieht wie folgt aus: LOG_DIRECTORY_LISTENER = /orabase/network/log LOG_FILE_LISTENER = listener.log LISTENER = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = rhlinux)(PORT = 1521)) )
Wichtig ist das Verständnis, dass in jedem der drei definierten Parameter der Name des Listeners (in diesem Falle LISTENER) vorkommt. Parameter für einen weiteren Listener würde man in der gleichen Datei hinterlegen; sie heißen dann z.B. LOG_DIRECTORY_LSNR2, LOG_FILE_LSNR2 und LSNR2 für einen Listener LSNR2. Die Parameter LOG_DIRECTORY_LISTENER und LOG_FILE_LISTENER legen erwartungsgemäß Pfad und Dateinamen für eine Logdatei fest. Der Parameter LISTENER enthält zunächst einen Protokoll-Endpunkt, auf dem der Listener horcht. Im Beispiel wird der Standardport 1521 für Oracle Net verwendet; es kann aber auch ein beliebiger freier Port eingetragen werden. Im Übrigen verbirgt sich hinter dem Hostnamen (in diesem Fall rhlinux) eine Netzwerkschnittstelle bzw. IP-Adresse. Die Zuordnung von IP-Adressen zu Netzwerkschnittstellen erfolgt entweder manuell (durch Konfiguration des Servers) oder automatisch mit DHCP4. An dieser Stelle sei dringend empfohlen, Rechner mit Serverfunktionen wie Instanzen, Listenern oder Connection Managern ausschließlich manuell zu konfigurieren. Die Änderung einer IP-Adresse kann für solche Serverdienste enorm viel Ärger bereiten, was oft genug heißt, dass die Dienste für eine mehr oder weniger lange Zeit nicht zur Verfügung stehen. Sobald die Konfiguration vorhanden ist, kann man mit dem Listener Control Utility LSNRCTL und dem Kommando START den Listener starten: $ lsnrctl start LSNRCTL for Linux: Version 10.1.0.3.0 - Production on 04-FEB-2005 16:39:22 Copyright (c) 1991, 2004, Oracle.
All rights reserved.
Starting /orabase/product/O1010/bin/tnslsnr: please wait... TNSLSNR for Linux: Version 10.1.0.3.0 – Production System parameter file is /orabase/network/admin/listener.ora Log messages written to /orabase/network/log/listener.log Listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=rhlinux)(PORT=1521)))
4
Dynamic Host Configuration Protocol
288
Zugriff auf die Datenbank
Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=rhlinux)(PORT=1521))) STATUS of the LISTENER -----------------------Alias LISTENER Version TNSLSNR for Linux: Version 10.1.0.3.0 – Production Start Date 04-FEB-2005 16:39:22 Uptime 0 days 0 hr. 0 min. 0 sec Trace Level off Security ON: Local OS Authentication SNMP OFF Listener Parameter File /orabase/network/admin/listener.ora Listener Log File /orabase/network/log/listener.log Listening Endpoints Summary... (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=rhlinux)(PORT=1521))) The listener supports no services The command completed successfully
Das Listener Control Utility kann entweder auf der Kommandozeile mit allen Parametern für einen Befehl bestückt (wie im o.a. Beispiel) oder als interaktives Werkzeug benutzt werden. Für den letzten Fall ruft man es ohne weitere Parameter auf. In der Ausgabe der Listener Control Utilities sind verschiedene Dinge zu sehen. Der Listener bestätigt die mit TNS_ADMIN gesetzten Orte für die Konfigurationsdatei (system parameter file bzw. Listener Parameter File). Die konfigurierte Logdatei wird ebenfalls bestätigt (log messages written to bzw. Listener Log File). Die Listening Endpoints Summary bestätigt die konfigurierte Auswahl. Offensichtlich kann man mit dem Listener ansonsten noch nichts tun: The listener supports no services. In diesem Zustand würde jeder Versuch, einen Verbindungsaufbau über diesen Listener anzufordern, in folgender Fehlermeldung enden: TNS-12514: TNS:listener does not currently know of service requested in connect descriptor
Erst nach dem automatischen Anmelden einer Instanz beim Listener ist diese auch erreichbar. Dieser Vorgang wird als Dienstregistrierung (service registration) bezeichnet. Eine Instanz versucht die automatische Anmeldung grundsätzlich an der Standardnetzwerkschnittstelle auf dem Port 1521. Läuft der Listener auf einer anderen Schnittstelle oder einem anderen Port, so muss der Initialisierungsparameter local_listener der Instanz auf die gültige Listener-Adresse zeigen: local_listener = '(ADDRESS=(PROTOCOL=TCP)(HOST=rhlinux)(PORT=1521))'
Alternativ kann als Wert für den Parameter local_listener ein Net-Aliasname gesetzt werden, der in der lokalen Datei tnsnames.ora in eine Adresse bzw. Adressliste übersetzt wird: local_listener = 'LISTENER.LOCAL'
Oracle Net
289
Der Eintrag für die Datei tnsnames.ora sieht wie folgt aus: LISTENER.LOCAL= (ADDRESS_LIST= (ADDRESS=(PROTOCOL=TCP)(HOST=rhlinux)(PORT=1521)) )
Die Ausgabe des Kommandos STATUS in das Listener Control Utility hat nach der Instanzanmeldung (zusätzlich zum fast identischen Aussehen zum START-Kommando) folgenden Inhalt: Services Summary... Service "RH10.hl.de" has 1 instance(s). Instance "RH10", status READY, has 1 handler(s) for this service...
Bei der Anmeldung am Listener hinterlässt die Instanz sowohl ihren Instanznamen (RH10) als auch ihren Dienstnamen (RH10.hl.de). Der Instanzname entspricht dem Wert der Variablen ORACLE_SID; der Dienstname setzt sich bei nicht gesetztem Systemparameter service_names aus db_name und db_domain zusammen. Nun kann man zur Konfiguration des Clients übergehen. Beim Client sollten die beiden Dateien sqlnet.ora und tnsnames.ora konfiguriert werden – das Verzeichnis wird wie beim Server festgelegt. Die Datei sqlnet.ora sollte zur lokalen Namensauflösung zumindest die beiden Einträge erhalten: NAMES.DIRECTORY_PATH = (TNSNAMES) NAMES.DEFAULT_DOMAIN = hl.de
Hiermit wird einerseits festgelegt, dass die Auflösung von Net-Aliasnamen in einer tnsnames.ora-Datei erfolgt. Net-Aliasnamen haben die Form .<domain> und bekommen eine Zieladresse (die einem Listener entsprechen muss) sowie einen Servicenamen zugewiesen. Andererseits wird ein Standardwert für die Domäne festgelegt, so dass beim späteren Verbindungsaufbau für .<domain> die Angabe von reicht, falls <domain> dem Standardwert entspricht. Die Datei tnsnames.ora muss mindestens einen Eintrag wie den folgenden enthalten: RH10.HL.DE = (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP) (HOST = rhlinux) (PORT = 1521) ) ) (CONNECT_DATA = (SERVICE_NAME = RH10.hl.de) ) )
290
Zugriff auf die Datenbank
Hiermit wird dem Net-Aliasnamen RH10.HL.DE sowohl eine Adresse (nämlich die gleiche, die als Listener-Endpunkt definiert ist) als auch ein Dienstname zugeordnet. Der Net-Aliasname und der Dienstname der Instanz sind im Übrigen nur zufällig identisch; für beide können auch unterschiedliche Namen gewählt werden. In vielen Fällen werden jedoch beide aus Datenbanknamen und -domäne zusammengesetzt. Basiskonfiguration mit dem Net-Konfigurationsassistenten Alternativ zur manuellen Konfiguration kann man z.B. den Net-Konfigurationsassistenten verwenden, um eine Basiskonfiguration zu erstellen. Der Assistent wird z.B. auch während der Basisinstallation aufgerufen, um einen Listener, Benennungsmethoden und einen Aliasnamen zu konfigurieren. Die hier gezeigte Sitzung mit dem Net-Konfigurationsassistenten stammt nicht aus der Installation, sondern ist ein manueller Aufruf. Daher ist auf der ersten Seite die Konfigurationsauswahl zu sehen; während der Installation sind die entsprechenden Schritte vorgegeben. Der Aufruf selbst erfolgt unter MS-Windows aus dem Startmenü oder alternativ – für alle Plattformen inklusive MS-Windows – mit dem Aufruf netca aus der Kommandozeile. Im Einstiegsbildschirm wurde zunächst die Listener-Konfiguration ausgewählt. Zum Bestätigen der Fenster wird im Verlauf der Sitzung jeweils die Schaltfläche Weiter angeklickt.
Abbildung 7.4: Einstiegsbildschirm
Da noch kein Listener konfiguriert ist, muss mit Hinzufügen die einzig mögliche Variante ausgewählt werden.
Oracle Net
291
Abbildung 7.5: Listener hinzufügen
Der vorgegebene Name des Listeners ist wie bei der o.a. Beispielkonfiguration LISTENER.
Abbildung 7.6: Listener benennen
Im nächsten Fenster können die Protokolle des Listeners ausgewählt werden. Auch hier bliebt TCP die einzige Auswahl.
292
Zugriff auf die Datenbank
Abbildung 7.7: Protokolle für den Listener auswählen
Im nächsten Schritt wird der Port für den Listener ausgewählt. Der Standard-Port 1521 ist voreingestellt.
Abbildung 7.8: Listener-Port
Es können mehrere Listener konfiguriert werden. Für die Basiskonfiguration reicht einer auf jeden Fall aus.
Oracle Net
Abbildung 7.9: Weitere Listener
Damit ist die Listener-Konfiguration abgeschlossen.
Abbildung 7.10: Abschluss der Listener-Konfiguration
Der nächste Schritt ist die Auswahl der Benennungsmethoden.
293
294
Zugriff auf die Datenbank
Abbildung 7.11: Benennungsmethoden
Um die Aliasnamen in einer tnsnames.ora-Datei auflösen zu können, muss mindestens Lokale Benennung ausgewählt werden. Zusätzliche Methoden können ebenfalls ausgewählt werden.
Abbildung 7.12: Auswahl der Benennungsmethoden
Oracle Net
295
Damit ist dieser Schritt bereits abgeschlossen.
Abbildung 7.13: Abschluss Benennungsmethoden
Abschließend sollte mindestens ein Aliasname konfiguriert werden, damit man die bisher gemachten Eingaben testen kann.
Abbildung 7.14: Auswahl Konfiguration Aliasname
296
Zugriff auf die Datenbank
Auch hier sind alle Optionen außer Hinzufügen zunächst nicht anwählbar.
Abbildung 7.15: Aliasnamen hinzufügen
Zunächst muss der Dienstname der Datenbank bzw. Instanz angegeben werden (siehe Abschnitt auf Seite 282).
Abbildung 7.16: Dienstnamen angeben
Als Nächstes wird das Protokoll ausgewählt. Meistens handelt es sich um TCP.
Oracle Net
Abbildung 7.17: Protokollauswahl
Im Falle von TCP/IP fehlen nun noch Hostname oder IP-Adresse und Port.
Abbildung 7.18: Auswahl von Hostname und Port
297
298
Zugriff auf die Datenbank
Der neue Aliasname kann bereits jetzt getestet werden. Da der Listener in diesem Fall noch nicht aktiv ist, kann der Test weggelassen werden.
Abbildung 7.19: Test des Aliasnamen
Abschließend wird der Aliasname selbst noch benannt. Oft ist es sinnvoll, diesen Namen identisch zum Dienstnamen der Datenbank zu wählen.
Abbildung 7.20: Aliasname
Oracle Net
299
Auch hier können mehrere Aliasnamen definiert werden. In diesem Beispiel wird dies nicht genutzt.
Abbildung 7.21: Weitere Aliasnamen
Das Fenster zum Abschluss der Konfiguration von Aliasnamen wird nun bestätigt.
Abbildung 7.22: Abschluss Konfiguration von Aliasnamen
300
Zugriff auf die Datenbank
Die Konfiguration ist hiermit beendet und wird mit einem Klick auf Beenden abgeschlossen und in die Oracle Net-Konfigurationsdateien geschrieben.
Abbildung 7.23: Beenden des Net-Konfigurationsassistenten
Das Resultat der Konfiguration ist jeweils eine Datei listener.ora, sqlnet.ora und tnsnames.ora mit folgenden Inhalten: # listener.ora Network Configuration File: /orabase/network/admin/listener.ora # Generated by Oracle configuration tools. SID_LIST_LISTENER = (SID_LIST = (SID_DESC = (SID_NAME = PLSExtProc) (ORACLE_HOME = /orabase/product/db/10.1.0) (PROGRAM = extproc) ) ) LISTENER = (DESCRIPTION_LIST = (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = rhas4)(PORT = 1521)) ) (ADDRESS_LIST = (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC)) ) ) ) Listing 7.1: Datei listener.ora
Oracle Net
301
Die Datei hat einige Ähnlichkeit mit der o.a. listener.ora. Es gibt in der SID_LIST_LISTENER einen Eintrag für externe Prozeduren (eine Funktion, mit der man externe Bibliotheken in PL/SQL integrieren kann), der aber nur selten gebraucht wird. Es fehlen andererseits die Einträge zur gezielten Ablage der Logdatei des Listeners. # sqlnet.ora Network Configuration File: /orabase/network/admin/sqlnet.ora # Generated by Oracle configuration tools. NAMES.DIRECTORY_PATH= (TNSNAMES, EZCONNECT) Listing 7.2: Datei sqlnet.ora
In der Datei sqlnet.ora sind lediglich die Benennungsmethoden konfiguriert. Es fehlt die Standarddomäne. # tnsnames.ora Network Configuration File: /orabase/network/admin/tnsnames.ora # Generated by Oracle configuration tools. RH4.HL.DE = (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = rhas4)(PORT = 1521)) ) (CONNECT_DATA = (SERVICE_NAME = RH4.hl.de) ) ) Listing 7.3: Datei tnsnames.ora
Die Datei tnsnames.ora ist genau nach Vorgabe konfiguriert. Zur Aufbereitung der Konfiguration können die Dateien entweder manuell ergänzt oder mit einem weiteren Werkzeug, dem Net Manager, bearbeitet werden. Dieses Werkzeug kann unter MS-Windows aus dem Startmenü oder auf allen Plattformen mit dem Programmnamen netmgr aufgerufen werden. Der Net Manager hat auf der linken Seite einen Navigationsbaum, der für die lokale Konfiguration die Bereiche Profil, Dienstbenennung und Listener (für die Dateien sqlnet.ora, tnsnames.ora sowie listener.ora) enthält. In der Kopfzeile wird grundsätzlich das aktuelle Konfigurationsverzeichnis angegeben, mit dem der Net Manager gerade arbeitet. Hierdurch wird sichergestellt, dass die richtige Konfiguration bearbeitet wird.
302
Zugriff auf die Datenbank
Abbildung 7.24: Der Net Manager
Durch einen Klick auf Profil gelangt man in den Bereich zur Konfiguration der Datei sqlnet.ora. Die Auswahlbalken oben auf dem Bildschirm sollte auf Namensgebung eingestellt werden. Dann kann die Standarddomäne hl.de eingegeben werden.
Abbildung 7.25: Standard-Domäne setzen
Oracle Net
303
Mit einem Klick auf den bereits konfigurierten Listener LISTENER gelangt man in den Bereich zur Konfiguration des Listeners. Dort wählt man mit dem oberen Auswahlbalken zunächst Allgemeine Parameter aus, dann den Karteireiter Protokollierung & Tracing. Nun kann der gewünschte vollständige Pfadname für die Logdatei nach den eigenen Wünschen geändert werden.
Abbildung 7.26: Pfadangaben für Listener-Logdatei
Um die Änderungen zu speichern, wählt man im Menü Datei den Punkt Netzwerkkonfiguration speichern... aus.
304
Zugriff auf die Datenbank
Abbildung 7.27: Speichern der Konfiguration
Nach dem Speichern der Konfiguration kann man die Anpassung der Parameter in den Dateien listener.ora und sqlnet.ora nachvollziehen. # listener.ora Network Configuration File: /orabase/network/admin/listener.ora # Generated by Oracle configuration tools. SID_LIST_LISTENER = (SID_LIST = (SID_DESC = (SID_NAME = PLSExtProc) (ORACLE_HOME = /orabase/product/db/10.1.0) (PROGRAM = extproc) ) ) LOG_DIRECTORY_LISTENER = /orabase/network/log LOG_FILE_LISTENER = LISTENER.log
Oracle Net
305
LISTENER = (DESCRIPTION_LIST = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = rhas4)(PORT = 1521)) ) (DESCRIPTION = (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC)) ) ) Listing 7.4: Datei listener.ora nach Änderung # sqlnet.ora Network Configuration File: /orabase/network/admin/sqlnet.ora # Generated by Oracle configuration tools. NAMES.DIRECTORY_PATH= (TNSNAMES, EZCONNECT) NAMES.DEFAULT_DOMAIN = hl.de Listing 7.5: Datei sqlnet.ora nach Änderung
Wie erwartet, sind in der Datei listener.ora die Parameter LOG_DIRECTORY_LISTENER und LOG_FILE_LISTENER sowie in der Datei sqlnet.ora der Parameter NAMES.DEFAULT_ DOMAIN ergänzt worden. Wie man recht schnell beim Ausprobieren der Werkzeuge erkennen kann, bietet der Net Manager bei weitem mehr Möglichkeiten als der Konfigurationsassistent. Daher empfehlen wir grundsätzlich, den Net Manager einzusetzen. Auch einfachste Konfigurationen sind mit dem Net-Konfigurationsassistenten nicht wesentlich schneller fertig. Konfiguration von Instanzen für den Listener Die weiter oben aufgeführte Basiskonfiguration für den Listener enthält keine Liste der Instanzen, da diese sich nach dem Start automatisch beim Listener anmelden. Diese Art der Konfiguration hat z.B. den Vorteil, dass gewisse Instanz-Statusinformationen an den Listener weitergegeben werden können. Sobald eine Instanz in den RESTRICTED SESSION-Modus gesetzt ist, verweigert der Listener eine Verbindung mit der Fehlermeldung: ORA-12526: TNS:listener: all appropriate instances are in restricted mode
Auch in der Ausgabe des STATUS-Kommandos des Listener Control Utilitys kann der RESTRICTED-Modus nachvollzogen werden: Services Summary... Service "RH10.hl.de" has 1 instance(s). Instance "RH10", status RESTRICTED, has 6 handler(s) for this service...
Dies ist zwar zunächst positiv zu bewerten, da man hiermit den Zugriff auf den Datenbankserver aus dem Netzwerk komplett blockieren kann; allerdings erhalten diese Fehlermeldung auch Oracle-Benutzer, die das Privileg RESTRICTED SESSION besitzen, sich also eigentlich anmelden dürfen.
306
Zugriff auf die Datenbank
Es kann auch aus weiteren Gründen vorteilhaft sein, Instanzen für den Listener zu konfigurieren, z.B. wenn man in der Lage sein möchte, die Instanz über eine Oracle Net-Verbindung zu starten. Hierzu muss die Datei listener.ora zusätzlich zu den bereits bekannten Parametern eine SID-Liste enthalten: SID_LIST_LISTENER = (SID_LIST = (SID_DESC = (GLOBAL_DBNAME = RH10.hl.de) (ORACLE_HOME = /orabase/product/O1010) (SID_NAME = RH10) ) )
Führt man mit dem neuen Parameter einen Neustart des Listeners oder das Kommando RELOAD aus, so ändert sich die Ausgabe des STATUS-Kommandos wie folgt: Services Summary... Service "RH10.hl.de" has 2 instance(s). Instance "RH10", status UNKNOWN, has 1 handler(s) for this service... Instance "RH10", status RESTRICTED, has 6 handler(s) for this service...
Der Listener führt intern eine weitere Instanz des Services, die grundsätzlich den Status UNKNOWN hat. Mit dieser Konfiguration sind Verbindungen an die Instanz möglich, auch wenn diese sich im RESTRICTED SESSION-Modus befindet oder heruntergefahren ist.
7.1.2 Shared Server Architektur Die am häufigsten benutzte Methode für Serverkonfiguration ist die Eins-zu-einsBeziehung zwischen Clients bzw. Sitzungen (Sessions) und Serverprozessen. Diese wird auch als Dedicated Server bezeichnet. Dieses Konzept kann in bestimmten Situationen zu Problemen führen – etwa wenn in Summe zu viele Sitzungen existieren oder wenn Sitzungen zu häufig geöffnet und geschlossen werden, z.B. von Applikationsservern. Als Alternative gilt dann der Shared-Server-Modus, bei dem die Clients beim Öffnen der Sitzung einem Dispatcher fest zugeordnet werden. Ein Dispatcher kann für mehrere Clients da sein und bleibt während des Bestehens einer Sitzung fester Ansprechpartner. Über Queue-Mechanismen verteilt der Dispatcher die Anfragen der Clients an die Shared-Server-Prozesse, deren Zuordnung zu Clients bzw. zu einer Sitzung immer nur für die Dauer der Bearbeitung eines einzelnen Aufrufs bestehen bleibt. Zum Verständnis der Architektur sind folgende Anmerkungen wichtig: Die Zuordnung zwischen Client und Shared Server ist lose und dauert genauso lange wie die Abarbeitung eines einzelnen Aufrufs. Der nächste Aufruf kann also bereits von einem anderen Shared Server bearbeitet werden. Es können die Phasen Execute und Fetch zur Cursor-Abarbeitung von verschiedenen Prozessen durchgeführt werden. Daher wandern im Falle von Shared-Server-Sitzungen
Oracle Net
307
Informationen, die bei Dedicated-Server-Sitzungen in der PGA der Prozesse gespeichert werden, in die SGA; dies sind z.B. Cursor-Informationen und Sort Areas. Daraus folgt, dass ein oft vorgebrachtes Argument für Shared-Server-Architekturen, nämlich eine Einsparung großer Mengen von Hauptspeicher für Prozesse, nur teilweise gilt. Die SGA muss bei der Benutzung von Shared Servern i.A. um den entsprechenden Betrag vergrößert werden. Ein einzelner Aufruf kann z.B. die Execute-Phase eines komplexen SQL-Befehls sein, der mehrere Minuten dauert. In diesem Fall ist der Shared Server für die komplette Zeit an diese Sitzung gebunden, d.h., für die anderen Sitzungen geht ein Shared-Server-Prozess für diese Zeit verloren. Shared-Server-Prozesse werden mit S000, S001 … Snnn; Dispatcher mit D000, D001 … Dmmm bezeichnet.
Abbildung 7.28: Dedicated und Shared Server
Bei den Queues handelt es sich um genau eine Request Queue, in der die Dispatcher alle Anfragen zur Bearbeitung durch die Shared-Server-Prozesse hinterlegen. Die Abarbeitung erfolgt durch einen beliebigen freien Shared-Server-Prozess, der die Antwort für den Client in einer Response Queue, die dem Dispatcher fest zugeordnet ist, hinterlegt. Jeder Dispatcher verfügt über eine eigene Response Queue. Hiermit werden Wartezustände bei der Verteilung der Antworten vermieden.
308
Zugriff auf die Datenbank
Konfiguration Shared Server werden nicht über Oracle Net, sondern über Datenbankparameter konfiguriert. Die einfachste Möglichkeit, dies zu tun, ist, den Initialisierungsparameter shared_servers auf einen vom Standardwert 0 unterschiedlichen Wert zu setzen. Dies bestimmt die initiale und minimale Anzahl der Shared-Server-Prozesse; im weiteren Verlauf ist deren Anzahl dynamisch und wird vom Oracle-System selbst bestimmt. Mit max_shared_servers kann die Maximalzahl der Shared Server vorgegeben werden; hierzu muss dieser Parameter mindestens auf den Wert von shared_servers eingestellt werden. Wenn max_shared_servers kleiner als shared_servers eingestellt ist, kann das Oracle-System praktisch beliebig viele Shared Server starten. Dabei lässt es immer mindestens 1/8 der maximalen Anzahl von Prozessen (Initialisierungsparameter processes) für Dedicated-Server-Prozesse frei. Die Anzahl der benötigten Shared Server für ein bestimmtes System ergibt sich praktisch automatisch aus dem Verhalten des Systems. Als erste Schätzung kann 1/10 der erwarteten Sitzungen angenommen werden. Falls die Systemlast auch »Langläufer« enthält, kann die Zahl der benötigten Shared Server größer sein; falls nur kurze Aufrufe an das OCI gemacht werden, kann sich auch eine kleinere Zahl ergeben. Shared_servers sollte auf jeden Fall so gewählt werden, dass nur in Ausnahmefällen zusätzliche Shared-Server-Prozesse gestartet werden und nicht permanent. Bei den Dispatchern ist die Bestimmung der benötigten Anzahl ein bisschen schwieriger, insbesondere weil Oracle bei Bedarf nicht automatisch Dispatcher nachstartet – hier hat der DBA die Pflicht, sich aus einigen V$-Views Informationen über die Auslastung der Dispatcher zu beschaffen. Falls – wie oben angegeben – ausschließlich shared_servers gesetzt wird, um Shared Server zu aktivieren, wird damit implizit dispatchers = '(PROTOCOL=TCP)'
gesetzt und genau ein Dispatcher gestartet. Möchte man mehr als einen Dispatcher gestartet haben, geht das z.B. mit dispatchers = '(PROTOCOL=TCP)(DISPATCHERS=3)'
Für die Dispatcher können mehrere Parameterwerte angegeben werden. Falls man mit einer Initialisierungsparameterdatei arbeitet, können mehrere aufeinander folgende Zeilen mit dem Parameter dispatchers eingetragen werden. Im Falle einer Serverparameterdatei oder bei ALTER SYSTEM-Kommandos werden einfach mehrere Parameter in Hochkommata als Liste (mit Komma getrennt) angegeben. Dies wird z.B. benötigt, wenn man für jeden Dispatcher einen eigenen Port angeben möchte, um somit Kontrolle über die verwendeten Ports zu bekommen, etwa um diese in einer Firewall gezielt freischalten zu können. Dies könnte wie folgt aussehen: dispatchers = '(ADDRESS=(PROTOCOL=TCP)(HOST=rhlinux)(PORT=1522))' dispatchers = '(ADDRESS=(PROTOCOL=TCP)(HOST=rhlinux)(PORT=1523))'
Mit der gleichen Methode können auch unterschiedliche IP-Adressen angegeben werden. In unserem Beispiel sind die Ports 1522 und 1523 mit Dispatchern belegt. Das kann über das Kommando SERVICES des Listener Control Utilitys überprüft werden:
Oracle Net
309
Services Summary... Service "RH10.hl.de" has 1 instance(s). Instance "RH10", status READY, has 3 handler(s) for this service... Handler(s): "DEDICATED" established:0 refused:0 state:ready LOCAL SERVER "D001" established:0 refused:0 current:0 max:972 state:ready DISPATCHER <machine: rhlinux, pid: 6685> (ADDRESS=(PROTOCOL=TCP)(HOST=rhlinux)(PORT=1523)) "D000" established:0 refused:0 current:0 max:972 state:ready DISPATCHER <machine: rhlinux, pid: 6683> (ADDRESS=(PROTOCOL=TCP)(HOST=rhlinux)(PORT=1522))
Jeder Dispatcher wird mit Prozessnummer und Port aufgeführt. Sollten die Dispatcher im Listener nicht aufgeführt sein, so kann dieser auch keine Verbindungen im Shared-Server-Modus aufbauen. Meist liegt die Ursache darin, dass der Listener nicht auf der erwarteten Adresse horcht, so dass der Initialisierungsparameter local_listener gesetzt werden muss. Es gibt einen weiteren Parameter mts_max_dispatchers, den zumindest Oracle 10g Release 1 nicht weiter betrachtet.5 In früheren Releases konnte hiermit eine online nicht änderbare Maximalzahl von Dispatchern festgelegt werden. Die Konfiguration des oder der Dispatcher lässt sich über die View v$dispatcher_ config überprüfen. Hierbei gibt es für jeden dispatchers-Eintrag eine Zeile, die über die Spalte conf_indx eindeutig identifiziert werden kann. Dies ist wichtig, wenn man online die Konfiguration eines Eintrags bzw. eines einzelnen Dispatchers ändern möchte. Durch die Verwendung der Option (INDEX=n) wird das Kommando der Konfiguration zugeordnet, bei der conf_indx den Wert n enthält. Connection Pooling Eine interessante Option für Dispatcher ist das Connection Pooling. Sie ist gedacht für eine große Zahl von logischen Verbindungen mit relativ langen »Denkpausen«. Dabei wird die Anzahl der benötigten Netzwerkverbindungen dadurch reduziert, dass die Verbindungen einzelnen momentan inaktiven Sitzungen entzogen werden, um sie für aktive Sitzungen zu nutzen. Connection Pooling wird über den zusätzlichen Eintrag (POOL=<x>) des Parameters dispachers aktiviert Dabei kann <x> die folgenden Werte annehmen: ON, YES, TRUE oder BOTH, wenn Connection Pooling sowohl für eingehende als auch für ausgehende Verbindungen aktiviert werden soll, IN für eingehende Verbindungen, OUT für ausgehende Verbindungen sowie OFF, NO oder FALSE für nicht aktiviert.
5
Zitat Oracle Database Administrator’s Guide: In this release of Oracle Database, you can increase the number of dispatchers to more than the limit specified by the max_dispatchers parameter. It is planned that max_dispatchers will be taken into consideration in a future release.
310
Zugriff auf die Datenbank
Dabei gilt ein Standardwert für 10 Ticks als Timeout für die Verbindungen. Soll vom Standardwert abgewichen werden, kann dies mit den Parametern IN und OUT wie folgt gesetzt werden: (POOL=(IN=20)(OUT=50))
Die Dauer eines Ticks wird bei Bedarf mit (TICKS=)
als weitere Option in Sekunden angegeben; der voreingestellte Wert ist hier 1. Eine komplette Dispatcher-Konfiguration für Connection Pooling kann wie folgt angegeben werden dispatchers = '(ADDRESS=(PROTOCOL=TCP)(HOST=rhlinux)(PORT=1523))\ (POOL=(IN=15)(OUT=20))(TICKS=2)'
Eine weitere Option zur Konfiguration des Dispatchers, Session Multiplexing, wird im Zusammenhang mit dem Connection Manager weiter unten erläutert. Verbindungsaufbau Sind Shared Server eingerichtet, so können in der Regel ohne weitere Änderungen auf dem Client Verbindungen an diese aufgebaut werden. Hat der Listener beim Verbindungsaufbau die Wahl zwischen Dedicated und Shared Server, so wird er grundsätzlich Shared-Server-Verbindungen aufbauen. Mit dem Parameter shared_server_sessions kann eine maximale Anzahl von Shared Server Sessions bestimmt werden; jede weitere bekommt bei der Anmeldung den Fehler: ORA-00018: maximum number of sessions exceeded
Zur Überprüfung, ob eine Verbindung tatsächlich im Shared-Server-Modus läuft, kann z.B. die View v$session mit folgender Abfrage herangezogen werden: SELECT saddr, username, program, server FROM v$session;
Ein Auszug aus der Antwort sieht dann wie folgt aus: SADDR -------5D38F964 5D391D34 5D392F1C 5D394104
USERNAME --------------SYSTEM SYSTEM SYSTEM SYSTEM
PROGRAM -----------------------------sqlplusw.exe sqlplusw.exe sqlplusw.exe sqlplusw.exe
SERVER --------SHARED NONE NONE DEDICATED
Der Benutzer SYSTEM ist hier mit vier SQL*Plus-Sitzungen (unter Windows) an das System angemeldet; davon gibt es eine Sitzung im Dedicated-Server-Modus (SERVER ist DEDICATED); die anderen drei sind im Shared-Server-Modus. Die Anzeige unter SERVER wechselt zwischen NONE und SHARED, je nachdem, ob gerade ein Shared Server zugeordnet ist (also ein Aufruf über OCI ausgeführt wird) oder nicht. In diesem Beispiel hat die SQL*Plus-Sitzung in der ersten Zeile die Abfrage ausgeführt, daher ist auch ein Shared Server zugeordnet.
Oracle Net
311
Die Zuordnung der Shared Server zu Sitzungen kann in der View v$circuit nachvollzogen werden: SELECT saddr, dispatcher, server, queue FROM v$circuit WHERE queue = 'SERVER';
Hier die Ausgabe: SADDR DISPATCH SERVER QUEUE -------- -------- -------- ---------------5D38F964 5D306048 5D306558 SERVER
Die Adresse der Sitzung SADDR stimmt mit der obigen Ausgabe überein. Der Dispatcher lässt sich aus der nächsten Ausgabe herauslesen: SELECT name, paddr, network FROM v$dispatcher; NAME ---D000 D001
PADDR -------5D305B38 5D306048
NETWORK -------------------------------------------------(ADDRESS=(PROTOCOL=TCP)(HOST=rhlinux)(PORT=1522)) (ADDRESS=(PROTOCOL=TCP)(HOST=rhlinux)(PORT=1523))
Es handelt sich also um den Dispatcher D001 auf Port 1523. In ähnlicher Art und Weise lässt sich der Shared Server aus der View v$shared_server identifizieren. Weiter unten im Abschnitt über den Connection Manager werden weitere Konfigurationsvarianten für Shared Server beschrieben. Auswahl zwischen Dedicated und Shared Server Bei Shared-Server-Verbindungen sind für den Verbindungstyp kurze Befehle mit kleinen Ergebnismengen optimal. Lange und lang laufende Befehle sowie die Übertragung großer Ergebnismengen sind eher ungeeignet. Für DBA-Aufgaben wie Instanzstart und -stopp können Shared Server überhaupt nicht eingesetzt werden: SQL> SHUTDOWN ORA-00106: cannot startup/shutdown database when connected to a dispatcher
Da die Verwendung von Shared Servern immer dann stattfindet, wenn es möglich ist, empfiehlt es sich beim Einsatz von Shared Servern, zusätzliche Oracle NetAliasnamen zu konfigurieren, die explizit Dedicated Server anfordern: RH10D.HL.DE = (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = rhlinux)(PORT = 1521)) ) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = RH10.hl.de) ) )
312
Zugriff auf die Datenbank
Ein solcher Eintrag kann dann sowohl für DBAs als auch für Batches, Reports usw. genutzt werden. Falls ein Client grundsätzlich Dedicated-Server-Verbindungen erhalten soll, unabhängig von der Parametrierung der einzelnen Aliasnamen, kann in der Datei sqlnet.ora der Parameter USE_DEDICATED_SERVER = ON
gesetzt werden. Dedicated oder Shared Server? Die Diskussion, ob Dedicated oder Shared Server eingesetzt werden sollen, wird recht häufig geführt. Die Erfahrung (insbesondere mit früheren Oracle-Versionen) zeigt grundsätzlich, dass man so lange Dedicated Server betreiben sollte, wie sich damit keine Probleme zeigen. Häufig zeigt sich, dass moderne Rechner mit großen Prozesszahlen keine besonderen Schwierigkeiten haben. Auch das Starten und Beenden von Prozessen ist nicht mehr so aufwändig für das System. Dies spricht grundsätzlich für den Einsatz von Dedicated Servern. Ein weiterer Grund spricht dafür, ein funktionierendes Dedicated-Server-System nicht umzukonfigurieren: Wenn die Ressourcen für den Betrieb von Dedicated Server ausreichend sind, so ist dieser immer schneller als der Betrieb von Shared Servern, da die Datenübertragung mit Hilfe von Queues sowie die Prozesswechsel von Dispatcher zu Shared Server und zurück eingespart werden. Sind doch Gründe für die Einführung von Shared Servern vorhanden (also extrem große Zahl von Prozessen und/oder sehr häufiges Starten und Beenden von Sitzungen), so muss unbedingt die Auslastung der Shared Server und Dispatcher beobachtet werden, da die Queue-Mechanismen schnell zum Engpass werden können. Ein Grund für die Einführung einer Shared-Server-Konfiguration ist oft eine Firewall zwischen den Clients und dem Server: Man ist mit Hilfe der Dispatcher-Konfiguration in der Lage, die TCP/IP-Port für die Client-Server-Kommunikation exakt zu bestimmen, was bei einer Dedicated-Server-Konfiguration nicht gegeben ist. Weiterhin ist zu empfehlen, Anwendung für Anwendung zu entscheiden, ob sie Shared-Server-tauglich ist, da ein Mischbetrieb, wie weiter oben beschrieben, möglich ist.
7.1.3
Spezielle Parameter
In diesem Abschnitt werden einige Oracle Net-Parameter besprochen, die in Spezialfällen benötigt werden. Einige sind besonders für Hochverfügbarkeitsumgebungen mit RAC und/oder Data Guard sinnvoll (dies sind Client-Loadbalancing, Connect-Time Failover und Transparent Application Failover), die Einstellung der SDUGröße ist eher im Bereich Performance-Tuning einzuordnen, Dead Connection Detection zielt schließlich in den Bereich Troubleshooting.
Oracle Net
313
Client-Loadbalancing und Connect-Time Failover Hier geht es um zwei Oracle Net Client-Parameter, die beim Verbindungsaufbau wirken und zum einen für die etwa gleichmäßige Verteilung der Clients auf verschiedene Knoten sorgen und zum Anderen den Ausfall eines Knotens sofort durch den automatischen Kontakt des nächsten Knotens kompensieren. Die beiden Parameter werden gemeinsam besprochen, weil sie an der gleichen Stelle auf der ClientSeite (in der Datei tnsnames.ora) konfiguriert werden. Bei beiden Parametern werden Verbindungen an verschiedene Listener-Endpunkte aufgebaut, bei denen der Instanzname meist unterschiedlich ist. Daher ist es wichtig, dass zur logischen Adressierung in der CONNECT_DATA-Sektion der Net-Aliasnamendefinition nicht die vor Oracle8i übliche SID-Syntax, sondern die SERVICE_NAMEVariante verwendet wird. Weiterhin sollte man dafür sorgen, dass der angegebene Servicename in allen zum Verbindungsaufbau vorgesehenen Instanzen aktiviert wird; entweder durch Setzen des Systemparameters service_names oder durch entsprechende Aufrufe des Pakets dbms_service. Client-Loadbalancing wird durch den Parameter (LOAD_BALANCE = on) in der ADDRESS_LIST-Sektion einer Net-Aliasnamendefinition eingeschaltet und bewirkt, dass für den Verbindungsaufbau einer der ADDRESS-Einträge zufällig ausgewählt und benutzt wird. Damit erreicht man praktisch eine Gleichverteilung der Verbindungen z.B. auf alle Knoten eines RAC-Systems. Ein weiterer Parameter für die ADDRESS_LIST-Sektion der Net-Aliasnamendefinition ist (FAILOVER = on) und schaltet den Connect Time Failover an. Hierdurch wird einfach eine weitere Adresse aus der Liste genommen und für den Verbindungsaufbau verwendet, falls der Verbindungsaufbau mit der zuvor gewählten Adresse nicht funktioniert. Wenn Client-Loadbalancing angeschaltet ist, wird auch die nächste Adresse zufällig aus den übrig gebliebenen ausgewählt, wenn es ausgeschaltet ist, werden die Adressen der angegebenen Reihenfolge nach genutzt. Somit kann über den Connect-Time Failover die Nicht-Verfügbarkeit eines Knotens transparent behandelt werden, so dass beim Client (außer der vielleicht etwas längeren Zeit für den Verbindungsaufbau) keinerlei Unterschied zu bemerken ist. In Verbindung mit Client Load Balancing sind sowohl Umgebungen mit gleichberechtigten Servern, z.B. mit RAC, als auch Failover-Systeme, auch auf Basis von Data Guard oder Replikationsmechanismen, abbildbar. Abschließend ein Beispiel für eine Net-Aliasnamendefinition mit beiden Optionen: MYFAILOVER.HL.DE = (DESCRIPTION = (ADDRESS_LIST = (FAILOVER = on) (LOAD_BALANCE = on) (ADDRESS = (PROTOCOL = TCP)(HOST = rac1)(PORT = 1521)) (ADDRESS = (PROTOCOL = TCP)(HOST = rac2)(PORT = 1521)) ) (CONNECT_DATA = (SERVICE_NAME = MYFAILOVER.hl.de) ) )
314
Zugriff auf die Datenbank
TAF (Transparent Application Failover) Während die oben beschriebenen Optionen lediglich beim Verbindungsaufbau wirken, ist TAF eine Oracle Net-Funktion, die dafür sorgt, dass bereits aufgebaute Verbindungen auf einer anderen Instanz fortgesetzt werden, falls die bestehende Verbindung abbricht, z.B. aufgrund eines Knotenausfalls. Es sei der Hinweis gestattet, dass TAF keine RAC-Funktion ist, obwohl sie im RACUmfeld am meisten Sinn macht. Sie ist aber auch mit Data Guard oder Replikationslösungen von Drittanbietern anwendbar. Selbst komplett unabhängige Instanzen, die einen Verbindungsaufbau mit identischen Benutzerinformationen (inklusive Passwort) erlauben, können mit TAF konfiguriert werden. Hierbei gehen grundsätzlich Informationen verloren: begonnene Transaktionen sind nach einem TAF zurückgerollt und PL/SQL-Statusinformationen (z.B. Variableninhalte in Paketen) sind nicht mehr vorhanden. Allerdings kann die Anwendung ohne neue Verbindung weiterarbeiten; für SELECTs kann optional sogar die Fortsetzung der Fetch-Phase an exakt der gleichen Stelle gewährleistet werden. Wurde eine Transaktion vor der Übernahme der Sitzung angefangen, so reagiert die Anwendung auf weitere DML-Befehle mit Fehlermeldungen, bis ein ROLLBACK ausgeführt worden ist und die Anwendung somit wieder synchron zum Datenbankstatus ist. Die Konfiguration von TAF zeigt folgendes Beispiel: TAF.HL.DE = (DESCRIPTION = (ADDRESS_LIST = (FAILOVER = on) (LOAD_BALANCE = on) (ADDRESS = (PROTOCOL = TCP)(HOST = rac1)(PORT = 1521)) (ADDRESS = (PROTOCOL = TCP)(HOST = rac2)(PORT = 1521)) (ADDRESS = (PROTOCOL = TCP)(HOST = rac3)(PORT = 1521)) ) (CONNECT_DATA = (SERVICE_NAME = TAF.hl.de) (FAILOVER_MODE = (TYPE = SESSION) (METHOD = BASIC) ) ) )
Es ähnelt zunächst dem Beispiel für Client-Loadbalancing und Connect-Time Failover; im CONNECT_DATA-Bereich ist zusätzlich die Option FAILOVER_MODE konfiguriert. Hierbei sind die Optionen TYPE und METHOD angegeben. Der Wert SESSION für TYPE bedeutet, dass die Sitzung im Fehlerfall rudimentär übernommen wird. Alternativ kann SELECT angegeben, so dass Fetches fortgesetzt werden können. Hierbei entsteht auch im Normalbetrieb ein gewisser Overhead. Der Wert NONE entspricht dem Ausschalten von TAF. Bei METHOD kann BASIC (Übernahme der Sitzung im Fehlerfall) oder PRECONNECT (Aufbau der zweiten Verbindung im Voraus) verwendet werden. Im letzten Fall geht das Umschalten schneller; allerdings werden im Nicht-
Oracle Net
315
Fehlerfall erhebliche Ressourcen allokiert. Weitere Optionen sind BACKUP für die Spezifikation eines anderen Net-Aliasnamens für die zweite Verbindung, RETRIES für die Anzahl der Verbindungsversuche im Fehlerfall sowie DELAY für die Wartezeit in Sekunden zwischen den Versuchen. Abschließend sei die Bemerkung gestattet, dass der Einsatz von TAF wohl überlegt sein sollte. Eine Anwendung muss hierfür in den meisten Fällen neu strukturiert werden. Eine Alternative ist die einfache Reaktion mit dem Schließen und Neuaufbau einer Verbindung oder auch mit dem Schließen der Anwendung auf Verbindungsfehler wie: ORA-03113: end of file on communication channel
SDU-Größe Ein weiteres Beispiel ist die Spezifikation der SDU-Größe (Session Data Unit). Der Standardwert hierfür ist 2 KB (2048). Insbesondere bei Client-Server-Konfigurationen mit großen Datensätzen bzw. Transfer von großen Datenmengen kann es sinnvoll sein, die SDU-Größe zu verändern. Sie sollte auf ein Vielfaches der MSS (Maximum Segment Size) gesetzt werden. Die MSS für TCP/IP Version 4 auf Ethernet beträgt 1460. Falls auf Oracle Net-Ebene keine Verschlüsselung gewählt wird, d.h. in den meisten Fällen, sollte noch eins dazuaddiert werden, also z.B.: RH10.HL.DE = (DESCRIPTION = (SDU = 5841) (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP) (HOST = rhlinux) (PORT = 1521) ) ) (CONNECT_DATA = (SERVICE_NAME = RH10.hl.de) ) )
Die SDU-Größe muss sowohl auf der Client- als auch auf der Serverseite gesetzt werden. Für Dedicated-Server-Verbindungen kann die SDU-Größe lediglich für den Fall gesetzt werden, dass die Instanz manuell beim Listener registriert wird: SID_LIST_LISTENER = (SID_LIST = (SID_DESC = (SDU = 5841) (GLOBAL_DBNAME = RH10.hl.de) (ORACLE_HOME = /orabase/product/O1010) (SID_NAME = RH10) ) )
Für Shared Server wird der SDU-Parameter im Initialisierungsparameter DISPATCHERS gesetzt.
316
Zugriff auf die Datenbank
Dead Connection Detection Ein oft wiederkehrendes Problem im Client-Server-Umfeld ist der »abgestürzte« Client (oder auch: im Betrieb ausgeschalteter PC). Problematisch ist hier, dass der Server zunächst nichts von dieser Situation bemerkt – für ihn unterscheidet sich die Situation nicht von einer weiterhin verbundenen Sitzung, die momentan keine Aufrufe absetzt. Normalerweise ist hierfür das Protokoll selbst verantwortlich. Hierzu ist zu bemerken, dass TCP/IP eine entsprechende Funktion hat: das so genannte keepalive. Allerdings ist der Timeout für keepalive bei vielen Systemen so hoch gesetzt, dass die Anwendung keinen Sinn macht; bei vielen MS-Windows-Versionen ist keepalive sogar deaktiviert. An dieser Stelle übernimmt die Oracle Net-Funktion Dead Connection Detection: Diese ist serverbasiert und sendet im festgelegten Abstand ein Testpaket zum Client, wenn dieser inaktiv ist. Antwortet der Client nicht, so wird die Sitzung beendet und die entsprechenden Ressourcen freigegeben. Dead Connection Detection wird auf der Serverseite mit dem Parameter SQLNET.EXPIRE_TIME aktiviert; der Wert bestimmt den Timeout in Minuten. Die Einstellung SQLNET.EXPIRE_TIME = 10
würde demnach alle zehn Minuten eine Kommunikation mit dem Client auslösen. Hierzu eine Bemerkung: Obwohl die Dead Connection Detection als Funktion seit SQL*Net Version 2.1 vorhanden ist, scheint sie momentan nicht richtig zu funktionieren. Mit diversen MS-Windows- und Linux-Testinstanzen konnte die Funktion nicht nachgewiesen werden. Hinzu kommt, dass die Dokumentation hierzu verwirrend ist: Es gibt Stellen, die behaupten, dass SQLNET.EXPIRE_TIME in Sekunden angegeben wird, andere sprechen von Minuten. Auch ist man sich nicht einig darüber, ob der Parameter beim Client oder beim Server gesetzt werden muss. Grundsätzlich kann man nur empfehlen, ihn auf beiden Seiten zu setzen. Als Lektüre zu dieser Problematik empfiehlt sich der Metalink-Artikel 151972.1 mit dem Titel »Dead Connection Detection (DCD) Explained«.
7.1.4 Instant Client Mit dem Instant Client existiert erstmalig eine von Oracle offiziell unterstützte Lösung, eine Clientinstallation ohne den Universal Installer durchzuführen. Der Client ist für diverse Plattformen verfügbar und besteht lediglich aus einigen Bibliotheken. Diese werden in ein beliebiges Verzeichnis kopiert und über die %PATH%-Variable (unter MS-Windows) bzw. $LD_LIBRARY_PATH-Variable (unter UNIX) erreichbar gemacht. Damit sind OCI-, OCCI- sowie JDBC-OCI-Anwendungen ausführbar. Zusätzlich zu einem Basispaket sind diverse Zusatzpakete für weitere Anwendungstypen erhältlich (z.B. unter MS-Windows JDBC, ODBC sowie SQL*Plus inklusive ausführbarem Programm).
Alternative Methoden zur Namensauflösung
317
Der Instant Client kann als ZIP-Archiv von der Oracle-Website heruntergeladen werden (Größe ca. 30 MB). Nach dem Auspacken in ein Verzeichnis (z.B. C:\oracle\InstantClient) sollte ein kleines Skript geschrieben werden, das Umgebungsvariablen für den Client setzt und ggf. (auf UNIX) exportiert. Das Beispiel für MS-Windows kann folgendermaßen aussehen: SET SET SET SET SET
PATH=C:\oracle\InstantClient;%PATH% TNS_ADMIN=C:\oracle\InstantClient LD_LIBRARY_PATH=C:\oracle\InstantClient SQLPATH=C:\oracle\InstantClient NLS_LANG=<entsprechend Client-NLS-Umgebung>
In das durch TNS_ADMIN angegebene Verzeichnis sollten auch die zu benutzende tnsnames.ora sowie sqlnet.ora gelegt werden.
7.2
Alternative Methoden zur Namensauflösung
Im bisherigen Kapitel haben wir implizit die meistgenutzte Methode zur Auflösung von Oracle Net-Aliasnamen genutzt: die tnsnames.ora-Datei. Oracle Net wäre jedoch kein richtiges Oracle-Produkt, gäbe es nicht noch einige zusätzliche Möglichkeiten zur Namensauflösung. Dabei gibt es Ergänzungen sowohl am oberen Ende der Skala für zentrale Organisation, in diesem Fall die Speicherung von Oracle Net-Konfigurationsdaten in einem LDAP-Server wie dem Oracle Internet Directory OID, als auch am unteren Ende: Hostnaming und Easy Connect. Für Kenner von früheren Oracle-Versionen: Das LDAP-Verzeichnis hat Oracle Names nun endgültig ersetzt. In Oracle 10g gibt es keinerlei Support für Oracle Names mehr, auch nicht für die Oracle Names Proxies, die Clients unter Verwendung von Oracle Names-Mechanismen mit Informationen aus einem LDAP-Verzeichnis versorgt haben.
7.2.1 Hostnaming und Easy Connect Mit der «einfachen Verbindung« Easy Connect begibt sich Oracle Net nach langer Zeit wieder in früher bekannte Gefilde, bei denen es möglich ist, ohne eine gespeicherte Konfiguration eine Verbindung aufzubauen.6 Dass dies funktioniert, hat auch die Verwendung des Thin JDBC-Treibers gezeigt: Auch hier werden Verbindungen nicht konfiguriert, da das Konzept dieses Treibers voraussetzt, dass keinerlei Installation und Konfiguration auf dem entsprechenden Rechner stattgefunden hat. Die als Hostnaming bekannte Methode wurde bereits mit Oracle8i eingeführt und ist ein Spezialfall der Easy-Connect-Methode. Der Oracle Net-Bezeichner sieht wie folgt aus: [//][:<port>][/<service>]
6
Wer Versionen vor Oracle7 Release 7.3 kennt, erinnert sich vielleicht noch an SQL*Net Version 1 mit so genannten Connectstrings der Form T::<SID>.
318
Zugriff auf die Datenbank
Der einzige nicht-optionale Parameter ist – damit ist die HostnamingMethode elegant integriert. Falls <port> nicht angegeben wird, gilt der Standardwert 1521. Als Standardwert für <service> wird angenommen. Wer Angaben in Form einer URL mag, kann den Doppelslash voranstellen. Eine Verbindung kann somit wie folgt aufgebaut werden: sqlplus scott/tiger@localhost:1521/O10.test.hl.de
Die Easy-Connect-Methode kann verwendet werden, wenn entweder keine Datei sqlnet.ora in $TNS_ADMIN bzw. $ORACLE_HOME/network/admin existiert oder die verwendete Datei für den Parameter NAMES.DIRECTORY_PATH den Wert EZCONNECT enthält, wie z.B. in: NAMES.DIRECTORY_PATH = (TNSNAMES, EZCONNECT)
Bei der Verwendung einer sqlnet.ora-Datei kann das tnsping-Werkzeug zur Kontrolle eingesetzt werden: > tnsping localhost/O10.test.hl.de TNS Ping Utility for 32-bit Windows: Version 10.1.0.4.0 - Production on 13-APR-2005 21:40:44 Copyright (c) 1997, 2003, Oracle.
All rights reserved.
Used parameter files: D:\OraBase\Network\Admin\sqlnet.ora Used EZCONNECT adapter to resolve the alias Attempting to contact (DESCRIPTION=(CONNECT_DATA=(SERVICE_NAME=O10.test.hl.de)) (ADDRESS=(PROTOCOL=TCP)(HOST=127.0.0.1)(PORT=1521))) OK (20 msec)
Der Easy-Connect-Bezeichner wird für den Test in das Oracle Net-Format gebracht und der Listener entsprechend kontaktiert.
7.2.2 JDBC Thin Driver Der JDBC Thin Driver stellt eine Ausnahme dar, da keine Oracle Client-Installation existiert – noch nicht einmal ein Instant Client. Im JDBC Thin Driver wird daher die Client-Funktionalität innerhalb von Java emuliert. Da die bekannten Mechanismen und Dateien nicht zur Verfügung stehen, müssen die Verbindungsdetails dem JDBC Thin Driver auf eine andere Art und Weise übermittelt werden. Das passiert im Programm in etwa wie folgt: OracleDataSource ods = new OracleDataSource(); String URL = "jdbc:oracle:thin:@//myhost:1521/orcl", ods.setURL(URL); ods.setUser("scott"); ods.setPassword("tiger"); Connection conn = ods.getConnection();
Alternative Methoden zur Namensauflösung
319
Es ist auch möglich, einen Net-Aliasnamen in einer tnsnames.ora-Datei aufzulösen. Allerdings ist es eher üblich, die oben angegebene Methode zu verwenden, da der JDBC Thin Driver in den allermeisten Fällen eben nicht vom Vorhandensein einer tnsnames.ora-Datei ausgehen kann.
7.2.3 LDAP-Verzeichnisse Die Auflösung von Net-Aliasnamen durch LDAP-Abfragen (LDAP-Benennung) bietet sich in größeren Umgebungen an. Hierzu ist es erforderlich, einen Oracle Internet Application Server zu betreiben. Das Internet Directory ist Bestandteil der Identity-Management-Komponente des Oracle Internet Application Servers. Da es sich hierbei um ein separates Produkt handelt, das nicht im Rahmen der Oracle Database 10g zur Verfügung gestellt wird, wird die Installation und Konfiguration des Internet Directorys an dieser Stelle nicht im Detail behandelt. Um einen Client für die Verwendung der LDAP-Benennung zu konfigurieren, muss diese Methode zunächst mit dem Net-Konfigurationsassistenten eingerichtet werden. Hierfür wählt man auf dem ersten Bildschirm den Punkt Konfiguration von Directory-Verwendung aus.
Abbildung 7.29: Grundkonfiguration LDAP-Benennung
320
Zugriff auf die Datenbank
Auf der nächsten Seite kann ausgewählt werden, welcher Typ von Verzeichnisdienst zur Verfügung steht. Neben dem Oracle Internet Directory steht auch die Möglichkeit, ein MS-Active Directory anzusprechen, zur Verfügung. Wir gehen hier von einem Oracle Internet Directory aus.
Abbildung 7.30: Auswahl des Verzeichnistyps
Weiterhin muss angegeben werden, auf welchem Rechner das Verzeichnis installiert ist und welche Ports verwendet werden. In einem weiteren Fenster kann dann ein DN (Distinguished Name) angegeben werden, der bestimmt, an welcher Stelle im Verzeichnis der Oracle Context abgelegt ist. Dieser enthält die Directory-Einträge zur Namensauflösung. Die Konfigurationsergebnisse werden in einer ldap.ora-Datei abgelegt. Diese befindet sich, wie die anderen Net-Konfigurationsdateien, im Verzeichnis $ORACLE_HOME/ network/admin bzw. $TNS_ADMIN. Der Inhalt einer solchen Datei sieht etwa wie folgt aus: # ldap.ora Network Configuration File: /orabase/network/admin/ldap.ora # Generated by Oracle configuration tools. DIRECTORY_SERVERS= (ldapsrv:389:636) DIRECTORY_SERVER_TYPE = OID DEFAULT_ADMIN_CONTEXT="o=Oracle,c=US" Listing 7.6: Datei ldap.ora
Alternative Methoden zur Namensauflösung
321
Abbildung 7.31: Host und Ports des Verzeichnisses
Sobald eine erste Einrichtung mit dem Net-Konfigurationsassistenten erfolgt ist, können weitere Konfigurationsschritte mit dem Net Manager durchgeführt werden. Im Bereich Profil kann z.B. die Methode LDAP hinzugefügt werden; die Rangordnung der Benennungsmethoden kann durch die Schaltflächen Vorziehen und Zurückstufen beeinflusst werden. Weiterhin enthält der Navigationsbaum des Net Managers nunmehr den Teilbaum Verzeichnis, mit dem Net-Aliasnamen im Verzeichnis gepflegt werden können. Durch die Nennung von LDAP an erster Stelle wird in der Datei sqlnet.ora der Parameter NAMES.DIRECTORY_PATH wie folgt verändert: NAMES.DIRECTORY_PATH= (LDAP, TNSNAMES, EZCONNECT)
Dies bedeutet, dass für die Auflösung eines Net-Aliasnamens zunächst ein Verzeichnisdienst, dann eine tnsnames.ora-Datei und zuletzt die Easy-Connect-Methode verwendet wird.
7.2.4 Welche Methode ist die beste? Den schnellsten Erfolg liefert sicherlich die Easy-Connect-Methode – zumindest dann, wenn man gerade eben den Listener konfiguriert hat und somit alle Kontaktdaten auswendig kennt. Falls eine Anwendung betrieben werden soll, ist es in den allermeisten Fällen angebracht, mit der Auflösung von logischen Namen (Net-Aliasnamen) zu arbeiten. Das hat den Vorteil, dass z.B. bei der Verlagerung einer Instanz von einem Server auf den anderen keine Programme geändert werden müssen, sondern eben nur die Konfiguration.
322
Zugriff auf die Datenbank
Abbildung 7.32: LDAP-Benennungsmethode
Für viele Umgebungen sind tnsnames.ora-Dateien praktikabel, insbesondere wenn nicht allzu häufig Serverdaten geändert werden oder neue Datenbanken hinzukommen. Ab einer gewissen Zahl von Clients ist es allerdings ratsam, sich über die automatisierte Verteilung der Dateien Gedanken zu machen – kein DBA kopiert gerne manuell immer wieder die gleiche Datei an Dutzende Clients. Von der Methode, die Net-Konfigurationsdateien auf einem zentralen Laufwerk abzulegen und über die Variable $TNS_ADMIN zu adressieren, wird, zumindest bei großen tnsnames.ora-Dateien, also ab einigen Dutzend Einträgen, abgeraten. Bei der Namensauflösung greift der Oracle Net Client zeilenweise auf die Datei zu, so dass die Geschwindigkeit für die Namensauflösung im Netzwerk stark beeinflusst wird. Für die Verwendung von LDAP als Auflösung von Net-Aliasnamen ist zunächst eine Lizenz für den Oracle Internet Application Server erforderlich. Es fällt schwer, die Anschaffung eines weiteren, nicht gerade billigen, Produkts zu empfehlen, nur weil Konfigurationsdaten für den Verbindungsaufbau dort verwaltet und aufgelöst werden. Allerdings macht die Verwendung eines Verzeichnisdienstes in größeren Umgebungen Sinn, insbesondere wenn aus anderen Gründen bereits ein Internet Application Server (oder ein MS Active Directory) im Einsatz ist.
Connection Manager
7.3
323
Connection Manager
Der Connection Manager ist eine Art Proxyserver innerhalb der Oracle Net-Umgebung. Mit Hilfe des Connection Managers können Verbindungen über bestimmte Rechner geroutet und dabei die verwendeten Ports definiert werden. Es ist weiterhin möglich, eine Zugriffskontrolle durchzuführen. Schließlich ist im Zusammenhang mit speziellen Dispatcher-Konfigurationen das Session Multiplexing möglich, bei dem mehrere logische Verbindungen über eine einzige tatsächliche Netzwerkverbindung geführt werden. Dies kann im WAN-Umfeld sowohl Performance- als auch Kostenvorteile bringen. Es gibt zwei Einschränkungen für den Connection Manager: 1. Diese Komponente ist der Enterprise Edition der Oracle Database vorbehalten. 2. Die Konfiguration des Connection Managers wird durch keinerlei Werkzeuge unterstützt. Zur Konfiguration eines Connection Managers muss demnach grundsätzlich eine Datei manuell gepflegt werden. Diese heißt cman.ora und ist im Verzeichnis $ORACLE_HOME/network/admin oder $TNS_ADMIN untergebracht. Ein Beispiel für eine Konfiguration folgt: CMWIN= (CONFIGURATION= (ADDRESS=(PROTOCOL=TCP)(HOST=192.168.149.111)(PORT=1525)) (RULE_LIST= (RULE=(SRC=192.168.149.0/24)(DST=*)(SRV=*)(ACT=accept)) (RULE=(SRC=hllap11)(DST=127.0.0.1) (SRV=cmon)(ACT=accept)) ) (PARAMETER_LIST= (LOG_DIRECTORY=D:\OraBase\Network\Log) (LOG_LEVEL=USER) (TRACE_DIRECTORY=D:\OraBase\Network\Log) (TRACE_LEVEL=off) (CONNECTION_STATISTICS=yes) (MAX_CONNECTIONS=20) (MIN_GATEWAY_PROCESSES=5) (MAX_GATEWAY_PROCESSES=20) ) )
Hiermit wird ein Connection Manager namens CMWIN konfiguriert. Im ADDRESSBereich wird die Listener-Adresse des Connection Managers eingestellt; hier mit Port 1525, da 1521 durch den Listener selbst belegt ist. In der RULE_LIST werden ein oder mehrere RULEs (Regeln) angegeben, die beschreiben, wie der Connection Manager funktionieren soll. Es müssen immer mindestens zwei Regel angegeben werden, weil: die Standardeinstellung für Situationen, die nicht über eine Regel beschrieben sind, ist, dass die Verbindung blockiert wird und dass eine zweite Regel für den Monitorprozess (SRV=cmon) vorhanden sein muss.
324
Zugriff auf die Datenbank
In der Parameterliste PARAMETER_LIST können dann noch zusätzliche Parameter für den Connection Manager für das allgemeine Verhalten, z.B. Logging oder Tracing, angegeben werden. Die Kommunikation mit dem Datenbankserver wird durch die Gateway-Prozesse durchgeführt. Man kann mit MIN_GATEWAY_PROCESSES und MAX_GATEWAY_PROCESSES deren minimale und maximale Anzahl bestimmen, wobei das Maximum jeweils 64 ist. MAX_CONNECTIONS bestimmt, wie viele logische Verbindungen bzw. Sitzungen ein Gateway-Prozess verwalten kann; hier liegt das Maximum bei 1024. In Summe können also bis zu 65536 Verbindungen über einen Connection Manager laufen. Zur Administration des Connection Managers wird cmtl benutzt. Ähnlich lsnrctl kann man das kommandozeilenbasierte Werkzeug aufrufen und interaktiv nutzen; alternativ gibt es einen Kommandozeilenmodus. Aus der Kommandozeile ruft man z.B. zum Starten des Connection Managers CMWIN auf: cmctl startup -c cmwin
Mit dem Kommando HELP bekommt man eine Liste der vorhandenen Kommandos. Wichtig für die weitere Administration sind folgende Kommandos: cmctl reload -c für die Aktualisierung der Konfiguration aus der Datei cman.ora cmctl show status -c cmctl show services -c Clients können mit Hilfe der Adressliste explizit konfiguriert werden, indem man sowohl die Adresse des Connection Managers als auch die des Listeners angibt. Dann muss in der Adressliste zusätzlich der Parameter (SOURCE_ROUTE = YES) angegeben werden. RH4CM.HL.DE = (DESCRIPTION = (ADDRESS_LIST = (SOURCE_ROUTE = YES) (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.149.111) (PORT = 1526)) (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.149.211) (PORT = 1521)) ) (CONNECT_DATA = (SERVICE_NAME = RH4.hl.de) ) )
Eine weitere Möglichkeit besteht darin, der Instanz über die Konfiguration des Systemparameters remote_listener den Connection Manager anzugeben. In diesem Fall bekommt der Connection Manager von der Instanz selbst die Konfigurationsdaten des lokalen Listeners sowie der verfügbaren Dienste (Service Registration, wie beim Listener), so dass für den Client lediglich die Adresse des Connection Managers konfiguriert werden muss.
Connection Manager
325
RH4CM.HL.DE = (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.149.111) (PORT = 1526)) ) (CONNECT_DATA = (SERVICE_NAME = RH4.hl.de) ) )
Session Multiplexing Diese Option wird für Dispatcher an der Instanz konfiguriert, betrifft jedoch sowohl den Dispatcher als auch den Connection Manager. Session Multiplexing bewirkt, dass alle Verbindungen zwischen dem Connection Manager und dem Dispatcher über eine einzige logische Netzwerkverbindung laufen. Im Normalfall bekommt jede Oracle Net-Verbindung auch eine eigene Netzwerkverbindung. Die Konfiguration erfolgt dadurch, dass bei der Dispatcher-Konfiguration die zusätzliche Option (MULTIPLEX=<x>) angegeben wird, wobei <x> für einen der folgenden Werte steht: 1, ON, YES, TRUE oder BOTH bedeuten, dass Session Multiplexing sowohl für eingehende als auch für ausgehende Verbindungen verwendet wird, IN für eingehende Verbindungen, OUT für ausgehende Verbindungen sowie 0, OFF, NO oder FALSE für abgeschaltet. Die Funktionsweise ist auf dem Rechner, wo der Connection Manager läuft, z.B. unter MS-Windows mit dem Kommando netstat -a
aus einer DOS-Box leicht nachzuvollziehen. Dort bekommt man für jede Netzwerkverbindung eine Zeile, die wie folgt aussieht: TCP
hllap11:1743
192.168.45.119:1527
HERGESTELLT
Hierbei läuft der Connection Manager auf dem Rechner hllap11 und hat eine Verbindung, ausgehend von Port 1743, zum Rechner 192.168.45.199 auf Port 1527. Für dieses Beispiel wurde auf der letzten Adresse ein Dispatcher konfiguriert. Ist Session Multiplexing ausgeschaltet, so bekommt man je eine solche Zeile (mit verschiedenen Ausgangsports und der identischen Zieladresse inklusive Port) pro Verbindung. Mit Session Multiplexing ist eine Zeile pro Connection-Manager-GatewayProzess vorhanden (normalerweise zwei). Auch bei vielen Verbindungen (z.B. zehn SQL*Plus-Aufrufe) erhöht sich die Anzahl der Verbindungen nicht.
326
7.4
Zugriff auf die Datenbank
Firewall
Das Zusammenspiel von Firewalls mit Oracle Net ist in den Fällen problematisch, in denen die Firewall selber ausschließlich über die Freischaltung von Ports konfiguriert werden kann. Da für die meisten Client-Server-Verbindungen der Port 1521 lediglich für den Verbindungsaufbau genutzt wird, die Kommunikation im Weiteren über einen beliebigen Port durchgeführt wird, bleibt diese Konfiguration oft in der Firewall hängen. Hierfür gibt es vier brauchbare Lösungsansätze: 1. Oracle-taugliche Firewall Es gibt Firewalls, die den Oracle-Mechanismus »verstehen« und dynamisch weitere Ports – ausschließlich für bestehende Verbindungen – freischalten. Dies ist sicherlich die eleganteste Methode, da alle möglichen Oracle-Konfigurationen hiermit funktionieren. 2. Dispatcher mit fest zugewiesenen Ports Für den Fall einer Shared-Server-Konfiguration können dem oder den Dispatcher(n) feste Ports zugewiesen werden. Somit muss man diese Ports zusätzlich zum Listener-Port freischalten. Diese Methode hilft natürlich nur im Falle einer Shared-Server-Konfiguration weiter. Sie hat des Weiteren zur Folge, dass jeder nicht mehr benutzte oder neu konfigurierte Dispatcher in der Firewall nachkonfiguriert werden muss – immer die Strategie vor Augen, keine Firewall-Löcher auf Reserve zu konfigurieren. 3. Connection Manager Der im vorangegangenen Abschnitt beschriebene Connection Manager hat wie ein Dispatcher feste, vorkonfigurierte Kommunikationsports. Diese können ebenfalls freigeschaltet und dann zur Dedicated-Server-Kommunikation genutzt werden. Als Nachteil könnte sich herausstellen, dass die gesamte Kommunikation über einen Port läuft und dass mit dem Connection Manager eine weitere Komponente im Einsatz ist, die administriert und beobachtet werden muss. 4. Listener-Port teilen für MS-Windows-Systeme In der Registrierung kann unter dem Schlüssel \\HKEY_LOCAL_MACHINE\SOFTWARE \ORACLE\KEY_ eine Zeichenkette USE_SHARED_SOCKET eingerichtet werden, deren Wert auf TRUE gesetzt wird. Damit kann der Port des Listeners mit den Verbindungen geteilt werden, d.h., falls der Listener auf 1521 horcht, laufen alle Verbindungen ebenfalls über 1521. Nach der Einrichtung sollten sowohl Listener als auch Instanz neu gestartet werden. Für das Monitoring aller vier Lösungsansätze sind sowohl Oracle Net-Client-Tracing als auch das netstat-Kommando sehr hilfreich. Client-Tracing kann in der Datei sqlnet.ora eingeschaltet werden mit folgenden Einträgen: TRACE_LEVEL_CLIENT = 16 TRACE_DIRECTORY_CLIENT = D:\OraBase\Network\Trace
Java in der Datenbank
327
Für den Parameter TRACE_LEVEL_CLIENT können laut Handbuch die Parameter USER, ADMIN oder SUPPORT gesetzt werden. Diese entsprechen jedoch auch Zahlenwerten; und ein noch höherer Zahlenwert als SUPPORT ist mit 16 der höchste Trace-Level. Als Zielverzeichnis muss natürlich ein auf dem konkreten System vorhandenes Verzeichnis angegeben werden. Die wichtigste Empfehlung bezüglich Tracing lautet jedoch: Bitte unbedingt wieder ausschalten, nachdem die gewünschten Ergebnisse nachvollzogen sind.
7.5
Java in der Datenbank
Die letzten Jahre wurden geprägt durch eine rapide Entwicklung im Umfeld der Programmiersprache Java und eine ebenso heftige Diskussion darüber, welche Bedeutung dieses neue Paradigma für die Erstellung von Datenbankanwendungen hat. Die Firma Oracle hatte sich schon früh Java auf ihre Fahnen geschrieben: Einerseits wurden die wichtigsten Oracle-Werkzeuge nach Java portiert, andererseits hielt Java ab der Version 8.1.5 auch Einzug in die Datenbank selbst. Die folgenden Abschnitte geben einen kurzen Überblick über die Möglichkeiten, die uns in der Version 10g in Sachen Java zur Verfügung stehen. Sie können das umfangreiche und komplexe Thema jedoch nur kurz anreißen. Auch zu diesem Thema bietet das Internet eine ganze Fülle aktueller Informationen, vor allem unter http://java.sun.com.
7.5.1 Java-Grundlagen Java ist eine objektorientierte Sprache. Softwareobjekte, die wir mit objektorientierten Sprachen wie Java modellieren, befinden sich alle in einem Zustand und zeigen bestimmte Verhaltensweisen. Zustände finden in Variablen ihren Niederschlag, Verhaltensweisen in Methoden. Aus dieser Sicht stellt ein Objekt ein Softwarebündel aus Variablen und damit zusammenhängenden Methoden dar. Ein Auto kann beispielsweise durch folgende Variablen beschrieben werden: wie hoch die aktuelle Geschwindigkeit ist – 120 km/h –, wie viele Liter der Tank enthält – 45 Liter –, welcher Gang im Augenblick eingelegt ist – der dritte Gang. Darüber hinaus benötigt das Auto Methoden, wie z.B. die Methode »Gangwechsel«, die sein Verhalten bestimmen. Schematische Darstellungen von Objekten zeigen die Variablen im »schützenden« Kern, umgeben von dem Ring aus Methoden, welche die Variablen »einkapseln«. Damit ein Objekt in einem größeren Ganzen, wie z.B. einem Programm, mit anderen Objekten interagieren kann, müssen Nachrichten ausgetauscht werden. Variablen und Methoden, die für Objekte einer bestimmten Art charakteristisch sind, werden in Klassen definiert. In diesem Sinne stellen Klassen Baupläne oder Prototypen von Objekten dar: Die Klasse Automobile beschreibt prototypisch verschiedene individuelle Autos, wobei jedes Fahrzeug eine Instanz der Klasse Automobile darstellt. Die Begriffe Objekt, Instanz und Klasse werden im täglichen Gebrauch jedoch oft inkonsistent gebraucht.
328
Zugriff auf die Datenbank
Abbildung 7.33: Schematische Darstellung eines Objekts
Klassen können entweder von Grund auf neu definiert werden oder auf bereits existierenden Klassen aufbauen, indem sie deren Variablen und Methoden erben (Vererbung) und diese ergänzen oder überschreiben. Auf diese Weise kann eine Klassenhierarchie entstehen. Klassen werden schließlich in Paketen zusammengefasst. Java bietet eine Reihe von vordefinierten Standardpaketen, wie z.B. java.lang, die eine Fülle von Methoden und Variablen für grundlegende Funktionalitäten zur Verfügung stellen. Java-Klassen werden in gleich lautenden Dateien mit der Erweiterung .java erstellt – die Klasse automobile beispielsweise wird in der Datei mit Namen automobile.java definiert. Der Übersetzer erstellt daraus eine Klassendatei automobile.class, die den plattformunabhängigen Java-Bytecode enthält. Dieser plattformunabhängige Bytecode ist es, der einen Großteil zur Verbreitung der Sprache Java beigetragen hat. Zum Ausführen des Bytecodes ist schließlich ein Java-Intepreter erforderlich, der das betreffende Java-Programm im Kontext der virtuellen Java-Maschine (Java Virtual Machine) (JVM) auf einem konkreten Betriebssystem interpretiert. Um die Interpretation des Bytecodes zu beschleunigen, wurden in den letzten Jahren Justin-Time-Konzepte entwickelt, die über den Java-Interpreter per Parameter aktiviert werden können und den Java-Bytecode während der Laufzeit in plattformspezifischen C-Code umwandeln. Die JVM bildet zusammen mit den Standardpaketen die Java-Plattform. Über die Standards JDBC und SQLJ besteht die Möglichkeit, aus Java-Programmen heraus direkt auf relationale Datenbanksysteme zuzugreifen.
Java in der Datenbank
329
7.5.2 Java-APIs in der Datenbank Java-Code kann für unterschiedliche Kontexte mit jeweils eigenen Paradigmen programmiert werden. Jedes mögliche »Programmiermodell« wird dabei über eine eigene Namensgebung identifiziert: Java-Applets, Enterprise Java Beans (EJB), Servlets, Java Server Pages (JSP), um nur einige der Modelle zu nennen. Diese Begriffsvielfalt spiegelt die Flexibilität der Sprache wider, trägt aber leider auch viel zur allgemeinen Verwirrung bei und wirkt in vielen Fällen eher abschreckend als motivierend. Um Java-Code nicht nur in der Datenbank zu speichern, sondern auch ausführen zu können, ist eine virtuelle Java-Maschine notwendig. Diese wurde bereits ab der Version 8.1.5 in der Oracle-Datenbank implementiert – damals JDK 1.1. Unter Oracle 10g wird derzeit der Standard Java 2 (JDK 1.2, 1.3 und 1.4) mit JDBC 2.0 sowie nahezu allen Funktionen von JDBC 3.0 unterstützt. JDK 1.1 wird dagegen nicht mehr unterstützt, ein Migrationspfad wird in der Dokumentation Oracle 10g JDBC Developer’s Guide and Reference beschrieben. Ein Merkmal der Oracle-JVM ist, dass sie in dem jeweiligen Session-Kontext des ausführenden Datenbankbenutzers läuft, wodurch sich einige Besonderheiten gegenüber Java-Programmen außerhalb der Datenbank ergeben: Der datenbankinterne Java-Code ist von Haus aus thread safe. Die automatisierte Speicherplatzverwaltung (Garbage Collector) arbeitet im Kontext nur eines Benutzers, statt sich um die Speicherverwaltung aller Benutzer kümmern zu müssen. Beim dynamischen Laden von Klassen (Dynamic Class Loading) werden die benötigten Java-Klassen zum Zeitpunkt der Anforderung in den Shared-MemoryBereich der SGA übertragen. Auf diese Weise stehen sie danach für alle weiteren Sessions zur Verfügung. Wie der vorangehende Abschnitt gezeigt hat, kann Java in unterschiedlichen Kontexten eingesetzt werden. Zum Zeitpunkt der Version 10g stehen die folgenden Kontexte oder APIs im Rahmen der Oracle-Datenbank zur Verfügung: Per JDBC können aus Applikationen oder Applets heraus SQL-Kommandos ausgeführt sowie PL/SQL-Code aufgerufen werden. Dabei wird von dem Client-Programm aus eine normale Oracle-Session aufgebaut, und über diese werden entsprechende SQL-Befehle ausgeführt. Java Stored Procedures und Functions können über PL/SQL-Code aufgerufen werden oder können ihrerseits PL/SQL-Code aufrufen. Die Nutzung dieser Prozeduren und Funktionen ist vollkommen transparent für den betreffenden Benutzer, d.h., er kann den Code innerhalb einer normalen Datenbanksitzung explizit aufrufen oder – im Falle einer Funktion – im Kontext von SQL-Befehlen benutzen. Die Speicherung von Java-Code in der Datenbank macht es grundsätzlich möglich, Anwendungen der traditionellen »Mittelschicht« in der Datenbankschicht zu installieren.
330
Zugriff auf die Datenbank
Fortgeschrittenere J2EE-Technologien wie Java Servlets (ehemals Oracle Servlet Engine, OSE), Java Server Pages (ehemals OJSP), CORBA oder EJB konnten bis zur Version 9.0.1 direkt in der Oracle-Datenbank eingerichtet werden. Mit den Datenbank-Versionen 9.2.0 sowie 10g wird dies jedoch nicht mehr unterstützt, hierfür wird stattdessen der Oracle Application Server (iAS) mit den Oracle Containers for Java (OC4J) benutzt. Da dieser nicht zur eigentlichen Datenbank gehört, wird im Folgenden nicht weiter auf die damit verbundenen Möglichkeiten eingegangen. Innerhalb der Datenbank werden ausschließlich J2SE-Technologien unterstützt, nämlich JDBC und Java-Prozeduren und Funktionen. SQLJ (Java mit eingebauten SQL-Statements, die von einem Präprozessor in JDBC-Aufrufe umgewandelt werden) wird mit der Version 10g dagegen nicht mehr unterstützt. Hier sollten stattdessen reine JDBC-Anwendungen benutzt werden.
7.5.3 Server-seitige Installation Die Installation der JVM-Option lässt sich am besten über den Database Configuration Assistant und durch Auswahl der entsprechenden Option bewerkstelligen. Der Assistent führt dann eine Reihe von SQL-Skripten aus den Verzeichnissen $ORACLE_HOME/javavm/install, $ORACLE_HOME/xdk/admin und $ORACLE_HOME/rdbms/admin aus; Log-Dateien mit gleichem Namen wie die SQL-Dateien werden im Zuge der Installation erstellt.
Abbildung 7.34: Installation der Oracle JVM durch den Konfigurationsassistenten
Java in der Datenbank
331
Abhängig von den genutzten Java-APIs sind auch spezifische Verbindungsprotokolle zur Datenbank im Kontext der Dateien listener.ora und tnsnames.ora zu konfigurieren. Die Einzelheiten dieser Konfigurationen wurden bereits in Kapitel 7.1.1 besprochen. Sowohl für JDBC als auch zum Aufruf von von Java Stored Procedures oder Functions genügt eine »normale« Oracle Net-Verbindung, beispielsweise über TCP/IP. Zusätzlich sind die folgenden Serverparameter zu konfigurieren oder zu überprüfen: shared_pool_size – der Shared-Pool-Bereich der SGA wird zum Laden von JavaKlassen und zum Ausführen von Java-Objekten benötigt, wobei jede Klasse etwa 8 KB Speicher benötigt. Für die Initialisierung der Datenbank mit über 10000 Core-Klassen sollten mindestens 80 MB, besser jedoch ca. 150 MB bereitgestellt werden. java_pool_size – spezifiziert den Speicherbereich für die Methoden- und Klassendefinitionen mit einem Minimum von 20 MB. java_soft_sessionspace_limit – definiert die »weiche« maximale Grenze des Java-Speicherplatzes pro Session. Beim Überschreiten dieser Grenze wird eine Warnung in eine Trace-Datei geschrieben. java_max_sessionspace_size – definiert eine »harte«, maximale Obergrenze für den Speicherplatz pro Java-Session. Der Standardwert von 4 GB ist extrem hoch gewählt worden und sollte reduziert werden. Beim Überschreiten dieser Grenze wird die Session abgebrochen. Ob die Oracle JVM überhaupt in der Datenbank installiert ist, kann am einfachsten durch folgende Abfrage festgestellt werden: SQL> SELECT comp_id, comp_name, version, status FROM dba_registry COMP_ID COMP_NAME VERSION STATUS -------- ------------------------------ ---------- -----JAVAVM JServer JAVA Virtual Machine 10.1.0.3.0 VALID CATJAVA Oracle Database Java Packages 10.1.0.3.0 VALID
Der aktuelle Verbrauch von Speicherplatz in der SGA kann über die dynamische View v$sgastat abgerufen werden: SQL> SELECT * FROM v$sgastat WHERE pool = 'java pool';
POOL -----------java pool java pool java pool
NAME BYTES -------------------------- ---------joxs heap 149184 free memory 7055040 joxlod exec hp 5378688
Bevor die Datenbank für Entwickler oder Endbenutzer freigegeben wird, sollte auch ein einfacher Funktionstest der Oracle JVM durchgeführt werden. Dies kann z.B. mit folgendem Mini-Java-Programm geschehen (Skript dbatest.java):
332
Zugriff auf die Datenbank
public class dbatest { public static void main (String[] args){ for (int i=0; i<args.length;i++) System.out.println(args[i]); } }
Das Skript wird zunächst kompiliert und die resultierende Klassendatei in die Datenbank geladen: $ javac dbatest.java $ loadjava -user username/password@ps10 -verbose -resolve dbatest.class creating : class dbatest loading : class dbatest created : CREATE$JAVA$LOB$TABLE resolving: class dbatest
Die Java Stored Procedure wird nun als PL/SQL-Prozedur veröffentlicht und ausgeführt. SQL> CREATE OR REPLACE PROCEDURE dba_test ( s1 varchar2, s2 varchar2 ) AS LANGUAGE JAVA NAME 'dbatest.main(java.lang.String[])'; / Prozedur wurde angelegt. SQL> SET SERVEROUTPUT ON SQL> EXEC dbms_java.set_output(5000); PL/SQL-Prozedur wurde erfolgreich abgeschlossen. SQL> EXEC dba_test('Test 1', 'Test 2'); Test 1 Test 2 PL/SQL-Prozedur wurde erfolgreich abgeschlossen.
7.5.4 Clientseitige Installation Voraussetzung für den Aufruf von Java Stored Procedures und Functions ist zunächst eine Anmeldung an die Datenbank. Dafür wird entweder eine Oracle Client-Installation benötigt oder der seit der Datenbank-Version 10g ebenfalls verfügbare »Oracle Instant Client« (siehe Kapitel 7.1.4).
Java in der Datenbank
333
7.5.5 JDBC-Treiber Mit der Oracle-Datenbank 10g bzw. den Client-Installationen werden vier verschiedene JDBC-Treiber ausgeliefert, die für unterschiedliche Szenarien optimiert sind: Der JDBC Thin-Treiber ist komplett in Java geschrieben und daher plattformunabhängig. Er benötigt keinerlei Oracle-Installation. Dieser Treiber kann für alle Arten von Java-Clients, also Java-Applikationen und auch Java-Applets, benutzt werden (in letzterem Fall wird der Treiber einfach in das Applet heruntergeladen). Die Kommunikation mit dem Datenbank-Listener läuft via Java-Sockets über TCP/IP, andere Protokolle sind nicht möglich. Für Applets ist die Benutzung dieses Treibers die einzig mögliche Option. Der JDBC OCI-Treiber benötigt eine vorhandene Oracle Client- oder InstantClient-Installation und übersetzt JDBC-Aufrufe in OCI-Aufrufe. Er liegt als Shared Library vor, ist somit plattformspezifisch und kann daher ausschließlich in Applikationen, nicht jedoch in Applets verwendet werden (ein Herunterladen in das Applet ist offenbar nicht möglich). Nur dieser Treiber ist in der Lage, alle Oracle Net-Adapter (TCP/IP, IPC etc.) zu nutzen. Außerdem bietet er Unterstützung für einige spezielle OCI-Features. Der JDBC Server-Side Internal-Treiber (auch KPRB-Treiber genannt) läuft nicht auf dem Client, sondern auf der Datenbank. Er bietet maximale Performance für Java Stored Procedures, die auf die Datenbank zugreifen müssen. Bei Benutzung dieses Treibers findet keinerlei Netzwerk-Kommunikation statt, sondern lediglich Prozeduraufrufe, da alle beteiligten Komponenten (Oracle-Server, SQL-Engine, JVM und JDBC-Treiber) in demselben Prozess und Adressraum liegen. Der Funktionsumfang ist identisch mit dem des JDBC OCI-Treibers. Zu beachten ist, dass aufgrund der Architektur nur die vorhandene Connection (die so genannte Default-Connection) genutzt werden kann. Weitere Verbindungen an dieselbe oder an andere Datenbanken sind mit diesem Treiber prinzipiell nicht möglich. Der JDBC Server-Side Thin-Treiber ist im Hinblick auf den Funktionsumfang mit dem Thin-Treiber identisch, aber speziell für die Benutzung in Java Stored Procedures und Functions ausgelegt. Er läuft nicht auf dem Client, sondern direkt in der Datenbank und bietet daher die beste Performance beim Zugriff auf die betreffende Datenbank. Im Gegensatz zum Server-Side Internal-Treiber sind aber auch Connects an andere Datenbanken möglich. Dieser Treiber ist interessant, wenn die betreffende Datenbank als Middle-Tier agiert und auf Daten von anderen Datenbanken zugreifen muss. Hier sollen noch einmal einige Entscheidungshilfen für die Wahl des richtigen Treibers gegeben werden: Für Client-Applikationen sollte – wenn nichts dagegen spricht – der Thin-Treiber gewählt werden, da er die beste Performance und Plattformunabhängigkeit bietet und außerdem sowohl für Applikationen als auch für Applets verwendet werden kann. Für Applets muss der Thin-Treiber verwendet werden.
334
Zugriff auf die Datenbank
Für Netzwerke, die nicht auf TCP/IP basieren, kommt nur der OCI-Treiber in Frage Für die Benutzung von LDAP over SSL muss der Thin-Treiber benutzt werden. Bestimmte Oracle-Features, z.B. TAF (Transparent Application Failover, siehe Kapitel 7.1.3), oder die Verwendung von PL/SQL-Index-by-Tabellen werden nur vom OCI-Treiber unterstützt. Genauere Angaben hierzu finden sich in der Dokumentation Oracle 10g JDBC Developer’s Guide and Reference. Läuft der Java-Code auf Server-Seite (also in Java Stored Procedures und Functions) und ist kein Zugriff auf weitere Sessions oder andere Datenbanken nötig, sollte der Server-Side Internal-Treiber verwendet werden, da er hierfür die beste Performance bietet Es muss aber abgeschätzt werden, ob die Beschränkung auf eine einzige Datenbank-Session auf Dauer haltbar ist. Läuft der Java-Code auf Server-Seite, benötigt aber auch Zugriffe auf andere Datenbanken und/oder andere Sessions, sollte der Server-Side Thin-Treiber benutzt werden.
7.5.6 Verbindungen via JDBC Der Aufbau einer JDBC-Connection bildet eine Schnittstelle zwischen Administration und Entwicklung, da hier Besonderheiten der jeweiligen Datenbank bzw. des verwendeten JDBC-Treibers zu berücksichtigen sind. Daher soll dieses Thema hier anhand von Code-Beispielen erläutert werden. Weitergehende Programmbeispiele wie das Absetzen von SQL-Abfragen und die Verarbeitung der Ergebnismengen sind dagegen durch die JDBC-APIs standardisiert und gehören daher eindeutig in den Bereich Java-Entwicklung. Die Oracle-JDBC-Klassen befinden sich in dem Package oracle.jdbc. Für den Verbindungsaufbau wird außerdem das Package oracle.jdbc.pool benötigt. Der einschlägige Java-Code zur Erzeugung eines Connection-Objekts sieht dann wie folgt aus: import oracle.jdbc.*; import oracle.jdbc.pool.OracleDataSource; ... OracleDataSource ods = new OracleDataSource(); String URL = "JDBC-URL siehe unten"; ods.setURL(URL); ods.setUser("schwanke"); // Benutzername ods.setPassword("password"); // Passwort Connection conn = ods.getConnection(); ... conn.close();
Die JDBC-URL hat grundsätzlich das Format jdbc:oracle:driver_type:[username/password]@database_specifier
Java in der Datenbank
335
wobei für driver_type je nach zu verwendendem JDBC-Treiber thin (für den ThinTreiber), oci (für den OCI-Treiber) oder kprb (für den Server-Side Internal-Treiber) eingesetzt wird. Beispiele für JDBC-URLs: Mit jdbc:oracle:thin:@//hlsun:1521/sun10g wird eine Thin-Treiber-Verbindung (impliziert TCP/IP) an die Datenbank mit dem Service-Namen SUN10G auf dem Host HLSUN mit Listener auf Port 1521) aufgebaut. Da keine Oracle-Client-Installation vorausgesetzt wird, können auch keine TNS-Namen benutzt werden. Die Informationen für einen TNS-Eintrag (Host, Port und Service-Name) werden daher direkt in der URL mitgegeben. Bei der Verwendung des OCI-Treibers kann über die URL jdbc:oracle:oci:@sun10g direkt ein TNS-Name (hier SUN10G) angegeben werden. Für den Server-Side Internal-Treiber kann keine Verbindungsinformation angegeben werden, da stets die aktuelle Connection (Default-Connection) benutzt wird. Als URL kann wahlweise jdbc:oracle:kprb oder jdbc:default:connection benutzt werden. Einen Spezialfall bildet eine Anmeldung mit SYSDBA- oder SYSOPER-Privileg. Diese kann z.B. wie folgt geschehen: OracleDataSource ods = new OracleDataSource(); java.util.Properties prop = new java.util.Properties(); prop.put("user", "sys"); prop.put("password", "syspassword"); prop.put("internal_logon", "sysdba"); ods.setConnectionProperties(prop); String url = "jdbc:oracle:oci:@"; ods.setURL(url);
Ein solche Verbindung ist grundsätzlich nicht mit dem Server-Side Internal-Treiber möglich, da hier keine Authentifizierung durch das Betriebssystem möglich ist. Auch gibt es einige weitere Besonderheiten des Server-Side Internal-Treibers, die beachtet werden sollten: Cursor, also Select-Abfragen, müssen explizit geschlossen werden. Ggf. sollte außerdem der Serverparameter open_cursors angehoben werden. Auto-Commit (implizites Commit nach jedem SQL-Statement) ist nicht möglich. Die aktuelle Connection (Default-Connection) kann nicht geschlossen werden.
7.5.7 NLS-Einstellungen für JDBC Java-Methoden wie getString(), setString() oder toString() finden sich in diversen JDBC-Klassen (z.B. in java.sql.ResultSet, oracle.sql.CLOB oder oracle.sql.CHAR) und benötigen offensichtlich Informationen über die verwendeten Zeichensätze, d.h. Client-Zeichensatz sowie Datenbank-Zeichensatz, um geeignete Konvertierungen durchzuführen. Innerhalb einer JVM, also sowohl in Java Stored Procedures als auch in ClientApplikationen oder Applets, wird als Zeichensatz grundsätzlich UTF-16 verwendet.
336
Zugriff auf die Datenbank
Dabei handelt es sich um einen Zeichensatz mit variabler Kodierungslänge (2 Byte oder 4 Byte pro Zeichen), die meisten Zeichen benötigen 2 Byte. Der Client-Zeichensatz ist also festgelegt, eine evtl. gesetzte Umgebungsvariable NLS_LANG wird nicht beachtet. Die eigentliche Konvertierung ist etwas ungewöhnlich realisiert und erfolgt ggf. in zwei Schritten. Wenn als Datenbank-Zeichensatz US7ASCII oder WE8ISO8859P1 verwendet wird, wird direkt in diesen bzw. aus diesem Zeichensatz konvertiert. Ansonsten wird durch den JDBC-Treiber zunächst in UTF-8 konvertiert. Dies hat den Vorteil, dass die über das Netzwerk zu übertragende Datenmenge geringer ist, da die gebräuchlichen ASCII-Zeichen in UTF-8 jeweils 1-ByteRepräsentationen haben. Der zweite Konvertierungsschritt zwischen UTF-8 in dem Datenbank-Zeichensatz wird beim OCI-Treiber und beim Server-Side Internal-Treiber ebenfalls vom Treiber selbst geleistet. Beim Thin-Treiber dagegen wird dieser Schritt vom Datenbank-Server durchgeführt, da der Treiber nicht Informationen über alle Oracle-Zeichensätze hat. Die Sprach- sowie Territoriumseinstellungen werden normalerweise clientseitig über die Parameter NLS_LANGUAGE und NLS_TERRITORY eingestellt. Diese Parameter werden aber vom JDBC-Treiber bei der Anmeldung an die Datenbank gemäß den entsprechenden Einstellungen der JVM (Property user.language) gesetzt, in welcher der Treiber läuft. Dies stellt sicher, dass beispielsweise Oracle-Fehlermeldungen oder Wochentagsbezeichnungen beim Java-Client in dessen Sprache ankommen. Weitergehende Einstellungen sind leider nicht über die NLS-Umgebungsvariablen möglich, sondern müssen innerhalb der Java-Applikation auf Session-Ebene durch die JDBC-Schnittstelle hindurch getätigt werden, es müssen also per JDBC SQLKommandos z.B. der folgenden Art abgesetzt werden. ALTER SESSION SET NLS_DATE_FORMAT=’DD.MM.RRRR’ ALTER SESSION SET NLS_SORT=GERMAN
Eine Komplikation bezüglich der Zeichensatzkonvertierung kann in folgender Situation auftreten: Der Datenbank-Zeichensatz ist weder US7ASCII noch WE8ISO8859P1. Es ist also eine Konvertierung in zwei Schritten notwendig. Der JDBC Thin-Treiber wird benutzt. Dies ist der einzige Treiber, bei dem der zweite Konvertierungsschritt (von UTF-8 in den Datenbank-Zeichensatz) vom Datenbank-Server selbst ausgeführt wird. Eine Bindevariable vom Typ CHAR oder VARCHAR2 wird benutzt. Da die Ergebnisse des zweiten Konvertierungsschritts dem JDBC Thin-Treiber nicht bekannt sind, stellt sich die Frage, wie lang der Wert für eine solche Bindevariable clientseitig sein darf, ohne dass es serverseitig (nach der Konvertierung) zu einem Überlauf und damit einer Datenkorruption kommt. Diese Problematik wird durch einen Expansionsfaktor gelöst, der als konservative Obergrenze für die Verlängerung eines Strings im Rahmen der Konvertierung angesehen werden kann und eindeutig durch den Datenbank-Zeichensatz bestimmt ist. Der Expansionsfaktor entspricht dabei der maximalen Byte-Länge in dem betreffenden Zeichensatz (Ausnahme: UTF8 und AL32UTF8).
Java in der Datenbank
337
Günstig sind daher als Datenbank-Zeichensätze alle Zeichensätze mit fixer Codierungslänge 1 Byte sowie UTF8 oder AL32UTF8, da hier der Expansionsfaktor offensichtlich 1 ist und bis zu 4000 Byte lange Strings gebunden werden können. Ein Zeichensatz wie z.B. JA16EUC dagegen mit dem Expansionsfaktor 3 lässt maximal 4000/3 = 1333 Byte lange Strings zu. Dies führt in der Applikation oft zu Laufzeitfehlern, die schwierig zu finden und zu lösen sind.
7.5.8 Java-Objekte in der Datenbank Neben dem Zugriff via JDBC auf die Datenbank gibt es auch die Möglichkeit, JavaKlassen direkt in der Datenbank abzulegen, wobei der Datenbank-Server die Rolle einer JVM übernimmt. Auf diese Weise können Prozeduren, Funktionen und ganze Java-Applikationen in der Datenbank gespeichert und ausgeführt werden. Konzeptuell ist dies mit PL/SQL-Objekten vergleichbar, allerdings steht über die Programmiersprache Java gleich eine weite Welt an Standards, Implementierungen und Lösungen für die verschiedensten Probleme bereit. Auch das Ausführen von SQLKommandos aus Java-Objekten heraus ist über die JDBC-Treiber, hier insbesondere einen der Server-Side-Treiber, problemlos möglich. Folgende Java-Objekte können in der Datenbank gespeichert werden: Java-Source-Dateien, also .java-Dateien Java-Class-Dateien, also durch die Oracle JVM interpretierbarer Java-Bytecode Java-Resource-Dateien, z.B. mit den Endungen .properties oder .ser Alle vorhandenen Objekte können durch folgende Abfrage ermittelt werden: SQL> SELECT * FROM dba_objects WHERE object_type IN ( 'JAVA CLASS', 'JAVA SOURCE', 'JAVA DATA', 'JAVA RESOURCE');
Über die SQL-Kommandos CREATE/ALTER/DROP JAVA können Java-Objekte in der Datenbank erstellt, verwaltet und gelöscht werden. Üblicher und besser ist jedoch der Zugriff über die Kommandozeilen-Tools loadjava und dropjava, da durch diese Tools bestimmte Verwaltungsinformationen gepflegt werden (s.u.). Außerdem sollten Java-Source-Dateien stets außerhalb der Datenbank kompiliert (mittels javac) und debuggt und anschließend nur die Class-Dateien mittels loadjava geladen werden. Mit loadjava können auch ganze .jar- und .zip-Dateien mit beliebig vielen Klassen- und Resource-Dateien geladen werden. Sollen dagegen Source- und Class-Datei in der Datenbank verwaltet werden, sind beide Objekte voneinander abhängig. Das Class-Objekt kann nicht unabhängig geladen werden, sondern muss durch Kompilierung aus dem Source-Objekt hervorgehen (dies geschieht automatisch, wenn das loadjava-Tool benutzt wird). Ein erneutes Laden oder Löschen ist dann nur für das Source-Objekt möglich und führt ggf. zu einer Invalidierung des Class-Objekts (auf diese Weise werden inkonsistente Stände zwischen Source- und Class-Objekt verhindert). Der Versuch, das ClassObjekt direkt zu verändern, führt typischerweise zu der Fehlermeldung: ORA-29537: class or resource cannot be created or dropped directly
338
Zugriff auf die Datenbank
7.5.9 Resolving Beim Laden oder aber spätestens bei der Ausführung einer Klasse müssen Referenzen, also Bezugnahmen auf andere Klassen, aufgelöst werden, d.h., referenzierte Klassen müssen eindeutig identifiziert werden können. Normalerweise geschieht dies in Java durch Setzen der Umgebungsvariablen CLASSPATH, die angibt, in welchen Verzeichnissen nach den betreffenden Class-Dateien (ggf. in JAR- oder ZIPDateien) gesucht werden soll. Für die Oracle JVM, die Klassen ja nicht im Dateisystem, sondern in der Datenbank speichert und verwaltet, muss es hier offenbar einen anderen Mechanismus geben. Dieses so genannte Resolving, also das Auffinden einer referenzierten Klasse, geschieht in der Oracle JVM durch Angabe einer Liste von Schemata, die nach der betreffenden Klasse gesucht werden. Diese Liste wird »Resolver« genannt. Der Default-Resolver sucht zunächst im aktuellen Schema (also demjenigen Schema, in das die Klasse geladen wurde) und dann im Schema PUBLIC, wo sämtliche CoreKlassen aus dem SYS-Schema per Synonym zugreifbar sind. Befinden sich alle Java-Objekte in einem Schema, genügt daher der Default-Resolver. Sind die benötigten Java-Klassen in der Datenbank dagegen über mehrere Schemata verteilt, muss ein entsprechender Resolver angegeben werden. Dieser wird über eine Kommandozeilen-Option des loadjava-Tools mitgegeben, beispielsweise: $ loadjava –user system/manager@ps10 -schema SCHWANKE -resolve –resolver „((* SCHWANKE) (* AHRENDS) (* PUBLIC))“ dbatest.class
In diesem Fall werden referenzierte Klassen zunächst im Schema SCHWANKE, dann im Schema AHRENDS und schließlich unter den Core-Klassen gesucht. Im Gegensatz zum CLASSPATH, der als Umgebungsvariable global für alle Klassen gesetzt wird, hat in der Oracle JVM jede Klasse ihren eigenen Resolver. Dies erlaubt eine sehr feine granulare Steuerung des Resolving-Mechanismus, kann aber auch lästig und fehleranfällig sein, wenn immer wieder derselbe Resolver angegeben werden muss. Der Resolver und auch alle anderen Parameter können daher auch als Default-Optionen in einer Tabelle abgelegt werden (siehe nächster Abschnitt). Wird eine Klasse nicht gefunden, ist das Java-Objekt anschließend zwar vorhanden, aber invalid. Um dies bewusst zu verhindern, kann als letztes Argument im Resolver (* -) angegeben werden. In diesem Fall werden ggf. Laufzeitfehler ausgelöst. Weitere Steuerungsmöglichkeiten beim Resolving sind in der Dokumentation Oracle 10g Java Developer’s Guide beschrieben.
7.5.10 Tools zur Java-Verwaltung Zur Datenbanksoftware gehören auch die beiden bereits erwähnten Tools loadjava und dropjava. Ihnen sollte der Vorzug vor den SQL-Kommandos CREATE JAVA bzw. DROP JAVA gegeben werden, da sie einige für die Entwicklung transparente, für die Administration aber sehr nützliche Funktionen mitbringen.
Java in der Datenbank
339
Die Basisfunktionalität des loadjava-Tools wie auch des CREATE JAVA-Kommandos ist, eine Java-Klassen- oder Resource-Datei in die Datenbank zu laden, also zu einem für die Oracle JVM ausführbaren Java-Klassen- oder Resource-Objekt zu machen. Das dropjava-Tool sowie der DROP JAVA-Befehl entfernen ein entsprechendes Java-Objekt aus der Datenbank. Die beiden Varianten (SQL-Kommando oder Tool) sollten in ihrer Benutzung grundsätzlich nicht vermischt werden, da der Mehrwert der Tools unter anderem in der Pflege bestimmter Verwaltungsinformationen liegt, die nur dann konsistent vorliegen, wenn die Benutzung dieser Tools auch konsequent erfolgt. Insbesondere bei der Benutzung von Makefiles sowie bei umfangreichen JAR- und ZIP-Dateien oder Lade-Skripten zahlt sich eine konsequente Benutzung von loadjava aus, da dieses Tool eine so genannte Digest-Tabelle schreibt, in der jedem Klassen-Objekt in der Datenbank ein 16-Byte-Hashwert (nach dem MD5-Algorithmus) des Klasseninhalts zugeordnet wird. Bei einem erneuten Laden wird das KlassenObjekt nur dann ersetzt, wenn sich der Hash-Wert (auch Digest genannt) und damit der Klassen-Inhalt geändert haben. Die Digest-Tabelle befindet sich im Zielschema der Java-Objekte und trägt den Namen JAVA$CLASS$MD5$TABLE. Ein Löschen oder Manipulieren dieser Tabelle führt dazu, dass beim nächsten Mal evtl. unnötige Ladeoperationen durchgeführt werden. Auch das dropjava-Tool pflegt diese Tabelle. Sollte der Tabelleninhalt irgendwie korrumpiert worden sein, z.B. weil versehentlich eine Klasse über die SQL-Kommandos neu eingespielt wurde, kann mit der loadjava-Option –force ein erneuter Abgleich erzwungen werden. Für die Tabelle sollte kein Public Synonym angelegt sein, da sie nur für schemainterne Verwaltung ausgelegt ist, insbesondere wird Eindeutigkeit der Klassennamen vorausgesetzt. Nach dem ersten loadjava-Aufruf findet sich im Zielschema außerdem eine Tabelle CREATE$JAVA$LOB$TABLE, die den Inhalt einer Java-Datei in eine LOB-Spalte aufnimmt und daraus anschließend das Klassenobjekt definiert. Dieser Mechanismus erlaubt es, mittels loadjava ohne Vergabe von Zugriffsrechten auf Dateisystemebene den Inhalt einer Java-Datei zu lesen und in die Datenbank zu übertragen. Die Tabelle kann gelöscht werden, wird aber beim nächsten loadjava-Aufruf automatisch neu erstellt. Beim Laden von Java-Resource-Dateien ist zu beachten, dass der Name des Resource-Objekts nicht wie bei Klassen- oder Source-Dateien in der Datei selbst steht. Daher wird einfach der Dateiname inklusive angegebenem Pfad literal als Objektname übernommen. Es macht durchaus einen Unterschied, ob ein relativer oder ein absoluter Pfad angegeben wird. In der Praxis sollte versucht werden, Klassen- und Resource-Dateien in einer JAR-Datei zu bündeln, um diese Problematik zu beseitigen. Ist dies nicht der Fall, sollte loadjava aus dem so genannten PackageRoot-Verzeichnis heraus aufgerufen werden und zu ladende Resource-Dateien relativ zu diesem Verzeichnis qualifizieren.
340
Zugriff auf die Datenbank
7.5.11 Ausgabeumleitung Java-Ausgaben via system.out bzw. system.err gehen per Default in die Trace-Datei der Oracle-Session (das Verzeichnis für solche Trace-Dateien wird durch den Serverparameter user_dump_dest festgelegt). Diese kann daher u.U. stark anwachsen. Hier sollte vorsichtshalber eine Größenbegrenzung der Trace-Dateien mittels des Serverparameters max_dump_file_size etabliert werden. Alternativ kann durch folgenden Prozeduraufruf die Java-Ausgabe für den Rest der Session in den DBMS_OUTPUT-Puffer der Datenbank umgeleitet werden, also wie normale Ausgaben mittels DBMS_OUTPUT behandelt werden (der Parameter gibt die maximale Puffergröße an): SQL> EXECUTE dbms_java.set_output(5000); SQL> SET SERVEROUTPUT ON SIZE 5000
7.5.12 Publishing von Java-Klassen Aus Security-Gründen ist nicht jede in die Datenbank geladene Java-Klasse gleich allgemein verfügbar. Die Bekanntmachung, das so genannte Publishing, einer JavaKlasse, muss vielmehr explizit durch Definition eines Aufruf-Interfaces in Form einer herkömmlichen PL/SQL-Prozedur oder Funktion erfolgen. Eine solche PL/SQLRoutine dient einfach als Wrapper für eine Methode einer Java-Klasse. Im Abschnitt »Serverseitige Installation« (s.o.) ist ein entsprechendes Beispiel gegeben. Aus Gründen der Übersichtlichkeit können und sollten solche Wrapper-Routinen in PL/SQLPackages zusammengefasst werden. Auch Objektmethoden im Rahmen von SQLObjekttypen sind als Wrapper zugelassen. Die Package- bzw. Objekttyp-Deklaration sollte dabei bereits die LANGUAGE JAVA-Klausel umfassen, ein Package-Body oder TypeBody ist dann nicht notwendig. Zum Beispiel: SQL> CREATE OR REPLACE PACKAGE myjava AS PROCEDURE dba_test ( s1 varchar2, s2 varchar2 ) AS LANGUAGE JAVA NAME 'dbatest.main(java.lang.String[])'; END myjava; /
Um eine Java-Methode aufrufen zu können, ist es häufig interessant zu wissen, ob und – wenn ja – welche PL/SQL-Routine diese Java-Methode wrappt. Die Zuordnung von PL/SQL-Wrapper-Routinen zu Java-Methoden ist leider nicht direkt über eine Data-Dictionary-View zu haben. Ist auch kein entsprechendes EntwicklerKnow-how verfügbar, kann man sich aber mit folgender Abfrage behelfen: SQL> SELECT o.owner ,o.object_name AS ,i.procedurename AS ,j.classname AS ,j.methodname AS ,j.usersignature AS FROM sys.procedurejava$ ,sys.procedureinfo$ ,dba_objects o
plsql_object plsql_routine java_class java_method javasignature j i
Die Oracle XML DB WHERE AND AND
341
j.obj# = o.object_id j.obj# = i.obj# j.procedure# = i.procedure#;
Achtung: Diese Abfrage liefert nur dann alle Zuordnungen, wenn – wie oben angeraten – bereits in der Package- bzw. Objekttyp-Deklaration die LANGUAGE JAVA-Klausel angegeben wurde. Leider ist dies auch nicht für alle mitgelieferten PublishingWrapper der Fall.
7.5.13 Deinstallation der Oracle JVM Die Deinstallation der Oracle JVM geschieht, indem entsprechende kompensierende Skripte zu den Installationsskripten in umgekehrter Reihenfolge aufgerufen werden. Dies sind insbesondere in dieser Reihenfolge:
$ORACLE_HOME/rdbms/admin/catnoexf.sql $ORACLE_HOME/rdbms/admin/catnojav.sql $ORACLE_HOME/xdk/admin/rmxml.sql $ORACLE_HOME/javavm/install/rmjvm.sql
Zur Sicherheit sollte man sich bei der Installation der Oracle JVM vom DBCA ein Skript generieren lassen. Dort finden sich alle aufgerufenen Skripte. Die zugehörigen kompensierenden Skripte sind meist relativ leicht zu finden.
7.6
Die Oracle XML DB
Seit der Datenbankversion Oracle9i ist es möglich, XML-Daten und XML-Dokumente als solche in der Datenbank zu speichern, zu verwalten und zu verarbeiten (vorher war bestenfalls eine Speicherung in CLOB- oder LONG-Spalten möglich). Dies kann manuell durch den Benutzer eingerichtet werden, indem so genannte XMLTYPE-Tabellen oder Spalten mit XMLTYPE-Datentyp zur Speicherung solcher Dokumente definiert werden. Alternativ steht ein vorgefertigtes Repository zur Aufnahme von XML-Dokumenten zur Verfügung, das nach außen hin wie ein Dateisystem präsentiert werden kann (zugreifbar beispielweise über FTP oder Windows Explorer). Intern ist das Repository über Tabellen und Indizes in einem eigenen Schema XDB realisiert. Der Zugriff auf dieses Repository ist über diverse Schnittstellen möglich: Durch die Views RESOURCE_VIEW und PATH_VIEW im XDB-Schema Durch das PL/SQL-Package DBMS_XDB Via FTP, HTTP oder WebDAV. Hierbei kommen die so genannten XML DB-Protokollserver zum Einsatz. Im Folgenden werden die administrativen Aspekte bei der Arbeit mit der XML DB beschrieben, insbesondere die Installation sowie Konfiguration des Repositories und der Protokollserver.
342
Zugriff auf die Datenbank
7.6.1 Installation der XML DB Bei der Erzeugung einer Datenbank mit dem Database Configuration Assistant (DBCA) kann die Installation der XML DB unter dem Punkt »Standard-Datenbankkomponenten« angewählten werden:
Abbildung 7.35: Installation der XMLDB durch den Konfigurationsassistenten
Die Voreinstellung (Speicherung im Tablespace SYSAUX) ist nur eingeschränkt zu empfehlen. Wenn absehbar ist, dass nicht nur geringfügige Datenmengen abgespeichert werden sollen, ist ein eigener Tablespace für das XML-DB-Repository anzuraten. Ob die XML-DB überhaupt in der Datenbank installiert ist, kann am einfachsten durch folgende Abfrage festgestellt werden: SQL> SELECT comp_id, comp_name, version, status FROM dba_registry COMP_ID COMP_NAME VERSION STATUS -------- ------------------------------ ---------- -----XDB Oracle XML Database 10.1.0.3.0 VALID
Eine manuelle Nachinstallation des XML-DB ist einfach durch Aufruf folgender Skripte unter dem Benutzer SYS möglich: SQL> @?/rdbms/admin/catqm.sql <XDB-Passwort> <XDB-Tablespace> <XDB-Temp-Tablespace> SQL> @?/rdbms/admin/catxdbj.sql
Bei der Installation werden zwei Benutzer angelegt (XDB und ANONYMOUS). Beide Accounts sind zunächst gesperrt. Der Benutzer XDB ist der Besitzer des Repositories und sollte auch gesperrt bleiben. Der Benutzer ANONYMOUS hat überhaupt keine Objekte. Er kann zum Zwecke eines HTTP-Zugriffs ohne Logon entsperrt werden (siehe unten).
Die Oracle XML DB
343
7.6.2 Einrichtung der Protokollserver Der Zugriff auf die in der XML DB abgelegten Dokumente ist neben dem Weg über programmatische APIs (PL/SQL, Java, C etc.) auch über Standardprotokolle (FTP und HTTP) sowie aus WebDAV-Clients wie beispielsweise dem Windows Explorer heraus möglich. Der Zugriff geschieht dabei über TCP/IP-Ports auf dem Datenbankserver. Diese Ports werden durch den normalen Datenbank-Listener abgehört. Ein gestarteter Listener ist daher Voraussetzung für die Benutzung der Protokollserver. Achtung: Nach einem Neustart des Listeners dauert es ca. eine Minute, bis die Datenbank beim Listener automatisch registriert wird. Für Hochverfügbarkeitsumgebungen kann eine explizite Registrierung über den SQL-Befehl ALTER SYSTEM REGISTER durchgeführt werden. Per Default sind der Port 8080 für HTTP- und WebDAV-Zugriff sowie der Port 2100 für FTP-Zugriff eingerichtet. Die aktuellen Werte sind zwar nicht in der ListenerKonfigurationsdatei eingetragen, können aber dennoch über den Listener abgefragt werden: $ lsnrctl status ... Zusammenfassung Listening-Endpunkte ... (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=HLLAP53)(PORT=1521))) (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=HLLAP53)(PORT=2100)) (Presentation=FTP)(Session=RAW)) (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=HLLAP53)(PORT=8080)) (Presentation=HTTP)(Session=RAW)) Services Übersicht ... Dienst "PS10" hat 1 Instance(s). Instance "PS10", Status READY, hat 1 Handler für diesen Dienst ... Dienst "PS10XDB.WORLD" hat 1 Instance(s). Instance "ps10", Status READY, hat 1 Handler für diesen Dienst ... ...
Die beiden Listener-Endpunkte mit dem Argument Presentation geben die aktuellen Ports an. Bei einer Connect-Anforderung über einen dieser Ports wird durch den Listener eine Verbindung zur Datenbank im Shared-Server-Modus aufgebaut. Die Anmeldung geschieht dabei über den Dienst PS10XDB.WORLD. Als Anmeldeinformationen muss ein Oracle-Benutzer mit seinem Passwort angegeben werden. Damit dieser Dienst im Shared-Server-Modus benutzt werden kann, muss folgender Serverparameter gesetzt sein: dispatchers='(PROTOCOL=TCP) (SERVICE=XDB)'
Der DBCA setzt diesen Parameter beim Erzeugen der Datenbank automatisch. Im Falle einer Nachinstallation ist ein manuelles Setzen des Parameters (z.B. mittels ALTER SYSTEM-Kommando) inklusive anschließendem Neustart der Datenbank notwendig.
344
Zugriff auf die Datenbank
7.6.3 Benutzung der Protokollserver FTP-Zugriff Der FTP-Zugriff auf die XML-DB kann über jeden beliebigen FTP-Client erfolgen: $ ftp ftp> open hllap53 2100 Verbindung mit HLLAP53 wurde hergestellt. 220 HLLAP53 FTP Server (Oracle XML DB/Oracle Database 10g Enterprise Edition Release 10.1.0.3.0 - Production) ready. Benutzer (HLLAP53:(none)): system 331 pass required for SYSTEM Kennwort: 230 SYSTEM logged in ftp>
Anschließend kann mit den üblichen FTP-Kommandos (get, put, mkdir etc.) gearbeitet werden. HTTP-Zugriff Über die URL http://hllap53:8080 ist der lesende Zugriff aus einem Webbrowser heraus möglich.
Abbildung 7.36: Zugriff auf die XML DB via Webbrowser
Es kann auch ein anonymer HTTP-Zugriff (ohne Login) ermöglicht werden. Dazu ist in der Datenbank der Benutzer ANONYMOUS zu entsperren. SQL> ALTER USER anonymous ACCOUNT UNLOCK;
Die Oracle XML DB
345
Zugriff via WebDAV In MS-Windows 2000 und XP kann die XML DB über die Netzwerkumgebung auch im Windows Explorer oder in Dateiauswahl-Dialogen angesprochen werden. Dort wird die gesamte XML DB als Verzeichnis dargestellt, als so genannter Web-Folder. Um einen solchen Web-Folder unter MS-Windows XP einzurichten, wird zunächst der Menüpunkt »NETZLAUFWERK VERBINDEN...« aufgerufen, mit dem auch die üblichen Windows-Freigaben eingebunden werden. Anschließend wird aber kein Freigaben-Name eingetragen, sondern der Link »MIT EINEM NETZWERKSERVER VERBINDEN« ausgewählt.
Abbildung 7.37: Einrichtung eines Web-Folders
Der restliche Vorgang ist durch einen Assistenten geführt. Als Netzwerkadresse wird dieselbe URL wie oben für den HTTP-Zugriff verwendet (WebDAV ist technisch gesehen eine Erweiterung des HTTP-Protokolls), also beispielsweise http:// hllap53:8080. Nach Eingabe der Anmeldeinformationen kann ein beliebiger Verzeichnisname für den Web-Folder vergeben werden. Damit ist die Einrichtung schon komplett. Achtung: Im Gegensatz zu Netzlaufwerken wird einem Web-Folder kein Laufwerksbuchstabe zugeordnet. Stattdessen erscheint er mit seinem zugeordneten Namen unter der Windows-Netzwerkumgebung. Anders als bei Netzlaufwerken ist es auch nicht möglich, den Web-Folder direkt auf ein bestimmtes Verzeichnis der XML-DB (im Sinne einer Freigabe) zeigen zu lassen. Der Benutzer muss daher stets selbst in entsprechende Unterverzeichnisse navigieren. Da WebDAV als HTTP-Erweiterung ein zustandsloses Protokoll ist, gestaltet sich die Anzeige und Bearbeitung von Verzeichnissen mit sehr vielen Dateien aber performanter als bei den üblichen Windows-Verzeichnissen oder Freigaben.
346
Zugriff auf die Datenbank
7.6.4 Konfiguration der Protokollserver Die Protokollserver werden nicht über die Listener-Konfigurationsdatei konfiguriert, sondern haben eine eigene Konfigurationsdatei, die selber innerhalb der XML DB liegt. Ist letztere z.B. via FTP oder WebDAV verfügbar, kann sie entsprechend editiert werden. Die betreffende Datei liegt direkt im Hauptverzeichnis der XML DB und heißt xdbconfig.xml. Hier ein Ausschnitt aus der Datei xdbconfig.xml, in dem u.a. die Ports für die Protokollserver eingetragen sind: ... 2100 local_listener tcp 0 <session-timeout>6000 8192 8080 local_listener tcp <max-http-headers>64 <max-header-size>16384 <max-request-body>2000000000 <session-timeout>6000 <server-name>XDB HTTP Server 0 ...
Wird diese Datei durch eine veränderte Version ersetzt, werden die neuen Einstellungen automatisch sofort wirksam.
Globalization Support 8.1
Überblick
Unter dem Oberbegriff Globalization Support sind bei Oracle alle Mechanismen und Möglichkeiten zusammengefasst, die sich mit der Unterstützung von internationalen Anwendungen befassen. Dies betrifft Sprachen, z.B. für Fehlermeldungen, landesspezifische Konventionen, wie Dezimal- und Tausendertrennzeichen, Währungssymbole und Formate, sowie diverse Zeichensätze. In früheren Oracle-Versionen wurde hierfür die Bezeichnung National Language Support verwendet. Die alte Bezeichnung trifft den Hintergrund der Vorgehensweise, die damals im Fokus stand: In jedem Land sollten die dort verwendete Sprache sowie die für deren Darstellung üblichen Schriftzeichen unterstützt werden, d.h., die Betonung lag auf National. Heute ist es jedoch für Unternehmen unerlässlich, sich dem Trend der Globalisierung in der Weltwirtschaft anzuschließen. Daher müssen nicht mehr nur die eigene Sprache und vielleicht die des Nachbarlandes unterstützt werden, sondern zumindest die eines Kontinents – was in Europa bereits eine sehr anspruchsvolle Aufgabe ist – oder sogar der ganzen Welt. Somit ist der Name Globalization Support für diese neuen Anforderungen treffend gewählt.1 Damit diverse Sprachen, Konventionen und Zeichensätze gleichzeitig von verschiedenen Clients einer Instanz genutzt werden können, sind praktisch alle Parameter für den Globalization Support sowohl im Client als auch im Server einstellbar. Die Serverparameter haben den Sinn, Standardwerte für die Clients zu setzen, die keinen expliziten Wert setzen. Diese haben jedoch praktisch keine Auswirkungen auf irgendwelche Verbindungen, da durch den meist immer verwendeten Parameter NLS_LANG auf der Clientseite ebenfalls Standardwerte für die gewählte Sprache gesetzt werden. Daher werden Serverparameter in der Regel nicht benutzt. Zwei Parameter auf der Serverseite werden bereits beim Anlegen der Datenbank gesetzt und können dann nur noch unter recht scharfen Bedingungen und mit großem Aufwand geändert werden: der Datenbankzeichensatz und der nationale Datenbankzeichensatz. Diese beiden Zeichensätze bestimmen, wie sämtliche Zeichenketten innerhalb der Datenbank gespeichert werden – und damit natürlich auch, welche Zeichen dafür zur Verfügung stehen. Auf der Clientseite wird für jede Sitzung der passende Zeichensatz eingestellt. Die TTC-Schicht von Oracle Net ist dafür zuständig, die Zeichen für die Client-ServerKommunikation zu konvertieren, falls Client und Server nicht die gleichen Zeichensätze benutzen.
1
Trotz des Namenswechsel tragen die meisten Parameter nach wie vor das Kürzel NLS im Namen – eine Umbenennung wäre wohl auch zu viel des Guten.
348
8.2
Globalization Support
Grundeinstellung
Zunächst bestimmt man beim Anlegen der Datenbank mindestens den Datenbankzeichensatz sowie optional den nationalen Datenbankzeichensatz. Dies erfolgt innerhalb des CREATE DATABASE-Befehls mit den folgenden Optionen: ... CHARACTER SET WE8MSWIN1252 NATIONAL CHARACTER SET UTF8 ...
In diesem Beispiel werden als Datenbankzeichensatz der westeuropäische MS-Windows-Zeichensatz mit der Codepage 1252, als nationaler Datenbankzeichensatz der UNICODE-Zeichensatz UTF8 verwendet. Alle CHAR-Datentypen (wie CHAR, VARCHAR, VARCHAR2) benutzen in einer so erzeugten Datenbank den Zeichensatz WE8MSWIN1252, alle NCHAR-Datentypen (wie NCHAR, NVARCHAR, NVARCHAR2) UTF8. Bei der Auswahl der Zeichensätze ist darauf zu achten, dass alle Zeichen, die man in den CHAR- und NCHAR-Feldern der Datenbank speichern möchte, darin enthalten sind. Im zweiten Schritt muss der Client nur noch bestimmen, mit welchem Zeichensatz er arbeitet. Wird MS-Windows als Client verwendet, so ist dies zumindest in Deutschland (und wahrscheinlich auch im restlichen Westeuropa) ebenfalls WE8MSWIN1252. Der Parameter NLS_LANG, mit dem der Zeichensatz ausgewählt wird, enthält zusätzlich zum Zeichensatz je eine Komponente für die Sprache und das Gebiet in der folgenden Form: <Sprache>_.
Ein vollständiges Beispiel ist: NLS_LANG = GERMAN_GERMANY.WE8MSWIN1252
Beim Einsatz von MS-Windows steht dieser Parameter naturgemäß in der Registrierung unter dem Pfad: \\HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\KEY_
Unter Unix ist NLS_LANG als Umgebungsvariable zu setzen.
Sprachen und landesspezifische Konventionen
8.3
349
Sprachen und landesspezifische Konventionen
8.3.1 Sprache, Gebiet und Datumsformat Die Auswahl von Sprache und Gebiet über NLS_LANG ist sicher eine komfortable Möglichkeit, den Anwender einer Oracle-basierten Anwendung zu unterstützen. Gerade diese Auswahlmöglichkeit kann jedoch zu einiger Verwirrung bei der Ausführung von Anwendungen führen. Als Beispiel soll hier die Ausgabe zu folgendem SQL-Befehl dienen: SELECT TO_DATE('01.03.2005', 'DD.MM.YYYY') datum FROM DUAL /
Mit der Einstellung AMERICAN_AMERICA.WE8MSWIN1252 sieht die Ausgabe wie folgt aus: DATUM --------01-MAR-05
Folgendes Ergebnis erhält man mit GERMAN_GERMANY.WE8MSWIN1252: DATUM -------01.03.05
Ein weitere Variante ist GERMAN_AMERICA.WE8MSWIN1252: DATUM --------01-MRZ-05
Für diejenigen, die bereits mit älteren Oracle-Versionen gearbeitet haben: Die dreistellige Abkürzung für März war bis einschließlich Oracle9i Release 2 immer MÄR. Dabei handelt es sich aber offensichtlich um einen Bug, und mit dem Release 9.2.0.6 und in der Oracle 10g wurde dies in MRZ geändert (Bug 2964856). Aus den Ausgaben kann man schließen, dass offensichtlich die Einstellungen für Sprache und Gebiet Auswirkungen auf andere Parameter haben, etwa das Datumsformat (DD-MON-RR2 für das Gebiet Amerika, DD.MM.RR für Deutschland) und die Datumssprache (entsprechend der Sprache). An dieser Stelle sei erwähnt, dass Werte vom Datentyp DATE intern in einem Binärformat abgelegt werden, das vom Darstellungsformat unabhängig ist. Daher ist z.B. sichergestellt, dass Jahreszahlen grundsätzlich vierstellig gespeichert werden. Das Datumsformat ist zur Ein- und Ausgabe von DATE-Werten da. Bei der Ausgabe wird grundsätzlich die SQL-Funktion to_char mit der auf Sitzungsebene aktiven Formatmaske durchlaufen, bei der Eingabe von Werten entsprechend die SQL-Funktion to_date. 2
Das RR-Format ist ein zweistelliges Jahreszahlformat, bei dem das Jahrhundert etwas intelligenter gesetzt wird als beim YY-Format. Letzteres nimmt als Jahrhundert grundsätzlich das aktuelle Jahrhundert an. Beim RR-Format wird das vorangegangene Jahrhundert angenommen, wenn man sich in der ersten Hälfte eines Jahrhunderts befindet und eine Zahl größer oder gleich 50 als Jahreszahl eingibt. Bei der Eingabe von 98 im Jahr 2005 wird also 1998 angenommen anstelle von 2098 beim YY-Format. Analog wird in der zweiten Hälfte eines Jahrhunderts das Folgejahrhundert angenommen, wenn man eine Zahl kleiner 50 eingibt.
350
Globalization Support
Eine Zusammenfassung aller NLS-Parameter und deren für die aktuelle Sitzung gültigen Werte liefert die View nls_session_parameters. Hier die Ausgabe eines SELECTBefehls auf diese View mit der NLS_LANG-Einstellung GERMAN_GERMANY.WE8MSWIN1252: PARAMETER -----------------------------NLS_LANGUAGE NLS_TERRITORY NLS_CURRENCY NLS_ISO_CURRENCY NLS_NUMERIC_CHARACTERS NLS_CALENDAR NLS_DATE_FORMAT NLS_DATE_LANGUAGE NLS_SORT NLS_TIME_FORMAT NLS_TIMESTAMP_FORMAT NLS_TIME_TZ_FORMAT NLS_TIMESTAMP_TZ_FORMAT NLS_DUAL_CURRENCY NLS_COMP NLS_LENGTH_SEMANTICS NLS_NCHAR_CONV_EXCP
VALUE -----------------------------------GERMAN GERMANY € GERMANY ,. GREGORIAN DD.MM.RR GERMAN GERMAN HH24:MI:SSXFF DD.MM.RR HH24:MI:SSXFF HH24:MI:SSXFF TZR DD.MM.RR HH24:MI:SSXFF TZR BINARY BYTE FALSE
Auffällig ist, dass man nicht NLS_LANG, sondern zwei seiner Komponenten, die Sprache und das Gebiet, als NLS_LANGUAGE und NLS_TERRITORY wiederfindet. Diese beiden unterscheiden sich von den anderen dadurch, dass sie auf Sitzungs- und Systemparameterebene einzeln modifizierbar sind, als Umgebungsvariable jedoch nicht. Alle anderen Parameter können überall vorgegeben werden: als Systemparameter, als Umgebungsvariable und über einen ALTER SESSION-Befehl auf Sitzungsebene. Ist keine der Varianten vorgegeben, so zieht die jeweilige Standardeinstellung, die in den allermeisten Fällen der amerikanischen Variante entspricht. Ebenfalls auffällig ist, dass der eingestellte Clientzeichensatz nicht in der Liste vorkommt. Dieser ist auch mit anderen Mitteln nicht abfragbar! Eine mögliche Erklärung hierfür ist, dass der Clientzeichensatz bzw. dessen Konvertierung in den Datenbankzeichensatz transparent von der TTC-Schicht in Oracle Net übernommen wird, so dass beim Server keinerlei Information über den Clientzeichensatz ankommt. Sogar die Abfrage der sys_context-Funktion3 mit dem Parameter LANGUAGE ergibt zwar eine Zeichenkette, deren Format dem NLS_LANG-Parameter entspricht, enthält jedoch als dritte Komponente den Datenbankzeichensatz (und nicht den Clientzeichensatz): SQL> SELECT sys_context('USERENV', 'LANGUAGE') 2 FROM dual; SYS_CONTEXT('USERENV','LANGUAGE') --------------------------------AMERICAN_AMERICA.WE8ISO8859P15 3
Die sys_context-Funktion ist Bestandteil der Oracle SQL-Funktionen und erlaubt es, diverse Informationen über die aktuelle Sitzung abzufragen. Sie ersetzt die (aus Kompatibilitätsgründen nach wie vor vorhandene) userenv-Funktion.
Sprachen und landesspezifische Konventionen
351
Weitere wichtige NLS-Parameter sind NLS_DATE_FORMAT und NLS_DATE_LANGUAGE. Sie bestimmen das Standardformat für die Ein- und Ausgabe von Werten vom Datentyp DATE. Im o.a. Beispiel wurde das Format abhängig von der Gebietseinstellung verändert. Sowohl das Format als auch die Sprache können innerhalb der Sitzung bzw. über Umgebungsvariablen verändert werden: SQL> SELECT TO_DATE('01.03.2005', 'DD.MM.YYYY') datum 2 FROM DUAL 3 /
DATUM --------01-MAR-05 SQL> ALTER SESSION SET nls_date_format = 'DD.MM.YYYY HH24:MI:SS'; Session altered. SQL> SELECT TO_DATE('01.03.2005', 'DD.MM.YYYY') datum 2 FROM DUAL 3 / DATUM ------------------01.03.2005 00:00:00 SQL> SELECT sysdate FROM dual; SYSDATE ------------------03.06.2005 15:41:43
Möchte man das zuletzt verwendete Datumsformat inklusive Uhrzeit als Standard einstellen, kann man den Parameter NLS_DATE_FORMAT als Umgebungsvariable setzen: NLS_DATE_FORMAT="dd.mm.yyyy hh24:mi:ss" export NLS_DATE_FORMAT
Unter MS-Windows ist ein entsprechender Wert in der Registrierung zu setzen. Beim Oracle Datums- und Uhrzeitformat gibt es viele mögliche Einstellungen, u.a. für ausgeschriebene oder abgekürzte Tages- und Monatsbezeichnungen. Hierzu ist die Einstellung NLS_DATE_LANGUAGE wichtig:
352
Globalization Support
SQL> SELECT to_char(sysdate, 'Day') FROM dual; TO_CHAR(S --------Friday SQL> ALTER SESSION SET NLS_DATE_LANGUAGE = 'Spanish'; Session altered. SQL> SELECT to_char(sysdate, 'Day') FROM dual; TO_CHAR(S --------Viernes
Eine weitere Einstellung bezüglich des Datums ist NLS_CALENDAR. Für viele ist die Verwendung des gregorianischen Kalenders selbstverständlich – andere Kulturen verwenden jedoch auch andere Kalender. Momentan werden die Kalender Japanese Imperial, ROC Official (Republic of China), Thai Buddha, Persian, Arabic Hijrah und English Hijrah unterstützt. Die Darstellung setzt meist einen bestimmten Zeichensatz voraus.
8.3.2 Zeitzonen, Zeitstempel und Intervalle Eine Erweiterung des DATE-Datentyps ist TIMEZONE. Dieser enthält zusätzlich zu den Sekunden deren Bruchteile sowie optional Zeitzonen-Informationen. Mit den Zeitzonen verhält es sich wie mit den Zeichensätzen: Sowohl die Datenbank als auch jede Sitzung haben eine Zeitzone eingestellt, und wenn man nichts weiter unternimmt, stellt die Oracle-Software entsprechende Standardwerte ein. Diese werden dann entsprechend den Einstellungen des jeweiligen Betriebssystems übernommen. Die möglichen Werte für Zeitzonen sind: Offsets von der Coordinated Universal Time (UTC, entspricht Greenwich Mean Time) Ortsangaben, die implizit die Zeitzone enthalten (wie z.B. Europe/Berlin) Abkürzungen für Standardzeiten bzw. Sommerzeiten (wie CET oder CEST) Die Datenbankzeitzone wird beim CREATE DATABASE eingestellt, entweder auf einen vom Betriebssystem ausgelesenen Wert oder den Wert, der mit der SET TIME_ZONEKlausel des CREATE DATABASE-Befehls angegeben wird. Die Datenbankzeitzone kann mit einem ALTER DATABASE-Befehl später geändert werden, es sei denn, in der Datenbank existieren bereits Tabellen mit Spalten vom Datentyp TIMESTAMP WITH LOCAL TIME ZONE. Oracle empfiehlt, die Datenbankzeitzone für alle Datenbank auf UTC zu normieren, damit beim Datenaustausch zwischen den Systemen keine zeitaufwändigen Konvertierungen stattfinden. Die Datenbankzeitzone kann mit der SQL-Funktion dbtimezone abgefragt werden.
Sprachen und landesspezifische Konventionen
353
Die Einstellung der Zeitzone auf Sitzungsebene erfolgt entweder über die Umgebungsvariable ORA_SDTZ oder einen ALTER SESSION-Befehl wie: ALTER SESSION SET TIME_ZONE = 'CET';
Zur Abfrage der Sitzungszeitzone gibt es ebenfalls eine SQL-Funktion, nämlich sessiontimezone. Sommerzeiten (engl. Daylight Savings Time) werden von Oracle automatisch behandelt. Gültige Werte für Zeitzonen sind über die View v$timezone_names abfragbar. Der Inhalt dieser View entspricht der Zeitzonendatei, die Oracle gerade verwendet. Es werden grundsätzlich zwei Zeitzonendateien im Verzeichnis $ORACLE_HOME/oracore/ zoneinfo ausgeliefert. Es handelt sich um eine umfassende Datei timezlrg.dat sowie um eine Datei timezone.dat, die etwa die Hälfte der Einträge der ersten Datei besitzt – laut Oracle die am häufigsten genutzten Zeitzonen (allerdings ist z.B. Europe/Berlin nicht enthalten). Standardmäßig wird die große Datei benutzt.4 Will man die andere Datei benutzen, so muss vor dem Start der Instanz die Umgebungsvariable ORA_TZFILE gesetzt werden: ORA_TZFILE=$ORACLE_HOME/oracore/zoneinfo/timezone.dat export ORA_TZFILE
Es besteht jedoch aus Sicht der Autoren keinerlei Veranlassung zur Verwendung der kleinen Datei. Nachdem nun die Zeitzonen definiert sind, kann der Datentyp für Zeitstempel, TIMESTAMP, behandelt werden. Er enthält zusätzlich zu den in DATE vorhandenen Feldern Sekundenbruchteile mit 0 bis 9 Stellen Genauigkeit (Standardwert ist 6). Die Genauigkeit für Sekundenbruchteile kann bei der Deklaration in Klammern angegeben werden. Der Datentyp TIMESTAMP existiert weiterhin in drei Varianten: TIMESTAMP, TIMESTAMP WITH TIME ZONE und TIMESTAMP WITH LOCAL TIME ZONE. Für TIMESTAMP und TIMESTAMP WITH LOCAL TIME ZONE wird keine Zeitzoneninformation im Datensatz gespeichert, wobei für letzteren Datentyp die gespeicherten Werte auf die Datenbankzeitzone normiert werden, d.h., bei der Ein- und Ausgabe von Werten wird zwischen Sitzungs- und Datenbankzeitzone konvertiert, falls diese unterschiedlich sind. Für TIMESTAMP WITH TIME ZONE wird die Zeitzoneninformation im Datensatz abgelegt. Auch TIMESTAMP-Werte werden wie DATE-Werte in einem internen Binärformat gespeichert; daher sind ebenfalls Formatmasken für die Ein- und Ausgabe von Werten zuständig. Für Werte vom Typ TIMESTAMP und TIMESTAMP WITH LOCAL TIME ZONE ist die Variable NLS_TIMESTAMP_FORMAT, für Werte vom Typ TIMESTAMP WITH LOCAL TIME ZONE ist es NLS_TIMESTAMP_TZ_FORMAT. Zusätzlich zu den Formatelementen des DATE-Datentyps wird die Sekundenangabe (typischerweise SS) ergänzt um XFF[n]. Dabei steht das X für das Dezimaltrennzeichen zwischen Sekunden und Bruchteilen (und entspricht damit in etwa dem D-Formatelement bei den NUMBER-Formaten). Das FF steht für die eigentlichen Bruchteile und übernimmt die Anzahl Stellen vom Datentyp. Optional kann die Stellenzahl zwischen 1 und 9 auch explizit gewählt werden. 4
Dies ist ein Unterschied zu den Vorgängerversionen, die standardmäßig die kleine Datei benutzt haben.
354
Globalization Support
Zeitzonen werden im Format entweder über die Felder TZH und TZM (als Stunden und Minuten Differenz von UTC), die Regionsbezeichnung TZR (z.B. Europe/Berlin) bzw. die Standardabkürzung der Zeitzone inklusive Sommerzeitinformation TZD (z.B. CET bzw. CEST) dargestellt. Für international genutzte Anwendungen haben die TIMESTAMP WITH [LOCAL] TIME ZONE-Datentypen große Vorteile gegenüber DATE, da durch die Mitbetrachtung der Zeitzone die Zeitunterschiede zwischen den verschiedenen Benutzern der Anwendungen keine Fehler mehr verursachen können. Die Auswahl des Datentyps (LOCAL oder nicht) ist davon abhängig zu machen, ob die explizite Zeit inklusive Zeitzoneninformation später eine Rolle spielen kann oder nicht. Die zusätzlichen Datentypen zur Darstellung von Intervallen INTERVAL YEAR TO MONTH und INTERVAL DAY TO SECOND unterstützen die TIMESTAMP-Datentypen, so dass Berechnungen hiermit einfach möglich sind. Die bekannten Funktionen für die DATEArithmetik (wie z.B. add_months) sollten für TIMESTAMP-Berechnungen nicht verwendet werden, da diese eine implizite Typkonvertierung zu DATE durchführen und somit sowohl die Sekundenbruchteile als auch die Zeitzoneninformation verlieren.
8.3.3 Sortierreihenfolgen Die Einstellung der Sortierreihenfolge wird über den Parameter NLS_SORT gesteuert, dessen Standardwert BINARY ist. Wird die Sprache (NLS_LANGUAGE) auf GERMAN gesetzt, so gilt diese Einstellung zunächst auch für NLS_SORT. Allerdings gibt es insgesamt vier deutsche Sortierreihenfolgen für Oracle: GERMAN, GERMAN_DIN, XGERMAN und XGERMAN_DIN. Alle basieren auf der Norm DIN 5007, unterscheiden sich jedoch in der Behandlung von Groß- und Kleinschrift, den Umlauten gegenüber AE, OE und UE sowie des »ß«. Zur Einstellung der gewünschten Sortierreihenfolge sollte man die Möglichkeiten ausprobieren und die gewünschte Variante auswählen. Nähere Informationen hierzu finden sich auch in der folgenden Metalink Notiz »Note: 130318.1 How Sorting with NLS_SORT=GERMAN Works«. Wichtig im Zusammenhang mit Sortierreihenfolgen ist, dass Indizes auf CHARDatentypen grundsätzlich binär sortiert sind. Damit ist es (unabhängig von allen anderen Optimierungskriterien) grundsätzlich nicht möglich, eine ORDER BYAbfrage durch einen Standardindex auf dem Sortierfeld zu unterstützen, sobald NLS_SORT auf einem von BINARY unterschiedlichen Wert steht. Das Problem kann dadurch umgangen werden, dass ein funktionsbasierter Index mit der SQL-Funktion nlssort aufgebaut wird, z.B.: CREATE INDEX kunden_name_xgerman_din ON kunden (nlssort(name, 'NLS_SORT = Xgerman_DIN')) ...
Dieser Index kann zur indexunterstützten Sortierung wiederum verwendet werden.
Zeichensätze
355
8.3.4 Weitere NLS-Parameter Der Parameter NLS_NUMERIC_CHARACTERS bestimmt, welche Zeichen als Dezimal- und Tausendertrennzeichen bei der Formatierung von NUMBER-Werten benutzt werden. Hiermit wird hauptsächlich der Umstand abgefangen, dass im Englischen der Punkt als Dezimal- und das Komma als Tausendertrennzeichen verwendet wird; im Deutschen ist es genau umgekehrt. Die Voreinstellung ist abhängig von der Wahl des Gebiets. Dieser Parameter kann bei einigen Anwendungen, die auf die OracleDatenbank zugreifen, Ursache für Fehler sein. Da der Parameter über die Standardsprache (NLS_LANGUAGE) entsprechend gesetzt wird, kann es daher vorkommen, dass Fehlermeldungen, wie z.B. »ungültige Zahl (ORA-01722)«, von der Anwendung geliefert werden. In der Regel ist dies auf eine fehlerhafte Kodierung zurückzuführen, bei der Punkt und Komma explizit gesetzt wurden. Für Währungen können die Parameter NLS_CURRENCY und NLS_ISO_CURRENCY verwendet werden, wobei NLS_CURRENCY das Währungssymbol (etwa € oder $) enthält, NLS_ISO_CURRENCY die Bezeichnung des ISO-Währungssymbols (also AMERICAN oder GERMAN). Bei der Verwendung des Formatelements L wird dann das Währungssymbol, bei C die ISO-Abkürzung der Währung (USD, EUR usw.) ausgegeben. Aus der Zeit der Euroumstellung ist ein weiterer Parameter, NLS_DUAL_CURRENCY, vorhanden, mit dem ein zweites Währungssymbol definiert werden kann. Dieser ist aktuell nicht mehr dokumentiert, aber nach wie vor vorhanden. Weitere NLS-Parameter werden im nächsten Abschnitt erläutert.
8.4
Zeichensätze
Die Auswahl der Zeichensätze für eine Datenbank ist keine triviale Aufgabe. Im Gegensatz zum englischsprachigen Raum ist es jedoch unerlässlich, einen passenden Zeichensatz auszuwählen – da der Standardwert für den Datenbankzeichensatz US7ASCII ist und somit z.B. keine Umlaute enthält. Es wird im Übrigen dringend von dem Trick abgeraten, die Datenbank mit US7ASCII zu betreiben und alle Clients ebenfalls mit der Einstellung US7ASCII zu fahren. Damit führt die TTC-Schicht von Oracle Net keinerlei Konvertierung durch – und es ist somit möglich, z.B. mit MS-Windows-Clients zu arbeiten und alle üblichen Umlaute und Sonderzeichen in die Datenbank hinein und sogar wieder heraus zu bekommen. Allerdings fehlt der Datenbank damit auch jegliches Wissen über diese Umlaute, und das bedeutet, dass weder richtige Sortierreihenfolgen noch spätere Integration von anderen Clients oder Umstellungen auf andere Zeichensätze möglich sind. Die Auswahl der Zeichensätze sollte im Falle einer Umgebung mit mehreren Datenbanken besonders gut überlegt sein. Die Möglichkeit, Daten zwischen verschiedenen Datenbanken mit Hilfe von transportablen Tablespaces auszutauschen, wird seit mehreren Versionen unterstützt und funktioniert für Oracle 10g-Datenbanken sogar bei Datenbanken mit verschiedenen Betriebssystemplattformen (siehe hierzu Abschnitt 15.1.1). Allerdings müssen sowohl die Zeichensätze als auch die nationalen Zeichensätze von Quell- und Zieldatenbank übereinstimmen – bzw. der Zei-
356
Globalization Support
chensatz der Zieldatenbank muss eine strikte Obermenge des jeweiligen Zeichensatzes der Quelldatenbank sein. Die letzte Einschränkung deckt jedoch fast ausschließlich Fälle ab, in denen die Quelldatenbank mit US7ASCII betrieben wird, das eine strikte Teilmenge von fast allen Single-Byte-Zeichensätzen ist. Ein Zeichensatz X wird als strikte Obermenge eines anderen Zeichensatzes Y bezeichnet, wenn alle Zeichen aus Y in X enthalten sind und für alle Zeichen aus Y gilt, dass ihre Binärdarstellung (hierfür wird auch der Begriff Code Point verwendet) in X und Y identisch ist. Y wird dann auch als strikte Teilmenge bezeichnet. Eine gute Übersicht über alle hier besprochenen Zeichensätze findet sich im Internet unter der URL http://en.wikipedia.org/wiki/Character_encoding. Für die weiter unten besprochenen UNICODE-Zeichensätze empfiehlt sich ebenfalls die URL http://www.unicode.org.
8.4.1 Single-Byte-Zeichensätze Übliche Single-Byte-Zeichensätze für deutsche Installationen sind WE8ISO8859P1 (insbesondere dann, wenn die Datenbank bereits länger existiert), WE8ISO8859P15 (wie der vorige, enthält jedoch zusätzlich das €-Symbol) oder WE8MSWIN1252. Bei einer neu einzurichtenden Datenbank mit Single-Byte-Zeichensatz würde man grundsätzlich WE8MSWIN1252 den Vorzug geben, falls größtenteils mit MS-WindowsClients gearbeitet wird. Neben den meisten Unix-Umgebungen nutzen viele Javaund Webanwendungen ISO-Zeichensätze; hierbei wird heute meist WE8ISO8859P15 der Vorzug gegeben, weil es einerseits der neuere Zeichensatz ist und andererseits das €-Symbol enthält. Die ältere Variante, WE8ISO8859P1, wird oft genutzt, wenn ältere Datenbanken migriert werden und man daher auch weiß, dass das €-Symbol nicht benutzt wird. Nach der Einrichtung der Datenbankzeichensätze ist die richtige Einstellung des Clientzeichensatzes letztendlich bei jedem Programmaufruf zu überprüfen. Hierzu folgende Beispiele: Ein deutsches MS-Windows verwendet auf der grafischen Oberfläche den oben genannten Zeichensatz WE8MSWIN1252. Innerhalb einer DOS-Box verwendet es WE8PC850 (DOS Codepage 850). Daher arbeitet die grafische Version von SQL*Plus (sqlplusw.exe) mit dem ersten, die Kommandozeilenversion (sqlplus.exe) mit dem zweiten Zeichensatz. Lädt man Daten mit dem SQL*Loader in die Datenbank, so sollte man den Zeichensatz mit NLS_LANG auswählen, der die zu ladenden Daten beschreibt. Je nachdem, wo die Daten herkommen, hat dieser Zeichensatz nichts mit dem Zeichensatz des Clients zu tun. Beim Export/Import von Daten werden Meldungen über Zeichensätze angezeigt, z.B. wie folgende: Export done in WE8ISO8859P1 character set and UTF8 NCHAR character set server uses WE8ISO8859P15 character set (possible charset conversion)
Zeichensätze
357
Gerade die Anmerkung »possible charset conversion« könnte zu dem Schluss verleiten, dass die Daten vom Datenbankzeichensatz WE8ISO8859P15 in den eingestellten Clientzeichensatz WE8ISO8859P1 konvertiert werden – allerdings bezieht sich dies lediglich auf Data Dictionary-Informationen wie Tabellennamen usw. In früheren Export-Versionen wurde tatsächlich konvertiert, was oft zu Verlust von Umlauten, Sonderzeichen usw. führte. Seit Oracle9i konvertiert ein Export jedoch (glücklicherweise) nicht mehr, sondern belässt alle Zeichenketten im Zeichensatz der Datenbank.
8.4.2 Multi-Byte-Zeichensätze, insbesondere UNICODE Multi-Byte-Zeichensätze werden in dem Moment erforderlich, wo es nicht mehr ausreicht, alle Zeichen zu erfassen, die in einem Land, einer Region oder einem Teilkontinent verwendet werden. Diese Art der Abbildung von Regionen oder sprachlich verwandten Ländern wird beispielsweise durch das Konzept der ISO-Zeichensätze abgebildet. Es existieren u.a. spezielle Multi-Byte-Zeichensätze für Sprachen, die eine große Anzahl von Schriftzeichen benötigen, wie Chinesisch oder Japanisch. Diese spielen in Europa jedoch keine große Rolle, da diese Zeichensätze unsere ASCII-Zeichen i.A. nicht enthalten und erst recht keine Umlaute. Interessanter sind da die UNICODE-Zeichensätze, bei denen versucht wird, alle benötigten Schriftzeichen für internationale Anwendungen, also auch für alle Sprachen, in einem Zeichensatz zusammenzufassen. Hierbei gibt es unterschiedliche Kodierungsschemata (Encodings) und Versionen, da nach und nach immer mehr Sprachen und Zeichen integriert werden. An dieser Stelle sollte sofort klar sein, dass Single-Byte-Zeichensätze hierfür nicht geeignet sind und selbst 16-BitZeichensätze nicht ausreichen. Das meist genutzte Kodierungsschema wird mit UTF-8 bezeichnet und ist variabel lang: Zeichen werden mit einer Länge von einem bis vier Bytes kodiert. Dabei entsprechen die 1-Byte-Zeichen den ASCII-Zeichen. Umlaute werden z.B. bereits mit 2 Bytes dargestellt. Bei Oracle 10g sind neben UTF-8 auch die Kodierungen UCS-2 und UTF-16 wichtig. UCS-2 ist eine 2-Byte-Kodierung. UTF-16 ist eine strikte Obermenge von UCS-2 neueren Datums (UNICODE Version 3.2) und lässt zusätzlich 4-Byte-Darstellungen, insbesondere für Sonderzeichen, die bei UCS-2 nicht enthalten sind, zu. UTF-16 wird z.B. von MS-Windows 2000 und Java genutzt. Als Datenbankzeichensatz unterstützt Oracle 10g zwei UTF-8-Kodierungen: UTF8 und AL32UTF8. Der Unterschied zwischen den beiden Zeichensätzen ist, dass mit UTF8 die UTF-8-Kodierung der UNICODE-Version 3.0 unterstützt wird: die im Übrigen identisch zu Oracle8i und Oracle9i ist. AL32UTF8 unterstützt die jeweils neueste UNICODE-Version, was für Oracle 10g Version 3.2 bedeutet, für Oracle9i Version 3.1 und für Oracle8i Version 3.0. Für hostbasierte Umgebungen wird mit UTFE zusätzlich eine UTF-EBCDIC-Kodierung unterstützt.
358
Globalization Support
Die Unterstützung für nationale Zeichensätze unterscheidet sich von der für Datenbankzeichensätze: Hier werden ausschließlich die Zeichensätze UTF8 (wie oben) und AL16UTF16 akzeptiert. Letzterer entspricht der UTF-16-Kodierung der UNICODE-Version 3.2. Besonderheiten weisen die Oracle-Datentypen CLOB und NCLOB auf: Sobald der Datenbankzeichensatz ein Multi-Byte-Zeichensatz ist, werden CLOBWerte in UCS-2 kodiert, unabhängig davon, welcher Zeichensatz für die Datenbank gewählt wurde. NCLOB-Werte werden grundsätzlich (unabhängig vom Datenbankzeichensatz und vom nationalen Datenbankzeichensatz) in UTF-16 kodiert. Generell bedeutet die Verwendung von UNICODE als Datenbankzeichensatz, dass die Darstellung von Zeichenketten tendenziell verlängert wird. Die tatsächliche Verlängerung variiert zumindest bei der Verwendung der UTF-8-Kodierung: Je mehr Umlaute und Sonderzeichen verwendet werden, desto länger wird die Darstellung. Bei UCS-2- und UTF-16-Kodierungen verdoppelt sich der benötigte Speicherplatz gegenüber der Single-Byte-Darstellung. Längensemantik Bei der Arbeit mit Multi-Byte-Zeichensätzen stellt sich eine Frage, die bei SingleByte-Zeichensätzen nicht auftaucht: Was ist mit VARCHAR2(n) gemeint? Die Standardantwort überrascht ein bisschen: Es ist gemeint, dass die Darstellung einer Zeichenkette die Länge von n Bytes nicht überschreiten darf, und nicht etwa, dass n Zeichen als Länge der Zeichenkette nicht überschritten werden dürfen. Beim Übergang von einem Single-Byte-Zeichensatz auf UNICODE sind daher Probleme vorprogrammiert: Lässt man die Tabellendefinitionen so, wie sie sind, passen eventuell in ein Feld nicht mehr alle Zeichen hinein, die vorher enthalten waren. Zur Lösung des Problems kann die Längensemantik von BYTE (was der obigen Beschreibung entspricht) auf CHAR umgeschaltet werden. Dies geschieht entweder durch die Angabe der gewünschten Semantik in der Typdefinition (z.B. VARCHAR2(30 CHAR)) oder durch Änderung des NLS-Parameter NLS_LENGTH_SEMANTICS (auf Sitzungs- oder Instanzebene) auf einen der Werte BYTE oder CHAR. Für die meisten Anwendungen macht die CHAR-Längensemantik mehr Sinn als BYTE. Daher ist es empfehlenswert, den Parameter NLS_LENGTH_SEMANTICS mit dem Wert CHAR als Standardparameter aufzunehmen – und dies nicht nur für Datenbanken mit Multi-Byte-Zeichensätzen, sondern auch bei Single-Byte-Zeichensätzen. Bei Feldern, die auf dem nationalen Zeichensatz basieren (NCHAR usw.), gilt unabhängig von der Einstellung des Parameters NLS_LENGTH_SEMANTICS immer die CHARSemantik. Weiterhin gilt die Einschränkung, dass die Maximallängen für Zeichenketten in Bytes festgelegt sind (2000 Bytes für CHAR/NCHAR, 4000 Bytes für VARCHAR2/NVARCHAR2) und auch bei CHAR-Semantik nicht überschritten werden können. Dies bedeutet,
Zeichensätze
359
dass bei der Definition von z.B. VARCHAR2(4000 CHAR) je nach verwendetem Zeichensatz und den enthaltenen Zeichen die maximal mögliche Zeichenzahl kleiner als 4000 ist. Programmierung Die Behandlung von speziellen Zeichen erfordert oft die Benutzung von speziellen Funktionen. Ein Beispiel wurde mit der Funktion NLSSORT, mit der landesspezifische Sortierreihenfolgen abgebildet werden können, weiter oben bereits angegeben. Die SQL-Funktionen LOWER, UPPER und INITCAP sind jeweils in einer weiteren Version NLS_LOWER, NLS_UPPER und NLS_INITCAP vorhanden. In den NLS-Versionen werden landesspezifische Konventionen berücksichtigt, wie folgendes Beispiel zeigt: SQL> SELECT nls_upper('Fußball', 'NLS_SORT=German') 2 FROM dual; NLS_UPP ------FUßBALL SQL> SELECT nls_upper('Fußball', 'NLS_SORT=XGerman') 2 FROM dual; NLS_UPPE -------FUSSBALL
Die Originalversionen der Funktionen kennen solche Feinheiten nicht und manipulieren Zeichenketten immer nur Zeichen für Zeichen, wobei die Ergebniszeichenkette immer genauso lang ist wie der Ausgangswert. Mit der Funktion CONVERT(<str>, [, ]) können Zeichenketten in einen anderen Zeichensatz konvertiert werden. Der Quellzeichensatz ist normalerweise der Datenbankzeichensatz; allerdings können mit dieser Funktion unter Angabe des Quellzeichensatzes auch »falsche Daten« korrigiert werden. Diese können entstehen, wenn Clients mit falscher NLS_LANG-Einstellung Daten in die Datenbank schreiben.
8.4.3 Migration von Zeichensätzen Oft stellt sich bei einer Datenbankmigration (z.B. auf eine neue Version) die Frage, ob der Zeichensatz geändert werden soll. Aber auch ohne eine solche Migration stellt sich manchmal die Frage nach einem anderen Datenbankzeichensatz, z.B. wenn die Anforderung zur Darstellung von speziellen Zeichen auftaucht. Man muss unterscheiden, ob diese Migration mit der bestehenden Datenbank (In–PlaceMigration) oder durch einen Neuaufbau der Datenbank inklusive Ent- und Beladen der Daten, z.B. mittels Export und Import erfolgen muss. Bei der In-Place-Migration bleibt der Datenbankzeichensatz zunächst erhalten. Mit Hilfe des CSALTERSkripts kann dann für eine bestehende Datenbank, gewisse Vorbedingungen vorausgesetzt, der Datenbankzeichensatz geändert werden.
360
Globalization Support
Neuaufbau der Datenbank Beim Neuaufbau der Datenbank ist man in der Wahl des Zeichensatzes nicht sehr eingeschränkt; man sollte sicherstellen, dass der neue Zeichensatz eine Obermenge des alten ist oder dass der neue Zeichensatz zumindest alle verwendeten Zeichen des alten Zeichensatzes enthält. Beim Import werden alle Zeichen in den neuen Zeichensatz konvertiert. Zu beachten ist, dass beim Import die Feldwerte für die Längensemantik von der Quelldatenbank übernommen werden. Beim Import zieht die Einstellung von NLS_LENGTH_SEMANTICS also nicht. Möchte man die Längensemantik umstellen, so müssen zunächst die Tabellen über Skripte mit der gewünschten Einstellung von NLS_LENGTH_SEMANTICS angelegt werden. Danach kann der Import in die bestehenden Tabellen erfolgen. Verwendung des CSALTER-Skripts Zunächst eine Warnung: Mit der Umstellung des Zeichensatzes bzw. des nationalen Zeichensatzes einer Datenbank wird ein zentraler Parameter der Datenbank umgestellt, der extrem viel Einfluss auf die Funktionsweise und das Verhalten des Gesamtsystems hat. Diese Umstellung ist nicht trivial und erfordert ein Höchstmaß an Sicherheitsvorkehrungen. Für produktive Systeme gelten mindestens die folgenden Voraussetzungen: Die Umstellung muss zunächst an einer Kopie des produktiven Systems getestet werden. Der Test bezieht sich nicht nur auf die reine Konvertierung des Zeichensatzes, sondern auch auf die Funktionsfähigkeit sämtlicher Programme, die auf die Datenbank zugreifen. Vor der Umstellung des produktiven Systems muss in jedem Fall eine vollständige Sicherung durchgeführt werden. Empfehlenswert ist ebenfalls eine weitere Sicherung nach der erfolgten Umstellung. Das CSALTER-Skript verpackt den Befehl ALTER DATABASE [NATIONAL] CHARACTER SET INTERNAL_USE
in eine Umgebung, die versucht, mögliche Fehler bei der Konvertierung von Zeichensätzen auszuschließen. Während in früheren Version der oben angegebene Befehl direkt eingegeben werden konnte, gilt für Oracle 10g, dass ausschließlich der offizielle Weg über das CSALTER-Skript unterstützt wird. Das CSALTER-Skript erlaubt die Konvertierung des Datenbankzeichensatzes dann und nur dann, wenn für alle vorhandenen Zeichen in Benutzertabellen gilt, dass sie im neuen Zeichensatz die gleiche Binärdarstellung haben wie im alten Zeichensatz. Das bedeutet, dass zumindest für die Teilmenge der benutzten Zeichen gilt, dass der neue Zeichensatz eine strikte Obermenge des alten Zeichensatzes ist. Hierzu einige Beispiele: Die Konvertierung von US7ASCII in einen ISO-, Windows- oder UNICODE-Zeichensatz sollte praktisch immer funktionieren.
Zeichensätze
361
Die Konvertierung eines ISO-Zeichensatzes in UNICODE funktioniert nur dann, wenn alle verwendeten Zeichen im Bereich des US7ASCII-Zeichensatzes liegen. Mit anderen Worten: wenn keine Umlaute vorhanden sind. Falls von einem Single-Byte- in einen Multi-Byte-Zeichensatz konvertiert wird, dürfen keine CLOB-Spalten in Benutzertabellen vorhanden sein. Daraus folgt, dass das CSALTER-Skript keinerlei Konvertierungen auf Benutzerdaten vornimmt. Allerdings werden Zeichen im Data Dictionary passend konvertiert. Daher muss vorher mit dem Characterset Scanner Utility CSSCAN untersucht werden, ob diese Konvertierung verlustfrei durchgeführt werden kann. Voraussetzung für die Durchführung des CSALTER-Skripts ist ein vollständiger Durchlauf von CSSCAN, der nicht länger als sieben Tage zurückliegt. Das Characterset Scanner Utility benötigt seinerseits einige Datenbankobjekte, die mit dem Skript $ORACLE_HOME/rdbms/admin/csminst.sql angelegt werden. Das Skript legt u.a. den Benutzer CSMIG an, für den ein Passwort eingegeben werden muss. Der Aufruf des CSSCAN-Utilities sieht wie folgt aus: csscan system/ tochar=al32utf8 array=1000000 process=1 full=y
Mit dem Parameter TOCHAR wird der Zielzeichensatz angegeben. Alternativ kann mit TONCHAR auch ein geänderter nationaler Zeichensatz bestimmt werden. Mit ARRAY wird die Puffergröße für das Lesen von Daten eingestellt, mit PROCESS die Anzahl der Scanprozesse. Mit FULL wird bestimmt, dass die gesamte Datenbank gescannt werden soll. Es gibt einige weitere Parameter, mit denen das Verhalten von CSSCAN beeinflusst werden kann; einen Überblick bekommt man mit: csscan help=y
Das CSSCAN-Utility erzeugt mindestens eine Datei scan.txt, in der die Ergebnisse des Scans enthalten sind. Dort findet man u.a. Hinweise, ob eine Konvertierung ohne Risiko durchgeführt werden kann oder nicht. Falls die Konvertierung nicht durchgeführt werden kann, sollten die Gründe hierfür analysiert werden. Wenn ein Großteil der Datenbank Daten enthält, die einer Konvertierung im Wege stehen, so bietet sich eine Export-/Import-Umstellung in eine neue Datenbank an. Falls nur wenige Datenbankobjekte betroffen sind, können diese exportiert, gelöscht und nach der Konvertierung wieder importiert werden. Das CSALTER-Skript wird wie folgt aufgerufen: sqlplus / as sysdba @?/rdbms/admin/csalter.plb
Es benötigt eine SYSDBA-Anmeldung, da es zunächst die Instanz in den RESTRICTED SESSION-Modus setzt und dann, nach einer Reihe von weiteren Prüfungen, den zu Beginn dieses Abschnitts dargestellten ALTER DATABASE-Befehl zur tatsächlichen Änderung des Zeichensatzes (bzw. nationalen Zeichensatzes) absetzt. Falls das Skript erfolgreich durchläuft, muss der RESTRICTED SESSION-Modus anschließend wieder aufgehoben werden. Wie weiter oben bereits erwähnt, ist das CSALTER-Skript keine risikolose Angelegenheit; deshalb ist eine Vollsicherung vorher unerlässlich. Insbesondere für den Fall, dass Objekte mit Export/Import behandelt werden, ist eine weitere Vollsicherung nach der Aktion ebenfalls notwendig.
Sicherheit 9.1
Einführung
Das funktionale Umfeld, in dem Datenbanksysteme zum Einsatz kommen, ist in den letzten Jahren dramatisch erweitert worden. Vorbei sind die Zeiten, in denen einzig und allein Client-Anwendungen durch direkte Connect-Operationen auf relationale Daten zugriffen. Drei- und mehrschichtige Architekturen erfordern heute auch dann sichere Authentifizierungen und Autorisierungen der Anwender, wenn diese nicht als Benutzer in der Datenbank registriert wurden. Gleichermaßen fordern Anwender, die mit einer Vielzahl von Systemen arbeiten müssen, eine zentrale, sichere Identifizierung für den Zugriff auf alle Systeme. Einhergehend mit dieser Entwicklung wurden neue, erweiterte Anforderungen an die Sicherheitsmerkmale von Datenbanksystemen gestellt. Vor diesem Hintergrund wurden auch die Sicherheitsmerkmale von Oracle9i und Oracle 10g durch neue Funktionalitäten ergänzt, so dass dem Datenbankverwalter nun eine breite Palette erprobter Techniken für die sichere Konfiguration seiner Systeme zur Verfügung steht. Das Thema Sicherheit im Kontext von Datenbanken wird jedoch nicht durch den Einsatz einzelner Features erledigt, sondern lebt erst durch die konzertierte Planung, Konfiguration und kontinuierliche Überwachung der relevanten Systeme. In vielen Fällen wird dem Thema Sicherheit immer noch zu wenig Aufmerksamkeit geschenkt. Sicherheit kostet Zeit und Geld für die Planung und Implementierung, Geld für Hard- und Software, Zeit und Geld für die Ausbildung der Beteiligten. Wir sollten uns hüten, Sicherheit nur als Synonym für Datenverschlüsselung zu handeln, um das unerlaubte Abhören, Lesen und Modifizieren von Daten während der Übertragung über ein Netzwerk zu verhindern. Sicherheit hat viele wichtige Seiten! Eine angemessene Benutzerplanung und Authentifizierung, Strategien bei der Wahl und Verwaltung von Schlüsselwörtern, die bewusste und maßvolle Zuteilung von Privilegien sowie die Beobachtung des Systems sind mindestens ebenso wichtig für eine sichere Datenbankumgebung wie die oben genannte Verschlüsselung. Es sollte daher in jedem Projekt von Anfang an auch für diese Aspekte genügend Zeit eingeplant werden. Der große Nachteil einer ungenügenden Sicherheitsplanung ist leider der, dass die Sicherheitslücken oftmals über Jahre nicht bemerkt werden, ganz im Gegensatz zu einer unvollständigen Planung von Funktionen, die jedem Anwender sofort ins Auge springt, weil er bestimmte Aktionen nicht ausführen kann. Die Literatur ist voll von Definitionen zum Begriff »Datenbanksicherheit«. Eine dieser Definitionen soll dieses Kapitel einleiten: »Datenbanksicherheit besteht aus einem Korpus von Maßnahmen, Verfahrensweisen (Policy) und Mechanismen, welche die Geheimhaltung, Integrität und Verfügbarkeit von Daten sicherstellen und mögliche interne und externe Angriffe, ob bösartiger oder zufälliger Art, abwehren sollen.«1
364
Sicherheit
Diese Definition macht bereits deutlich, dass Sicherheit im Allgemeinen und Datenbanksicherheit im Besonderen nicht nur aus einem Katalog von technischen Features besteht, sondern in ein breites organisatorisches Umfeld eingebettet ist. Sicherheit beginnt mit der Bereitschaft der Unternehmensleitung und der betreffenden Abteilungen, in die notwendigen Maßnahmen zu investieren, geht dann über rein »physikalische« Maßnahmen, die regeln, wer wann Zugang zur Hardware der betreffenden Datenbank haben darf, bis hin zur »logischen« Lösung der Problemstellungen über die zur Verfügung stehende Software. Sicherheit im Bereich der Datenbank geht dabei in vielen Aspekten über die Anforderungen der zugrunde liegenden Betriebssysteme hinaus. Ist die Datei für das Betriebssystem die kleinste Einheit, für die Zugriffe definiert werden können, muss die Datenbanksoftware die Zugriffe auf wesentlich feinere Art regeln. Jede Datenbankdatei enthält bekanntlich eine beliebige Anzahl von Objekten, deren Zugriff einzeln zu legitimieren ist. Innerhalb der Objekte muss es ferner möglich sein, den Zugriff für einzelne Tupel oder Attribute zu bestimmen. Schließlich werden dynamisch Ergebnistabellen generiert, die ebenfalls Sicherheitsanforderungen genügen können. Die Risiken, die entstehen, wenn das Thema Sicherheit nicht in der notwendigen Form Berücksichtigung findet, sind vielfältig: Verletzung der Geheimhaltungspflicht (Privacy) durch unberechtigten Zugriff auf Daten, Verletzung der Integrität durch unerlaubtes Modifizieren von Daten Verletzung der Geheimhaltung durch unerlaubte Schlussfolgerungen (Die Fehlermeldung ORA-00001: Verstoß gegen Eindeutigkeit ... lässt beispielsweise den Schluss zu, dass ein Datensatz mit dem angegebenen Schlüssel bereits existiert, auch wenn er vom Benutzer nicht gelesen werden kann.) Verletzung der Geheimhaltung durch das Aggregieren von Daten (Das Lesen einzelner Sätze einer Tabelle mag beispielsweise erlaubt sein, aber die Bildung von maximalen Werten oder Durchschnittswerten über die gesamte Tabelle kann eine Verletzung der Geheimhaltung bedeuten.) Daten können auch über verdeckte Kanäle (Covert Disclosure) an Unbefugte gelangen. (Einem Benutzer A wird das Recht gegeben, Tabelle T1 zu lesen, Benutzer B dagegen nicht. Benutzer A darf darüber hinaus eigene Tabellen erzeugen. Er kann nun die Daten der Tabelle T1 in eine eigene Tabelle einfügen und Benutzer B ein Leserecht an dieser Tabelle einräumen.) Das folgende Kapitel soll daher eine Anleitung zur Planung und Konfiguration einer sicheren Datenbankumgebung liefern. Dabei ist vor allem auch wichtig, dass Datenbanksicherheit auch das hardware- und softwaretechnische Umfeld betrachten muss. Das bedeutet konkret: Datenbanksicherheit ist nur dann möglich, wenn auch das umgebende Betriebssystem und die Netzwerkumgebung entsprechend abgesichert werden. Darüber hinaus gilt es, in dem Kräftedreieck aus Kosten, Sicherheitsanforderungen und Performance eine Lösung zu finden, die der entsprechenden Anwendungsumgebung und dem zur Verfügung stehenden Budget gerecht wird. Nicht jede Lösung erfordert die höchste Sicherheitsstufe, aber umgekehrt darf Sicherheit auch nicht dem – konfiguratorischen – Zufall überlassen werden. 1
Castano et al., Database Security, Seite IX.
Einführung
365
Die folgenden Meilensteine können das Projekt Datenbanksicherheit markieren: Identifizierung: Sensible Daten können nur dann geschützt werden, wenn zugreifende und ändernde Benutzer eindeutig identifiziert und aufgrund der Identifizierung sicher authentifiziert werden können. Dies wird durch eine gute Benutzerplanung erreicht. Privilegierung: Die eindeutige Identifizierung der Benutzer gibt den Weg für ihre Privilegierung frei, durch die nur solche Daten sichtbar und modifizierbar sind, die für den betreffenden Benutzer freigegeben sind (Least Privilege-Prinzip). Systemüberwachung: Sicherheitstechnik ist wertlos, wenn sie nicht überwacht wird. Es ist daher wichtig, sensible Bereiche auch mit Mitteln des Auditings zu kontrollieren und die entstehenden Zugriffsprotokolle auch auszuwerten! Verschlüsselung: Unzureichend geplante Sicherheitssysteme können leicht durch »Maskerade« (Masquerading oder Spoofing) geknackt werden, indem Externe die Identität registrierter Benutzer annehmen und dadurch – scheinbar legal – Informationen einsehen können. Um Maskerade zu verhindern oder zumindest zu erschweren, ist nicht nur eine starke Authentifizierung notwendig, sondern ebenso die durch Verschlüsselung geschützte Übertragung der Daten über die vorhandenen Kommunikationswege. In besonders sensiblen Fällen kann es auch notwendig werden, Daten innerhalb der Datenbank zu verschlüsseln, um sie der Interpretation von SELECT ANY Benutzern zu entziehen. Dem Verwalter stehen dabei aus Sicht der Datenbank folgende Instrumente zur Verfügung: Identifizierung und Authentifizierung: Die Authentifizierung von Benutzern kann über die Datenbank – mit oder ohne Passwort – erfolgen oder über externe Instanzen, wie z.B. LDAP-Directory Services, Kerberos und verwandte Verfahren. Datenbankbenutzer können dabei wahlweise individuell oder als »Gruppenbenutzer« konfiguriert werden. Für die Privilegierung der Benutzer stehen System- und Objektprivilegien zur Verfügung. Über Rollen lassen sich diese Privilegien bündeln und den Benutzern zuordnen. Für besondere Anforderungen kann die Aktivierung der Rollen an Passwörter gebunden oder über definierte und gesicherte Packages ausgeführt werden, um zu verhindern, dass Benutzer eigenmächtig Privilegien in nicht freigegebenen Kontexten nutzen. Rollen lassen sich auch zentralisiert – als Enterprise Roles – im Rahmen von Oracle Internet Directory definieren und steuern dann die Aktivierung der Datenbankrollen in konkreten Zielsystemen. Dort wo die objektbezogene Privilegierung nicht ausreicht, lässt sich eine zeilen- und spaltenspezifische Freigabe von Daten konfigurieren. Hierzu stehen die Techniken Virtual Private Database und Label Security zur Verfügung. Besonders sensible Daten können in der Datenbank mit Hilfe des Pakets DBMS_CRYPTO2 verschlüsselt werden. Die Übertragung der Daten von und an die jeweiligen Clients kann über Parameter im Kontext von Oracle NET konfiguriert werden. 2
Der Vorgänger dieses Pakets (Version 9) war DBMS_OBFUSCATION_TOOLKIT.
366
Sicherheit
Vielfältige Auditing-Funktionen ermöglichen eine maßgeschneiderte Überwachung der Zugriffe. Die oben zusammenfassend erwähnten Maßnahmen sind für jedes Projekt und jede Anwendung individuell zu planen und zu konfigurieren. Darüber hinaus gibt es jedoch eine Reihe von allgemeinen konfiguratorischen Aktionen, die der Verwalter unabhängig von einzelnen Anwendungen im Kontext der Datenbank durchführen sollte, um die Grundlage für eine sichere Umgebung zu schaffen. Diese grundlegenden Maßnahmen werden im folgenden Abschnitt dargestellt. Es versteht sich, dass diese Maßnahmen im Umfeld der Netzwerke und Betriebssysteme zu ergänzen sind.
9.2
Grundlegende Maßnahmen
Wie bereits erwähnt gibt es einige Maßnahmen, die der Verwalter unabhängig von den die Datenbank nutzenden Anwendungen aus Gründen der Sicherheit durchführen sollte.
9.2.1
Maßgeschneiderte Installation
Bei der Installation der Software sollten nur die Komponenten aufgespielt werden, die im Rahmen des betreffenden Home-Verzeichnisses auch tatsächlich benötigt werden. Hier bietet die CUSTOM- Auswahl des Universal Installers die entsprechenden Möglichkeiten. Das Gleiche gilt auch für die Installation und Konfiguration der einzelnen Datenbanken. Viele Optionen, wie z.B. Intermedia oder Spatial, legen in eigenen Schemata Objekte in der Datenbank ab. Die jeweiligen Schemabenutzer werden mit Standardpasswörtern angelegt, sind in der Regel hoch privilegiert und stellen – wenn sie nicht genutzt und dementsprechend konfiguriert werden – ein beträchtliches Risiko für die Sicherheit der Datenbank dar.
9.2.2
Standardpasswörter
Standardpasswörter sind auf jeden Fall zu vermeiden. Dies gilt nicht nur für die hochrangigen Benutzer SYS und SYSTEM und die im vorangehenden Abschnitt erwähnten Optionsbenutzer, sondern auch für die – möglicherweise – zahlreichen Benutzer, die durch Skripte und Tools nach der eigentlichen Installation angelegt werden und die in vielen Fällen mit sehr üppigen Privilegien ausgestattet sind. Pete Finnigan hat sich zusammen mit einige Kollegen die Mühe gemacht, diese Benutzer und ihre Standardkennwörter auf seiner Website3 zu veröffentlichen. Seine Liste weist zum Zeitpunkt der Drucklegung dieses Buches knapp 600 Einträge auf! Der Datenbank-Konfigurationsassistent bietet neuerdings die Möglichkeit, unterschiedlichen Systembenutzern – die Auswahl ist abhängig von den gewählten Installationsoptionen – eigene Kennwörter zuzuteilen. Hier sollten unbedingt unterschiedliche Kennwörter verwendet und auf die Zuteilung desselben Kennwortes verzichtet werden. 3
Die URL lautet: http://www.petefinnigan.com/default/default_password_list.htm
Grundlegende Maßnahmen
367
Abbildung 9.1: Anpassung von Standardpasswörtern
Darüber hinaus werden zum Ende der Installation einige der Accounts für Optionen, wie z.B. LBACSYS für die Label Security, gesperrt. Dies ist sicherlich sehr sinnvoll. Trotz allem bleiben hohe Risiken, weil einige Benutzer erst nachträglich über Installationsskripte von externen Werkzeugen, wie z.B. SQL Navigator, angelegt werden oder aber Optionsbenutzer nach der Installation wieder aktiviert und durch ihr kompromittierendes Kennwort zum Risiko werden können. Neben Benutzern legen Werkzeuge auch Rollen an, die kritische Privilegien enthalten können. Es ist daher dringend zu empfehlen, produktive Systeme nach diesen Standardbenutzern und neue Rollen zu durchforsten. Im Einzelnen ist folgendes Vorgehen ratsam: Feststellen, welche Standardbenutzer installiert wurden. Wenn diese Benutzer noch mit dem Standardkennwort versehen sind, sollte dieses sofort über den Befehl alter user (s.u.) geändert werden. Für alle Accounts, deren Objekte zwar benötigt werden, die jedoch kein direktes Connect erfordern, ist das Privileg create session über den Befehl revoke zu entziehen. Hierbei ist zu beachten, dass dieses Privileg durchaus redundant vergeben worden sein kann, etwa über eine oder mehrere Rollen oder auch als direktes Systemprivileg. Abschnitt Privilegien und Rollen dieses Kapitels beschreibt die hierfür wichtigen Informationsquellen. Zusätzlich oder alternativ kann das Schema über den Befehl alter user auch gesperrt werden. Accounts, deren Objekte überhaupt nicht benötigt werden, sollten vollständig gelöscht werden: drop user <username> cascade;
368
Sicherheit
Über die bereits erwähnte Webseite von Pete Finnigan lässt sich auch ein kleines Werkzeug laden, mit dem Datenbanken auf Standardbenutzer und ihre unveränderten Passwörter hin untersucht werden können. Dieses Werkzeug besteht aus einer Hilfstabelle mit den betreffenden Daten der Standardbenutzer und einer kleinen PL/SQL-Prozedur, welche die »gehashten« Kennwortdaten4 der View dba_users mit den Standarddaten der Hilfstabelle vergleicht. Das Ergebnis ist ein kleiner Report, der auf die gefundenen Schwachstellen hinweist. Die Prozedur untersucht jedoch nicht, ob hoch privilegierte Rollen von Werkzeugen bereits dritten Benutzern zugeteilt wurden.
Abbildung 9.2: Beispielausgabe des Password-Checkers
9.2.3
Vordefinierte Rollen und Grants
Nach der Installation der Datenbank steht bekanntlich eine ganze Reihe von vordefinierten Rollen, allen voran die Rollen CONNECT, RESOURCE und DBA, zur Verfügung. Vor allem die Privilegien der Rollen CONNECT und RESOURCE sollten vom DBA geprüft und ggf. angepasst werden, bevor sie leichtfertig an Endbenutzer vergeben werden. In vielen Fällen werden eigene Standardrollen – z.B. _connect – angelegt, die den Benutzern grundlegende Systemprivilegien in einer Form zuteilen, die konform zu den jeweiligen Sicherheitsrichtlinien ist. Alle Einzelheiten zur Arbeit mit Rollen finden sich in Abschnitt Privilegien und Rollen. 4
Passwörter für Benutzer oder Rollen werden in den Metadaten des Data Dictionarys nicht verschlüsselt, sondern »gehasht« als hexadezimale Zeichenkette der Länge 16 gespeichert. Gehashte Zeichenketten lassen sich – im Gegensatz zu verschlüsselten Daten – nicht in den Originalwert zurückführen. Wohl aber ergibt jede Zeichenkette immer wieder einen identischen Hashwert. Auf diese Weise funktioniert der Mechanismus der Authentifizierung.
Grundlegende Maßnahmen
369
Gleichfalls sollten Grants, die im Kontext von Tabellen, Views oder Prozeduren an PUBLIC vergeben wurden, bekannt sein und überprüft werden. Die durch die Installation vergebenen Grants für die Pakete utl_smtp, utl_tcp, utl_http und utl_file sollten auf jeden Fall zurückgenommen werden. Grundsätzlich gilt auch hier, dass Privilegien nur für die Benutzer erteilt werden, die mit den Rechten legitim arbeiten müssen. Ein häufiges Problem stellen in diesem Zusammenhang Anwendungen dar, die herstellerunabhängig entwickelt wurden und aus diesem Grunde nicht sehr differenziert mit Privilegien umgehen – mit anderen Worten, Zugriffsfehler dadurch eliminieren, dass sie höchstprivilegierte Rechte voraussetzen. Hier kann es notwendig werden, derartige Anwendungen in separaten Instanzen zu isolieren, wo sie den geringsten möglichen Schaden anrichten können.
9.2.4
Patches
Software ist niemals vollständig und für alle Zeiten sicher. Dies gilt auch für OracleDatenbanken. Aus diesem Grunde sollten relevante Sicherheits-Patches so zügig wie möglich5 eingespielt werden. Seit dem Jahr 2005 veröffentlicht Oracle im Internet6 vierteljährlich so genannte Critical Patch Updates, die relevante Sicherheitsprobleme beschreiben und entsprechende Patches bereitstellen. Die Veröffentlichung findet jeweils am ersten Dienstag nach dem 15. der Monate Januar, April, Juli und Oktober statt. Die veröffentlichte Liste enthält auch Verweise auf Metalink-Dokumente, welche die Einzelheiten der betreffenden Patches beschreiben. In den vorangehenden Jahren wurden stattdessen in unregelmäßiger Folge Security Alerts bereitgestellt, die relevante Sicherheitsprobleme und ihren Kontext beschrieben haben und auf entsprechende Patches verwiesen. Die oben erwähnte URL gibt eine vollständige Übersicht über alle verfügbaren Patch-Updates und Alerts. Darüber hinaus enthält das Metalink-Dokument 237007.1 mit dem Titel FAQ for Security Alerts und Critical Patch Updates eine gute Einführung in das Thema sowie die Liste aller Alerts und Patches seit November 2001. Der Support-Status für Oracle 10g Release 1 sowie verfügbare Alerts werden auch in dem Dokument mit der ID 263719.1 beschrieben. Entsprechende Dokumente sind auch für ältere Versionen über Metalink verfügbar7.
5
6 7
Der Zeitpunkt ist einerseits abhängig von der individuellen betriebsinternen Situation, andererseits auch von technischen Kontroversen – siehe hierzu die kritische Diskussion von Patches am Beispiel des Juli 2005 Patches unter http://red-database-security.com. Die URL lautete zur Drucklegung: http://otn.oracle.com/deploy/security/alerts.htm Für die Version 9i Release 2 das Dokument 189908.1, für Version 9i das Dokument 149018.1 und für Version 8.1.7 das Dokument 120607.1
370
9.3
Sicherheit
Sichern der Datenübertragung
Vorbei sind die Zeiten, da Benutzer direkt auf den Server-Maschinen ihre Datenbankverbindungen aufgenommen haben. In der Regel werden Sessions from remote, sei es aus Client-Applikationen heraus oder über einen Application-Server, initiiert. In diesen Fällen werden die Daten über mehr oder weniger sichere Netzwerke transportiert. Wenn auch der eigentliche Authentifizierungsprozess, d.h., die Übermittlung des Benutzerkennwortes in verschlüsselter Form und damit hinreichend sicher erfolgt, ist es trotzdem aus unterschiedlichen Gründen sinnvoll, zusätzlich in die Netzwerksicherheit zu investieren: Werkzeuge zum »Schnüffeln« in Netzwerken (Network Sniffer) können leicht aus dem Internet besorgt und problemlos installiert werden. Der komplette Datenverkehr außerhalb der Authentifizierung läuft unverschlüsselt ab. Damit können alle SQL-Befehle und die zurückfließenden Antworten im Klartext abgefangen und ausgewertet werden. Bei dem Datenverkehr können auch Kennwörter unverschlüsselt gesendet werden, wenn beispielsweise Rollen, die über Passwörter geschützt sind, mit dem Befehl set role aktiviert werden. Neben der Verschlüsselung des Datenstromes, der sicherstellt, dass Pakete von Unbefugten nicht gelesen werden können, sollten auch Modifikationen dieser Daten während der Übertragung vereitelt werden. Letzteres lässt sich durch den Einsatz von kryptografischen Hash-Funktionen erreichen, die Prüfsummen der übermittelten Datenpakete vergleichen und im Falle einer Modifikation entsprechende Meldungen ausgeben. Schließlich ist es wichtig, die für die Datenbankverbindung notwendigen Prozesse – hier vor allem den Listener-Prozess – und die NET-Konfigurationsdateien vor unerwünschten Modifikationen zu schützen. Die folgenden Abschnitte beschreiben die hierfür notwendigen Schritte.
9.3.1
Konfiguration des Listener-Prozesses
Der Listener-Prozess wird bekanntlich benötigt, um eingehende Verbindungsanforderungen an Datenbanken entgegenzunehmen, zu verarbeiten und dafür zu sorgen, dass die Kommunikation des Clients mit der geforderten Datenbank hergestellt werden kann. Die benutzten Authentifizierungsmechanismen sorgen letzten Endes dafür, ob die gewünschte Verbindung erfolgreich aufgebaut werden kann. Bis zur Version 9i war es dringend zu empfehlen, das Herunterfahren und Neuladen des Listener-Prozesses mit Hilfe des Befehls lsnrctl über ein Passwort zu schützen. Dies war vor allem auch deshalb ratsam, weil Listener-Prozesse grundsätzlich auch from remote administriert werden können. Hierzu ist lediglich das lsnrctl-Programm und eine jeweils lokale listener.ora-Datei nötig, die einen Eintrag mit entsprechender host-Spezifikation für den betreffenden Listener auf der remoten Maschine enthält. Mit diesen Mitteln lassen sich dann alle lsnrctl-Befehle außer dem start-Befehl absetzen!
Sichern der Datenübertragung
371
Ab der Version 10g wird der Listener-Prozss mit Mitteln des jeweiligen Betriebssystems geschützt. Das bedeutet: Der Listener kann nur von dem Betriebssystembenutzer gestoppt oder neu konfiguriert werden, der ihn auch gestartet hat; und das auch nur auf dem Rechner, auf dem der betreffende Listener gestartet wurde. Diese Default-Einstellung kann über den Befehl lsnrctl stat leicht kontrolliert werden. Security
ON: Local OS Authentication
Wird in dieser Konfiguration versucht, den Listener zu stoppen, erscheint die folgende Fehlermeldung: LSNRCTL> stop Connecting to (DESCRIPTON=(ADDRESS=(PROTOCOL=TCP)(HOST=NandaDevi)(PORT=1529))) TNS-01190: The user is not authorized to execute the requested listener command
Die Konfiguration eines Passwortes empfiehlt sich aus diesem Grunde nur dort, wo ein anderer Benutzer legitim das Stoppen oder Neuladen des Listeners ausführen oder die Administration des Listeners auch from remote möglich sein soll. Die Konfiguration kann über das Werkzeug Oracle Net Manager – Aufruf über netmgr – oder, vielleicht einfacher, direkt mit Hilfe des Kommandozeilenprogramms lsnrctl (Listener Control) erfolgen. Für die erstmalige Passwortkonfiguration eines Listeners mit Namen Listener2 sind beispielsweise die folgenden Kommandos erforderlich: LSNRCTL> set current_listener listener2 Current Listener is listener2 LSNRCTL> change_password Old password: New password: Reenter new password: Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=NandaDevi)(PORT=1529))) Password changed for listener2 The command completed successfully LSNRCTL> save_config Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=NandaDevi)(PORT=1529))) Saved listener2 configuration parameters. Listener Parameter File /app/oracle/product/10gR1/network/admin/listener.ora Old Parameter File /app/oracle/product/10gR1/network/admin/listener.bak The command completed successfully
Nach dem Anlegen – und natürlich auch Ändern – des Passwortes über change_password muss die neue Einstellung mit save_config in die Konfigurationsdatei listener.ora übernommen werden. Diese speichert das Kennwort in »gehashter« Form. lsnrctl fügt darüber hinaus – anders als netmgr – entsprechende Kommentare hinzu: #----ADDED BY TNSLSNR 11-AUG-2005 21:58:30--PASSWORDS_LISTENER2 = (B86693A9CB9FB57D) #--------------------------------------------
372
Sicherheit
Zur Kontrolle der Einstellungen zeigt lsnrctl stat anschließend folgendes Bild: Security
ON: Password or Local OS Authentication
Es ist auf jeden Fall davon abzuraten, das Passwort direkt in die Datei listener.ora zu schreiben, weil es in diesem Fall unverschlüsselt erscheint und damit leicht kompromittierbar ist. Der Benutzer, unter dem der Listener gestartet wurde lässt sich – unter Unix – leicht über das Kommando ps –ef | grep <listener_name> ermitteln: oracle
8512
1
0 Aug11 ?
00:00:00 /app/oracle/product/10gR1/bin/tnslsnr listener2
In diesem Beispiel läuft der Prozess unter dem Oracle Installations-Account oracle. Folglich müssen Dritte, die den Listener listener2 stoppen oder neu konfigurieren, das eingestellte Passwort nutzen: LSNRCTL> set current_listener listener2 Current Listener is listener2 LSNRCTL> set password Password: The command completed successfully LSNRCTL> stop listener2 Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=NandaDevi)(PORT=1529))) The command completed successfully
Die Online-Modifikation sämtlicher Listener-Parameter kann neuerdings auch vollständig über den Parameter ADMIN_RESTRICTIONS_<listenername> = on unterbunden werden. Der Parameter bewirkt, dass keine set-Befehle von lsnrctl akzeptiert werden. Die Änderung der Parameter kann jedoch immer noch durch Modifikation der Parameterdatei listener.ora und anschließendes Neuladen – reload – des Listeners erfolgen. Der gewährte Schutz ist also nur von begrenzter Natur. Auch für den Listener gilt, dass die sicher eingestellte Konfiguration kontrolliert werden sollte. Hierzu reicht es aus, das Logging einzuschalten – und auch zu sichten –, um die abgesetzten Befehle und damit eventuelle Attacken leichter erkennen zu können. Die folgenden Befehle sind hierzu notwendig. Auf die Eingabe des Passwortes kann – wie oben dargelegt – im Standardfall verzichtet werden: LSNRCTL> set current_listener <listener name> LSNRCTL> set password Password: <enter listener password> LSNRCTL> set log_directory /network/log LSNRCTL> set log_file <sid name>.log LSNRCTL> set log_status on LSNRCTL> save_config
Das Log- wie auch das Konfigurationsverzeichnis sollten gut geschützt werden, d.h., Lese- und Schreibrechte sollten nur für den Oracle-Installationsbenutzer gewährt werden. Alle nicht benötigten Services, die explizit in der listener.ora-Datei konfiguriert oder über Kopieraktionen leichtfertig übernommen wurden, sollten gelöscht werden. Per Default findet sich dort häufig ein Eintrag (key = extproc) für externe Pro-
Sichern der Datenübertragung
373
zeduraufrufe, der nur gerechtfertigt ist, wenn – z.B. über die Intermedia-Option – tatsächlich mit externen Programmaufrufen gearbeitet wird. Zusätzlich können dem Listener IP-Adressen übergeben werden, denen er vertrauen oder nicht vertrauen darf. Diese Option ist vor allem dort von Interesse, wo die Anzahl der zulässigen IP-Adressen bekannt bzw. überschaubar ist und auch keine zu große Dynamik aufweist – idealerweise bei Betrieb eines Application-Servers, über den alle Verbindungsanforderungen an die Datenbank abgesetzt werden. Diese Option ist zwar nicht völlig »wasserfest«, da IP-Adressen bekanntlich gefälscht werden können (Spoofing), setzt den Schwierigkeitsgrad für potenzielle Eindringlinge jedoch ein ganzes Stück nach oben. Die Konfiguration erfolgt über die Profile-Datei sqlnet.ora und kann dort entweder per Editor oder mit Hilfe des Net-Manager-Werkzeugs8 vorgenommen werden. Die Parameter erlauben das Aktivieren oder Deaktivieren der Prüfung sowie die konkrete Einstellung der Adressen oder Hostnamen. Es werden keine Wildcards akzeptiert: TCP.VALIDNODE_CHECKING = YES TCP.INVITED_NODES= (192.168.33.120, MyServer)
Über den Parameter TCP.EXCLUDED_NODES lassen sich entsprechende Schwarzlisten konfigurieren. Des Weiteren kann überlegt werden, den Standard-Listenerport 1521 sowie die häufig genutzten Ports 1522 bis 1540, die gerne von Hackern für Portscans genutzt werden, zu meiden und stattdessen eine weniger bekannte »Port-Nische« zu nutzen. Diese Maßnahme erhöht den Aufwand für die genannten Portscans erheblich und verbessert auf diese Weise den Schutz. Für den Fall, dass externe Prozeduraufrufe nötig sind, sollten diese über einen separaten Listener-Prozess ausgeführt werden, der nicht unter dem Oracle-Benutzer läuft. Ein Sicherheitsrisiko kann in diesem Bereich deshalb entstehen, da die externen Programme die Privilegien des Oracle-Installations-Accounts und damit die Zugriffsrechte auf die Datenbankdateien erben könnten. Aus diesem Grunde sind die folgenden Maßnahmen ratsam: Konfiguration eines separaten Listeners mit eigenem Namen – beispielsweise listener_ext –, eigener Portnummer und eigenem Log-Verzeichnis. Start dieses Listeners über lsnrctl start <listenername> unter einem gering privilegierten Benutzer. Damit dies gelingt, muss der Betreffende Zugriff auf das Kommando lsnrctl, Leserechte auf der Konfigurationsdatei listener.ora sowie Schreibrechte in dem konfigurierten Log-Verzeichnis haben. Beginnend mit der Version 9.2.0 hat Oracle den Zugriff auf externe Programme standardmäßig auf das Verzeichnis $ORACLE_HOME/bin (unter Windows) oder $ORACLE_HOME/lib (unter Unix) beschränkt. Programme, die sich in anderen Verzeichnissen befinden, können zunächst nicht aufgerufen werden, es sein denn, der Listener wird explizit dafür konfiguriert. Die Konfiguration kann zusätzlich zu den bestehenden Standards oder explizit erfolgen und wird über den envsParameter der Datei listener.ora gesteuert. 8
Die Einstellung erfolgt über Profil -> Allgemein -> Zugriffsrechte.
374
Sicherheit
Im folgenden ersten Beispiel wird die Konfiguration in Erweiterung der Standardvorgaben vorgenommen, im zweiten Ausschnitt exklusiv. Es versteht sich, dass dieser Parameter genauestens kontrolliert werden muss. LISTENER_EXT= (DESCRIPTION= (ADDRESS_LIST= (ADDRESS=(PROTOCOL=tcp)(HOST=myserver)(PORT=1599)) (ADDRESS=(PROTOCOL=ipc)(KEY=extproc)) ) ) SID_LIST_LISTENER_EXT= (SID_LIST= (SID_DESC= (GLOBAL_DBNAME=global.db.name) (ORACLE_HOME=/u01/app/oracle) (SID_NAME=test10)) (SID_DESC= (SID_NAME=plsextproc) (ORACLE_HOME=/oracle) (PROGRAM=extproc) (ENVS="EXTPROC_DLLS=/u01/app/oracle/common/shell.so"))) Listing 9.1: Erweiterung des Standard-DLL-Pfades (ENVS="EXTPROC_DLLS=ONLY:/u01/app/oracle/common/shell.so") Listing 9.2: Ausschnitt aus listener.ora für exklusive DLL-Zuweisung.
9.3.2
Verschlüsselung und Integrität
Um die Daten während der Übertragung vor unerlaubtem Lesen und vor unberechtigten Veränderungen zu schützen, d.h., die Geheimhaltung (Data Privacy) und Integrität zu garantieren, ist es notwendig, Algorithmen für die Verschlüsselung sowie für die Generierung von Prüfsummen zu konfigurieren. Dies ist sowohl für Clients möglich, die über Oracle Net Services mit der Datenbank kommunizieren, als auch für solche, die über »dünne« JDBC-Treiber (thin JDBC) ihre Verbindungen aufbauen. Das Prozedere, das in beiden Umgebungen durchlaufen wird, ist im Wesentlichen identisch: Client und Server stimmen sich über die von ihnen unterstützten Algorithmen und ihre Bereitschaft zu verschlüsseln ab, generieren Zufallszahlen, tauschen über das Diffie-Hellmann-Verfahren ihre Session-Keys aus und nutzen das Oracle Login-Protokoll. Die Verschlüsselung und Integrität wird – im Kontext von Oracle Net Services – über die Profildatei sqlnet.ora gesteuert. Beide Verfahren können unabhängig voneinander konfiguriert werden, wenn sie auch in der Regel im Verbund eingesetzt werden, um einen umfassenden Schutz zu garantieren. Die Konfiguration kann direkt durch Editieren der Datei sqlnet.ora oder – komfortabler – mit Hilfe des Net Managers und dort über PROFIL – ORACLE ADVANCED SECURITY sowie die Tab-Reiter INTEGRITÄT und VERSCHLÜSSELUNG konfiguriert werden. Es werden die Einstellungen für Client und Server jeweils getrennt konfiguriert. Für beide Parteien lässt sich, neben den unterstützten Algorithmen, auch das Verhalten in Bezug auf Verschlüsselung und Integritätsprüfung getrennt angeben:
Sichern der Datenübertragung
375
zurückgewiesen (rejected) – weist die Anforderung zurück. Sollte die Gegenseite auf der Anforderung bestehen, kann die Verbindung nicht aufgebaut werden. akzeptiert (accepted) – erklärt die Bereitschaft für den Fall, dass die Gegenseite die Verschlüsselung anfordert (requested) oder obligatorisch voraussetzt (required). angefordert (requested) – verschlüsselt oder prüft die Integrität, es sei denn, die Gegenseite weist die Anforderung zurück (rejected). obligatorisch (required) – besteht auf der Verschlüsselung bzw. Integritätsprüfung. Wenn die Gegenseite hierzu nicht bereit ist, wird die Verbindung abgelehnt. Bei den Einstellungen ist darauf zu achten, dass die Verhaltensweisen eindeutig genug konfiguriert werden. Wählt man »akzeptiert« und die Gegenseite »akzeptiert« ebenfalls, kann eine Verbindung aufgebaut werden, jedoch ohne Verschlüsselung und Integritätsprüfung! Schließlich ist auch noch ein Verschlüsselungsschema (Crypto Seed) vorhanden, d.h. eine beliebige alphanumerische Zeichenfolge, die als Grundlage für die Generierung einer Zufallszahl genommen wird, über welche die Session-Keys erzeugt werden.
Abbildung 9.3: Oracle Net Manager: Konfiguration von Advanced Security
Die entsprechende sqlnet.ora-Datei enthält beispielsweise die folgenden Einträge: SQLNET.CRYPTO_SEED = jfkdjfks4384kjfkds SQLNET.ENCRYPTION_SERVER = required SQLNET.ENCRYPTION_CLIENT = accepted SQLNET.ENCRYPTION_TYPES_CLIENT= (3DES168, RC4_128) SQLNET.ENCRYPTION_TYPES_SERVER= (3DES168) SQLNET.CRYPTO_CHECKSUM_CLIENT = requested SQLNET.CRYPTO_CHECKSUM_SERVER = required SQLNET.CRYPTO_CHECKSUM_TYPES_SERVER= (SHA1) SQLNET.CRYPTO_CHECKSUM_TYPES_CLIENT= (SHA1) Listing 9.3: sqlnet.ora-Parameter für Verschlüsselung und Integritätsprüfung
376
Sicherheit
Es versteht sich, dass auf der Client-Seite nur die client-spezifischen Parameter gesetzt werden müssen. Eine Verbindung zwischen Client und Server kommt nach der Aktivierung immer dann zustande, wenn die konfigurierten Verhaltensweisen kompatibel sind und für den Fall, dass verschlüsselt wird bzw. die Prüfsummen gebildet werden, gemeinsame Algorithmen auf beiden Seiten gefunden werden. In unserem Beispiel wären das 3DES168 und SHA1. Kommt es zu keiner Übereinkunft der Algorithmen oder der Verhaltensweisen – eine Seite verweigert möglicherweise die Verschlüsselung –, kommt es zu folgender Fehlermeldung, und die Verbindung wird nicht aufgebaut: ORA-12660: Encryption or crypto-checksumming parameters incompatible Listing 9.4: Fehlgeschlagene Verbindung bei Advanced Security
Es ist durchaus möglich, dass die Verschlüsselung und Integritätsprüfung die Performance negativ beeinflusst. Dies hängt von vielen Faktoren, u.a. von den gewählten Algorithmen, ab. So sind die triple DES-Verfahren im Allgemeinen langsamer als die DES-Verfahren. Genaue Zahlen können nur durch individuelle Tests gewonnen werden. Bei der Entscheidung, welche Verfahren zum Einsatz kommen, sollte jedoch nicht nur die Performance im Vordergrund stehen!
9.4
Benutzerplanung
Beim Aufbau eines Sicherheitskonzeptes ist die Planung und Konfiguration von Datenbankbenutzern ein ganz wesentlicher Faktor. Erst über die vertrauenswürdige Identifikation und Authentifizierung von Benutzern ist eine sichere Autorisierung möglich. Es sind im Einzelnen die folgenden Kriterien zu beachten: 1. Wer greift aus welchem Kontext bzw. aus welcher Applikation auf die Systeme zu? 1. Welche Datenbereiche sind schützenswert? 2. Wie und in welchem Kontext soll die Authentifizierung der Benutzer durchgeführt werden? Wer soll über die Datenbank, wer extern authentifiziert werden? 3. Welche Benutzer erhalten welche Privilegien, und wie werden die Privilegien vergeben? 4. Über welche Benutzer wird die Verwaltung der Datenbank realisiert, und wie werden die Administratoren authentifiziert? Folgende Zusammenhänge sind hierbei zu beachten: Privilegien, die den Zugriff auf Objekte regeln, können nur im Kontext von Datenbankbenutzern vergeben werden. Dies bedeutet, dass alle physischen Benutzer, die sich über einen Datenbankbenutzer an der Datenbank anmelden, mit identischen Privilegien arbeiten und auch von Auditing-Verfahren als ein Benutzer erkannt werden.
Benutzerplanung
377
Um den besonderen Anforderungen von webbasierten Anwendungen gerecht zu werden, wurden schon in der Version 9i so genannte Shared Schemas bereitgestellt, bei denen die Authentifizierung und Autorisierung über Verzeichnisdienste gesteuert werden9. Die Zuteilung der Privilegien wird dort mit Hilfe von Enterprise Roles geregelt, die ihrerseits mit globalen Datenbankrollen korrespondieren. Auf diese Weise können sich beliebig viele physische Benutzer ein Datenbankschema teilen, trotzdem erhält jeder dieser Benutzer nur die Privilegien, die seiner geschäftlichen Funktion angemessen sind. Ebenfalls mit Blick auf Webanwendungen wurden Secure Application Roles geschaffen, die nur über autorisierte Pakete aktiviert werden können. Auf diese Weise lassen sich ebenfalls unterschiedliche Privilegienprofile wechselweise in einem Schemakontext realisieren. Schließlich gibt es noch das Verfahren Proxy Authentication, bei dem ein Benutzer im Namen anderer für zentralisierte Login-Verfahren genutzt werden kann. Datenbankbenutzer A kann also als Datenbankbenutzer B agieren – sofern er über spezielle grant-Befehle dazu autorisiert wurde – und erhält ganz oder teilweise dessen Privilegien. Auch dieses Verfahren ist vornehmlich für Webapplikationen interessant, die einen zentralen Benutzer für die Verbindungsanforderungen aus dem Middle-Tier heraus nutzen und trotzdem individuelle Privilegien vergeben wollen. Benutzer, die mit ihren eigenen Objekten arbeiten, haben grundsätzlich alle möglichen Rechte in Bezug auf diese Objekte und können diese Rechte nach eigenem Gutdünken an Dritte weitergeben10. Aus diesem Grund wird in der Regel das Schema, das die Objekte der betreffenden Applikation enthält, nicht für Connects genutzt. Zugriffskontrollen (auditing) können ebenfalls nur im Kontext von Datenbankbenutzern und in ihrem Kontext gesetzten Client-Identifiern durchgeführt werden. Teilen sich also mehrere physische Benutzer ein Schema, so sind sie aus Sicht des Auditings nicht differenzierbar. Je mehr physische Benutzer sich also einen Datenbankbenutzer »teilen«, sprich sich unter diesem Benutzer bei der Datenbank anmelden, desto undurchsichtiger wird für den Administrator die Vermeidung von destruktiven Operationen und die Zuordnung dieser Operationen zu bestimmten Personen oder Personenkreisen – Ausnahme sind hier die oben erwähnten Shared Schemas, Secure Application Roles oder Proxy Authentication. Arbeiten alle Benutzer in dem Schema des Eigentümers der Objekte, wird jede Zugriffsverwaltung ad absurdum geführt, weil im Prinzip alle Aktionen für alle erlaubt sind. Zugriffsbeschränkungen, die nur in der jeweiligen Anwendung realisiert werden, lassen sich bekanntlich sehr leicht unterlaufen, denn das Werkzeug SQL*Plus ist in wenigen Minuten auf jedem PC installiert, und damit ist dem direkten Zugriff auf die Daten Tür und Tor geöffnet.
9 Siehe hierzu den Abschnitt Variante 3: Enterprise-Benutzer und Enterprise-Rollen auf Seite 397 10 Dies wird als »Discretionary Access Control« bezeichnet. Ein alternatives Modell, das über Labels arbeitet, steht mit dem so genannten Mandatory Access Control zur Verfügung. Zu Labels siehe den Abschnitt Labels.
378
Sicherheit
Aus diesen Gründen sollte auf jeden Fall für jede bekannte, physische Person, die mit der Datenbank arbeitet und sensible Datenbereiche nutzt, entweder ein eigener Datenbankbenutzer erzeugt oder ein schlüssiges Konzept für die individuelle Privilegienzuteilung über zentralisierte, extern authentifizierte Benutzer vorgelegt werden. Gibt es Benutzerkreise, d.h. Gruppen von Personen, welche die gleichen Zugriffsrechte an der Datenbank benötigen, so lässt sich die Administration der notwendigen Privilegien über geeignete Rollen sehr leicht realisieren. Diese einfachen Regeln werden leider immer dort verletzt, wo eine Anwendung für unterschiedliche Datenbanksysteme tauglich sein soll, die über unterschiedliche technische Möglichkeiten verfügen. Aus Sicht der Applikation ist es wichtig, dass sensible Daten nur eindeutig authentifizierten, individuellen Benutzern zugänglich gemacht werden. Hierfür stehen Passwörter, Zertifikate oder biometrische Verfahren zur Verfügung. Aus Sicht der Datenbank ist die eindeutige Identifizierung ausschlaggebend für eine individuelle Privilegierung. Hierbei kann jeder natürlichen Person ein Datenbankbenutzer zugeordnet werden, es können aber auch – wie bereits erwähnt – »zentrale« Applikationsbenutzer eingerichtet werden, über die Gruppen von Personen authentifiziert werden können und die trotzdem eine individuelle Privilegierung Einzelner sicherstellen. Für die Authentifizierung Einzelner stehen aus Sicht der Datenbank unterschiedliche Wege offen: Das für die Authentifizierung notwendige Passwort wird direkt in der Datenbank gespeichert. Die Authentifizierung findet demnach in der Datenbank statt. In diesem Verfahren sind individuelle Datenbankbenutzer nötig. Die Datenbank speichert selbst kein Passwort und »vertraut« externen Verfahren und Instanzen. Hiermit lassen sich auch Single-Sign-on-Prozesse realisieren. Es stehen in diesem Zusammenhang unterschiedliche Verfahren zur Verfügung, die in den folgenden Abschnitten unter den Rubriken »externe« und »globale« Authentifizierung gehandelt werden – Das Betriebssystem authentifiziert die Benutzer, Oracle ordnet diesen Benutzern automatisch interne Benutzer zu und verzichtet auf die Eingabe eines Passwort (externe Authentifizierung). In einer erweiterten Variante ist es sogar möglich, externen Rechnern und deren Betriebssystemen zu vertrauen und deren Benutzer ohne zusätzliche Authentifizierung zuzulassen. – Die Anmeldung nutzt das SSL-Protokoll für die direkte Anmeldung an die Datenbank. Der im Zertifikat des Wallets des Benutzers ausgewiesene Distinguished Name steuert die Zuordnung zu einem Datenbankbenutzer. – LDAP-Verzeichnisse, wie z.B. das Oracle Internet Directory, authentifizieren und autorisieren den Benutzer. Für die Authentifizierung können Passwörter oder Zertifikate im Rahmen des SSL-Protokolls genutzt werden. Die Zuordnung dieser Benutzer zu konkreten Datenbankbenutzern kann flexibel, z.B. über Shared Schemas oder exklusiv über den ausgewiesenen Distinguished Name des Benutzers erfolgen. – Dienste wie Kerberos und RADIUS authentifizieren die Benutzer und geben die erfolgreiche Authentifizierung an die Datenbank weiter.
Interne Benutzerverwaltung
379
Die Möglichkeiten der externen Authentifizierung sind, wie diese kurze Übersicht bereits deutlich macht, dermaßen komplex, dass deren detaillierte Darstellung die Intentionen dieses Buches bei weitem übersteigen würde. Aus diesem Grunde konzentrieren wir uns in diesem Kapitel auf die am häufigsten eingesetzten Verfahren. Die zweite Lösung, nämlich der Verzicht auf ein eigenes Datenbankschlüsselwort, ist in der Regel für die Benutzer vorteilhafter, weil einfacher, setzt aber ein absolut sicheres System zur Authentifizierung außerhalb der Datenbank voraus. Für den DBA kann dagegen die genaue Ermittlung der Privilegien für einzelne Benutzer komplexer werden, wenn diese über externe Verfahren wie z.B. Enterprise Roles zugewiesen werden. Zusätzlich zu der Authentifizierung der Applikationsbenutzer muss auch die Authentifizierung der DBAs konfiguriert werden. Natürlich können alle DBA-Aufgaben pauschal über die Benutzer SYS oder SYSTEM abgewickelt werden. Bei großen Umgebungen, die mehrere Personen in der Rolle des DBA beschäftigen, ist in der Regel die Schaffung individueller DBA-Benutzer zu empfehlen, um die Verantwortlichkeiten klarer zu regeln. Diese Benutzer können dann auch ganz gezielte Verwaltungsrechte zur Erfüllung ihrer Aufgaben erhalten. Vor diesem Hintergrund ist beispielsweise ein Sicherheitsadministrator denkbar und auch über entsprechende Systemprivilegien konfigurierbar.
9.5
Interne Benutzerverwaltung
Der Zugriff auf Oracle-Datenbanken erfolgt stets in Form von Sitzungen (Sessions). Sitzungen wiederum laufen im Kontext von Benutzern (Usern) ab, die vorher in der Datenbank angelegt werden müssen. Über Authentifizierungsmechanismen, die letztendlich einer Sitzung einen Benutzer zuordnen, ist das Datenbanksystem in der Lage, die Autorisierung, d.h. die Zuordnung definierter Privilegien, durchzuführen11. Je differenzierter die Benutzerstrukturen in der Datenbank oder in externen Diensten aufgebaut werden, desto differenzierter lassen sich Identitäten feststellen und über diese notwendige Privilegienmuster ableiten und initialisieren. Der Zugriff über Pauschal- oder Gruppenbenutzer erfordert – sofern eine exakte Privilegierung überhaupt gewünscht wird – die Identifizierung der Benutzer über jede der zugreifenden Anwendungen und ist aus diesem Grunde entsprechend aufwändig in der Programmierung und im Testen. In diesem Zusammenhang kümmert sich die interne Benutzerverwaltung um die Planung und Verwaltung von Benutzern innerhalb der Datenbank. Für das Anlegen von Benutzern ist das Privileg CREATE USER erforderlich, das standardmäßig über die DBA-Rolle vergeben wird.
11 Beim Einsatz von Verzeichnisdiensten kann die Autorisierung auch extern erfolgen. Siehe hierzu den Abschnitt Internet Directory, LDAP und SSL.
380
9.5.1
Sicherheit
Möglichkeiten der Authentifizierung
Beim Anlegen eines Benutzers in der Datenbank wird bereits eine geeignete Authentifizierungsmethode festgelegt. Es stehen unterschiedliche Methoden der Authentifizierung für die Identifikation von Kommunikationspartnern zur Verfügung: Bei der internen Authentifizierung wird der betreffende Benutzer mit einem Passwort angelegt, das in der Datenbank gespeichert wird und aus diesem Grunde auch über die Datenbank verifiziert werden kann. Die externe Authentifizierung verzichtet auf die Speicherung eines Passwortes in der Datenbank. Zur Verifizierung der Identität müssen aus diesem Grunde externe Quellen, z.B. das Betriebssystem, herangezogen werden. Die globale Authentifizierung speichert ebenfalls kein Passwort in der Datenbank. Die Identifikation erfolgt in diesem Falle über externe, in der Regel zentrale oder zentral autorisierte Quellen wie digitale Zertifikate und Verzeichnisdienste. Für die globale Identifizierung kann ein gültiger X.509-Name oder ein Leerstring angegeben werden. Im letzten Fall erfolgt die Zuordnung eines externen zu dem entsprechenden internen Benutzer über Enterprise-User-Definitionen des Verzeichnisdienstes (Internet Directory). Bei der Proxy-Authentifizierung übernimmt eine Mittelschicht (Middle-Tier) die Authentifizierung der Clients und meldet sich über einen zentralen Applikationsbenutzer im Namen des betreffenden Clients bei der Datenbank an. Diese Weiterleitung kann mit oder ohne Übergabe des originalen Client-Passwortes erfolgen. In beiden Fällen müssen die betreffenden Benutzer der Datenbank bekannt sein, d.h., dort angelegt worden sein (create user). Eine abgewandelte Form der Proxy-Authentifizierung (Application User Proxy Authentication) übergibt lediglich die Identitätsdaten an die Datenbank, die diese dann in Form von ClientIdentifiern den betreffenden Sessions übergibt. In diesem Fall ist es nicht erforderlich, die betreffenden Benutzer in der Datenbank anzulegen und zu verwalten. Die einzelnen Verfahren werden in den folgenden Abschnitten detailliert besprochen.
9.5.2
Interne Authentifizierung
Die interne Authentifizierung stellt die »klassische« und am einfachsten zum implementierende Authentifizierungsmethode dar: Benutzer werden hierbei mit ihnen zugeordneten Passwörtern in der Datenbank angelegt. Bei der Anmeldung an die Datenbank wird der Benutzername zusammen mit dem verschlüsselten Passwort an den Datenbankserver übermittelt und dort mit den Einträgen des Data Dictionarys verglichen. Da Passwörter in »gehashter« Form im Data Dictionary gespeichert werden, erfolgt ihr Vergleich entsprechend in »gehashter« Form. Jeder Kommunikationspartner, der einen Benutzernamen mit dem ihm zugeordneten Passwort reproduzieren kann, hat aus diesen Gründen Zugang zur Datenbank mit den Privilegien, die dem entsprechenden Benutzer zugeordnet wurden. Aus diesem Grunde wird das Verfahren auch als »schwache« Authentifizierung bezeichnet. Die interne Authentifizierung ist zweifelsfrei die einfachste Methode, hat jedoch auch eine Reihe gravierender Nachteile:
Interne Benutzerverwaltung
381
»Schwache« oder schriftlich fixierte Passwörter können leicht erraten oder reproduziert werden. Benutzername und Passwort müssen explizit – entweder interaktiv oder, schlimmer noch, hart kodiert – angegeben werden. Dies führt – vor allem, wenn mit einer Vielzahl von Datenbanken gearbeitet wird – zur Auswahl von primitiven Passwörtern, die der Einfachheit halber auf allen Systemen identisch sind. Benutzer müssen auf jeder Datenbank separat angelegt und verwaltet werden, was bei einer großen Benutzerzahl zu einer entsprechenden administrativen Belastung führt. Im folgenden Beispiel wird der Benutzer guenter mit dem Passwort unbescheid definiert: SQL> CREATE USER guenter IDENTIFIED BY unbescheid PASSWORD EXPIRE;
Für die Benennung von Benutzern stehen im Prinzip alle Zeichen des betreffenden Zeichensatzes der Datenbank zu Verfügung, Kennwörter dagegen dürfen jedoch nur aus Zeichen mit einem Byte Länge bestehen. Um Probleme beim Wechsel von Zeichensätzen oder Migrationen von Schemata zu vermeiden, wird dringend empfohlen, die Bezeichner für Benutzer und Kennwörter aus dem Vorrat von ASCII-Zeichen zu wählen. Die PASSWORD-Klausel bewirkt, dass der betreffende Benutzer bei seiner ersten Anmeldung zur Eingabe eines neuen Passwortes aufgefordert wird. Auf diese Weise lassen sich vom Datenbankverwalter einfach zu erinnernde Erstlingspasswörter vergeben, die der Endbenutzer entsprechend differenzieren muss12. Die Auswahl von Passwörtern ist sorgfältig zu überlegen. Ein leicht zu erratendes Schlüsselwort ist bekanntlich wertlos. Aus diesem Grunde ist es durchaus sinnvoll, entsprechende Standards für die Wahl von Schlüsselwörtern festzulegen und den Benutzern zu empfehlen. Die grundlegende Anforderung an Schlüsselwörter ist so einfach wie schwierig: Sie sollten schwer zu erraten, aber für den betreffenden Benutzer leicht zu behalten sein. Eine Empfehlung für die Erzeugung eines solchen Schlüsselwortes könnte z.B. lauten: Es sind zwei Wörter auszuwählen und nach bestimmten Regeln zu kombinieren, z.B. durch »Mischen« der Wörter auf Buchstabenebene: Erstes Wort: »Haus« Zweites Wort »1234« Daraus resultierendes Schlüsselwort: »h1a2u3s4« Schlüsselwörter sollten darüber hinaus in regelmäßigen Abständen geändert und nicht niedergeschrieben werden.
12 Siehe hierzu und zu den Regeln der Passwortvergabe auch den Abschnitt Password-Management.
382
Sicherheit
Der oben abgebildete Befehl legt lediglich den Benutzer an, er vergibt noch keine Privilegien! Die Anmeldung an die Datenbank ist aus diesem Grunde zu diesem Zeitpunkt noch gar nicht möglich. Informationen über Benutzer können mit Hilfe der Views dba_users, all_users oder user_users abgefragt werden: SQL> SELECT username, user_id, password FROM dba_users WHERE username = 'GUENTER'; USERNAME USER_ID PASSWORD --------- ------------ ---------------------------------------GUENTER 31 86F7130824E83895
Das Passwort des Benutzers wird – wie bereits erwähnt – in gehashter Form gespeichert und bei dieser Abfrage auch entsprechend – hexadezimal mit 16 Zeichen – angezeigt. Die – hier sichtbare – verschlüsselte Form kann keinesfalls als Eingabe für Authentifizierungen benutzt werden, weil die Eingabe während des Login-Verfahrens nochmals verschlüsselt wird und die Authentifizierung damit fehlschlägt. Wohl aber kann über die values-Klausel die verschlüsselte Form eines Kennwortes direkt in die Datenbank übernommen werden. Dies ist in manchen Fällen hilfreich, wenn z.B. ein nicht bekanntes, jedoch temporär geändertes Kennwort auf den alten Wert zurückgesetzt werden soll, so dass sich der betreffende Benutzer ohne Störungen anmelden kann: SQL> ALTER USER guenter IDENTIFIED BY VALUES '86F7130824E83895';
Die Änderung des vergebenen Passwortes ist jederzeit, sowohl für den DBA als auch den betreffenden Benutzer, über den Befehl ALTER USER möglich: SQL> ALTER USER guenter IDENTIFIED BY neues_passwort;
Im Gegensatz zum DBA darf ein normaler Benutzer diesen Befehl nur zur Änderung seines eigenen Passworts nutzen.
9.5.3
Externe Authentifizierung
Extern authentifizierte Benutzer werden ohne Passwort in der Datenbank angelegt. Dementsprechend können sie nicht mit Mitteln der Datenbank identifiziert werden. Die Authentifizierung der Benutzer und die Verwaltung von Schlüsselwörtern erfolgt vielmehr mit aus Sicht der Datenbank fremden Mitteln, eben extern. Die Datenbank startet lediglich auf Anforderung eine Session mit dem Benutzer, der ihr von der externen Quelle »übergeben« wird. Dadurch ist es möglich, den Connect an die Datenbank ohne Angabe eines Benutzernamens und eines Passwortes wie im folgenden Beispiel durchzuführen: sqlplus /@test10
Wie oben bereits erwähnt wurde, gibt es sehr unterschiedliche Verfahren für die externe Authentifizierung, die sich nicht nur technologisch erheblich unterscheiden. Sie werden daher im Folgenden getrennt voneinander behandelt.
Interne Benutzerverwaltung
383
Nutzung des Betriebssystems Die erste Möglichkeit besteht in der Nutzung des Betriebssystems. Hierbei wird ein vom Betriebssystem authentifizierter Benutzer mit einem bestimmten Benutzer der ausgewählten Datenbank verbunden. Die Regeln dieser Zuordnung werden über den statischen Systemparameter os_authent_prefix festgeschrieben, der mit dem Wert OPS$ vorbelegt ist. Im folgenden Beispiel wird der Benutzer johannes mit externer Authentifizierung in der Datenbank angelegt: SQL> CREATE USER ops$johannes IDENTIFIED EXTERNALLY;
In diesem Fall würde der Betriebssystembenutzer johannes ohne Angabe eines Passwortes mit dem Benutzer ops$johannes der Datenbank verbunden. johannes hätte – da für ihn kein Passwort hinterlegt ist – auch keinerlei Möglichkeit, sich anderweitig zu authentifizieren. os_authent_prefix kann genauso gut mit einer »leeren« Zeichenkette (»«) vorbelegt werden, wodurch eine Zuordnung identischer Benutzernamen möglich wird. Die externe Authentifizierung über das Betriebssystem ist standardmäßig nur für lokale Verbindungen zulässig. Sollen auf diese Weise auch entfernte Verbindungen zur Datenbank aufgebaut werden, ist zusätzlich der Systemparameter remote_os_authent auf true zu setzen. Die Datenbank vertraut in diesem Fall den von den Clients übermittelten Benutzernamen ohne weiteres und führt die Verbindung an die Datenbank durch. Es versteht sich, dass diese Einstellungen extrem gefährlich und daher nur in Ausnahmefällen zu empfehlen sind. Für die entfernte Einwahl ohne Angabe von Passwörtern stehen andere, wesentlich sicherere Verfahren zu Verfügung, wie z.B. die Nutzung von Verzeichnisdiensten13 und Authentifizierungsservern. Die dargestellte Methode mutet etwas antiquiert an, hat jedoch auch heutzutage noch einige Vorteile: Die Benutzer müssen sich keine zusätzlichen Passwörter für ihre Datenbankverbindungen merken und können sich sicher authentifizieren für den Fall, dass sie direkt auf dem Datenbankserver arbeiten. Batch-Programme, die sehr häufig direkt auf dem Server zur Ausführung gebracht werden, kommen ohne hart kodierte Passwortanweisungen aus. Das Verfahren hat jedoch auch Nachteile: Die Einwahl von entfernten Clients (remote Login) ist in der Regel extrem unsicher und sollte auf jeden Fall vermieden werden. Jeder externe Benutzer kann immer nur mit einem speziellen internen Benutzer verbunden werden.
13 Siehe hierzu die ausführliche Besprechung in den Abschnitten Internet Directory, LDAP und SSL f.
384
Sicherheit
Unter den Betriebssystemen Windows 2000 und XP werden Authentifizierungen – transparent für den Benutzer – über eigene Authentifizierungsprotokolle durchgeführt14. Die Nutzung dieser Protokolle muss in der Datei sqlnet.ora entsprechend vorbereitet werden: sqlnet.authentication_services = (NTS)
Das Fehlen dieses Parameters beschert dem Benutzer den folgenden Fehler: ORA-01004: default username feature not supported; logon denied
Für einen fehlerfreien Verbindungsaufbau unter Windows ist es gleichermaßen notwendig, dass der Benutzername in der Datenbank aus dem Domänennamen, einem umgekehrten Schrägstrich und dem eigentlichen Benutzernamen zusammengesetzt wird: Aus dem Benutzer johannes des Betriessystems wird daher auf dem Computer bzw. unter der NT-Domäne RECHNER1 der Benutzer rechner1\johannes für den Fall, dass der Parameter os_authent_prefix mit "" belegt wurde. Für das Anlegen von extern authentifizierten Oracle-Benutzern empfiehlt sich das Werkzeug ORACLE ADMINISTRATION ASSISTANT FOR WINDOWS, das auf jeder Oracle-CD für Windows enthalten ist und separat installiert werden muss. Es ist natürlich auch möglich, einen Benutzer mit intern gespeichertem Passwort zu definieren und sich trotzdem ohne Passwort über die oben beschriebenen Mechanismen bei der Datenbank anzumelden. Im Unterschied zu externen Benutzern kann ein solcher Benutzer auch – falls das Passwort bekannt ist – von beliebigen Betriebssystembenutzern angewählt werden. Nutzung von externen Authentifizierungsservern Für sichere, zentralisierte Authentifizierungen im Client-Server-Umfeld kann darüber hinaus eine Reihe weiterer, etablierter Produkte und Verfahren für die Authentifizierung von Datenbankbenutzern eingesetzt werden. Dies können auf der einen Seite Authentifizierungsdienste wie Kerberos und RADIUS sein, die durch so genannte Smart-Cards ergänzt werden können, auf der anderen Seite ebenso biometrische Verfahren, bei denen Fingerabdrücke oder Netzhautmuster interpretiert werden. Die Nutzung dieser Dienste ist vor allem dort interessant, wo sie bereits in Kontexten außerhalb von Oracle eingesetzt werden und entsprechende administrative Erfahrungen vorliegen. Sie ermöglichen die Authentifizierung nach dem Single-Sign-on-Prinzip, bei dem sich Benutzer einmal anmelden und dann verschiedene Dienste, unter ihnen auch Datenbanken, ohne erneute Authentifizierung nutzen können. Zusätzlich kann bei diesen Verfahren auch die Verschlüsselung der Daten erfolgen. Die konfiguratorische Einbindung dieser externen Umgebungen in die Oracle-Welt wird über Oracle Net und dort vor allem über die Datei sqlnet.ora15 realisiert. Eine detaillierte Besprechung der einzelnen Methoden würde den Rahmen dieses Buches sprengen. Sie findet sich vielmehr in der Oracle-Dokumentation, dort vor allem unter dem Thema Advanced Security.
14 Dies sind standardmäßig Kerberos für Windows 2000 und NT LAN Manager für Windows NT. 15 Hier vor allem über den Parameter SQLNET.AUTHENTICATION_SERVICES.
Interne Benutzerverwaltung
9.5.4
385
Globale Authentifizierung
Bei der globalen Authentifizierung werden Benutzer über digitale Zertifikate oder über Kennwörter identifiziert. Zentrale Verzeichnisdienste regeln auf dieser Basis die Anmeldung an autorisierte Datenbanken und können darüber hinaus auch entsprechende Privilegien in Form von Enterprise-Rollen an den Benutzer übertragen. Die Verschlüsselung der Daten kann hierbei ebenfalls durchgeführt werden. Auf diese Weise lässt sich auch das oben beschriebene Single-Sign-on-Prinzip implementieren. Verzeichnisdienste und die mir ihrer Hilfe mögliche globale Authentifizierung werden ausführlich im Abschnitt Internet Directory, LDAP und SSL auf Seite 395 besprochen.
9.5.5
Proxy-Authentifizierung
Der Einsatz einer so genannten Mittelschicht (Middle-Tier), z.B. beim Einsatz von Applikationsservern, stellt besondere Anforderungen an die Authentifizierung von Benutzern in der Datenbank, sofern diese überhaupt gewünscht wird. Es stehen unterschiedliche Modelle und Technologien zur Verfügung, um die Authentifizierung im 3-Schicht-Betrieb sicherzustellen. 1. Im einfachsten Fall stellt der Application-Server eine zentrale Verbindung zu der betreffenden Datenbank her. Die Authentifizierung zwischen Applikationsserver und Datenbank erfolgt über ein Kennwort, das explizit und hart codiert im Kontext der Anwendung auf dem Applikationsserver verankert werden muss. Auf diese Weise stehen jedem Benutzer prinzipiell alle Privilegien des zentralen Datenbankbenutzers zur Verfügung. Individuelle, einschränkende Privilegienzuteilungen an einzelne Benutzer müssen über den jeweiligen Applikationscode geregelt werden. Hinzu kommt, dass Kennwortänderungen auf Seiten der Datenbank Codeanpassungen der Applikation nach sich ziehen. Es versteht sich, dass diese Art der Authentifizierung wegen der erwähnten Nachteile nur in Ausnahmefällen zu empfehlen ist, z.B. dort, wo die Authentifizierung individueller Clients gegenüber der Datenbank nicht gefordert wird. Darüber hinaus wird diese Methode in strengem Sinne nicht unter dem Terminus Proxy Authentication gehandelt. 2. In einem zweiten Modell wird der Client von der Mittelschicht über eine beliebige Methode authentifiziert. Die Mittelschicht authentifiziert sich gegenüber der Datenbank – hart codiert oder über geeignete kennwortlose Verfahren – über einen zentralen Applikationsbenutzer, trägt jedoch die Identität des betreffenden Endbenutzers über entsprechende Client-Identifier in die Datenbank hinein. Die Privilegierung des Benutzers kann dann – abhängig von dem gesetzten Client-Identifier – über eine Startprozedur erfolgen, die entsprechende Application Roles16 aktiviert. Die Frage, welche Rollen für welche Benutzer zu aktivieren sind, kann entweder über die Applikation selbst oder über »Dummy«-Benutzer innerhalb der Datenbank erfolgen. Diese Dummy-Benutzer sind in der Datenbank ohne das Privileg create session jedoch mit den für sie wichtigen Application Roles angelegt. Diese Benutzer dienen demnach nur als »Repository« für die 16 Application Roles werden in Abschnitt 9.7.3 besprochen.
386
Sicherheit
Aktivierung der Rollen über die betreffende Applikation. Die zugeteilten Rollen können von den Benutzern selbst jedoch niemals direkt aktiviert werden, weil die zur Aktivierung vorgesehene Prozedur im Schema des Applikationsbenutzers liegt. Der zugewiesene Client-Identifier erlaubt darüber hinaus auch die Nutzung von Auditing-Verfahren und ist über die Funktion sys_context jederzeit innerhalb von SQL-Anweisungen abrufbar. Der Vorteil dieser Methode gegenüber der oben erwähnten ersten besteht in der individuellen Privilegierung von Endbenutzern und in der zentralen Verwaltung der Privilegien innerhalb der Datenbank. Die folgenden Codezeilen skizzieren die für dieses Modell mögliche Syntax in Ausschnitten. Es handelt sich dabei keinesfalls um eine fertige und ausführbare Prozedur. Einige der hier genutzten Konstrukte werden im Detail erst in den nachfolgenden Abschnitten behandelt. Security-Kontext für Applikations-DEMO -- Einrichten von Secure Application Roles für Benutzerprofile ENDUSER und ADMIN -- Die Rollen werden geschaltet über das Schema APPUSER CREATE ROLE demo_admin IDENTIFIED USING appuser.appstart; CREATE ROLE demo_enduser IDENTIFIED USING appuser.appstart; -- Kontrolle der angelegten Application Roles SELECT ROLE, SCHEMA, PACKAGE FROM dba_application_roles WHERE SCHEMA = 'APPUSER'; -- Einrichten des Schema-Owners (enthält alle Datenbankobjekte) CREATE USER appowner IDENTIFIED BY ownpwd; -- zuteilen der Owner-Privilegien, z.B. GRANT CONNECT, RESOURCE TO ownpwd; -- Aufbau der Objekte und .. -- Zuteilung der Objektprivilegien an die Application Roles -- GRANT select, update ON tabelle1 TO demo_enduser; -- Einrichten der Endbenutzer, kein connect vorgesehen CREATE USER u4711 IDENTIFIED EXTERNALLY; -- Zuteilung der Application Roles an die Benutzer -- keine weiteren Systemprivilegien GRANT demo_enduser TO u4711; -- Application Roles sollen keine Default Rollen sein: ALTER USER u4711 DEFAULT ROLE NONE; -- ## Einrichten des separaten zentralen "Proxy"-Benutzers, -- der von der Mittelschicht angewählt wird und die Rollen aktiviert CREATE USER appuser IDENTIFIED BY apppwd; -- Grant von minimalen Privilegien, z.B. GRANT CREATE SESSION TO appuser; -- Anlegen eines Startpaketes für Appuser, z.B. über separaten DBA-user -- dadurch braucht APPUSER keine entsprechenden Systemprivilegien -- die Mittelschicht übergibt den authentifizierten Endbenutzer -- ... der vorgestellte Code enthält nur Fragmente! CREATE OR REPLACE PROCEDURE appuser.appstart ( client_in IN v$session.client_identifier%TYPE )
Interne Benutzerverwaltung
387
AUTHID CURRENT_USERüfen etc. IF sys_context('userenv', 'ip_address') IN ..... THEN -- ... um schliesslich die gegranteten Rollen zu ermitteln FOR rec_role in (SELECT granted_role FROM dba_role_privs WHERE granted_role IN ( SELECT ROLE FROM dba_application_roles WHERE SCHEMA = USER ) AND grantee = client_id_in) LOOP -- hier einen kommaseparierten String aufbauen END LOOP; -- ... diesen String schliesslich zum Aktivieren nutzen DBMS_SESSION.SET_ROLE (lv_rolestring); END IF; DBMS_SESSION.set_identifier (cliend_in); EXCEPTION WHEN ..... END appstart; / -- Der gesetzte Client-Identifier kann dann beliebig im SQL-Kontext genutzt werden select * FROM my_view WHERE benutzer = sys_context('userenv', 'client_identifier');
Ein drittes mögliches Modell arbeitet mit der Proxy-Authentifizierung im eigentlichen Sinne. Hierbei wird ebenfalls ein Applikationsbenutzer angelegt, der selbst nur minimale Privilegien erhält und über den sich der Application-Server einwählt. Die Authentifizierung dieses Benutzers in der Datenbank kann über ein Passwort oder über ein Zertifikat per SSL erfolgen: CREATE USER application1 IDENTIFIED BY ......; GRANT .... TO applikation1;
Die für die Anwendung nötigen Endbenutzer sind ebenfalls in der Datenbank angelegt worden und haben die für ihre Aufgaben nötigen Datenbankrollen erhalten. Für den Fall, dass sie außerhalb der Anwendung keine separaten Aktivitäten durchführen sollen, kann ihnen das Privileg create session vorenthalten werden: CREATE USER client1 IDENTIFIED .....; GRANT rolle1,rolle2 TO client1;
Im nächsten Schritt erhält nun der Anwendungsbenutzer das Recht, client1 für den Sitzungsaufbau als Proxy zu nutzen: ALTER USER client1 GRANT CONNECT THROUGH applikation1 WITH ROLE rolle2;
Zusätzlich wird in diesem Beispiel für client1, wenn er über den Applikationsbenutzer applikation1 mit der Datenbank verbunden wird, nur die Rolle rolle2 aktiviert. Die Mittelschicht ist nun in der Lage, die Session von applikation1 im Namen und mit den Privilegien von client1 zu nutzen, unter der Voraussetzung, dass die Verbindung über den »dicken« JDBC-Treiber17 aufgebaut wird. Im angegebenen Beispiel wird die Session ohne weitere Authentifizierung im Namen von client1 17 Auch OCI JDBC-Treiber genannt, weil er auf den Oracle Call Interface APIs aufbaut. Im Gegensatz zum »dünnen« JDBC-Treiber setzt dieser Treiber die Installation von ORACLE Net auf der Client-Seite voraus.
388
Sicherheit
eröffnet. Alternativ sind jedoch Varianten denkbar, bei denen der Applikationsbenutzer zum Verbindungsaufbau im Namen des Clients zusätzliche Authentifizierungsmethoden einsetzen muss: -- (a) Passwort von CLIENT1 muss mit angegeben werden ALTER USER client1 GRANT CONNECT THROUGH applikation1 AUTHENTICATED USING PASSWORD; -- (b) Zertifikat von CLIENT1 muss geliefert werden ALTER USER client1 GRANT CONNECT THROUGH applikation1 AUTHENTICATED USING CERTIFICATE; -- (c) Distinguished Name von CLIENT1 muss mit angegeben werden ALTER USER client1 GRANT CONNECT THROUGH applikation1 AUTHENTICATED USING DISTINGUISHED NAME;
Proxy-Einstellungen dieser Art lassen sich über die View dba_proxies18 abfragen: PROXY CLIENT AUTHENTICATION AUTHORIZATION_CONSTRAINTROLE ------------- ------- -------------- ------------------------ ---------------APPLICATION1 CLIENT1 NO PROXY MAY ACTIVATE ROLECONNECT
Die Vorteile der Proxy-Authentifizierung liegen vor allem darin, dass über eine physische Verbindung unterschiedliche Sessions im Namen und mit den Privilegien bekannter Datenbankbenutzer aufgebaut werden können. JDBC nutzt dazu den OCI Connection-Pool, der in der Lage ist, so genannte Lightweight Sessions zu initialisieren, indem bereits initiierte physische Verbindungen zu der Datenbank für unterschiedliche Sessions genutzt werden. Das folgende kurze Codebeispiel illustriert das Vorgehen im Kontext eines Java-Client-Programms. Da – wie bereits erwähnt – zur Nutzung der Proxy-Authentifizierung der »dicke« JDBC-Treiber benötigt wird, ist es wichtig, den Klassenpfad vor der Ausführung des Programms auf $ORACLE_HOME/jdbc/lib zu setzen. Dieses Verzeichnis enthält die »dicken« JDBC-Treiber. Wenn dieser Test mit Hilfe vom JDeveloper ausgeführt wird, lässt sich der Pfad einstellen über: – Project Properties – Profiles – Development – Libraries. package mypackage1; import java.sql.*; import java.util.*; // Pfad muss auf DICKES JDBC zeigen import oracle.jdbc.*; import oracle.jdbc.pool.OracleOCIConnectionPool; import oracle.jdbc.oci.OracleOCIConnection; public class ProxConn { public static void main (String [] args) { String aliasName = "(DESCRIPTION = (ADDRESS_LIST = (ADDRESS = " + " (PROTOCOL = TCP) (HOST = myServer) (PORT = 1521)))" + " (CONNECT_DATA = (SERVICE_NAME = TEST10.DBCONSULT.DE)))"; 18 Unter Oracle8i ist die View proxy_users zu benutzen.
Interne Benutzerverwaltung
389
try { OracleOCIConnectionPool db = new OracleOCIConnectionPool(); db.setURL("jdbc:oracle:oci:@"+aliasName); // Benutzer für Applikationsidentität db.setUser("application1"); db.setPassword("apppwd"); Properties pr = new Properties(); // OCI Connection-Pool:Initiale + maxim. Anzahl physischer Connects pr.setProperty(OracleOCIConnectionPool.CONNPOOL_MIN_LIMIT,"1"); pr.setProperty(OracleOCIConnectionPool.CONNPOOL_INCREMENT,"1"); pr.setProperty(OracleOCIConnectionPool.CONNPOOL_MAX_LIMIT,"10"); db.setPoolConfig(pr); // Einstellungen fuer Proxy-User Properties proxyUser = new Properties(); proxyUser.setProperty(OracleOCIConnectionPool.PROXY_USER_NAME, "client1"); Connection co = db.getProxyConnection(OracleOCIConnectionPool.PROXYTYPE_USER_NAME, proxyUser); System.out.println("Erfolgreich!"); // Abwarten, um ueber v$session zu beobachten Thread.sleep(15000); co.close(); } catch (Exception ex) { System.out.println(ex.toString()); } } }
Auf Seiten der Datenbank lässt sich über die View v$session der Verbindungsaufbau gut verfolgen: SELECT schemaname, status, username, type, server FROM v$session WHERE username IS NOT NULL; 01 SCHEMANAME STATUS USERNAME TYPE SERVER 02 ------------ ------------ ------------ --------- ----------03 CLIENT1 INACTIVE CLIENT1 USER PSEUDO 04 APPLICATION1 INACTIVE APPLICATION1 USER DEDICATED 05 SYSTEM ACTIVE SYSTEM USER DEDICATED
Zeile 4 zeigt die dedizierte Verbindung über den Benutzer application1, die der OCI Connection-Pool minimal initiiert. Durch den Proxy-Connect wird eine Session unter client1 erzeugt (Zeile 3), welche die physische Verbindung von application1 nutzt, jedoch in der View als Pseudo-Server angezeigt wird. Die Session in Zeile 5 hat die Abfrage abgesetzt. Die Übergabe des Passwortes für den Applikationsbenutzers application1 erfolgt in unserem Beispielprogramm hart codiert. Alternativ könnten Verfahren, beispielsweise über SSL, zum Einsatz kommen, bei denen kein Passwort explizit übergeben werden muss oder bei denen durch die Verschlüsselung und Integritätsprüfung die übertragenen Daten entsprechend abgesichert werden. Für Verbindungen aus dem OCI-Kontext stehen in diesem Zusammenhang grundsätzlich die gleichen Mechanismen wie für Oracle Net bereit.
390
9.5.6
Sicherheit
Authentifizierung von Datenbankadministratoren
Für die Authentifizierung von Administratoren, welche die Datenbank starten oder herunterfahren, Backup- und Recovery-Operationen durchführen, Parameterdateien erzeugen oder den Datenbankmodus ändern müssen, stehen zwei alternative Verfahren zur Verfügung: die Authentifizierung über das Betriebssystem oder über eine Passwortdatei. Die Autorisierung erfolgt in diesem Fall über die Systemprivilegien SYSDBA und SYSOPER. Die folgende Tabelle zeigt, welche Operationen die beiden Privilegien im Einzelnen zulassen: Systemprivileg
Erlaube Operationen/Befehle
Datenbankbenutzer
SYSDBA
STARTUP, SHUTDOWN
SYS
CREATE/ALTER DATABASE Zeichensatz anpassen CREATE SPFILE archivelog Recovery Restricted Session Privilege SYSOPER
STARTUP, SHUTDOWN
SYS (eingeschränkt)
CREATE SPFILE ALTER DATABASE OPEN/MOUNT/BACKUP archivelog Recovery Restricted Session Privilege Tabelle 9.1: Systemprivilegien SYSDBA und SYSOPER
Datenbankverwalter, die nicht mit den oben beschriebenen Kernaufgaben betraut sind, sondern sich beispielsweise um die Benutzerverwaltung oder das Anlegen von Rollen kümmern, können wie normale Benutzer über die Datenbank oder externe Verfahren authentifiziert werden und benötigen nicht die in den vorangehenden Abschnitten beschriebenen Verfahren. Die Authentifizierung über das Betriebssystem Bei der Authentifizierung über das Betriebssystem wird die Zugehörigkeit des Betriebssystembenutzers zu entsprechend vordefinierten Betriebssystemgruppen – OSDBA und OSOPER – herangezogen. Zusätzlich muss der Systemparameter remote_login_passwordfile für die betreffende Datenbank mit dem Wert none belegt worden sein: Die Zugehörigkeit zu der Gruppe OSDBA erlaubt dem Betreffenden den Connect mit dem Privileg SYSDBA, die Zugehörigkeit zu der Gruppe OSOPER erlaubt den Connect als SYSOPER, wie das folgende Beispiel zeigt. sqlplus /nolog SQL> CONNECT / AS SYSDBA
Interne Benutzerverwaltung
391
Die Authentifizierung von Administratoren über Gruppenzugehörigkeiten ist nur für lokale Zugriffe empfehlenswert. In allen anderen Fällen sollte von einer entsprechend konfigurierten Passwortdatei – wie im folgenden Abschnitt beschrieben – Gebrauch gemacht werden. Die Authentifizierung über eine Passwortdatei Bei der Authentifizierung über eine Passwortdatei spielt die Gruppenzugehörigkeit des betreffenden Betriebssystembenutzers keine Rolle. Die Identität wird vielmehr über eine separate, mit dem Werkzeug orapwd erstellte Datei verifiziert. Im folgenden Beispiel wird diese Datei für die Instanz T1 erzeugt. Das Passwort für den Datenbankbenutzer SYS wird auf den Wert geheim gesetzt, der Dateiname orapwT1 und der Pfad sind unter Unix für diesen Instanznamen obligatorisch. Die Datei wird für 20 Einträge, d.h. Benutzer, vorbereitet: orapwd file=$ORACLE_HOME/dbs/orapwT1 password=geheim entries=20 force=n
Unter Windows muss die Datei pwd<sid>.ora heißen und unter dem Verzeichnis %ORACLE_HOME%\database liegen. Für die Nutzung von Passwortdateien sind – über den Systemparameter remote_login_passwordfile – zwei unterschiedliche Verfahren konfigurierbar: 1. Der Wert exclusive reserviert die Passwortdatei für jeweils eine Instanz. Beliebigen Benutzern können in diesem Fall die Privilegien SYSOPER und SYSDBA zugeteilt werden. In unserem Beispiel erhält der Benutzer scott das SYSOPER-Privileg. Über die AS-Klausel kann er anschließend beim Verbindungsaufbau diese zusätzlichen Privilegien aktivieren. Die Datenbank identifiziert ihn in diesem Fall als public und nicht als scott. Entsprechend würde er – für den Fall, dass er das SYSDBA-Privileg erhalten hätte – als SYS authentifiziert. GRANT SYSOPER TO scott; ... CONNECT scott/tiger AS SYSOPER
2. Der Wert shared öffnet die Passwortdatei für mehrere Datenbanken. Die Datei speichert in diesem Fall jedoch nur Passwörter für den Benutzer SYS. Privilegien, die über Oracle-Passwortdateien verwaltet werden, lassen sich über die View v$pwfile_users auflisten.
392
9.5.7
Sicherheit
Benutzerverwaltung
Zur Benutzerverwaltung gehört mehr als das Festlegen des Benutzernamens und der geplanten Authentifizierungsmethode. Die wichtigsten Aufgaben werden in den folgenden Abschnitten besprochen. Tablespaces und Quoten Jedem Benutzer, der in der Datenbank definiert wird, lassen sich die folgenden Standardwerte zuteilen: DEFAULT TABLESPACE gibt den Tablespace an, der für die Speicherung der Objekte des betreffenden Benutzers standardmäßig genutzt wird, sofern diese nicht über eine explizite TABLESPACE-Klausel angelegt werden. Für Default Tablespaces sind auf jeden Fall Quoten notwendig! Die Quota-Klausel erteilt Benutzern Speicherquoten in bestimmten Tablespaces. Speicherquoten benötigt ein Benutzer zum Aufbau eigener Tabellen, Cluster oder Indizes. Es ist auf alle Fälle darauf zu achten, dass Benutzer in ihrem Default Tablespace entsprechende Quoten haben, sofern sie überhaupt zum Speichern von Objekten autorisiert werden sollen. TEMPORARY TABLESPACE teilt dem Benutzer einen Tablespace für die Speicherung temporärer Daten zu. Temporäre Daten sind zum einen zwischengespeicherte Sortierungen, wie sie beispielsweise für ORDER BY- oder DISTINCT-Klauseln benötigt werden, wenn der Sortierbereich im Speicher zu klein ist, zum anderen aber auch temporäre Tabellen und temporäre CLOBs. Ab der Version 9i kann ein so genannter Default Temporary Tablespace definiert werden, der automatisch jedem Benutzer als Temporary Tablespace zugewiesen wird. Im folgenden Beispiel wird dem Benutzer guenter der Standard-Tablespace users mit einer Quote von 100 MByte zugeteilt. Zusätzlich erhält er für den Tablespace indexes eine unbegrenzte Quote. Seine temporären Daten landen in tempts: SQL> ALTER USER guenter DEFAULT TABLESPACE users TEMPORARY TABLESPACE tempts QUOTA 100M ON users QUOTA UNLIMITED ON indexes;
Die Klauseln können auch schon bei dem Befehl CREATE USER angegeben werden. Für die Speicherung temporärer Daten sind grundsätzlich keine Quoten erforderlich. Benutzer und ihnen erteilte Quoten werden über die View dba_ts_quotas aufgelistet. Die View gibt darüber hinaus auch Auskunft über die Speicherbelegung der Benutzer in den einzelnen Tablespaces. Sperren und Löschen von Benutzern Benutzer können vom Administrator gesperrt werden. Die Sperre verwehrt dem Benutzer die Verbindung zur Datenbank, ohne seine Objekte und erteilten Privilegien zu zerstören. Andere Benutzer können weiterhin auf die Objekte des Gesperrten zugreifen, sofern sie die notwendigen Privilegien dazu haben. Das Sperren von Benutzern wird gerne verwendet, um Schemata, die Datenbankobjekte enthalten, vor dem direkten Zugriff zu schützen.
Interne Benutzerverwaltung
393
ALTER USER scott ACCOUNT LOCK;
Die Sperre kann vom Administrator jederzeit durch die UNLOCK-Klausel aufgehoben werden. Das Löschen von Benutzern erfolgt über den Befehl DROP USER. Hat der Benutzer eigene Objekte angelegt, ist zusätzlich die CASCADE-Klausel anzugeben. Die Löschung erfolgt ohne Rückfrage und kann nicht zurückgerollt werden! DROP USER guenter CASCADE;
Lizenzen verwalten Für die Lizenzierung von Oracle-Datenbanken stehen unterschiedliche Modelle zur Verfügung, die darüber hinaus in ihren Details von Zeit zu Zeit angepasst werden. Im Wesentlichen unterscheiden diese Modelle zwischen: namentlich registrierten Benutzern (Named User) gleichzeitig aktiven Benutzern oder Datenbanksitzungen (Concurrent Usage) Zur Überwachung der im Einzelfall vereinbarten Maximalwerte stehen die folgenden, dynamischen Systemparameter zur Verfügung: sessions_max gibt die maximal zulässigen Datenbanksitzungen an. Wird der Grenzwert erreicht, können nur noch Benutzer, die das Privileg restricted session haben, Verbindung zur Datenbank aufnehmen. Alle anderen erhalten eine Fehlermeldung. Der vorbelegte Wert 0 hebt die Begrenzung auf. sessions_warning setzt den Schwellenwert für Warnungen im Zusammenhang mit Datenbanksitzungen. Beim Erreichen des Schwellenwertes wird einerseits eine Meldung in die Alert-Datei geschrieben, andererseits erhalten Benutzer, die das Privileg restricted session haben, beim Anmelden einen Hinweis. sessions_current gibt die aktuelle Anzahl von Sessions an. sessions_highwater gibt die maximale Anzahl von Sessions an, die über die Instanz seit ihrem Start betrieben wurden. users_max gibt die maximale Anzahl von Benutzern (Named User) an, die in der Datenbank angelegt werden können. Über die View v$license können sowohl die vorgenommenen Einstellungen als auch die Hochwassermarke für Sitzungen aufgelistet werden. Standardbenutzer Bei der Installation von Oracle werden – abhängig von den angekreuzten Optionen – einige Standardbenutzer mit Standardpasswörtern angelegt. Es ist – wie bereits eingangs erwähnt wurde – dringend zu empfehlen, für diese Benutzer entweder die Passwörter abzuändern, die Benutzer zu sperren oder ganz zu löschen, falls sie nicht benötigt werden. Bei der Installation über den KONFIGURATIONSASSISTENTEN werden bereits einige Änderungen generiert, d.h., manche Benutzer gesperrt. Im Zweifelsfalle hilft die folgende Abfrage weiter: SQL> SELECT username, account_status, lock_date, expiry_date FROM dba_users;
394
Sicherheit
Die folgende Tabelle gibt einen Überblick über die wichtigsten Standardbenutzer. Benutzer
Standardpasswort
Kontext
Privilegien
Bemerkungen
SYS
CHANGE_ON_INSTALL
Schema des Data Dictionarys
Volle DBARechte
Passwort unbedingt nach der Installation ändern!
SYSTEM
MANAGER
Schema für Objekte von »Werkzeugen«, z.B. Metatabellen für die Replikation
Volle DBARechte
Passwort unbedingt nach der Installation ändern!
MDSYS
MDSYS
InterMedia Spatial
AURORA$JIS$ UTILITY$
Zufallsgenerierung
JServer
RESOURCE, UNLIMITED TABLESPACE
AURORA$ORB$ UNAUTHENITCATED$
Zufallsgenerierung
JServer
CREATE SESSION; RESTRICTED SESSION
OSE$HTTP$ADMIN$
Zufallsgenerierung
JServer
RESOURCE; JAVAUSERPRIV; CREATE SESSION; UNLIMITED TABLESPACE
DBSNMP
DBSNMP
Intelligent Agent
CONNECT, RESOURCE, SNMPAGENT, UNLIMITED TABLESPACE
OUTLN
OUTLN
Schema für Stored Outlines
CONNECT, RESOURCE, EXECUTE ANY PROCEDURE, UNLIMITED TABLESPACE
CTXSYS
CTXSYS
Oracle Text
ORDPLUGINS
ORDPLUGINS
InterMedia Audio
ORDSYS
ORDSYS
InterMedia Audio
Tabelle 9.2: Vordefinierte Datenbankbenutzer
Nach Änderung Datei snmp_rw.ora anpassen
Internet Directory, LDAP und SSL
9.6
395
Internet Directory, LDAP und SSL
Das Volumen der Daten, die in relationalen Datenbanken gespeichert werden, ist in den letzten Jahren drastisch angestiegen. Mit dem größeren Datenvolumen sind auch die Anforderungen an die Datensicherheit und den Zugriffsschutz gewachsen. Immer mehr Benutzer benötigen heute für die Durchführung ihrer täglichen Arbeit Zugriff auf ein oder – in den meisten Fällen – mehrere relationale Systeme. Die herkömmliche Authentifizierung durch die Eingabe von Benutzernamen und ihnen zugeordneten Kennwörtern führt bei der Menge der Systeme zu schwachen, leicht zu erratenden Kennwörtern, die eine sichere Datenhaltung ad absurdum führen. Darüber hinaus müssen die Benutzer einzeln in den betreffenden Datenbanken eingerichtet werden. Noch schlechter steht es um das Thema Sicherheit, wenn »Gruppenbenutzer« angelegt werden, die eine Maximalmenge der erforderlichen Privilegien erhalten. Über diese Gruppenbenutzer werden dann sämtliche Verbindungen einzelner Anwendungen abgewickelt. Individuelle Privilegien müssen in diesen Fällen mühsam in den Modulen der betreffenden Anwendungen programmiert werden. Sie können auf diese Weise leicht durch eine direkte Verbindung zur Datenbank umgangen werden. Zusätzlich besteht die Gefahr, dass die Daten während der Übertragung über Netzleitungen von Dritten abgehört und verändert werden. Um in Szenarien, wie sie oben beschrieben wurden, eine starke Authentifizierung und individuelle Privilegierung der Benutzer sowie eine sichere Übertragung der Daten zu gewährleisten, ohne dabei die Abläufe an der Oberfläche der Anwendung zu komplizieren, ist Folgendes notwendig: Eine zentrale, datenbankübergreifende Verwaltung von Benutzern (Enterprise User) und ihnen zugeteilten Privilegien (Enterprise Roles) in Bezug auf definierte Zielsysteme Die Authentifizierung jedes Benutzers über diese zentrale Instanz (Single Sign on) Nach der Authentifizierung: die privilegierte Nutzung der Zielsysteme ohne erneute Eingabe eines Kennwortes Die freie Verknüpfung von zentral authentifizierten Benutzern mit bestimmten Datenbankschemata der betreffenden Zielsysteme Bei der Übertragung: die Sicherung der Daten durch geeignete Verschlüsselungsalgorithmen (Encryption) Das vorliegende Kapitel zeigt Lösungsmöglichkeiten für die Erfüllung dieser Forderungen.
396
9.6.1
Sicherheit
Die Möglichkeiten im Überblick
Die oben genannten Forderungen sind mittlerweile auch im Kontext von OracleDatenbanken realisierbar. Für ihre Umsetzung stehen die folgenden »Bausteine« zur Verfügung: Verzeichnisdienste (Directories) stellen standardisierte Speicherstrukturen für die zentrale Erfassung von Benutzern, Rollen und Datenbanken u.v.a. zur Verfügung. Standardisierte Zugriffsprotokolle – wie z.B. LDAP19 – regeln den Zugriff auf diese Verzeichnisdienste. Am Markt sind unterschiedliche LDAP-Server verfügbar. Einer von ihnen ist der Server des Oracle Internet Directorys (OID), der die Verzeichnisdaten gemäß den standardisierten Verzeichnisstrukturen in einer Oracle-Datenbank speichert. Digitale Zertifikate speichern Identitäten und ihnen zugeordnete Schlüssel. Identitäten in digitalen Zertifikaten werden über so genannte Distinguished Names – z.B. cn=guenter, o=databaseconsult, c=de – eindeutig bezeichnet. Digitale Zertifikate können in Containern, so genannten Wallets, gespeichert werden. Wallets lassen sich über Kennwörter öffnen und authentifizieren dann deren Benutzer für den Zugriff auf Datenbanken oder andere Ressourcen. Protokolle für die Verschlüsselung, Authentifizierung und Integritätsprüfung – wie z.B. SSL20 – regeln den sicheren Verbindungsaufbau und die Verschlüsselung der Daten bei der Übertragung über das Netz. Globale Benutzer können in jeder Oracle-Datenbank angelegt werden und beziehen sich auf jeweils eine per Zertifikat oder Passwort ausgewiesene Identität. »Offene« Benutzer (Shared Schemas) lassen sich in jeder Oracle-Datenbank anlegen und müssen über Verzeichnisdienste einer oder mehreren zertifizierten Identitäten, d.h. Benutzern (Enterprise User), zugeordnet werden. Enterprise-Rollen werden in Verzeichnisdiensten definiert und dort ebenfalls Identitäten (Enterprise User) zugeordnet. Sie werden darüber hinaus mit globalen Rollen, die in der Zieldatenbank angelegt werden müssen, verknüpft. Dienstbenennungen (Net Service Names) können – statt in der lokalen Datei tnsnames.ora – über Verzeichnisdienste verwaltet und beim Aufbau einer Datenbanksitzung von dort abgerufen werden. Die oben aufgezählten »Bausteine« lassen sich technisch in unterschiedlichen Nutzungsvarianten kombinieren, von denen nur die wichtigsten in diesem Zusammenhang besprochen werden können: Variante 1: Auflösung von Dienstbenennungen Bei dieser Variante werden lediglich die Servicenamen für den Verbindungsaufbau zu den Zieldatenbanken über einen Verzeichnisdienst – z.B. Oracle Internet Directory – bereitgestellt. Die Authentifizierung und Autorisierung der Benutzer erfolgt 19 LDAP steht für Lightweight Directory Access Protocol. 20 SSL steht für Secure Sockets Layer. Das Protokoll sorgt für die Authentifizierung, Verschlüsselung und Integritätsprüfung einer TCP/IP-Verbindung.
Internet Directory, LDAP und SSL
397
auf herkömmliche Art direkt in der Datenbank. Auf die Verschlüsselung der Daten während der Übertragung wird verzichtet. Für diese Konfiguration werden die folgenden Bausteine benötigt: LDAP-Server Verzeichnisdienst (OID) mit entsprechenden Einträgen zur Namensauflösung Variante 2: Authentifizierung globaler Benutzer In diesem Modell erfolgt die Authentifizierung der Benutzer über standardisierte digitale Zertifikate. Ein über das betreffende Zertifikat identifizierter Benutzer wird genau einem globalen Benutzer in einer Zieldatenbank zugeordnet. Die Zuordnung erfolgt über die Identität der Namen (Distinguished Name). Da die Verbindung zur Datenbank über SSL aufgebaut wird, ist auf diesem Wege auch die Verschlüsselung der Daten möglich. Der Benutzer kann sich – bei geöffnetem Zertifikat – ohne Kennwort bei dem Zielsystem anmelden. Diese Konfiguration setzt die folgenden Bausteine voraus: Gültige digitale Zertifikate für den betreffenden Benutzer und die Zieldatenbank Globale Datenbankbenutzer, deren Distinguished Names mit denen der geöffneten Zertifikate der Clients identisch sind Konfiguration des Clients und des Datenbank-Listeners, um den Verbindungsaufbau über SSL zu ermöglichen Variante 3: Enterprise-Benutzer und Enterprise-Rollen Im Unterschied zur Variante 2 wird in diesem Modell die Zuordnung der Benutzer zu bestimmten Datenbankschemata über einen Verzeichnisdienst geregelt. Im Kontext des Verzeichnisdienstes werden Enterprise-Benutzer und – ihnen zugeordnet – Enterprise-Rollen definiert. Den Enterprise-Rollen werden – ebenfalls über den Verzeichnisdienst – globale Rollen der Zieldatenbanken zugeordnet. EnterpriseRollen erhalten ihre Privilegien ausschließlich über diese globalen Rollen, die in den Zieldatenbanken mit den notwendigen Privilegien definiert werden. Hier werden ebenfalls globale Benutzer ohne explizite Distinguished Names angelegt. Auch die Zuordnung der globalen Rollen zu den Benutzern erfolgt nicht in den Zieldatenbanken, sondern nur über den Verzeichnisdienst. Auf Grund dieser »Offenheit« der globalen Benutzer ist es möglich, ihnen mehr als einen Enterprise-Benutzer zuzuordnen, daher der Begriff Shared Schema. Da auch die Zuordnung der Privilegien über den Verzeichnisdienst geregelt wird, können unterschiedliche EnterpriseBenutzer mit jeweils unterschiedlichen Privilegien ein Datenbankschema nutzen. Die Authentifizierung der Benutzer erfolgt in diesem Modell über Kennwörter, die für den Enterprise-Benutzer im Verzeichnisdienst gespeichert werden, oder Zertifikate. Der Verbindungsaufbau zur Datenbank erfolgt über Oracle Net oder – bei der Nutzung von Zertifikaten – über SSL. Im letzteren Fall werden auch die Verschlüsselung der Daten und die Integritätsprüfung durchgeführt.
398
Sicherheit
Enterprise User - Global User Enterprise User Enterprise Role Global Role Global User Privilegien
Directory Service
Datenbank
Abbildung 9.4: Beziehungen zwischen Enterprise-Objekten und globalen Objekten
Im Einzelnen werden für die dritte Variante die folgenden Bausteine benötigt: Verzeichnisdienst mit entsprechenden Einträgen für Enterprise-Benutzer und Enterprise-Rollen Bei Nutzung von SSL: gültige digitale Zertifikate für den betreffenden Benutzer und die Zieldatenbank Globale Datenbankbenutzer ohne Angabe eines Distinguished Names sowie globale Rollen in den Zielsystemen, welche die entsprechenden Privilegien enthalten Bei Nutzung von SSL: Konfiguration des Clients und des Datenbank-Listeners, um den Verbindungsaufbau über SSL zu ermöglichen Konfiguration des Servers zur Kommunikation mit dem LDAP-Server und dem Verzeichnisdienst, um die Zuordnung der Benutzer zu den Schemata vornehmen zu können Variante 4: Kombination der vorangehenden Modelle Natürlich lassen sich die vorangehenden Modelle auch mischen: Auf diese Weise können nicht nur Enterprise-Benutzer, sondern auch Dienstbenennungen über Verzeichnisdienste interpretiert werden.
Internet Directory, LDAP und SSL
399
Die zur technischen Umsetzung dieser Modelle notwendigen Konfigurationsmaßnahmen werden in den Abschnitten Modell 1: Auflösung von Dienstbenennungen bis Modell 3: Enterprise-Benutzer und Enterprise-Rollen im Einzelnen erläutert.
9.6.2
Grundlegende Standards und Begriffe
Bei der Beschreibung der oben dargestellten Variante wurden Standards erwähnt, die in dem vorliegenden Abschnitt eingehender erläutert werden sollen. Verzeichnisdienste Verzeichnisdienste (Directories) sind spezialisierte Datenbanken, die Informationen über Personen, Rechner, Privilegien und vieles mehr enthalten können. Wir sprechen deshalb von spezialisierten Datenbanken, weil Zugriffe auf ihre Daten – im Gegensatz zu denen auf »herkömmliche« Datenbanken – durch besondere Merkmale charakterisiert werden: Die Informationen werden im Wesentlichen gelesen, nur selten geändert. Es gibt eine hohe Anzahl paralleler Client-Zugriffe, jeder Client ist nur schwach aktiv. Jeder Client fordert nur geringe Datenmengen – z.B. eine E-Mail-Adresse – an. Verzeichnisdienste können beliebig im Netzwerk repliziert oder verteilt werden. Die Replikation und Verteilung der Daten ist transparent für die zugreifenden Clients. Der Aufbau von Verzeichnisdiensten wird über den X.500-Standard geregelt. Informationen werden nach diesem Standard hierarchisch in Form von Einträgen (Entries) im Kontext eines Verzeichnisinformationsbaumes (Directory Information Tree) abgelegt. Jeder Eintrag wird dabei über ein oder mehrere Attribute näher beschrieben. Einträge mit identischen Attributtypen werden in Objektklassen zusammengefasst. Objektklassen selbst sind in Super- und Subklassen gegliedert. Subklassen erben – wie üblich – die Attribute ihrer Superklassen. Attribute können obligatorisch oder optional sein. Die Objektklasse organisationalPerson beispielsweise wird aus der Klasse person abgeleitet. Sie hat die obligatorischen Attribute sn (surname) und cn (common name) sowie eine Reihe weiterer optionaler Attribute wie z.B. userpassword, telephonenumber und title. Es ließe sich für diese Objektklasse ein entsprechender Eintrag mit den Attributwerten cn=unbescheid und sn=guenter definieren. Da die Person unbescheid in der deutschen Firma databaseconsult arbeitet, wird ihr Eintrag hierarchisch unter dem Objekt der Klasse organization mit dem Attributwert o=databaseconsult angelegt. Das Objekt o=databaseconsult liegt seinerseits unter dem Objekt c=de vom Type country.
400
Sicherheit
Die Identifizierung jedes Verzeichniseintrages ist dementsprechend auf unterschiedliche Weise möglich: 1. Innerhalb einer Ebene eines Unterbaumes über den »relativen eindeutigen« Namen (Relative Distinguished Name – RDN). Der RDN enthält dabei alle Attributtypen und ihnen zugeordnete Werte, die im Rahmen der betreffenden Objektklasse intern als markant (distinguished) definiert wurden. Im oben genannten Beispiel lautet der RDN cn=unbescheid, obwohl die Objektklasse zwei obligatorische Attributtypen – cn und sn – enthält. 2. Innerhalb des gesamten Verzeichnisbaumes über einen global eindeutigen Namen (Distinguished Name – DN), der die RDNs aller übergeordneten Einträge zur Identifizierung mitführt. Im oben genannten Beispiel lautet der DN dementsprechend cn=unbescheid, o=databaseconsult, c=de. Neben den hier dargestellten Benutzerattributen enthalten Objektklassen eine Reihe von weiteren, operationalen Attributen, wie z.B. Zeitstempel, die für administrative Operationen des Verzeichnisses benötigt werden. Neue Objektklassen und Attributtypen lassen sich im Rahmen des oben dargestellten Modells beliebig anlegen, wodurch Verzeichnisdienste einen großen Teil ihrer Flexibilität und Dynamik erhalten. Der X.500-Standard definiert allerdings einen allgemein gültigen Satz aus Attributtypen und Objektklassen, um die internationale Nutzung der Dienste sicherzustellen. Die Erweiterung der Attributtypen ist auf der anderen Seite überall dort sinnvoll, wo Hersteller spezifische Informationen für die Funktionalität ihrer Produkte in dem betreffenden Verzeichnis speichern wollen. Das Verzeichnisschema (Directory Schema) enthält dementsprechend alle Metainformationen zu Objektklassen, Attributtypen, Datenformaten (Syntax) und Vergleichsregeln (Matching Rules) eines Verzeichnisses. Auch Oracle hat im Rahmen von Oracle Internet Directory zusätzliche Objektklassen und Attributtypen definiert, so z.B. die Objektklasse orclDBServer zur Verwaltung von Oracle-Datenbanken. Oracle Internet Directory Architektur Oracle Internet Directory implementiert die im vorangehenden Abschnitt beschriebenen Verzeichnisdienste. Es besteht im Einzelnen aus einer Reihe unterschiedlicher Komponenten, die gemeinsam auf einem Rechner oder verteilt installiert und verwaltet werden können. LDAP-Server Der LDAP-Server nimmt Anfragen an den Verzeichnisdienst entgegen und leitet sie an die betreffende Datenbank weiter. LDAP-Server werden als Instanz gestartet. Jede LDAP-Instanz besteht aus einem Dispatcher- bzw. Listener-Prozess, der auf eine konfigurierbare Portnummer – z.B. 386 oder 639 – »horcht«, und einem oder mehreren Serverprozessen, welche die Verbindung zur Verzeichnisdatenbank über Threads aufbauen. Die Anzahl der Serverprozesse sowie der Threads sind ebenfalls konfigurierbar. Es lassen sich ein oder mehrere LDAP-Instanzen auf einem Server starten. Die Datenbank mit den Verzeichnisdaten kann sowohl lokal als auch entfernt konfiguriert werden.
Internet Directory, LDAP und SSL
401
LDAP-Server Instanzen
LDAP-Server
LDAP Anforderungen
OID Listener
LDAP-Server
Net Listener
LDAP-Server
Oracle Net
Abbildung 9.5: LDAP-Diagramm
Directory Replication-Server Der Directory Replication-Server sorgt für die Replikation der Verzeichnisdaten. Verzeichnisdatenbank Die Verzeichnisdatenbank speichert die Verzeichnisdaten. Aus Gründen der Konformität mit dem LDAP-Standard der Version 3 muss diese Datenbank mit dem UTF8-Zeichensatz angelegt werden. Die Kommunikation zwischen den LDAP-Instanzen und der Verzeichnisdatenbank erfolgt über Oracle-Netzdienste (Oracle Net Services21). Die Datenbank muss darüber hinaus die für die Verwaltung der Verzeichnisdaten notwendigen Schemaobjekte enthalten, die im Zuge der Installation angelegt werden. OID-Monitor Der Monitorprozess wird zum Starten und Stoppen sowie zur Beobachtung (Monitoring) der LDAP-Instanzen benötigt. Er wird über Befehle angesprochen, welche die OID Control Utility generiert.
21 Oracle Net Services ist der neue Name für SQL*Net und Net8. Er wurde mit Oracle9i eingeführt.
402
Sicherheit
OID Control Utility OID Control Utility ist ein Werkzeug zum Starten, Stoppen und Konfigurieren von LDAP-Servern. Die für die Konfiguration notwendigen Parameter – z.B. die Anzahl der LDAP-Serverprozesse – werden innerhalb der Verzeichnisdatenbank in so genannten Configuration Set Entries oder Configsets gespeichert. Beim Start einer LDAP-Instanz über die Control Utility wird der gewünschte Configset referenziert. Anwendungen Zur Administration und Nutzung des Internet Directorys stehen diverse Webanwendungen und Java-Client-Programme zur Verfügung, wie z.B. Enterprise Manager Application Server Control zum Starten und Stoppen der OIC-Instanzen oder der Enterprise Security Manager zur Verwaltung von LDAP-Benutzern. Installation und Konfiguration Oracle Internet Directory ist seit der Version 10g in die Identity-ManagementInfrastruktur des Oracle Application-Servers integriert und wird aus diesem Kontext heraus auch installiert. Die Software ist derzeit über die Option 1 – »Oracle Application-Server – Portal and Wireless« über das Technologie-Netzwerk22 herunterzuladen und nach den aktuellen Lizenzbestimmungen nutzbar. Es ist dringend zu empfehlen, vor der Installation die entsprechenden Installationsvoraussetzungen zu beachten. Hierzu stehen wie üblich die plattform-spezifische Dokumentation sowie Readme-Dateien zur Verfügung. Zusätzlich bietet Metalink für Linux-Plattformen unter der Nummer 309401.1 ein Dokument mit genauen Prüfroutinen an. In diesem Zusammenhang steht auch ein sehr nützliches Shell-Skript zur Prüfung der Installationsvoraussetzungen zum Download bereit. Bevor dieses Skript nicht fehlerfrei durchlaufen wird, sollte nicht an eine Installation gedacht werden! Die Installation selbst wird – wie gewohnt – über den Universal Installer und dort über die Installationsart »OracleAS Infrastructure« und anschließend »Identity Management und Metadaten-Repository« ausgeführt. Sie hat in einem separaten Home-Verzeichnis zu erfolgen. In einem weiteren Fenster sind dann die einzelnen Komponenten auszuwählen: Hier sollte neben ORACLE INTERNET DIRECTORY auf jeden Fall noch DELEGATED ADMINISTRATION SERVICE ausgewählt werden, um einige Webanwendungen zur Benutzerverwaltung zu installieren. Diese Installationsart installiert Komponenten, wie den HTTP-Server, eine 10gDatenbank als Repository für die Infrastruktur-Komponenten, unter ihnen auch Oracle Internet Directory, einen minimalen Application-Server (ORACLEAS CONTAINERS FOR J2EE) für die administrativen Anwendungen sowie explizit ausgewählten Komponenten.
22 http://technet.oracle.com
Internet Directory, LDAP und SSL
403
Abbildung 9.6: Installation von Oracle Internet Directory
Abbildung 9.7: Auswahl der zu installierenden Komponenten
Nach der erfolgreichen Installation findet sich eine gute Zusammenfassung der installierten Komponenten sowie der URLs für die diversen Anwendungen in der Datei $ORACLE_HOME/install/setupinfo.txt. Hier finden sich alle relevanten Informationen, die während der Installation interaktiv abgefragt wurden.
404
Sicherheit
Die Installation hinterlässt eine fertig gestartete Umgebung des Application-Servers. Die Startseite ist unter der in der Setup-Info angegebenen URL erreichbar und über sie auch die Webanwendung Enterprise Manager 10g Application Server Control. Dort können alle installierten Komponenten, so auch das Internet Directory, administriert werden. Die Home-Page der betreffenden Server-Farm zeigt die Komponenten.
Abbildung 9.8: IAS Control-Homepage
Die Seite von Internet Directory kann über diese Homepage erreicht werden und zeigt in unserem Beispiel zwei gestartete OID-Instanzen sowie nützliche Links für die Arbeit: Um auch nach dem Neustart des Rechners eine gut funktionierende OID-Umgebung vorzufinden, sollen an dieser Stelle kurz die Schritte zusammengefasst werden, die zum manuellen Start der Umgebung unter Unix nötig sind. Es versteht sich, dass diese Schritte in einer produktiven Umgebung automatisiert werden: Als Erstes sind die Umgebungsvariablen einzustellen – beispielsweise über folgendes Shell-Skript: export PATH=${PATH}:/usr/local/bin export ORACLE_SID=IADB export ORAENV_ASK=NO . oraenv export LD_LIBRARY_PATH=/usr/lib:$ORACLE_HOME/lib export PATH=${PATH}:$ORACLE_HOME/bin:$ORACLE_HOME/dcm/bin:$ORACLE_HOME/opmn/ bin:$ORACLE_HOME/oca/bin export ORAENV_ASK=YES
Internet Directory, LDAP und SSL
405
Abbildung 9.9: OID-Homepage
Nachdem die Umgebung eingestellt wurde, können der Listener und die Repository-Datenbank wie üblich gestartet werden. Dies ist notwendig, damit im nächsten Schritt der Start der Hintergrundprozesse gelingt. Für das Prozessmanagement der Hintergrundprozesse des Application-Servers steht das Zeilenwerkzeug opmnctl zur Verfügung. Hierüber können einzelne oder alle Prozesse des Servers gestartet oder gestoppt werden. Mit dem Kommando opmnctl startall werden beispielsweise alle Hintergrundprozesse aktiviert. Nach kurzer Wartezeit gibt dann opmnctl status Auskunft über den Status:
Abbildung 9.10: Ausgabe von opmnctl status
Im letzten Schritt ist jetzt noch die Anwendung Enterprise Manager IAS Control wie folgt zu starten: emctl start iasconsole
406
Sicherheit
Neben den erwähnten administrativen Werkzeugen wird die inhaltliche Arbeit mit den Verzeichniseinträgen von OID über zusätzliche Tools geregelt, die alle im Zuge der Installation auf Platte kopiert werden: Der »Oracle Directory Manager« ist ein Java-Client-Werkzeug, über das sämtliche Verzeichnisstrukturen zugänglich und manipulierbar sind. Es wird jedoch für die praktische Arbeit mit Enterprise-Benutzern und für die Registrierung von Datenbanken nur selten genutzt, weil es dem Anwender eine genaue Kenntnis der internen Speicherstrukturen abverlangt. Das Werkzeug wird über oidadmin aufgerufen und erfordert zur Anmeldung an das Repository einen Benutzernamen – standardmäßig orlcadmin – und das entsprechende Passwort. Der »Enterprise Security Manager« ist ebenfalls ein Java-Client-Werkzeug, mit dem alle Aufgaben im Kontext mit Enterprise-Benutzern und Enterprise-Rollen sowie deren Zuordnung zu den registrierten Datenbanken komfortabel durchgeführt werden können. Das Werkzeug ist leider nur über die Client-Installation verfügbar. Es kann entweder direkt über den Befehl esm oder über die Java Enterprise Manager Console mit oemapp esm aufgerufen werden. Schließlich steht noch eine Webanwendung zur Verfügung, die auch den Titel »Enterprise Security Manager« trägt, jedoch in der Funktionalität etwas eingeschränkt wurde. Über sie können nur Enterprise-Benutzer angelegt und verwaltet werden, jedoch keine Zuordnung zu den Datenbanken und EnterpriseRollen vorgenommen werden. Die URL zum Aufruf dieser Anwendung lautet beispielsweise (die Portnummer kann von Installation zu Installation variieren): http://myServer:7780/oiddas/ui/oideushome
Verzeichnisdaten werden – wie bereits erwähnt – in Baumstrukturen in Form von Entries angelegt. Um Oracle-spezifische Daten, wie z.B. Benutzer- und Datenbanknamen, in Verzeichnissen zu speichern, sind spezifische Objektklassen, Attribute und Regeln notwendig, die als Metadaten in der betreffenden Datenbank gespeichert und zusammenfassend als das Oracle-Schema bezeichnet werden. Während der standardmäßigen Installationsprozedur über den Universal Installer wird dieses Oracle-Schema in der Zieldatenbank bereits aufgebaut. Für manuelle Neu- oder Nachinstallationen dieses Schemas steht das Werkzeug Net Configuration Assistant zur Verfügung. Mit Hilfe der im Oracle-Schema enthaltenen Objektklassen und Attribute können dann über Oracle Contexts individuelle Verzeichnisdaten zu Benutzern, Datenbank- und Dienstnamen eingetragen werden. Ein Oracle-Kontext ist demnach ein administrativer Kontext, der an einem Punkt innerhalb des Verzeichnisbaumes die Speicherung von Oracle-spezifischen Einträgen erlaubt und über den Client-Anwendungen Verzeichnisdaten suchen und abrufen können. Es sind durchaus mehrere Oracle-Kontexte pro Verzeichnisdatenbank möglich. Oracle-Kontexte werden – wie auch Oracle-Schemata – über das Werkzeug Net Configuration Assistant initiiert und können je nach Inhalt über unterschiedliche Werkzeuge verwaltet werden. Einzelheiten hierzu finden sich in den Abschnitten Modell 1: Auflösung von Dienstbenennungen bis Modell 3: Enterprise-Benutzer und Enterprise-Rollen.
Internet Directory, LDAP und SSL
407
Jede Oracle-Datenbank, die Verzeichnisdaten enthält, wird demnach durch die folgenden Merkmale charakterisiert: Sie enthält im Datenbankschema ods Tabellen, Pakete und Sequenzen zur Speicherung von Metadaten und Benutzerdaten. Sie enthält Oracle-spezifische Objektklassen und Attribute (Metadaten) in Form eines Oracle-Schemas, das in den Tabellen des Datenbankschemas ods gespeichert wird. Sie enthält einen oder mehrere Oracle-Kontexte, in denen benutzerspezifische Daten – ebenfalls in den Tabellen von ods – gespeichert und von Client-Anwendungen abgerufen werden. Digitale Zertifikate und SSL Digitale Zertifikate identifizieren Entitäten. Entitäten im Kontext von Oracle können z.B. globale Benutzer, Datenbanken oder Verzeichnisadministratoren sein. Digitale Zertifikate funktionieren vor dem Hintergrund der Public-Key-Kryptografie. Bei diesem Paradigma werden zwei verschiedene Schlüssel – ein öffentlicher (public) und ein privater – verwendet. Die Schlüssel werden so generiert, dass die Ableitung des öffentlichen Schlüssels aus dem privaten und umgekehrt mit vertretbarem Rechenaufwand nur schwer möglich ist und es keine Schlüssel gibt, die auf mehr als ein Schlüsselpaar verweisen. Beide Schlüssel können zur Verschlüsselung verwendet werden, die Entschlüsselung kann jedoch nur mit dem jeweils anderen Schlüssel des Paares erfolgen. Eine mit einem öffentlichen Schlüssel verschlüsselte Botschaft kann daher nur mit dem entsprechenden privaten Schlüssel entschlüsselt werden und umgekehrt. Wie die Namen bereits nahe legen, verbleibt der private Schlüssel in den »Händen« des Benutzers, der öffentliche kann entsprechend verteilt werden. Diese enge Koppelung der beiden Schlüssel eines Schlüsselpaares hat weitreichende Konsequenzen – nicht nur für die Verschlüsselung von Botschaften, sondern auch für die Authentifizierung ihrer Besitzer: Gelingt die Entschlüsselung einer Botschaft – z.B. mit Hilfe eines öffentlichen Schlüssels –, kann sich der Empfänger sicher sein, den für den privaten Schlüssel passenden Gegenschlüssel verwendet und damit auch die Authentizität der Botschaft nachgewiesen zu haben. Die Authentizität der Botschaft ist immer dann gegeben, wenn sich der Empfänger über die Zuordnung eines öffentlichen Schlüssels zu einer Entität absolut sicher sein kann. Diese Zuordnung eines öffentlichen Schlüssels zu einer Entität wird in Form eines digitalen Zertifikates beglaubigt, das von einer Zertifizierungsstelle (Certificate Authority, CA) »unterschrieben« ist. Die Unterschrift erfolgt in elektronischer Form durch den privaten Schlüssel der CA. Das Anwendungsprogramm kann dieses beglaubigte Zertifikat mit Hilfe des öffentlichen Schlüssels der unterzeichneten CA »auspacken«. Die öffentlichen Schlüssel von vertrauenswürdigen CAs sind in Form von so genannten Trust Points der betreffenden Anwendung bekannt zu machen, d.h., diese müssen entsprechend installiert werden. Der Standard X.509 legt den genauen Aufbau von digitalen Zertifikaten fest. Zertifikate enthalten neben dem Distinguished Name der betreffenden Entität und dem öffentlichen Schlüssel auch noch eine Seriennummer, ein Verfallsdatum sowie Informationen über die ausstellende CA.
408
Sicherheit
Alle identifizierenden Daten einer Entität – das Schlüsselpaar, das Zertifikat sowie vertrauenswürdige Trust Points – werden in Form eines so genannten Wallets gespeichert. Nach dem Öffnen eines Wallets, das über ein Passwort geschützt ist, stehen diese identifizierenden Daten zur Verfügung und können von Anwendungen im Zusammenspiel mit einem Verzeichnisdienst für die Authentifizierung und Autorisierung genutzt werden. Oracle stellt mit dem Oracle Wallet Manager ein Werkzeug zum Generieren von Zertifikatsanforderungen und Verwalten von Wallets zur Verfügung. Zertifikatsanforderungen können hier exportiert und – nach der Bearbeitung durch eine vertrauenswürdige Zertifizierungsstelle – als fertiges Zertifikat wieder importiert werden. Benutzern, die – vornehmlich zu Testzwecken oder für den produktiven Einsatz – eine eigene Zertifizierungsstelle betreiben möchten, stehen neben kommerziellen Produkten die Kryptografie-Bibliotheken und Werkzeuge des OpenSSL-Projektes23 kostenfrei zur Verfügung. Für die sichere Kommunikation über Netzverbindungen ist neben der oben beschriebenen Identifizierung des Kommunikationspartners auch die Verschlüsselung und Integritätssicherung der übermittelten Daten wichtig. Secure Sockets Layer (SSL) ist ein Protokoll zur sicheren Kommunikation über Netzverbindungen. SSL sorgt beim Verbindungsaufbau dafür, dass Zertifikate ausgetauscht, Verschlüsselungsalgorithmen ausgehandelt, und Integritätsprüfungen durchgeführt werden. Für die Verschlüsselung benutzt SSL herkömmliche symmetrische Algorithmen, wie z.B. DES oder RC4, die Integritätsprüfung wird mit Hilfe von Hash-Algorithmen, wie z.B. MD5 oder SHA, durchgeführt.
9.6.3
Modell 1: Auflösung von Dienstbenennungen
Die Nutzung von Verzeichnisdiensten im Kontext von Oracle-Datenbanken ist in vielfältiger Hinsicht möglich. In unserem ersten Nutzungsmodell werden die Dienstbenennungen von Oracle Net statt über die lokale Datei tnsnames.ora oder – wie in älteren Versionen – über Oracle Names nun über den Verzeichnisdienst aufgelöst. Hierzu sind neben den im Abschnitt »Installation und Konfiguration« beschriebenen Schritten die folgenden Arbeiten notwendig: Planung und Definition von Dienstbenennungen im Kontext des Verzeichnisdienstes Konfiguration des Clients
23 Informationen und Downloads finden sich unter der Internet-Adresse www.openssl.org.
Internet Directory, LDAP und SSL
409
Planung und Definition von Dienstbenennungen Einträge in Verzeichnisdiensten erfolgen – wie bereits in Abschnitt »Verzeichnisdienste« auf Seite 399 dargelegt wurde – auf der Basis von Objektklassen im Kontext von Verzeichnisbäumen. Um die in unserem Beispiel geforderten Dienstbenennungen für Oracle Net in Oracle Internet Directory zu platzieren, benötigen wir daher: Objektklassen, die in der Lage sind, die spezifischen Informationen von OracleDienstbenennungen zu repräsentieren Einen Wurzelpunkt im Kontext einer Verzeichnishierarchie, unter dem ein Oracle-Kontext aufgebaut werden kann Konkrete Einträge unter diesem Wurzelpunkt auf der Basis der oben erwähnten Objektklassen, welche die von uns benötigten Dienstbenennungen speichern In diesem Beispiel gehen wir davon aus, dass die spezifischen Objektklassen (Oracle-Schema) bereits im Rahmen der Installationsprozedur oder nachträglich über den Oracle Internet Configuration Assistant (oidca) aufgebaut wurden. Die nötigen Objektklassen sind also bereits vorhanden. Das Vorhandensein eines Oracle-Kontexts sowie seine versionsspezifische Verträglichkeit lassen sich ebenfalls über oidca im Voraus überprüfen. Das folgende Beispiel prüft den Kontext dc=dbconsult,dc=de erfolgreich: oidca mode=CREATECTX -silent oidhost=myServer nonsslport=3060 dc=orcladmin pwd=kennwort contextdn=“dc=dbconsult,dc=de“ Oracle Context ist aktuell.
Die Konfiguration der Dienstbenennungen über den Verzeichnisdienst kann über den Enterprise Manager oder den Net Manager vorgenommen werden. In beiden Fällen ist dem Client, von dem aus das Werkzeug aufgerufen werden soll, beizubringen, auf welchem Server sich der betreffende Verzeichnisdienst befindet und in welchem Bereich der dortigen Baumstruktur der Oracle Context angelegt wurde, der die Einträge aufnehmen soll. Diese Grundkonfiguration kann über den Net Configuration Assistant generiert werden, der die Datei ldap.ora erzeugt, die im Verzeichnis $ORACLE_HOME/network/admin abgelegt. wird. # ldap.ora Network Configuration File: H:\Oracle\Client10R1\network\admin\ldap.ora # Generated by Oracle configuration tools. DIRECTORY_SERVERS= (myServer:3060:3130) DEFAULT_ADMIN_CONTEXT = "dc=dbconsult,dc=de" DIRECTORY_SERVER_TYPE = OID Listing 9.5: LDAP.ora-Datei zur Bekanntmachung eines Verzeichnisdienstes
Die oben abgebildete ldap.ora-Datei hat den Port 3060 für normale und den Port 3130 für SSL-Verbindungen des OID-Verzeichnisdienstes auf myServer konfiguriert. Der administrative Kontext – unter dem standardmäßig Einträge erstellt und gesucht werden – ist dc=dbconsult,dc=de.
410
Sicherheit
Nachdem diese Voreinstellungen abgeschlossen sind, kann nun der Net Manager aufgerufen werden. Im linken Auswahlmenü wird ab sofort der Eintrag »Verzeichnis« angezeigt, über den Dienstbenennungen und Aliasnamen für Dienstbenennungen erzeugt oder modifiziert werden können. Dienstbenennungen spezifizieren den kompletten Kontext für die Verbindung – wie aus der Syntax der Datei tnsnames.ora hinlänglich bekannt sein dürfte –, Aliasnamen dagegen verweisen auf Dienstbenennungen, die im gleichen oder in fremden administrativen Kontexten angelegt wurden. Beim erstmaligen Aufklappen des Verzeichnisbaumes muss sich der Benutzer zunächst beim Verzeichnisdienst authentifizieren. Standardmäßig kann hierzu der LDAP-Benutzer cn=orcladmin oder ein beliebiger anderer genutzt werden. Wichtig ist nur, dass der betreffende für die Verwaltung von Dienstbenennungen privilegiert wurde und in dem konkreten administrativen Kontext – hier dc=dbconsult,dc=de – bekannt ist. Die folgende Abbildung zeigt Dienstbenennungen und Aliasnamen.
Abbildung 9.11: Oracle Net Manager zur Verwaltung von Dienstbenennungen und Aliasnamen über einen Verzeichnisdienst
Vorhandene Dienstnamen können – ebenfalls über Oracle Net Manager – aus einer lokalen Datei tnsnames.ora in das Verzeichnis importiert werden. Hierzu wird über die Menüleiste BEFEHL – DIRECTORY – NET SERVICE NAMES EXPORTIEREN aufgerufen. Im anschließenden Dialog lassen sich die Dienstnamen und die administrativen Kontexte auswählen. Konfiguration des Clients Die Konfiguration von Clients ist im Anschluss recht einfach durchzuführen. Hierzu sind die folgenden Aktionen durchzuführen: 1. Konfiguration der Methode für die Auflösung von Dienstnamen 2. Konfiguration des vorbereiteten Verzeichnisdienstes in Form der Portnummern, des Servernamens und des Diensttyps über die Datei ldap.ora
Internet Directory, LDAP und SSL
411
Alle genannten Aktionen lassen sich über Werkzeuge erledigen. Punkt 1, die Methode der Namensauflösung, wird im Netzprofil des Clients mit Hilfe des Werkzeugs Oracle Net Manager24 definiert und in der Datei sqlnet.ora gespeichert. Das folgende Beispiel zeigt den relevanten Ausschnitt aus dieser Datei. LDAP, das heißt der Verzeichnisdienst, wird hier als erste Wahl der Namensauflösung festgeschrieben. Für den Fall, dass eine Auflösung über LDAP nicht erfolgreich sein sollte, kann die lokale Datei tnsnames.ora herangezogen werden: names.directory_path = (LDAP, TNSNAMES)
Für die Konfiguration des Punktes 2 ist – wie bereits erwähnt – ein anderes Werkzeug, der Oracle Net Configuration Assistant, zuständig. Die Datei ldap.ora kann natürlich auch von Hand editiert werden. Der Verbindungsaufbau von Clientseite kann nun erfolgreich in der gewohnten Syntax durchgeführt werden: sqlplus scott/tiger@test9
Der Dienst- bzw. Aliasname test9 wird für den Zugriff auf den Verzeichnisdienst auf Grund des zugrunde liegenden administrativen Kontexts umgewandelt in: cn=test9,cn=OracleContext,dc=dbconsult,dc=de
Die Namensauflösung über Verzeichnisdienste ist – wegen des erforderlichen Zugriffs auf den LDAP-Server – geringfügig aufwändiger als die über die lokale Datei tnsnames.ora. Dem stehen jedoch die Vorteile der zentralisierten Namensverwaltung gegenüber.
9.6.4
Modell 2: Authentifizierung globaler Benutzer
Die Authentifizierung globaler Benutzer bietet Anwendern die Möglichkeit, Verbindungen zu entfernten Datenbanken ohne Angabe von Passwörtern aufzubauen. Der Anwender wird dabei mit dem globalen Datenbankbenutzer der Zieldatenbank verbunden, dessen global eindeutiger Name (Distinguished Name) identisch ist mit dem des geöffneten Wallets auf der Seite des betreffenden Clients. Verzeichnisdienste werden in diesem Modell nicht benötigt, wohl aber der Verbindungsaufbau über das SSL-Protokoll zwischen Client und Datenbank. Die SSL-Verbindung sorgt auch für die Verschlüsselung und Integritätsprüfung der übermittelten Datenpakete. Im Einzelnen sind für die Umsetzung dieses Modells die folgenden Konfigurationsschritte notwendig: 1. Generieren, Anfordern und Beglaubigen von digitalen Zertifikaten für Clients und Datenbanken 2. Anlegen der erforderlichen globalen Benutzer in den betreffenden Zieldatenbanken 3. Konfiguration des Listener-Prozesses der Datenbank für den Verbindungsaufbau über das SSL-Protokoll
24 Unter Oracle8i heißt dieses Werkzeug Oracle Net8 Assistant.
412
Sicherheit
4. Bereitstellen von Dienstnamen für die Herstellung der SSL-Verbindungen 5. Konfiguration des Clients für den Verbindungsaufbau über SSL Diese Konfigurationsschritte werden im Folgenden detailliert erläutert. Anlegen von Zertifikaten Die Grundlagen von Zertifikaten wurden bereits im Abschnitt Digitale Zertifikate und SSL und SSL besprochen. In unserem Beispiel wird zunächst mit Hilfe des Werkzeugs Oracle Wallet Manager über die Menüpunkte WALLET und NEU eine voll spezifizierte Zertifikatsanforderung für folgende Identität erstellt: DN: CN=Guenter, CN=dbconsult. Bei der Generierung ist ferner ein entsprechendes Passwort anzugeben und eine Schlüssellänge auszuwählen. Die Anforderung wird im vorgeschlagenen Standardverzeichn25is oder anderweitig gespeichert und dann über die Menüpunkte VORGÄNGE und ZERTIFIKATSANFORDERUNG EXPORTIEREN in eine Datei geschrieben. Diese Exportdatei muss nun an eine vertrauenswürdige Zertifizierungsstelle übermittelt werden. Wie bereits erwähnt wurde, lässt sich für Testzwecke eine eigene Zertifizierungsstelle mit Hilfe von openSSL anlegen. Von der betreffenden Zertifizierungsstelle erhält der Anwender das beglaubigte Zertifikat in Form einer Datei zurück. Nach dem Öffnen der Zertifikatsanforderung im Oracle Wallet Manager ist diese Datei dann über die Menüpunkte VORGÄNGE und BENUTZERZERTIFIKAT IMPORTIEREN einzulesen. Das Importieren kann dann entweder durch Einlesen der gelieferten Datei oder über Cut-und-Paste-Aktionen durchgeführt werden. Die Zertifikatsanforderung erhält dadurch den Status bereit und mutiert zu einem beglaubigten Zertifikat, sofern die ausstellende Zertifizierungsstelle mit ihrem Zertifikat als »vertrauenswürdig« im Oracle Wallet Manager aufgenommen wurde. Der Distinguished Name, den das Zertifikat beglaubigt hat, erscheint auf der rechten Seite des Wallet-Manager-Fensters unter »Betreff« – in unserem Beispiel CN=Guenter, CN=dbconsult. Die Zertifikate vertrauenswürdiger Zertifizierungsstellen erscheinen unter dem Verzeichnispunkt GESCHÜTZTE ZERTIFIKATE. Zusätzliche Trust Points lassen sich über die Menüpunkte VORGÄNGE und GESCHÜTZTES ZERTIFIKAT IMPORTIEREN anfügen. Zertifikate und ihnen anhängende Informationen werden in Form eines Wallets in dem angegebenen Verzeichnis gespeichert, unabhängig davon, wie der Distinguished Name angegeben wurde. Zertifikate für unterschiedliche Identitäten auf einem Client sind daher in unterschiedlichen Verzeichnissen abzulegen. Für erfolgreich geöffnete Wallets existiert zusätzlich in demselben Verzeichnis die Datei cwallet.sso. In gleicher Weise werden Zertifikate für die erforderlichen Datenbanken generiert. Der Distinguished Name der Datenbank kann dabei dem verwendeten Servicenamen entsprechen.
25 Unter Windows2000: c:\Dokumente und Einstellungen\Administrator\ORACLE\WALLETS
Internet Directory, LDAP und SSL
413
Abbildung 9.12: Oracle Wallet Manager mit Benutzerzertifikat
Definition globaler Benutzer Im nächsten Schritt sind entsprechend den Zertifikaten globale Benutzer in den betreffenden Datenbanken zu definieren. Beim Anlegen der Benutzer ist darauf zu achten, dass die global eindeutigen Namen beider Identitäten einschließlich der Groß- und Kleinschreibung genau übereinstimmen. In unserem Beispiel wird der Datenbankbenutzer GUENTER mit einem dem Zertifikat entsprechenden Distinguished Name in der Datenbank erzeugt: SQL> CREATE USER guenter PROFILE default IDENTIFIED GLOBALLY AS 'CN=Guenter, CN=dbconsult' DEFAULT TABLESPACE users TEMPORARY TABLESPACE temp ACCOUNT UNLOCK;
Da der Benutzer ohne Passwort angelegt wird, ist ein normaler Connect von vornherein nicht möglich. Verbindungen mit diesem Benutzer können nur über eine SSL-Verbindung aufgebaut werden. Den Anforderungen entsprechende Privilegien sind dem Benutzer danach über geeignete GRANT-Befehle zu erteilen.
414
Sicherheit
Datenbank-Listener konfigurieren Bevor eine SSL-Verbindung zur Datenbank hergestellt werden kann, ist der Listener-Prozess entsprechend zu konfigurieren oder ein separater Listener-Prozess zu starten. Diese Aufgabe ist mit Hilfe des Werkzeugs Oracle Net Manager zu erledigen. Im Kontext des Listeners sind die folgenden Einstellungen durchzuführen: Anlegen einer neuen Listener-Adresse für das TCPS-Protokoll (TCP/IP mit SSL), das für die SSL-Verbindung erforderlich ist. In diesem Zusammenhang ist auch die Angabe einer Portnummer notwendig – die Nummer 2484 wurde für diese Zwecke von Oracle offiziell reserviert und wird aus diesem Grunde hier empfohlen. Konfiguration des Verzeichnisses, in dem das Datenbankzertifikat gespeichert wurde: Diese Einstellungen werden über den Verzeichnispunkt PROFIL des Net Managers und dort über die Kontextauswahl ORACLE ADVANCED SECURITY und die Karteikarte SSL vorgenommen. Nach Auswahl der Option SERVER ist das entsprechende Verzeichnis anzugeben. Es ist darauf zu achten, dass an diesem Ort nicht nur das Wallet installiert wurde, sondern dass für dieses nach dem Öffnen im Oracle Wallet Manager die Option Automatische Anmeldung26 aktiviert wurde, damit das Zertifikat für andere Anwendungen – hier den Listener – nutzbar ist. Am gleichen Ort sind auch die vom Server unterstützten kryptografischen Algorithmen (Cipher Suite) und die SSL-Version auszuwählen.
Abbildung 9.13: Oracle Net Manager mit SSL-Konfiguration für den Server
26 Dort unter dem Menüpunkt WALLET
Internet Directory, LDAP und SSL
415
Die Konfiguration wird vom Oracle Net Manager in den Dateien listener.ora und Sqlnet.ora gespeichert. Die nachfolgenden Listen zeigen die relevanten Ausschnitte: # listener.ora Network Configuration File: /app/oracle/product/10gR1/network/admin /listener.ora # Generated by Oracle configuration tools. LISTENER = (DESCRIPTION_LIST = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = myServer)(PORT = 1525)) ) (DESCRIPTION = (ADDRESS = (PROTOCOL = TCPS)(HOST = myServer)(PORT = 2484)) ) ) SSL_CLIENT_AUTHENTICATION = FALSE WALLET_LOCATION = (SOURCE = (METHOD = FILE) (METHOD_DATA = (DIRECTORY = /app/oracle/admin/test10/wallet) ) Listing 9.6: Ausschnitte aus der Datei listener.ora auf dem Server SQLNET.AUTHENTICATION_SERVICES= (BEQ, TCPS) SSL_VERSION = 0 NAMES.DIRECTORY_PATH= (TNSNAMES) SSL_CLIENT_AUTHENTICATION = TRUE WALLET_LOCATION = (SOURCE = (METHOD = FILE) (METHOD_DATA = (DIRECTORY = /app/oracle/admin/test10/wallet) ) ) Listing 9.7: Ausschnitte aus der Datei sqlnet.ora auf dem Server
Dienstnamen für SSL definieren Es versteht sich, dass für den Verbindungsaufbau über SSL wegen der speziellen Portnummer ein vorhandener Dienstname modifiziert oder ein eigener aufgebaut werden muss. Je nachdem, wie Dienstnamen auf den jeweiligen Clients aufgelöst werden, kann dieser Name lokal in der Datei tnsnames.ora oder zentral im Kontext eines Verzeichnisdienstes definiert werden. Das folgende Beispiel zeigt einen Ausschnitt der Datei tnsnames.ora für den Dienstnamen test10ssl:
416
Sicherheit
TEST10SSL = (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCPS)(HOST = myServer)(PORT = 2484)) ) (CONNECT_DATA = (SERVICE_NAME = test10.nandadevi.dc) ) ) Listing 9.8: Ausschnitt aus der Datei tnsnames.ora auf dem Client
Wallet für Client konfigurieren Neben dem Dienstnamen müssen für den Verbindungsaufbau des Clients das Verzeichnis des Wallets, die unterstützten kryptografischen Algorithmen und die SSLVersion angegeben werden. Die Einstellungen erfolgen wiederum über den Oracle Net Manager – wie bereits erwähnt –, mit dem Unterschied, dass hier als Kontext die Option CLIENT aktiviert wird. Alle Angaben werden im Netzprofil in der Datei sqlnet.ora gespeichert, die hier in Auszügen abgedruckt ist: WALLET_LOCATION = (SOURCE = (METHOD = FILE) (METHOD_DATA = (DIRECTORY = C:\oracle\wallets) ) ) SSL_CIPHER_SUITES= (SSL_RSA_EXPORT_WITH_RC4_40_MD5) SSL_SERVER_DN_MATCH = No SSL_CLIENT_AUTHENTICATION = TRUE SSL_VERSION = 3.0 NAMES.DIRECTORY_PATH= (TNSNAMES) Listing 9.9: Ausschnitt aus der Datei sqlnet.ora auf dem Client
Bevor nun der erste Verbindungstest durchgeführt wird, sollte noch einmal überprüft werden, ob die Zertifikate auf dem Client und dem Server für die automatische Anmeldung konfiguriert wurden. Das zeigt das Häkchen bei AUTOMATISCHE ANMELDUNG im Menü des Wallet Managers. Ein weiterer Blick sollte auf die SSL-Versionen (Parameter SSL_VERSION) und den kryptografischen Algorithmus (Parameter SSL_CIPHER_SUITES) geworfen werden. Hier müssen auf beiden Seiten der Verbindung identische Einstellungen vorliegen. Bei der Komplexität der Konfiguration und der Vielzahl der zu verwendenden Werkzeuge können sich hier sehr leicht Fehler einschleichen. Die Fehlermeldungen, die beim Connect ausgeworfen werden, sind leider nicht immer so prägnant, dass die Ursache des Problems sofort ersichtlich wird.
Internet Directory, LDAP und SSL
417
Schließlich kann der Verbindungstest erfolgen: sqlplus /@test10ssl
Die Verbindung sollte nun zu dem globalen Benutzer guenter der Zieldatenbank hergestellt werden, dessen global eindeutiger Name mit dem Distinguished Name des verfügbaren Zertifikats übereinstimmt. Zur Kontrolle lässt sich in der betreffenden Session folgende Abfrage starten: SELECT global_name, user , sys_context('userenv','external_name') external_user FROM global_name; GLOBAL_NAME USER EXTERNAL_USER -------------------- ---------- -----------------------------TEST10.NANDADEVI.DC GUENTER cn=Guenter,cn=Users
9.6.5
Modell 3: Enterprise-Benutzer und Enterprise-Rollen
In diesem dritten Nutzungsmodell wird die feste Bindung eines globalen Datenbankbenutzers an ein Zertifikat, die im Abschnitt Modell 2: Authentifizierung globaler Benutzer beschrieben wurde, aufgebrochen. Enterprise-Benutzer werden im Verzeichnisdienst definiert und korrespondieren mit globalen Benutzern, die ohne Zuordnung eines Distinguished Nam27es in der Datenbank angelegt werden. Die Zuordnung von Enterprise-Benutzern und ihren Identitäten zu den Benutzern vorgegebener Datenbanken erfolgt ausschließlich über einen Verzeichnisdienst. Auf diese Weise lassen sich mehrere Enterprise-Benutzer an einen Datenbankbenutzer binden, daher der Begriff Shared Schema. Da möglicherweise nicht alle Identitäten, die ein Shared Schema benutzen, die gleichen Privilegien erhalten dürfen, lassen sich Rollen ebenso über Verzeichnisdienste zuteilen: In der Datenbank definierte globale Rollen mit ihren Privilegien werden so genannten Enterprise-Rollen zugeordnet, die im Kontext des Verzeichnisdienstes ohne Angabe von Privilegien angelegt wurden. Über den Verzeichnisdienst werden dann die Enterprise-Rollen den Enterprise-Benutzern im Kontext bestimmter Zieldatenbanken zugeordnet. Die Authentifizierung der Enterprise-Benutzer kann über Zertifikate oder Passwörter erfolgen. Im letzten Fall werden die Passwörter zentral im Verzeichnisdienst verwaltet, die Benutzer melden sich unter ihrem Enterprise-Namen und Passwort bei einer Zieldatenbank an, diese überprüft die Identität mit Hilfe des Verzeichnisdienstes und verbindet den Betreffenden mit dem für ihn konfigurierten globalen Schema der Datenbank. Auf diese Weise lassen sich Passwörter zentral verwalten. Für dieses Modell sind die folgenden Komponenten notwendig: Funktionsfähiger Verzeichnisdienst/LDAP-Dienst Registrierung der Zieldatenbanken bei dem Verzeichnisdienst Datenbanken mit globalen Benutzern und – möglicherweise – globalen Rollen Konfiguration der Enterprise-Benutzer im Verzeichnisdienst
27 In einer Sonderform kann die Identifizierung auch über Distinguished Names erfolgen. Diese Variante wird hier jedoch nicht beschrieben.
418
Sicherheit
Zur Implementierung dieses Modells sind dementsprechend die folgenden Arbeiten durchzuführen: 1. Grundinstallation des Verzeichnisdienstes mit dem Aufbau des Oracle-Schemas und des Oracle-Kontextes – wie bereits beschrieben. Optional kann ein Identity Management Realm angelegt werden. 2. Konfiguration der Directory-Anbindung und Registrierung der betreffenden Datenbanken bei dem Verzeichnisdienst 3. Anlegen von globalen Benutzern und Rollen in den Zieldatenbanken 4. Anlegen von Enterprise-Benutzern und -Rollen in dem Verzeichnisdienst 5. Zuordnung der Enterprise-Benutzer und -Rollen zu den globalen Rollen der Datenbanken Diese Aufgaben sollen nun – sofern dies nicht schon in vorangehenden Abschnitten geschehen ist – im Detail besprochen werden: Anlegen eines Identity Management Realms Unter einem Identity Management Realm versteht man einen Teil der gesamten DIT-Baumes eines Verzeichnisses, der Identitäten und mit ihnen verbundene Richtlinien administrativ zusammenfasst. Auf diese Weise lassen sich unterschiedliche Benutzerpopulationen und für sie verantwortliche Administratoren konfiguratorisch festlegen. Bereits während der Installation wird standardmäßig das Realm »Default Company« angelegt. Über die SELF-SERVICE-CONSOLE28 von Oracle Internet Directory können jedoch jederzeit neue Realms angelegt oder bestehende modifiziert werden. Diese Konsole bietet einen separaten Arbeitsbereich »Realm Management«, über den die notwendigen Arbeiten ausgeführt werden können. Die Konfiguration eines Realms besteht letzten Endes aus Verzeichnispunkten für Benutzer und Gruppen. Beim Anlegen eines Realms wird unter seinem jeweiligen Wurzelpunkt – in unserem Fall dc=Dcintern, dc=de – ein eigener Oracle Context angelegt, der von Oracle-Produkten und Applikationen für interne Informationen genutzt wird. In unserem Beispiel werden Details des Realms »DCintern« angezeigt. In dem STANDARDVERZEICHNIS genannten Bereich der Self-Service-Konsole – dort unter dem Tab-Reiter KONFIGURATION – lassen sich schließlich das Realm einstellen, mit dem die Konsole arbeiten soll, sowie weitere Einstellungen vornehmen.
28 Diese Konsole kann entweder über die der Enterprise Manager IAS Console – OID – zugehörigen Links erreicht werden oder direkt über die URL http://<servername>:7780/oiddas. Es versteht sich, dass die Portnummer je nach Installation variieren kann.
Internet Directory, LDAP und SSL
419
Abbildung 9.14: Auswahlseite Identity Management Realms
Abbildung 9.15: Details eines ausgewählten Identity Management Realms
Registrierung der Datenbanken Die Registrierung der Datenbanken erfolgt über das Werkzeug Oracle Database Configuration Assistant. Damit dies gelingt, ist vorher über den Net Configuration Assistant unter der Option »Konfiguration von Directory-Verwendung« oder manuell die Datei ldap.ora zu generieren, die auch den Pfad zu dem betreffenden Identity Management Realm oder administrativen Kontext enthält – in unserem Beispiel dc=dbconsult,dc=de. DIRECTORY_SERVERS= (Nandadevi:3060:3130) DEFAULT_ADMIN_CONTEXT = "dc=dbconsult,dc=de" DIRECTORY_SERVER_TYPE = OID Listing 9.10: Datei ldap.ora mit den Einstellungen für den Verzeichnisdienst sowie dem Identity Management Realm für das betreffende Home-Verzeichnis
Nun kann der Configuration Assistant aufgerufen werden. Über die Option DATENBANKOPTIONEN KONFIGURIEREN wird die betreffende Datenbank ausgewählt und im vierten Schritt schließlich die Authentifizierung bei dem Verzeichnisdienst – mit vollem Distinguished Name – vorgenommen sowie das Passwort für das Datenbank-Wallet angegeben.
420
Sicherheit
Abbildung 9.16: Registrierung der Datenbank
Im Einzelnen wird bei der Registrierung Folgendes ausgeführt: Im Verzeichnisdienst wird unter dem in der Datei ldap.ora angegebenen administrativen Kontext und dort unter dem obligatorischen Oracle Context die Datenbank mit dem ihr zugeordneten Unterbaum eingetragen. Die Datenbank mit dem Namen (db_unique_name von v$database) test10 wird demnach im administrativen Kontext dc=dbconsult,dc=de mit dem folgenden Distinguished Name erfasst: cn=test10, cn=OracleContext, dc=dbconsult, dc=de. Der neue Eintrag kann über das Java-Client-Werkzeug Oracle Directory Manager29 oder das Werkzeug Enterprise Security Manager30 verifiziert werden. Innerhalb jedes realm können Enterprise Domains angelegt werden, die der Gruppierung von Datenbanken und Enterprise-Rollen dienen. Bereits beim Anlegen eines realm wird ein Standard Enterprise Domain mit Namen OracleDefaultDomain erzeugt. Diesem Standard-Domain wird die neu registrierte Datenbank zugeschlagen. Der Administrator hat natürlich die Möglichkeit, weitere Domains innerhalb des realm anzulegen und die Datenbank dorthin zu transferieren – Datenbanken müssen immer eindeutig einem Enterprise Domain zugeteilt werden.
29 Aufruf über oidadmin 30 ESM gibt es als Webapplikation und als Java-Client-Programm. Zu Verwaltung der Datenbankeinträge ist leider nur der Java-Client zu gebrauchen. Der Programmstart erfolgt über esm.
Internet Directory, LDAP und SSL
421
Abbildung 9.17: Der Java Client Enterprise Security Manager mit registrierten Datenbanken eines realm
Innerhalb jedes Realms lässt sich der Standard für die Berechtigungsprüfung der registrierten Datenbanken gegenüber dem Verzeichnisdienst festlegen. Der Standard für die Berechtigungsprüfung lautet password, was bedeutet, dass sich registrierte Datenbanken per Default mittels Passwörtern beim Verzeichnisdienst anmelden müssen. Alternativ können sich Datenbanken auch per SSL beim Verzeichnisdienst authentifizieren. Während der Registrierung wird demnach für jede Datenbank auch ein internes Passwort generiert. Dieses Passwort darf nicht verwechselt werden mit dem Passwort, das bei der Registrierung angegeben wird und nur zum Öffnen des Datenbank-Wallets geeignet ist. Das interne Passwort der Datenbank hingegen wird einerseits im Verzeichnisdienst in »gehashter« Form, andererseits im Datenbank-Wallet gespeichert. In Abhängigkeit von der für das betreffende Realm festgelegten Authentifizierungsmethode wird der Systemparameter ldap_directory_access vorbelegt. In unserem Beispiel wurde für das realm dbconsult der Standard belassen. Dementsprechend wird generiert: ldap_directory_access=password
Der Parameter kann dynamisch über den Befehl alter system verändert werden. Ein Neustart der Instanz ist also nicht erforderlich. Der Parameter kann auch sehr sinnvoll verwendet werden, um den Zugriff auf den Verzeichnisdienst – vorübergehend oder dauerhaft – zu unterbinden: alter system set ldap_directory_access=none scope=both;
422
Sicherheit
Abbildung 9.18: Enterprise Security Manager: Festlegen der Berechtigungsprüfung für Datenbanken
Wie bereits erwähnt wurde, wird auch ein Datenbank-Wallet generiert. Dieses Wallet enthält neben dem Passwort der Datenbank auch deren Distinguished Name, wie er im Verzeichnisdienst eingetragen wurde. Das Wallet enthält jedoch kein Zertifikat der Datenbank. Dieses muss – für den Fall, das eine Authentifizierung über SSL gewünscht ist – nachträglich bei einer vertrauenswürdigen CA beantragt und importiert werden. Dieses Verfahren wird hier nicht im Detail beschrieben. Das Wallet wird – unter Unix – im Administrationsverzeichnis der betreffenden Datenbank und dort in dem Unterverzeichnis wallet abgelegt: $ORACLE_BASE/admin/$ORACLE_SID/wallet
Über den Oracle Wallet Manager, der über den Befehl owm aufgerufen wird, lässt sich das generierte Wallet öffnen. Bei der Passwortabfrage ist das Passwort, das im Dialog des Configuration Assistants ausgewählt wurde, anzugeben. Die folgende Abbildung zeigt den Zustand nach der erfolgreichen Registrierung: Das Zertifikat ist leer, und im Bereich Secret Store erscheinen die Abschnitte Distinguished Name (ORACLE.SECURITY.DN) und Password (ORACLE.SECURITY.PASSWORD), die der Wallet Manager nicht im Detail anzeigt. Über das Zeilenkommando mkstore können diese Bereiche auch inhaltlich ausgegeben werden. Es versteht sich, dass hierzu auch das Passwort für das Wallet erfolgreich angegeben werden muss:
Internet Directory, LDAP und SSL
423
Abbildung 9.19: Oracle Wallet Manager mit Datenbank-Wallet nach der erfolgreichen Registrierung mkstore -wrl /app/oracle/admin/test10/wallet -viewEntry ORACLE.SECURITY.DN Kennwort eingeben ORACLE.SECURITY.DN = cn=test10,cn=OracleContext,dc=dbconsult,dc=de oracle@NandaDevi:~> mkstore -wrl /app/oracle/admin/test10/wallet -viewEntry ORACLE.SECURITY.PASSWORD Kennwort eingeben ORACLE.SECURITY.PASSWORD = /X7WRKF8 Listing 9.11: Anzeigen des Secret Store des Wallets über das Kommando mkstore
Globale Benutzer und globale Rollen Globale Benutzer, die von unterschiedlichen digitalen Identitäten benutzt werden sollen (Shared Schema), dürfen selbst keine Distinguished Names enthalten. Dementsprechend wird beispielsweise der »offene« globale Benutzer jedermann mit leerer AS-Klausel wie folgt aufgebaut: CREATE USER jedermann PROFILE DEFAULT IDENTIFIED GLOBALLY AS '' DEFAULT TABLESPACE users TEMPORARY TABLESPACE temp;
Da jedermann von unterschiedlichen Identitäten mit möglicherweise unterschiedlichen Anforderungen an die erforderlichen Privilegien genutzt werden kann, wird ihm lediglich das Privileg CREATE SESSION zugewiesen: GRANT CREATE SESSION TO jedermann;
Im nächsten Schritt sind für jedes erforderliche Privilegienbündel, das für die Nutzung der globalen Benutzer notwendig ist, entsprechende globale Rollen anzulegen. Das Beispiel zeigt die Syntax für die globale Rolle r_global1: CREATE ROLE r_global1
IDENTIFIED GLOBALLY;
424
Sicherheit
Es versteht sich, dass diesen Rollen über GRANT-Befehle die notwendigen Privilegien zuzuweisen sind. Im Gegensatz zu »normalen« Rollen werden sie jedoch nicht mit Datenbankbenutzern verbunden. Globale Benutzer und globale Rollen sind in allen Zieldatenbanken aufzubauen, die über Enterprise-Benutzer des Verzeichnisdienstes versorgt werden sollen. Enterprise-Benutzer und Enterprise-Rollen Im nächsten Schritt sind nun Enterprise-Benutzer und -Rollen anzulegen und ihnen entsprechende globalen Benutzer und Rollen zuzuweisen. Diese Arbeitsschritte können vollständig über das Java-Client-Werkzeug Enterprise Security Manager ausgeführt werden. Das Anlegen von Benutzern lässt sich alternativ auch über die Webapplikation Enterprise Security Manager erledigen. Diese Anwendung ist Bestandteil der Komponente OC4J_SECURITY der Identity-Management-Infrastruktur des Application-Servers und wird im Rahmen der Delegated Administration Services installiert. Sie kann entweder aus dem Client-Werkzeug heraus – über VORGÄNGE – ESM-KONSOLE STARTEN – oder über folgende URL aufgerufen werden: http://myserver:7780/oiddas/ui/oideushome
Es versteht sich, dass der Servername und ggf. auch die Portnummer den konkreten Testverhältnissen anzupassen sind. Nach erfolgreicher Anmeldung stehen die Service-Seiten zur Verfügung. In der folgenden Abbildung wird der Enterprise-Benutzer johannes mit allen erforderlichen Attributen angelegt. Die Kopfleiste zeigt, dass viele zusätzliche Attribute eingegeben werden können.
Abbildung 9.20: Webanwendung Enterprise Security Manager: Anlegen eines neuen Benutzers
Internet Directory, LDAP und SSL
425
Als eine weitere Alternative zum Anlegen von Benutzern bietet sich die – sehr ähnliche – Webapplikation OID Self-Service-Konsole an. Sie kann aus der Enterprise Manager IAS Control oder direkt über die folgende URL aufgerufen werden: http://myserver:7780/oiddas
Über die Seiten dieser Anwendung können auch Gruppen angelegt und verwaltet werden, welche die Administration von Enterprise-Benutzern vereinfachen. Enterprise-Benutzer lassen sich Gruppen zuordnen und diese wiederum Enterprise-Rollen, was die Arbeit bei einer großen Anzahl von Benutzern erheblich vereinfachen kann. Die folgende Abbildung zeigt die Anwendung mit der ApplikationsgruppeX.
Abbildung 9.21: OID Self-Service-Konsole mit der Gruppenseite
Die weiteren Arbeitsschritte können nur über das oben erwähnte Client-Werkzeug ausgeführt werden. Es empfiehlt sich hierbei das folgende Vorgehen: Datenbankschema-Zuordnung: Hierbei werden Enterprise-Benutzern eines realm globale Benutzer – Shared Schema – von registrierten Datenbanken zugeordnet. Die Zuordnung kann individuell für einzelne Datenbanken oder pauschal für Enterprise-Domänen erfolgen. Im letzteren Fall gilt die Zuweisung für sämtliche Datenbanken, die in der betreffenden Domäne konfiguriert wurden. Zusätzlich lässt sich die Auswahl der Enterprise-Benutzer individuell, d.h. auf Basis eines einzelnen Eintrags, oder für einen ganzen Zweig des Verzeichnisbaumes durchführen. Die Konfigurationsmöglichkeiten sind also recht vielfältig. Die folgende Abbildung zeigt einen Ausschnitt aus dem Client-Werkzeug Enterprise Security Manager. Es wird dort für alle Datenbanken, die in der Domäne OracleDefaultDomain des Realms dbconsult konfiguriert wurden, festgelegt, dass der Enterprise-Benutzer johannes mit dem globalen Benutzer jedermann verbunden wird. Der Benutzer muss natürlich auf allen Datenbanken vorhanden sein. Des Weiteren werden alle Enterprise-Benutzer, die in dem Unterbaum cn=Users, dc=DBintern, dc=de angelegt wurden, mit dem globalen Benutzer gben verbunden.
426
Sicherheit
Abbildung 9.22: Enterprise Security Manager: Zuordnung von globalen Datenbankschemata zu Enterprise-Benutzern
Zuordnung von globalen Rollen zu Enterprise-Rollen: Nach Auswahl der betreffenden Enterprise-Rolle wird über den Tab-Reiter GLOBALE DATENBANKROLLEN über den Knopf HINZUFÜGEN eine Zieldatenbank ausgewählt und nach der Authentifizierung eine Liste gültiger globaler Rollen angezeigt. Hier können eine oder mehrere Rollen ausgewählt und zugeordnet werden, wie die folgende Abbildung zeigt. Die vorgenommenen Änderungen werden erst dann dauerhaft gespeichert, wenn der Knopf ANWENDEN betätigt wurde.
Abbildung 9.23: Enterprise Security Manager: Enterprise-Rollen und globale Rollen
Internet Directory, LDAP und SSL
427
Zuordnung von Enterprise-Rollen zu Enterprise-Benutzern: Nach Auswahl einer Enterprise-Rolle lassen sich über den Tab-Reiter BENUTZER und den Knopf HINZUFÜGEN Enterprise-Benutzer oder Gruppen auswählen, denen die entsprechende Enterprise-Rolle zugeteilt wird. Gruppen wie Benutzer müssen vorher – wie besprochen – angelegt worden sein. Mit diesen Einstellungen wäre die Beispielkonfiguration von Enterprise-Benutzern, die über Passwörter authentifiziert werden, komplett. Ein erster Verbindungsversuch kann wie folgt unternommen werden: sqlplus johannes/testpw@test10
In diesem Beispiel wird zunächst eine Verbindung zur Zieldatenbank über den Aliasnamen test10 hergestellt. Wie dieser Name aufgelöst wird, hängt von der Konfiguration ab: entweder über die Datei tnsnames.ora oder über den Verzeichnisdienst wie in Abschnitt xx besprochen. In der Zieldatenbank wird zunächst eine lokale Authentifizierung versucht. Gelingt diese, d.h., gibt es den lokalen Benutzer johannes und ist das Passwort gültig, wird entsprechend verbunden. In unserem Beispiel existiert jedoch kein Datenbankbenutzer johannes. Aus diesem Grunde wird der Systemparameter ldap_directory_access geprüft, der in unserem Fall die Verbindung zum Verzeichnisdienst über die Passort-Authentifizierung vorsieht. Die Datenbank nimmt daher mit Hilfe der Datei ldap.ora Verbindung über den dort angegebenen SSL-Port zum Verzeichnisdienst auf und authentifiziert sich dort mit Hilfe des Passwortes, das sie aus ihrem Wallet liest. Damit die Verbindung klappt, ist es wichtig, dass über den konfigurierten SSL-Port Verbindungen ohne Berechtigungsprüfung akzeptiert werden. Diese Verbindungen erfordern keine Zertifikate, sondern nutzen lediglich die Möglichkeiten der Verschlüsselung von SSL. Sollte es während des Verbindungsaufbaus zu folgendem Fehler kommen ERROR: ORA-28030: Server ist beim Zugriff auf LDAP-Verzeichnisdienst auf Probleme gestoßen
sind auf jeden Fall die Portnummer und die Instanzen des Verzeichnisdienstes zu überprüfen. Die Prüfung erfolgt über das Java-Client-Werkzeug Oracle Directory Manager. Dort werden unter SERVER-VERWALTUNG und DIRECTORY-SERVER diverse Konfigurationsgruppen aufgelistet. Für die genutzte SSL-Portnummer muss auf jeden Fall für SSL-BERECHTIGUNGSPRÜFUNG KEINE SSL-BERECHTIGUNGSPRÜFUNG ausgewählt worden sein. Dies ist der Fall, wenn die standardmäßigen Voreinstellungen ohne Modifikationen benutzt werden. Alternativ kann die Prüfung auch über die Webapplikation Enterprise Manager IAS Control erfolgen. Dort werden nach Anwahl der Systemkomponente OID die gestarteten Instanzen des Verzeichnisdienstes aufgelistet und mit ihnen auch die für die Instanzen gültigen Konfigurationsgruppen. Nach Auswahl des betreffenden Links werden die Details der betreffenden Gruppe angezeigt, wie die nachfolgende Abbildung verdeutlicht.
428
Sicherheit
Abbildung 9.24: IAS Control: Anzeige der Konfigurationsparameter für Instanzen des Internet Directory Servers
Kann die Verbindung zum Verzeichnisdienst jedoch erfolgreich aufgebaut werden, wird der Benutzer des Connect-Strings – in unserem Beispiel johannes – im angegebenen administrativen Kontext lokalisiert und über das Passwort authentifiziert. Der zugeordnete globale Benutzer wird ermittelt sowie die globalen Rollen, die über die zugeteilten Enterprise-Rollen aktiviert werden müssen. Dementsprechend wird die Verbindung zur Zieldatenbank hergestellt. Nach erfolgreicher Anmeldung kann der Betreffende das ihm zugeteilte Schema sowie sein externe Herkunft wie folgt verifizieren: SQL> SELECT user, sys_context('userenv','external_name') extern FROM dual; USER EXTERN --------------- -------------------------------------------------JEDERMANN cn=johannes,cn=users,dc=dbconsult,dc=de
Die aktivierten Datenbankrollen lassen sich über die View session_roles leicht ermitteln. Schlussbetrachtung Die Authentifizierung von Enterprise-Benutzern über Passwörter und die Nutzung von Enterprise-Rollen bieten gute Möglichkeiten, eine beliebig große Anzahl von Benutzern funktionsgerecht im Kontext von Zieldatenbanken zu authentifizieren und autorisieren. Der laufende Verwaltungsaufwand in diesem Bereich kann mit diesem Modell langfristig deutlich reduziert werden. Für die Anwendungen ist dieses Modell ebenfalls transparent. Durch die Einbindung des Verzeichnisdienstes wird die Grundkonfiguration allerdings zunächst einmal komplex, vor allem dann, wenn die gesamte Infrastruktur in Form des Oracle Identity Managements noch eingerichtet und trainiert werden muss. Die – verwirrende – Anzahl der beteiligten
Internet Directory, LDAP und SSL
429
Werkzeuge – Directory Manager, Net Configuration Assistant, Network Manager, Database Configuration Assistant, Enterprise Security Manager, Wallet Manager sowie diverse Selbstbedienungskonsolen – tragen nicht gerade dazu bei, den Einarbeitungsaufwand zu minimieren. Der DBA muss darüber hinaus, bei der individuellen Prüfung von Benutzern und deren Privilegien, nicht nur die lokalen DatenbankViews, sondern ebenso die Anzeigen des Enterprise Security Managers berücksichtigen! Trotz alledem bieten Verzeichnisdienste für Oracle-Datenbanken sehr elegante Möglichkeiten der zentralisierten Benutzer- und Privilegienverwaltung. Für den Fall, dass neben der zentralisierten Benutzerverwaltung auch noch die Zertifizierung von Clients und Servern sowie die Verschlüsselung des Datenverkehrs gefordert wird, können Enterprise-Benutzer auch im Kontext von SSL konfiguriert werden. Bei diesem Modell sind für alle Beteiligten, d.h. Endbenutzer und Datenbanken, gültige Zertifikate zu installieren. Dieses Modell wird hier jedoch aus Platzgründen nicht besprochen31.
9.6.6
Verwaltung von Oracle Internet Directory
In den vorangehenden Abschnitten haben wir uns auf die Grundlagen von Verzeichnisdiensten sowie die Möglichkeiten der Authentifizierung und Autorisierung von Clients konzentriert. In der Praxis kommt zu den hier dargestellten Aufgabenbereichen jedoch eine Reihe weiterer, nicht minder bedeutsamer, hinzu, die hier aus Platzgründen jedoch nur stichwortartig erwähnt werden können: Konfiguration gesicherter Zugriffe auf das Verzeichnis über SSL-Verbindungen und Installation eines Wallets für den Dienst Anlegen von Benutzern für die Verwaltung bestimmter Bereiche des Verzeichnisses, z.B. zum Registrieren von Datenbanken oder Dienstnamen Vergabe von Lese- und Schreibrechten auf Bereichen des Verzeichnisbaumes Replikation von Verzeichnisdiensten, um die Ausfallsicherheit zu erhöhen Aufbau von Namensbereichen (Naming Context) und Aufteilung der Verzeichnisdaten über mehrere LDAP-Server Synchronisation mit Metadirectories Konfiguration einer Audit-Log-Verwaltung Tuning des LDAP-Servers durch den Start mehrerer LDAP-Instanzen und -Prozesse
31 Details zur Konfiguration finden sich in Avanced Security Administrator´s Guide der Oracle-Dokumentation.
430
9.7
Sicherheit
Privilegien und Rollen
Unabhängig davon, wie wir Benutzer authentifizieren, ob intern in der Datenbank oder extern über Verzeichnisdienste, letztlich werden die Privilegien für den Zugriff in der betreffenden Datenbank selbst definiert. Hierzu stehen uns Systemprivilegien, Objektprivilegien und Rollen zur Verfügung. Die Privilegien können dabei entweder einem Benutzer – einzeln oder in Form von Rollen – direkt zugeordnet oder ohne jede Zuordnung in Form von Rollen zusammengefasst werden. Im letzteren Fall muss die Kopplung von Benutzern und Rollen über externe Mechanismen, wie z.B. Verzeichnisdienste, wie in den vorangehenden Abschnitten beschrieben erfolgen.
9.7.1
Systemprivilegien
Durch Systemprivilegien wird festgelegt, welche Aktionen ein Benutzer innerhalb einer Oracle-Datenbank durchführen darf. Daher stimmt der Name der Systemprivilegien in den meisten Fällen mit den privilegierten SQL-Befehlen überein. Die Liste der Systemprivilegien ist sehr umfangreich. Sie enthält mittlerweile über 100 unterschiedliche Privilegien. Das hat zur Folge, dass die Datenbankrechte jedes einzelnen Benutzers exakt an seine Aufgaben angepasst werden können. In Abschnitt Rollen wird erläutert, wie Rollen dazu benutzt werden können, die Administration der Systemprivilegien zu vereinfachen, indem diese gruppiert und als Ganzes an Benutzer vergeben werden. Die folgende Tabelle enthält eine Auswahl der wichtigsten Systemprivilegien, gruppiert nach Bereichen oder Objekttypen, die sie betreffen. Eine vollständige Liste findet sich in der Oracle Dokumentation SQL Reference und dort im Kontext des grant-Befehls. Unter den Privilegien finden sich auch einige any-Typen, wie z.B. drop any table. Die Wirkung dieser Privilegien hängt von dem Systemparameter o7_dictionary_accessibility ab. Der Standardwert false macht das jeweilige Privileg ungültig für das SYS-Schema. In unserem Beispiel können Tabellen also in allen Schemata mit Ausnahmen von SYS gelöscht werden. Bei Einstellung auf true gilt diese Einschränkung nicht! Bereich
Privileg
Berechtigung zu ...
Analysieren
ANALYZE ANY
Analysieren sämtlicher Tabellen, Indizes und Cluster in der Datenbank
Auditing
AUDIT ANY
Audit auf allen Datenbankobjekten
AUDIT SYSTEM
Privilegien- und Kommando-Audit
CREATE USER
Erstellen von Benutzern
BECOME ANY USER
Ein anderer Benutzer werden (für FULL-Imports benötigt)
ALTER USER
Verändern von Benutzerparametern anderer Benutzer (für eigenes Passwort nicht notwendig)
Benutzer
Tabelle 9.3: Übersicht Systemprivilegien
Privilegien und Rollen
431
Bereich
Privileg
Berechtigung zu ...
DROP USER
Benutzer entfernen
Cluster
CREATE CLUSTER
Cluster im eigenen Schema anlegen
CREATE ANY CLUSTER
Cluster in beliebigem Schema anlegen
ALTER ANY CLUSTER
beliebige Cluster verändern
DROP ANY CLUSTER
beliebige Cluster entfernen
Datenbank
ALTER DATABASE
Datenbank ändern (Status, Log-Gruppen usw.)
SYSTEM
ALTER SYSTEM
ALTER SYSTEM-Befehle ausführen
AUDIT SYSTEM
AUDIT-Befehl für SQL-Befehle ausführen
CREATE ANY CONTEXT
Namensbereich für Kontexte anlegen
Context DatenbankLinks
Dimensionen
Directories Indextypen
Indizes
DROP ANY CONTEXT
Namensbereich für Kontexte löschen
CREATE DATABASE LINK
Datenbank-Links im eigenen Schema anlegen
CREATE PUBLIC DATABASE LINK
Public-Datenbank-Links anlegen
DROP PUBLIC DATABASE LINK
Public-Datenbank-Links entfernen
CREATE DIMENSION
Eigene Dimension anlegen
CREATE ANY DIMENSION
Dimension in beliebigem Schema anlegen
ALTER ANY DIMENSION
Dimension in beliebigem Schema ändern
DROP ANY DIMENSION
Dimension in beliebigem Schema löschen
CREATE ANY DIRECTORY
Aliasname für Verzeichnis anlegen
DROP ANY DIRECTORY
Aliasname für Verzeichnis löschen
CREATE INDEXTYPE
Eigenen Indextyp anlegen
CREATE ANY INDEXTYPE
Indextyp in beliebigem Schema anlegen
ALTER ANY INDEXTYPE
Indextyp in beliebigem Schema ändern
DROP ANY INDEXTYPE
Indextyp in beliebigem Schema löschen
EXECUTE ANY INDEXTYPE
Indextyp in beliebigem Schema referenzieren
CREATE ANY INDEX
Indizes in beliebigem Schema auf beliebiger Tabelle anlegen
ALTER ANY INDEX
beliebigen Index ändern
DROP ANY INDEX
beliebigen Index entfernen
Tabelle 9.3: Übersicht Systemprivilegien (Forts.)
432
Sicherheit
Bereich
Privileg
Berechtigung zu ...
Anwendung
QUERY REWRITE
Query Rewrite für materialisierte Views, die Tabellen im eigenen Schema betreffen, oder Aufbau von entsprechenden Funktionsindizes (function-based Index)
GLOBAL QUERY REWRITE
Query Rewrite für materialisierte Views, die Tabellen in beliebigen Schemata betreffen, oder Aufbau von entsprechenden Funktionsindizes (function-based Index)
RESUMABLE
Ermöglicht wieder aufnehmbare Speicherplatzzuweisungen (z.B. beim Fehlschlagen von Insert-Operationen)
CREATE LIBRARY
Bibliothek externer Prozeduren im eigenen Schema anlegen
CREATE ANY LIBRARY
Bibliothek externer Prozeduren in beliebigem Schema anlegen
DROP LIBRARY
Bibliothek in eigenem Schema löschen
DROP ANY LIBRARY
Bibliothek in beliebigem Schema löschen
CREATE MATERIALIZED VIEW
Materialisierte View im eigenen Schema anlegen
CREATE ANY MATERIALIZED VIEW
Materialisierte View in beliebigem Schema anlegen
ALTER ANY MATERILIAZED VIEW
Materialisierte View in beliebigem Schema ändern
DROP ANY MATERIALIZED VIEW
Materialisierte View in beliebigem Schema löschen
ON COMMIT REFRESH
Einrichten von on Commit Refresh für materialisierte Views in beliebigem Schema
CREATE OPERATOR
Operator im eigenen Schema anlegen
CREATE ANY OPERATOR
Operator in beliebigem Schema anlegen
DROP ANY OPERATOR
Operator in beliebigem Schema löschen
EXECUTE ANY OPERATOR
Operator in beliebigem Schema referenzieren
CREATE ANY OUTLINE
Public Outlines erzeugen
ALTER ANY OUTLINE
Public Outlines ändern
DROP ANY OUTLINE
Public Outlines löschen
SELECT ANY OUTLINE
Eigene Outline mit Referenz auf Public Outline erstellen
GRANT ANY PRIVILEGE
Systemprivilegien erteilen
EXEMPT ACCESS POLICY
Umgehen von Zugriffskontrollen (Fine Grain Access Control)
Libraries
Materialisierte Views
Operatoren
Outlines
Privilegien
Tabelle 9.3: Übersicht Systemprivilegien (Forts.)
Privilegien und Rollen
433
Bereich
Privileg
Berechtigung zu ...
Prozeduren
CREATE PROCEDURE
Prozeduren, Funktionen und Pakete im eigenen Schema erstellen
CREATE ANY PROCEDURE
Prozeduren, Funktionen und Pakete in beliebigem Schema erstellen
ALTER ANY PROCEDURE
Prozeduren, Funktionen und Pakete in beliebigem Schema ändern (z.B. Übersetzen)
DROP ANY PROCEDURE
Prozeduren, Funktionen und Pakete in beliebigem Schema entfernen
EXECUTE ANY PROCEDURE
Prozeduren und Funktionen (auch in Paketen) in beliebigem Schema ausführen
CREATE PROFILE
Profile anlegen
ALTER PROFILE
Profile ändern
DROP PROFILE
Profile entfernen
CREATE ROLE
Rollen anlegen
ALTER ANY ROLE
beliebige Rollen ändern
DROP ANY ROLE
beliebige Rollen entfernen
GRANT ANY ROLE
beliebige Rollen zuweisen
CREATE ROLLBACK SEGMENT
Rollback-Segmente anlegen
ALTER ROLLBACK SEGMENT
Rollback-Segmente ändern
DROP ROLLBACK SEGMENT
Rollback-Segmente entfernen
CREATE SESSION
Verbindungsaufbau zur Datenbank
ALTER SESSION
Sitzungsparameter ändern (Tracing, NLS-Parameter usw.)
RESTRICTED SESSION
Verbindungsaufbau, auch wenn RESTRICTED SESSION aktiv ist
ALTER RESOURCE COST
Kosten für Ressourcen (Basis für Profile) ändern
CREATE SEQUENCE
Sequenzen im eigenen Schema anlegen
CREATE ANY SEQUENCE
Sequenzen in beliebigem Schema anlegen
ALTER ANY SEQUENCE
Sequenzen in beliebigem Schema ändern
DROP ANY SEQUENCE
Sequenzen in beliebigem Schema entfernen
SELECT ANY SEQUENCE
auf Sequenzen in beliebigem Schema zugreifen
CREATE SYNONYM
Synonyme im eigenen Schema anlegen
CREATE ANY SYNONYM
Synonyme in beliebigem Schema anlegen
DROP ANY SYNONYM
Synonyme in beliebigem Schema entfernen
CREATE PUBLIC SYNONYM
Public-Synonyme anlegen
Profile
Rollen
RollbackSegmente
Sessions
Sequenzen
Synonyme
Tabelle 9.3: Übersicht Systemprivilegien (Forts.)
434
Bereich
Tabellen
Tablespaces
Transaktionen
Trigger
Sicherheit
Privileg
Berechtigung zu ...
DROP PUBLIC SYNONYM
Public-Synonyme entfernen
CREATE TABLE
Tabellen (und für eigene Tabellen Indizes) im eigenen Schema anlegen
CREATE ANY TABLE
Tabellen in beliebigem Schema anlegen
ALTER ANY TABLE
Tabellen in beliebigem Schema anlegen
BACKUP ANY TABLE
Inkrementellen Export für Tabellen in beliebigem Schema ausführen
DROP ANY TABLE
Tabellen in beliebigem Schema anlegen
LOCK ANY TABLE
Sperren auf Tabellen in beliebigem Schema setzen
COMMENT ANY TABLE
Kommentare auf Tabellen in beliebigem Schema anlegen
SELECT ANY TABLE
Abfragen auf Tabellen in beliebigem Schema ausführen
INSERT ANY TABLE
INSERT-Befehle auf Tabellen in beliebigem Schema ausführen
UPDATE ANY TABLE
UPDATE-Befehle auf Tabellen in beliebigem Schema ausführen
DELETE ANY TABLE
DELETE-Befehle auf Tabellen in beliebigem Schema ausführen
CREATE TABLESPACE
Tablespaces anlegen
ALTER TABLESPACE
Tablespaces ändern
MANAGE TABLESPACE
Tablespaces online und offline setzen sowie Online Backup-Modus ein- und ausschalten
DROP TABLESPACE
Tablespaces entfernen
UNLIMITED TABLESPACE
unbeschränkt Platz in beliebigem Tablespace belegen
FORCE TRANSACTION
COMMIT oder ROLLBACK für eigene verteilte Transaktionen mit Zustand in doubt forcieren
FORCE ANY TRANSACTION
COMMIT oder ROLLBACK für beliebige verteilte Transaktionen mit Zustand in doubt forcieren
CREATE TRIGGER
Trigger für Tabellen im eigenen Schema anlegen
CREATE ANY TRIGGER
Trigger für Tabellen in beliebigem Schema anlegen
ALTER ANY TRIGGER
Trigger für Tabellen in beliebigem Schema ändern
DROP ANY TRIGGER
Trigger für Tabellen in beliebigem Schema entfernen
ADMINISTER DATABASE TRIGGER
Datenbank-Trigger anlegen (entsprechendes CREATE-Privileg erforderlich)
Tabelle 9.3: Übersicht Systemprivilegien (Forts.)
Privilegien und Rollen
435
Bereich
Privileg
Berechtigung zu ...
Objekttypen
CREATE TYPE
Objekttypen im eigenen Schema anlegen
CREATE ANY TYPE
Objekttypen in beliebigem Schema anlegen
ALTER ANY TYPE
Objekttypen in beliebigem Schema ändern
DROP ANY TYPE
Objekttypen in beliebigem Schema löschen
EXECUTE ANY TYPE
Benutzen von Objekttypen aus beliebigen Schemata
UNDER ANY TYPE
Subtypen anlegen
CREATE VIEW
View im eigenen Schema anlegen
CREATE ANY VIEW
View in beliebigem Schema anlegen
DROP ANY VIEW
View in beliebigem Schema entfernen
UNDER ANY VIEW
Für Objekt-Views: Sub-Views anlegen
SYSOPER
Ausführen der Kommandos STARTUP, SHUTDOWN, ALTER DATABASE MOUNT/OPEN, ALTER DATABASE BACKUP, ARCHIVE LOG und RECOVER (vollständiges Wiederherstellen) sowie RESTRICTED SESSION, CREATE SPFILE
SYSDBA
alle SYSOPER-/OSOPER- Privilegien, alle Systemprivilegien WITH ADMIN OPTION, CREATE DATABASE-Kommando, unvollständiges Wiederherstellen, CREATE SPFILE
SELECT ANY DICTIONARY
Abfragen von SYS-Tabellen und Views, überschreibt den Systemparameter O7_DICTIONARY_ACCESSIBILITY.
Views
Administration
Tabelle 9.3: Übersicht Systemprivilegien (Forts.)
Jeder Benutzer, der sich an die Datenbank anmeldet, muss das Privileg CREATE SESSION besitzen. Der Entzug dieses Privilegs kann andererseits dazu genutzt werden, bestimmten Benutzern die Anmeldung nicht zu ermöglichen. Ein eleganterer Weg ist hierzu freilich das Sperren des Benutzers. Benutzer, in deren Schema lediglich Objekte gespeichert werden, die über separate Benutzer abgefragt und verändert werden, erhalten konsequenterweise kein CREATE SESSION. Für alle Objekttypen, die zu Schemata gehören können, gibt es jeweils ein CREATEPrivileg, das dem Benutzer die Erstellung von Objekten dieses Typs im eigenen Schema ermöglicht. Soll ein Benutzer Objekte in beliebigen Schemata erstellen können, so muss das entsprechende CREATE ANY-Privileg zugewiesen werden. Da die Verwaltung von Objekten standardmäßig nur dem Besitzer gestattet ist, gibt es zusätzlich zum CREATE ANY-Privileg noch weitere Privilegien, wie z.B. ALTER ANY oder DROP ANY, die eine datenbankweite Administration der Objekte eines bestimmten Typs ermöglichen. Falls z.B. ein regelmäßig laufender Prozess alle Datenbankobjekte analysieren soll, um Statistiken für den kostenbasierten Optimizer aktuell zu halten, so kann einem Benutzer das ANALYZE ANY-Privileg zugewiesen werden. Der Benutzer benötigt ansonsten keine Privilegien, so dass er z.B. keine Tabellen abfragen kann. Mit diesem
436
Sicherheit
Benutzer kann somit ein Skript aufgesetzt werden, das für alle Datenbankbenutzer außer SYS die von Oracle mitgelieferte Prozedur dbms_utility.analyze_schema(’&BENUTZER’, ’ESTIMATE’);
aufruft. Die Zuweisung von Systemprivilegien an Benutzer erfolgt mit dem GRANT-Befehl. Eine Zuweisung kann mit der Klausel WITH ADMIN OPTION erfolgen, so dass der Empfänger der Systemprivilegien diese an andere Benutzer weitergeben kann. Der Pseudobenutzer PUBLIC steht für alle Benutzer in der gesamten Datenbank. Sowohl die Systemprivilegien als auch die Benutzernamen können als Liste angegeben werden. GRANT CREATE SESSION TO guenter, johannes, dierk; GRANT CREATE TABLE, CREATE VIEW TO patrick WITH ADMIN OPTION; GRANT ALTER SESSION TO PUBLIC;
Zugewiesene Systemprivilegien können mit dem REVOKE-Befehl wieder rückgängig gemacht werden. Mit dem folgenden REVOKE-Befehl wird dem Benutzer dierk das Privileg CREATE SESSION entzogen : REVOKE CREATE SESSION FROM dierk;
Systemprivilegien, die Benutzern oder Rollen zugewiesen wurden, können über die View dba_sys_privs abgefragt werden.
9.7.2
Objektprivilegien
Während die Systemprivilegien die erlaubten Kommandos und Aktionen eines Benutzers festlegen, regeln Objektprivilegien den Zugriff auf die Objekte innerhalb der Datenbank, also auf Tabellen, Views, Prozeduren usw. Viele Benutzer von Oracle-Datenbanken, zumeist Anwender von Oracle-basierten Software-Lösungen, besitzen vergleichsweise wenige Systemprivilegien, eventuell sogar nur das Privileg CREATE SESSION, dafür aber umso mehr Objektprivilegien. Über Objektprivilegien werden den Benutzern die Teile der Datenbank zur Verfügung gestellt, die sie nicht selbst besitzen, aber für ihre Anwendung benötigen. Dabei regeln Objektprivilegien nicht nur ob, sondern auch in welcher Art und Weise auf die Datenbankobjekte zugegriffen werden kann. Das meistverwendete Privileg ist das SELECT-Privileg, das für Tabellen, Cluster, Views, Sequenzen und Snapshots vergeben werden kann. Für Objekte, die auch mit DML-Operationen bearbeitet werden können, also Tabellen, Cluster und – zumindest teilweise – Views und Snapshots, gibt es zusätzlich die Objektprivilegien INSERT, UPDATE und DELETE. Bei Tabellen gibt es zusätzlich zu den genannten die Privilegien INDEX und REFERENCES, die es erlauben, für die Tabelle Indizes bzw. Fremdschlüsseldefinitionen anzulegen. Für praktisch alle Objekte kann das ALTER-Privileg zugewiesen werden, das die Veränderung des Objekts (z.B. Spalte hinzufügen für eine Tabelle oder Übersetzen einer Prozedur) erlaubt.
Privilegien und Rollen
437
Die Objektprivilegien INSERT, UPDATE und REFERENCES können auch auf Spaltenebene vergeben werden. Ein spezielles Privileg ist für aufrufbare PL/SQL-Objekte, also Prozeduren, Funktionen und Pakete, verfügbar: Mit dem EXECUTE-Privileg kann der Aufruf der Objekte gestattet werden. Bei Paketen gilt dies immer für das gesamte Objekt; einzelne Prozeduren oder Funktionen aus dem Paket können nicht zugewiesen werden. Der Zugriff auf Trigger muss nicht explizit gestattet werden, da Trigger implizit mit einem DML-Zugriff auf ein Objekt ausgeführt werden. Die Ausführungsberechtigung für den Trigger ist somit im entsprechenden DML-Recht enthalten. Wenn die zugewiesenen Rechte vom Empfänger an andere Benutzer weitergegeben werden sollen, muss der GRANT-Befehl die Klausel WITH GRANT OPTION enthalten. Einige Beispiele verdeutlichen den GRANT-Befehl: GRANT GRANT GRANT GRANT GRANT
SELECT ON emp TO patrick WITH GRANT OPTION; INSERT (empno, ename, deptno, mgr, hiredate) ON emp TO dierk; ALL ON dept TO PUBLIC; EXECUTE ON hire_employee TO dierk, johannes, guenter; SELECT, UPDATE (comm) ON emp TO guenter;
Man beachte, dass sowohl die Objektprivilegien als auch die Benutzer im GRANTBefehl als Liste angegeben werden können, die Objekte selbst jedoch nicht. Einmal zugewiesene Objektprivilegien können mit einem REVOKE-Befehl wieder entzogen werden: REVOKE ALL ON dept FROM PUBLIC; REVOKE UPDATE (comm) ON emp FROM guenter;
Ein Sonderfall bei Objektprivilegien ist das kaskadierende REVOKE. Nach den folgenden Befehlen USER1: GRANT SELECT ON user1.emp TO user2 WITH GRANT OPTION; USER2: GRANT SELECT ON user1.emp TO user3; USER1: REVOKE SELECT ON user1.emp FROM user2;
kann user3 nicht auf die Tabelle user1.emp zugreifen. Das Kommando USER3: SELECT * FROM user1.emp;
führt zu einer Fehlermeldung. Das bedeutet, dass bei Objektprivilegien im Data Dictionary mitgeführt wird, von wem diese zugewiesen worden sind. Falls diesem Benutzer die Grundlage für seinen Befehl entzogen wird, so werden alle abhängigen Zuweisungen aufgehoben. Das kaskadierende REVOKE gilt im Übrigen nicht für Systemprivilegien, also die Klausel WITH ADMIN OPTION. Objektprivilegien, die einer Rolle oder einem Benutzer zugewiesen wurden, können über die View dba_tab_privs abgefragt werden.
438
9.7.3
Sicherheit
Rollen
Mit den in den vorhergehenden Abschnitten genannten Möglichkeiten der Systemprivilegien und des Zugriffsschutzes lassen sich viele Aspekte der Sicherheit lösen. Allerdings kann der erforderliche Administrationsaufwand für den DBA bereits bei kleinen und mittleren Datenbanken problematisch werden. Sobald einige Dutzend Tabellen und Benutzer zu verwalten sind, sind bei einer gründlichen Sicherheitsverwaltung Hunderte oder Tausende von GRANT-Befehlen abzusetzen. Das Hinzufügen einer Tabelle oder eines Benutzers bedeutet ebenfalls umfangreiche Aktionen, die meist durch Skripte realisiert werden. Diese wiederum sind selbst bei guter Dokumentation nach relativ kurzer Zeit nicht mehr lesbar; bei Änderungen am Datenmodell entsteht somit ein immens hoher Pflegeaufwand. Das von Oracle bereits mit dem Release 7.0 des RDBMS eingeführte Rollenkonzept ermöglicht eine drastische Reduzierung des Wartungsaufwands für die Privilegienvergabe in produktiven Umgebungen. Zusätzlich sind durch die dynamischen Eigenschaften von Rollen viele spezielle Probleme lösbar, die sich z.B. durch unterschiedliche Vergabe von Möglichkeiten zur Selektion oder Manipulation von Daten in unterschiedlichen Anwendungsumgebungen ergeben. In einer Rolle können verschiedene Privilegien zusammengefasst und später als Einheit vergeben werden. Eine Rolle kann System- und Objektprivilegien sowie weitere Rollen enthalten, sie wird ansonsten (z.B. bezüglich der Zuweisung an Benutzer) wie ein Systemprivileg behandelt. Vordefinierte Rollen In einer Oracle-Datenbank gibt es bestimmte vordefinierte Rollen, welche die Zuweisung standardisierter Privilegiengruppen vereinfachen sollen. Die folgende Tabelle enthält eine Übersicht dieser Rollen und ihrer Privilegien: Rolle
Privileg
CONNECT
ALTER SESSION, CREATE CLUSTER, CREATE DATABASE LINK, CREATE SEQUENCE, CREATE SESSION, CREATE SYNONYM, CREATE TABLE, CREATE VIEW
RESOURCE
CREATE CLUSTER, CREATE PROCEDURE, CREATE SEQUENCE, CREATE TABLE, CREATE TRIGGER
DBA
alle Systemprivilegien WITH ADMIN OPTION
DELETE_CATALOG_ROLE
Löschen von Audit-Informationen
SELECT_CATALOG_ROLE
SELECT-Privilegien für die Objekte des Data Dictionarys
EXCUTE_CATALOG_ROLE
EXECUTE-Privilegien für die DBMS-Pakete von SYS
AQ_USER_ROLE AQ_ADMINISTRATOR_ROLE
Benutzer- bzw. Administratorprivilegien für Advanced Queuing
SNMPAGENT
Privilegien für den Intelligent Agent des Enterprise Managers
RECOVERY_CATALOG_OWNER
Privilegien für den Eigentümer des Recovery-Katalogs (Recovery Manager)
Tabelle 9.4: Vordefinierte Rollen
Privilegien und Rollen
439
Rolle
Privileg
HS_ADMIN_ROLE
Privilegien für Heterogeneous Services
LOG_STDBY_ADMINISTRATOR
Zur Administration von Logical Standby Databases
SCHEDULER_ADMIN
Alle Privilegien zum Administrieren des Job Schedulers
OEM_MONITOR
Privilegien zum Monitoring der Datenbank über den Enterprise Manager
LBAC_DBA
Rolle zum Administrieren der Label Security
EXP_FULL_DATABASE
SELECT ANY TABLE, BACKUP ANY TABLE, INSERT, DELETE, UPDATE ON SYS.INCVID, UPDATE ON SYS.INCFIL, UPDATE ON AND SYS. INCEXP
IMP_FULL_DATABASE
BECOME USER, WRITEDOWN
Tabelle 9.4: Vordefinierte Rollen (Forts.)
Beim GRANT der Rollen RESOURCE und DBA wird gleichzeitig das Systemprivileg UNLIMITED TABLESPACE, bei der Rolle DBA mit der Klausel WITH ADMIN OPTION zugewiesen. Diese Zuweisung erfolgt nicht als Bestandteil der Rolle, sondern als direktes Systemprivileg. In den meisten Fällen empfiehlt es sich, dies nicht bestehen zu lassen, sondern mit expliziten Quoten für einzelne Tablespaces zu arbeiten.32 Beim Aufsetzen eines Datenbanksystems erweisen sich die Rollen CONNECT, RESOURCE und DBA als praktisch, da man sofort ohne eigenes Sicherheitskonzept Benutzer privilegieren kann. Dabei passt die Rolle CONNECT für Anwendungsbenutzer und Entwickler, RESOURCE für fortgeschrittene Entwickler und DBA für Administratoren. In den meisten Fällen ist es jedoch empfehlenswert, eigene Rollen für spezielle Benutzerprofile zu erstellen. Für Entwickler gibt es z.B. oft die Anforderung, zusätzlich zu den CONNECT- und RESOURCE-Privilegien Public-Synonyme verwalten zu können, um Datenbankobjekte transparent zur Verfügung zu stellen. Hier empfiehlt es sich, eine eigene Rolle zu erstellen. Es wird entschieden davon abgeraten, die vordefinierten Rollen zu verändern, da die Änderungen bei einem eventuellen Neuaufsetzen des Systems, z.B. durch eine Export-/Import-Migration auf ein anderes Betriebssystem, verloren gehen oder Werkzeuge nicht mehr erwartungsgemäß arbeiten können (smnpagent). Rollen anlegen und zuweisen Eine Rolle wird erstellt durch den Befehl CREATE ROLE: CREATE ROLE entwickler;
Der Ersteller der Rolle benötigt das Privileg CREATE ROLE. Nach der Erstellung besitzt der Benutzer die Rolle WITH ADMIN OPTION, d.h., er kann sie weiteren Benutzern zuweisen. Die Rolle verhält sich bezüglich GRANT und REVOKE wie ein Systemprivileg, d.h., sie kann wie folgt anderen Benutzern zugewiesen werden: GRANT entwickler TO dierk, guenter, johannes;
Weiterhin können Rollen wiederum Rollen enthalten: GRANT CONNECT TO entwickler; 32 Das UNLIMITED TABLESPACE-Privileg wird aus Kompatibilitätsgründen zu Oracle Version 6 zugewiesen.
440
Sicherheit
Mit diesem Befehl wird die Rolle CONNECT Bestandteil der Rolle entwickler. Diese Rolle kann aber auch um Systemprivilegien erweitert werden: GRANT create public synonym, drop public synonym, create public database link, drop public database link TO entwickler;
Benutzer, die im Besitz der Rolle entwickler sind, können ab dem nächsten Verbindungsaufbau die neuen Systemprivilegien nutzen. Ebenso ist eine Erweiterung um Objektprivilegien möglich: GRANT select ON sys.dba_usrs TO entwickler;
Rollen können über die View dba_roles selektiert werden, den Rollen zugewiesene Privilegien entsprechend über dba_tab_privs und dba_sys_privs. Dynamisches Aktivieren von Rollen Wird die Rolle einem anderen Benutzer zugewiesen, so heißt das nicht, dass die enthaltenen Privilegien für diesen Benutzer grundsätzlich aktiv sind. Eine Eigenschaft von Rollen ist, dass sie dynamisch aktiviert und deaktiviert werden können. Hierzu gibt es den Befehl SET ROLE: SET SET SET SET SET
ROLE ROLE ROLE ROLE ROLE
entwickler; CONNECT, entwickler; ALL; ALL EXCEPT CONNECT; NONE;
Der Befehl SET ROLE hat den Effekt, dass die explizit angegebenen Rollen aktiviert werden. Vorher aktivierte Rollen bleiben nicht aktiv, es sei denn, dass sie ebenfalls explizit genannt sind. Sollen zugeteilte Rollen bereits beim Anmelden eines Benutzers aktiviert werden, so müssen diese als dessen Standardrollen – wie im folgenden Beispiel dargestellt – definiert werden. ALTER USER uwe DEFAULT ROLE ALL; /* Standardeinstellung */ ALTER USER dierk DEFAULT ROLE CONNECT; ALTER USER guenter DEFAULT ROLE NONE;
Falls das Systemprivileg CREATE SESSION dem Benutzer mittels einer Rolle zugewiesen wurde, so muss diese Rolle für den Benutzer als Standardrolle definiert sein. Andernfalls kann der Benutzer sich nicht an das System anmelden. Der einzelne Benutzer sieht über die View user_role_privs die ihm zugeteilten Rollen und über session_roles seine aktiven Rollen. session_privs zeigt alle aktiven Privilegien eines Benutzers. Passwörter für Rollen Zusätzlich zu den genannten Eigenschaften kann das Aktivieren einer Rolle mit einem Passwort geschützt werden. Damit kann verhindert werden, dass ein Benutzer mit jeder beliebigen Anwendung auf die in der Rolle enthaltenen Privilegien zugreift, wenn z.B. nur eine Anwendung selbst das Passwort zum Aktivieren der Rolle kennt.
Privilegien und Rollen
441
CREATE ROLE spezial IDENTIFIED BY keinerweiss; ALTER ROLE entwickler IDENTIFIED BY keinerkennt; ALTER ROLE rolle51 NOT IDENTIFIED;
Sobald ein Passwort für eine Rolle definiert ist, muss dies beim SET ROLE-Kommando angegeben werden: SET ROLE CONNECT, spezial IDENTIFIED BY keinerweiss, entwickler IDENTIFIED BY keinerkennt;
Für den Erfolg des SET ROLE-Kommandos muss sowohl die Rolle zugewiesen als auch das Passwort korrekt angegeben sein. Sind solche SET ROLE-Kommandos z.B. versteckt in Anwendungen kodiert, so können an bestimmten Stellen in der Anwendung Privilegien aktiviert werden, die ansonsten dem jeweiligen Benutzer vorenthalten bleiben. Es versteht sich, dass die im Anwendungscode hart codierten Passwörter ein ernst zu nehmendes Risiko für die Wartung und die Sicherheit darstellen. Werden Rollen, die über Passwörter geschützt sind, als Standardrollen vergeben, entfällt selbstverständlich die Angabe des Passwortes bei der Anmeldung des Benutzers. Zusätzlich ist zu bemerken, dass die Übermittlung der Passwörter zur Aktivierung der Rollen nicht verschlüsselt wird, wie dies beispielsweise mit Passwörtern beim Anmelden an die Datenbank geschieht. Aus diesem Grunde sind Passwörter im Kontext von Rollen nur dann übertragungstechnisch sicher, wenn die Datenpakete für die Netzübertragung entsprechend verschlüsselt werden. Secure Application Roles Eine wesentlich elegantere Methode, Rollen in spezifischen, für den Benutzer nicht nachvollziehbaren oder nicht kontrollierbaren Kontexten sicher zu aktivieren, stellen die so genannten Secure Application Roles dar. Diese Rollen werden so angelegt, dass eine namentlich genannte PL/SQL-Programmeinheit für ihre Aktivierung verantwortlich zeichnet. Innerhalb dieser Prozedur lassen sich dann sinnvolle Plausibilitäten einbauen, bevor die genannte Rolle aktiviert wird. Es versteht sich, dass die genannte Programmeinheit weder im Schema des Begünstigten liegen noch der Betreffende Ausführungsrechte für diese Programmeinheit haben sollte. Gleichfalls sollte die Rolle nicht als Default-Rolle an die Begünstigten vergeben werden. In der Regel wird ein separates Schema – beispielsweise ein Applikationsbenutzer – geschaffen, in dessen Kontext die entsprechende Programmeinheit angelegt wird. Im folgenden Beispiel wird die Rolle demo_enduser angelegt, die über die Programmeinheit app des Schemas appuser aktiviert werden soll. Für das Anlegen der Rolle ist es nicht notwendig, dass die Programmeinheit und der Benutzer bereits existieren: CREATE ROLE demo_enduser IDENTIFIED USING appuser.app;
Existierende Application Roles können über die View dba_application_roles selektiert werden. Zur Aktivierung der neuen Rolle ist nun im Schema appuser die Prozedur – oder das Paket – app anzulegen. Die Aktivierung erfolgt dann letztendlich über den Aufruf
442
Sicherheit
der set_role-Prozedur des Paketes DBMS_SESSION. Damit dies gelingt, muss die Prozedur app als Invokers-Right-Code deklariert worden sein. Gleichzeitig stehen alle möglichen Mechanismen zur Verfügung, vor der Aktivierung diverse Plausibilitätsprüfungen durchzuführen. Darüber hinaus kann die Prozedur auch »gewrapped« werden, um die Logik der Plausibilitätsprüfungen zu verschleiern. Schließlich sollte der Applikationsbenutzer – in unserem Beispiel appuser – durch starke Authentifizierungsmaßnahmen zusätzlich vor Missbrauch geschützt werden. Das folgende Codebeispiel zeigt Fragmente einer möglichen Aktivierungsprozedur: CREATE OR REPLACE PROCEDURE app (user_in IN VARCHAR2) AUTHID CURRENT_USER IS -- hier z.B. IP-Adresse des Application Servers, der sich einwählt lv_valid_ip CONSTANT VARCHAR2 (50) := '192.168.25.113'; -- Hostname des App-Server Rechners lv_valid_host CONSTANT VARCHAR2 (50) := 'myserver'; -- Externer Name bei einer Authentifizierung über Enterprise-Benutzer lv_valid_external CONSTANT VARCHAR2 (50) := 'cn=guenter,cn=users,dc=dbconsult,dc=de'; BEGIN -- .. je mehr kombiniert wird, desto sicherer IF SYS_CONTEXT ('userenv', 'ip_address') = lv_valid_ip AND SYS_CONTEXT ('userenv', 'host') = lv_valid_host AND SYS_CONTEXT ('userenv', 'external_name') = lv_valid_external THEN -- Rolle aktivieren DBMS_SESSION.set_role ('DEMO_ENDUSER'); -- Client-Identifier für authentifizierten Benutzer DBMS_SESSION.set_identifier (user_in); -- ... und Schema auf den Owner schalten spart Synonyme EXECUTE IMMEDIATE ('alter session set current_schema = APP_OWNER'); -- ggf. weitere Einstellungen: Client-Identifier/Client Info etc. END IF; EXCEPTION WHEN OTHERS THEN -- hier entsprechende Routinen RAISE; END app; / Listing 9.12: Fragment einer Programmeinheit zur Aktivierung von Secure Application Roles
Um die Logik der oben dargestellten Prozedur weitergehend zu schützen, bietet es sich an, den Code zu »wrappen«. In der Version 10g wurde dieses Feature dahingehend verbessert, dass nun sämtliche Zeichenketten in unleserlicher Form auftauchen und damit Rückschlüsse auf den Programmablauf nicht mehr möglich sind. Um die Prozedur app zu »wrappen«, wird im ersten Schritt der Code in eine Datei geschrieben – in unserem Beispiel die Datei app.sql. Auf der Kommandozeile kann dann das Hilfsprogramm wrap in folgender Form aufgerufen werden:
Privilegien und Rollen
443
wrap iname=app.sql PL/SQL Wrapper: Release 10.1.0.4.0- Production on Mon Aug 22 10:53:32 2005 Copyright (c) 1993, 2004, Oracle.
All rights reserved.
Processing app.sql to app.plb Listing 9.13: Wrap der Prozedur app
Die neue Datei app.plb enthält den »gewrappten« Code. Ein Blick auf den Inhalt zeigt keinerlei interpretierbare Zeichenketten, wie der folgende Ausschnitt aus der Datei app.plb zeigt: abcd 7 31d 223 abmdzXjvd7hFJQbws1ew0M8o9rQwg/DxzPYVfI4C/mgPUprlymWkSnkGhDxxF2fr8Rr8Qebq ahsRpHmNzZq7yU1Z31JrqHkpOrmtxHjMUkZ6XOdWoQ73J8MrWg72l8Mh4OUFdFQnYKyEicUC JVS1Lsr1pqY/0LCfl9SsuvfdOOktd0Chx0ZnjL9VRgf7RpD4SJjHErG5M4OQ/y60tQKIlYNx Listing 9.14: »Gewrappter« Code der Prozedur app
Zum Vergleich ein kurzes Fragment derselben Prozedur, »gewrapped« unter Version 9i. Deutlich sind hier sämtliche Konstanten sowie Teile der Programmlogik zu erkennen! 1APP: 1USER_IN: 1VARCHAR2: 1AUTHID: 1CURRENT_USER: 1LV_VALID_IP: 1CONSTANT: 150: 1192.168.25.113: 1LV_VALID_HOST: 1myserver: 1LV_VALID_EXTERNAL: 1cn=guenter,cn=users,dc=dbconsult,dc=de: 1SYS_CONTEXT: 1userenv: 1ip_address: 1=: 1host: 1external_name: 1DBMS_SESSION: 1SET_ROLE: 1DEMO_ENDUSER: 1SET_IDENTIFIER: 1EXECUTE: 1IMMEDIATE: 1alter session set current_schema = APP_OWNER: Listing 9.15: Prozedur app, „gewrapped“ unter Version 9i
444
Sicherheit
Globale Rollen Globale Rollen wurden bereits in Abschnitt Modell 3: Enterprise-Benutzer und Enterprise-Rollen im Zusammenhang mit Enterprise-Rollen erwähnt. Sie sind bekanntlich die in den Zieldatenbanken verankerten Gegenspieler der Enterprise Rollen. Globale Rollen werden über die Klausel IDENTIFIED GLOBALLY wie folgt angelegt: CREATE ROLE grole_demo IDENTIFIED GLOBALLY;
Existierende globale Rollen lassen sich über die View dba_roles ermitteln: SELECT ROLE FROM dba_roles WHERE password_required = 'GLOBAL';
Objekt- und Systemprivilegien oder normale Rollen werden globalen Rollen wie gewohnt über grant-Befehle zugeteilt bzw. über revoke wieder entzogen. Im Gegensatz zu normalen Rollen lassen sich globale Rollen selbst jedoch nicht an Benutzer oder andere Rollen granten: SQL>GRANT grole_demo TO scott; grant grole_demo to scott * FEHLER in Zeile 1: ORA-28021: Globale Rollen koennen nicht erteilt werden Listing 9.16: Fehler beim Zuteilen globaler Rollen
Die Nutzung globaler Rollen kann demnach nur im Kontext von Enterprise-Rollen des Verzeichnisdienstes erfolgen. Externe Rollen Externe Rollen werden – ähnlich wie globale Rollen – über externe Instanzen den Benutzern zugeteilt. Die externe Instanz ist bei externen Rollen jedoch nicht der Verzeichnisdienst, sondern das Betriebssystem oder die DCE33-Umgebung. Im folgenden Beispiel wird die externe Rolle ext_role angelegt: CREATE ROLE ext_role IDENTIFIED EXTERNALLY;
Existierende externe Rollen lassen sich über die View dba_roles selektieren: SELECT ROLE FROM dba_roles WHERE password_required = 'EXTERNAL';
Externe Rollen können zwar Benutzern oder anderen Rollen zugeteilt werden, sind aber nur dann wirksam, wenn der Betreffende die Rolle als Default-Rolle zugeteilt bekommen hat. Das explizite Aktivieren dieser Rollen über den set role-Befehl produziert hingegen die folgende Fehlermeldung:
33 DCE = Distributed Computing Environment, eine Middleware zwischen verteilten Applikationen und dem Betriebssystem, die diverse Netzwerkdienste, u.a. auch Sicherheitsdienste, bereitstellt
Privilegien und Rollen
445
SQL> set role ext_role; set role ext_role * FEHLER in Zeile 1: ORA-01989: Rolle 'EXT_ROLE' ist nicht vom Betriebssystem autorisiert Listing 9.17: Aktivierung externer Rollen
Externe Rollen werden in der Regel dort eingesetzt, wo die Rollenzuteilung einzig und allein über das Betriebssystem geregelt wird und keine Rollen-Grants im Kontext von Datenbankbenutzern durchgeführt werden. Auf diese Weise kann ein Betriebssystembenutzer immer mit den gleichen externen Rollen arbeiten, unabhängig davon, unter welchem Datenbankbenutzer es sich anmeldet. Rollenverwaltung über das Betriebssystem Die Zuweisung von Rollen an einzelne Benutzer, die im Normalfall über datenbankinterne Mechanismen behandelt wird, kann alternativ dem Betriebssystem überlassen werden. Dabei geht die Kontrolle über Rollenprivilegien komplett für alle Benutzer der Datenbank auf das Betriebssystem über, die Zuweisungen innerhalb der Datenbank haben keinerlei Bedeutung mehr.34 Eine Alternative stellt die in Abschnitt Modell 3: Enterprise-Benutzer und Enterprise-Rollen beschriebene Zuweisung von Rollen über Verzeichnisdienste dar. Die Verwaltung und Zuteilung von Rollen wird im Falle der Verwaltung über das Betriebssystem über Gruppen oder ähnliche Mechanismen abgebildet (Unix und Windows NT: Gruppen, VMS: Process Rights Identifier). Ein Datenbankbenutzer besitzt die Rolle rolle in der Instanz prod, falls er Mitglied der Gruppe ora_prod_rolle ist. Der Name der Gruppe kann zusätzlich das Postfix _d enthalten, um anzuzeigen, dass die Rolle als Default-Rolle zu betrachten ist. Wenn das Postfix _a enthalten ist, steht die Rolle WITH ADMIN OPTIONzur Verfügung. Das Postfix _da kombiniert diese beiden Eigenschaften. Die Eigenschaft WITH ADMIN OPTION hat die Auswirkung, dass der jeweilige Benutzer die Rolle anderen Benutzern zuweisen darf. Die Zuweisungen, die der Benutzer vornimmt, beziehen sich allerdings auf die Oracle-interne Verwaltung von Rollen, d.h., die Zuweisungen sind erst dann gültig, wenn die Rollenverwaltung nicht mehr über das Betriebssystem vorgenommen wird. Über den Initialisierungsparameter OS_ROLES = TRUE
wird die Rollenverwaltung über das Betriebssystem eingeschaltet. Zur Administration der Datenbank stehen die Rollen OSOPER und OSDBA zur Verfügung, die mit den gleichen Privilegien ausgestattet sind wie die Rechte SYSOPER und SYSDBA.
34 Das unterscheidet die Rollenverwaltung über das Betriebssystem von der Authentifizierung von Benutzern über das Betriebssystem: Bei Benutzern kann im Einzelfall entschieden werden, ob ein Benutzer ein datenbankinternes Passwort benutzt oder ob er extern authentifiziert wird.
446
Sicherheit
Empfehlungen für die Nutzung von Rollen Beim Design einer Rollenstruktur für eine Datenbank kann die Eigenschaft von Rollen, selbst wieder Rollen enthalten zu können, ausgenutzt werden. Dabei ist anzuraten, dass die Rollenhierarchie nicht mehr als zwei oder drei Ebenen umfassen sollte, da jede aktive Rolle einige Bytes in der so genannten Program Global Area benötigt. Die Forderung wird andererseits dadurch begründet, dass der Sicherheitsscheck in der Parse-Phase von SQL-Befehlen länger dauert, je mehr Rollen aktiviert sind. Es lässt sich eine systemweite Grenze aktivieren, welche die Anzahl der gleichzeitig aktiven Rollen pro Sitzung einschränkt, wobei die Unterrollen in einer Hierarchie mitzählen. Die Grenze wird vom Initialisierungsparameter max_enabled_roles vorgegeben, dessen Standardwert in der Version 10g 150 beträgt. Der Parameter wird in Version 10g allerdings nur noch aus Gründer der Abwärtskompatibilität unterstützt. Beim Anlegen von Rollen ist zu beachten, dass der anlegende Benutzer die neue Rolle automatisch mit Administratorrechten und als Default-Rolle zugeteilt bekommt. Dies führte unter der Version 935 häufig dazu, dass Rollen anlegende Benutzer sehr schnell an die durch max_enabled_roles vorgegebene Grenze stießen und eine Anmeldung nicht mehr möglich war. Hier hilft es, die Default-Rollen dieser Benutzer auf die für ihre Funktionen notwendigen einzuschränken. Ganz allgemein sollte darüber hinaus gelten: Benutzer erhalten nur die Rollen als DefaultRollen zugeteilt, die ihnen Rechte zuteilen, die für sie in allen möglichen Umgebungen automatisch gelten sollten. Rechte, die nur in speziellen Anwendungen zur Geltung kommen dürfen, werden stets über Rollen erteilt, die explizit – über Passwörter oder externe Komponenten – zu aktivieren sind. Auf diese Weise kann der Betreffende die anhängenden Rechte nicht – ohne nur schwer – in »offenen« Umgebungen, wie z.B. SQL*Plus, nutzen. Default-Rollen können über den alter user-Befehl eingestellt werden. Im folgenden Beispiel wird für den Benutzer scott nur die connect-Rolle als Default konfiguriert: ALTER USER scott DEFAULT ROLE connect;
Über die View dba_role_privs ist die Kontrolle über die Rollen möglich, die dem Betreffenden direkt zugeteilt wurden. Jedoch ist hier Vorsicht geboten: Alle Rollen, die über die direkt zugeteilten Rollen für den Betreffenden aktiv sind, erschienen bei dieser Abfrage nicht! SELECT granted_role, default_role FROM dba_role_privs WHERE grantee = 'SCOTT'; Listing 9.18: Ermittlung direkt zugeteilter Rollen
35 Unter der Version 9 war der Parameter mit dem Wert 20 vorbelegt, der Maximalwert betrug 148.
Privilegien und Rollen
447
Für die Gestaltung von Rollen wird empfohlen, System- und Objektprivilegien in unterschiedlichen Rollen zusammenzufassen. Die Rollen, die Systemprivilegien enthalten, beschreiben dann jeweils den Benutzertyp (z.B. anwender, entwickler, administrator), Rollen mit Objektprivilegien die bereitgestellten Anwendungen (z.B. buchhaltung, personal, lager). Bei einer komplexen Anwendungsstruktur kann es sinnvoll sein, die Anwendungsrollen in zwei Ebenen zu definieren. In der unteren Ebene sind dann jeweils Rollen definiert, die alle notwendigen Objektprivilegien zur Nutzung unterschiedlicher Anwendungsbereiche enthalten. In der Ebene darüber können dann Anwendungsprofile für verschiedene Benutzertypen erstellt werden, die aus den Rollen für einzelne Anwendungsbereiche zusammengesetzt sind. Rollen für Administratoren In der Standardrolle DBA sind alle Systemprivilegien mit WITH ADMIN OPTION enthalten. Falls ein Benutzer über diese Rolle verfügt, kann er die gesamte Datenbank in sämtlichen Aspekten administrieren. Gerade in größeren Teams ist dies jedoch nicht immer wünschenswert: Häufig ergibt sich eine Aufteilung der Administrationsaufgaben unter verschiedenen Personen, die dann Teilbereiche der Datenbank, etwa das Sicherheitssystem oder den physikalischen Datenbankaufbau, administrieren sollen. Eine Rolle für den physikalischen Datenbankaufbau kann etwa wie folgt definiert werden: CREATE ROLE ts_dba_role; GRANT CREATE TABLESPACE, ALTER TABLESPACE, MANAGE TABLESPACE TO ts_dba_role;
Diese Rolle kann nun z.B. einem Datenbankbenutzer zugeteilt werden, der sich in Absprache mit der Betriebssystemadministration um die Verwaltung des Festplattenspeicherplatzes für die Datenbank kümmert. Da das Privileg DROP TABLESPACE fehlt, kann dieser Administrator nicht destruktiv arbeiten. Auf diese Weise lassen sich auch andere Verwaltungsbereiche über Rollen definieren, wie etwas ein Security-Administrator.
448
Sicherheit
9.8
Virtual Private Database
9.8.1
Einführung
Das Konzept Virtual Private Database – kurz VPD – ist auch unter dem Namen Fine Grain Access Control bekannt geworden. Es wurde bereits unter der Version 8 eingeführt und sowohl unter Oracle9i und als auch unter 10g funktional erweitert. VPD steht im Rahmen der Enterprise Edition von Oracle zur Verfügung und ermöglicht die automatische Generierung von where-Klauseln für ausgesuchte Tabellen. Auf diese Weise lassen sich komplexe Konzepte des Zugriffsschutzes transparent und unabhängig von der jeweiligen Anwendung realisieren. Der Grundgedanke dieses Konzeptes ist – immer noch – recht einfach und bestechend: Um die für die Generierung der where-Klausel wichtigen, individuellen Parameter – wie z.B. die Abteilungsnummer oder den Einsatzort – zu speichern, kann ein spezifischer Anwendungskontext (Application Context) aufgebaut werden. Dieser Anwendungskontext muss innerhalb der Datenbank einen eindeutigen Namen haben und kann mit beliebigen Attributen und ihnen zugeordneten Werten belegt werden. Beim Anlegen des Kontextes wird gleichzeitig eine Programmeinheit definiert, die autorisiert ist, die Attribute und Attributwerte des betreffenden Kontextes zu definieren. Zusätzlich werden Funktionen benötigt, welche die Where-Klauseln für Tabellen, Views oder Synonyme generieren. Hierzu können die Funktionen die genannten Attributwerte eines Applikationskontextes nutzen. Damit VPD wirksam wird, benötigen wir darüber hinaus Richtlinien (Policies36), welche die zu schützenden Tabellen, Views oder Synonyme mit den erwähnten Funktionen verbinden. Diese Richtlinien lassen sich darüber hinaus explizit mit bestimmten DML-Operationen – z.B. SELECT oder DELETE – verknüpfen. VPD sorgt letzten Endes dafür, dass der originale SQL-Befehl im Rahmen der zutreffenden Richtlinie durch die generierte Where-Klausel erweitert und der Zugriff entsprechend gefiltert wird. VPD kann in diesem Sinne auch salopp als Automatische Where-Klausel-Generierung beschrieben werden. Die beschriebene Generierung der Where-Klauseln ist natürlich auch ohne Applikationskontexte möglich. Gleichwohl stellen diese eine eleganten und performante Möglichkeit dar, individuelle Attributwerte im Rahmen einer Session zu propagieren. Die Möglichkeiten, Applikationskontexte zu setzen, wurden in den letzten Versionen beträchtlich erweitert. Mittlerweile lassen sich zwei grundlegende Typen von Kontexten unterscheiden: Lokale Kontexte gelten jeweils im Rahmen einer Session und werden damit – umgekehrt formuliert – für jede Session neu initialisiert. Lokale Kontexte werden im Kontext der UGS gespeichert. Sie sind vor allem dort interessant, wo individuelle Benutzer mit jeweils eigenen Sessions arbeiten. Für die Initialisierung der Werte stehen – neben den erwähnten PL/SQL-Programmeinheiten – die folgenden alternativen Methoden zur Verfügung: 36 Die offizielle Übersetzung von Policy in den Oracle-Tools lautet »Strategie«.
Virtual Private Database
449
Die globale Initialisierung nutzt LDAP und einen Verzeichnisdienst, um Attributwerte, die im Kontext von Enterprise-Benutzern angelegt wurden, beim Connect des betreffenden Benutzers zu aktivieren. Die externe Initialisierung kann Attribute über die OCI-Schnittstelle setzen. Globale Kontexte werden im Kontext der SGA gespeichert und können dementsprechend von unterschiedlichen Sessions aus immer wieder genutzt werden. Sie sind vor allem dort interessant, wo eine große Anzahl von Endbenutzern sich über Application-Server mit einem zentralen Datenbankbenutzer verbinden. In diesem Modell werden die Sessions des zentralen Benutzers vom Appliction-Server wechselweise für unterschiedliche Endbenutzer aktiviert. Globale Applikationskontexte erlauben es dann, individuelle Attributwerte an Client-Identifier zu koppeln. Wenn der Application-Server bei Datenbankanforderungen die aktuelle Kennung des jeweiligen Endbenutzers in Form eines Client-Identifiers aktiviert37, werden die für diese Kennung relevanten Attributwerte bereitgestellt, ohne dass der gesamte Kontext jedes Mal initialisiert werden muss. Globale Kontexte dürfen nicht mit der oben besprochenen globalen Initialisierung lokaler Kontexte verwechselt werden. Da unter Oracle8i an jede Basistabelle pro DML-Operation nur eine Richtlinie gekoppelt werden konnte, war es schwierig, für unterschiedliche Anwendungen, die identische Basisobjekte mit gleichen Operationen bearbeiteten, spezifische, sich gegenseitig ausschließende Richtlinien zu implementieren. Aus diesem Grund wurden die Konzepte von Richtlinien seither deutlich ausgeweitet. Richtlinien für Objekte können mittlerweile über Richtliniengruppen (Policy Groups) gruppiert werden. Für jedes Objekt, definiert über seinen Schema- und Objektnamen, können beliebig viele Richtliniengruppen mit eindeutigen Namen angelegt werden. Für unterschiedliche Objekte können demnach durchaus gleichnamige Richtliniengruppen existieren. Richtlinien für einzelne Objekte können dann im Kontext dieser Gruppen aufgebaut werden. Richtlinien, die nicht explizit einer Gruppe zugeteilt wurden, werden der Standardgruppe SYS_DEFAULT untergeordnet und sind dem entsprechend stets aktiv. Für alle anderen Richtliniengruppen lässt sich jeweils ein »treibender« Kontext (Driving Application Context) definieren, über den die Richtlinien der betreffenden Gruppe aktiviert werden können. Auf diese Weise lassen sich für ein Datenbankobjekt unterschiedliche Sicherheitsrichtlinien definieren, die – abhängig von der zugreifenden Applikation – eingeschaltet werden können. Richtliniengruppen, deren treibender Kontext nicht festgelegt wurde, sind mit ihren Richtlinien stets aktiv. Unter der Version 10g wurde die Funktionalität von VPD nochmals erweitert. Nun ist es möglich, die VPD-Richtlinien in Abhängigkeit von Spalten zu definieren. Auf diese Weise wird die Richtlinie erst wirksam, wenn eine definierte Spalte selektiert wird, oder sie sorgt dafür, dass die Werte der betreffenden Spalte nur im vorgegebenen Kontext angezeigt und ansonsten mit null-Werten ausgegeben werden (Column Masking).
37 Dies geschieht über das Paket DBMS_SESSION.
450
9.8.2
Sicherheit
Aufbau einer VPD-Umgebung
Das folgende umfangreiche Beispiel soll das im vorangehenden Abschnitt dargestellte Konzept erläutern. Ermittlung der Anforderungen Wie überall anders, so sind auch beim Aufbau einer VPD-Umgebung eine genaue Ermittlung der Anforderungen und ein aus diesen Anforderungen abgeleitetes Feinkonzept unerlässlich. Für unser Beispiel sollen die folgenden Anforderungen gelten: Gegeben sind die Tabellen auftraege und mitarbeiter im Schema scott. Beide Tabellen werden von Mitarbeitern unterschiedlicher Firmen – hier FA und FB – genutzt. Jede Firma nutzt jeweils zwei unterschiedliche Anwendungen: eine Serviceanwendung (SE) für Reklamationen und eine Verkaufsanwendung (VE) für Abverkäufe. Jede Firma soll jedoch nur ihre eigenen Daten sehen. Darüber hinaus soll auch jede Anwendung nur die für sie relevanten Daten lesen und bearbeiten und dies auch in Abhängigkeit von dem angemeldeten Benutzer. Für Zugriffe auf die Tabelle auftraege gilt im Einzelnen: Jeder Benutzer sieht nur die Daten seiner Firma. Zusätzlich gilt: Jede Anwendung sieht und bearbeitet nur die in ihrem Kontext anfallenden Aufträge. Ferner gilt: Für den Verkauf sollen Manager alle Aufträge bearbeiten dürfen, die von ihnen selbst oder von Mitarbeitern ihrer Abteilung aufgenommen wurden. Die einfachen Mitarbeiter dagegen haben nur Zugriff auf ihre eigenen Aufträge. Diese Unterscheidung gilt nicht für den Service. Dort können alle Benutzer alle Serviceaufträge lesen, die ihnen im Rahmen der ersten beiden Bedingungen zugänglich sind. Für Zugriffe auf die Tabelle mitarbeiter gilt im Einzelnen: Alle Mitarbeiter haben lesenden Zugriff auf sämtliche Mitarbeiter ihrer Firma – mit Ausnahme der Spalte gehalt. Die Spalte gehalt steht lesend und schreibend nur Managern zur Verfügung und auch ihnen nur im Kontext ihrer eigenen Abteilung. Für normale Mitarbeiter werden beim Lesen dieser Spalte nur die eigenen Daten angezeigt. Darüber hinaus sollen die folgenden allgemeinen Rahmenbedingungen für unsere Testumgebung gelten: Die Authentifizierung der Benutzer erfolgt in der Datenbank über individuelle Datenbankbenutzer, die benannt sind nach der eindeutigen Personalnummer der betreffenden Person.
Virtual Private Database
451
Feinkonzept Aus den oben genannten Anforderungen lässt sich das folgende technische Implementierungskonzept ableiten: Die für VPD notwendigen Programmeinheiten sollen im Schema scott_sec angelegt werden. Da wir mit individuellen Datenbank-Sessions arbeiten, nutzen wir einen lokalen Anwendungskontext. Er soll unter dem Namen scott_con angelegt werden und über das Paket sec_init im Schema scott_sec befüllt werden. Das Attribut mit Name app soll innerhalb dieses Kontextes den Namen der Anwendung, das Attribut pos die Position des Mitarbeiters, das Attribut fir die Firma und abt die Abteilung speichern. Der Kontext scott_con soll über einen Logon-Trigger für die einzelnen Benutzer befüllt werden. VPD-Implementierung Die Benutzer scott und scott_sec werden wie gewohnt angelegt. Scott wird über die Rollen connect und resource privilegiert. Für das Anlegen der Objekte von scott_sec ergeben sich zwei unterschiedliche Möglichkeiten: Die Objekte werden von einem hochprivilegierten Benutzer – zum Beispiel system – für scott_sec angelegt. Scott_sec benötigt in diesem Fall keine expliziten Systemprivilegien. Die notwendigen Objektprivilegien sind identisch mit denen, die im folgenden Abschnitt genannt werden. Scott_sec legt die notwendigen Objekte direkt an und benötigt in diesem Fall folgende Systemprivilegien: create session, create procedure, create any context, exempt access policy. Darüber hinaus sind folgende Objektprivilegien notwendig: select auf die Tabelle mitarbeiter von scott, execute für das Paket dbms_rls von sys. Die Testtabellen werden nun im Schema scott angelegt. Das Beispiel zeigt den rudimentären Code, in der Praxis würden ggf. zusätzliche Trigger und Constraints benötigt: CREATE TABLE scott.auftraege ( a_nr VARCHAR2(10) NOT NULL, -- Auftragsnummer a_datum DATE NOT NULL, -- Auftragsdatum a_kunde VARCHAR2(10) NOT NULL, -- Kundennummer a_mitarb VARCHAR2(10) NOT NULL, --Personalnummer des Mitarbeiters a_abt VARCHAR2(10) NOT NULL, -- Abteilung des Mitarbeiters kontext VARCHAR2(2) NOT NULL, -- Kuerzel der Anwendung firma VARCHAR2(20) NOT NULL, -- Name der anlegenden Firma CONSTRAINT auf_pk PRIMARY KEY(a_nr), CONSTRAINT kont_chk CHECK (kontext IN ('SE','VE')) -- SErvice und VErkauf ); Listing 9.19: Anlegen der Tabelle auftraege
452
Sicherheit
Beim Anlegen eines Auftrages sorgen Trigger für das Befüllen der Personal- und Abteilungsnummer des bearbeitenden Mitarbeiters. Alle Endbenutzer bekommen die für sie nötigen Grundprivilegien – select, insert, update oder delete – für diese Tabelle über entsprechende Rollen. Die Tabelle mitarbeiter wird wie folgt angelegt: CREATE TABLE scott.mitarbeiter( m_mitarb VARCHAR2(10) NOT NULL, -- Personalnr des Mitarbeiters m_abt VARCHAR2(10) NOT NULL, -- Abteilung m_vorname VARCHAR2(50), m_nachname VARCHAR2(100), m_position VARCHAR2(100), m_gehalt NUMBER(6), firma VARCHAR2(20), CONSTRAINT mit_pk PRIMARY KEY(m_mitarb)); Listing 9.20: Anlegen der Tabelle mitarbeiter
Für die Tabelle wird ein direktes select-Privileg an den Benutzer scott_sec vergeben, damit dieser die Daten beim Initialisieren des Applikationskontextes lesen kann. Im nächsten Schritt kann nun der geplante Applikationskontext angelegt werden: CREATE CONTEXT
scott_con USING scott_sec.sec_init;
Listing 9.21: Anlegen eines Applikationskontextes
Beim Anlegen des Kontexts ist es nicht erforderlich, dass die angegebenen Programmeinheit – hier sec_init – bereits existiert. Sie kann nachträglich wie folgt aufgebaut werden: CREATE OR REPLACE PACKAGE scott_sec.sec_init AS lc_service CONSTANT VARCHAR2 (2) := lc_verkauf CONSTANT VARCHAR2 (2) := lc_manager CONSTANT VARCHAR2 (50) := lc_verkaeufer CONSTANT VARCHAR2 (50) :=
'SE'; 'VE'; 'Manager'; 'Verkäufer';
PROCEDURE init (user_in VARCHAR2, application_in VARCHAR2); END; / CREATE OR REPLACE PACKAGE BODY scott_sec.sec_init IS PROCEDURE init (user_in VARCHAR2, application_in VARCHAR2) IS lv_position scott.mitarbeiter.m_position%TYPE; lv_abt scott.mitarbeiter.m_abt%TYPE; lv_firma scott.mitarbeiter.firma%TYPE; BEGIN -- Userdaten ermitteln ACHTUNG: ohne VPD SELECT m.m_position, m.m_abt, m.firma INTO lv_position, lv_abt, lv_firma FROM scott.mitarbeiter m WHERE m.m_mitarb = user_in;
Virtual Private Database
453
-- VOR dem Setzen des Kontexts noch Plausis einbauen! -- Attributwerte für Position, Abteilung und Firma setzen DBMS_SESSION.set_context ('SCOTT_CON', 'POS', lv_position); DBMS_SESSION.set_context ('SCOTT_CON', 'ABT', lv_abt); DBMS_SESSION.set_context ('SCOTT_CON', 'FIR', lv_firma); DBMS_SESSION.set_context ('SCOTT_CON', 'APP', application_in); --- hier noch entsprechendes Exception-Handling hinzufügen EXCEPTION WHEN OTHERS THEN raise_application_error (-20001, SQLERRM (SQLCODE)); END init; -END; / Listing 9.22: Anlegen des Security-Paketes
Da die Tabelle mitarbeiter des Schemas scott, die im Rumpf dieses Paketes gelesen wird, selbst auch über VPD geschützt wird, ist es für eine fehlerfreie Funktion dieses Paketes unbedingt erforderlich, dem Benutzer sec_init das Systemprivileg exempt access policy zu geben. Ansonsten würde er nur einen Ausschnitt von mitarbeiter sehen und möglicherweise keine korrekte Initialisierung des Kontextes vornehmen können. Darüber hinaus versteht es sich, dass vor dem Setzen der Kontextattribute geeignete Prüfungen durchgeführt werden – z.B. Maschinen- oder Programmnamen oder IP-Adressen mit Hilfe des sys_context-Funktion. Nun werden die Funktionen angelegt, die für die Generierung der where-Klauseln zuständig sind. Um eine bessere Übersicht zu haben, unerwünschte Nebeneffekte auszuschließen und eine bessere Kombinierbarkeit zu erreichen, ist es empfehlenswert, pro Funktion immer nur ein Prädikat zu generieren. Dadurch, dass für jedes Objekt mehrere Policies definiert werden können, lassen sich Funktionen den Anforderungen entsprechend kombinieren. CREATE OR REPLACE FUNCTION scott_sec.aw_basic_function ( owner VARCHAR2, objname VARCHAR2 ) RETURN VARCHAR2 IS BEGIN -- Filtern nach Firma RETURN ' firma = SYS_CONTEXT(''SCOTT_CON'',''FIR'')'; END; / Listing 9.23: Filterfunktion für FIR
454
Sicherheit
CREATE OR REPLACE FUNCTION scott_sec.aw_basic2_function ( owner VARCHAR2, objname VARCHAR2 ) RETURN VARCHAR2 IS BEGIN -- Filtern nach Anwendung RETURN ' kontext = SYS_CONTEXT(''SCOTT_CON'',''APP'')'; END; / Listing 9.24: Filterfunktion für APP CREATE OR REPLACE FUNCTION scott_sec.aw_sal_function ( owner VARCHAR2, objname VARCHAR2 ) RETURN VARCHAR2 IS BEGIN -- Filtern nach Position oder User - je nach Position IF SYS_CONTEXT ('SCOTT_CON', 'POS') = 'Manager' THEN RETURN ' m_abt = SYS_CONTEXT(''SCOTT_CON'',''ABT'')'; ELSIF SYS_CONTEXT ('SCOTT_CON', 'POS') = 'Verkäufer' THEN RETURN ' m_mitarb = user'; ELSE RETURN ' 1 = 2'; END IF; END; / Listing 9.25: Filterfunktion für die Gehaltsspalte von Mitarbeitern
Gemäß dem oben dargelegten Feinkonzept können diese Funktionen nun über Richtlinien mit Datenbankobjekten verbunden werden. Die Tabelle mitarbeiter erhält demnach zwei – immer aktive – Standardfilter, einen für die Firma des Benutzers und einen für den Fall, dass die Gehaltsspalte selektiert wird. Standardfilter werden stets über die Richtliniengruppe sys_default angelegt: BEGIN DBMS_RLS.add_grouped_policy (object_schema => 'SCOTT', object_name => 'MITARBEITER', policy_group => 'SYS_DEFAULT', policy_name => 'FIR_FILTER', function_schema => 'SCOTT_SEC', policy_function => 'AW_BASIC_FUNCTION' );
Virtual Private Database DBMS_RLS.add_grouped_policy (object_schema => object_name => policy_group => policy_name => function_schema => policy_function => sec_relevant_cols => ); END; /
455
'SCOTT', 'MITARBEITER', 'SYS_DEFAULT', 'GEH_FILTER', 'SCOTT_SEC', 'AW_SAL_FUNCTION', 'M_GEHALT'
Listing 9.26: Standardrichtlinien für die Tabelle mitarbeiter
Da in dem vorangehenden Beispiel keine expliziten Angaben zum Befehlstyp gemacht wurden, gelten die Richtlinien gleichermaßen für select-, insert-, updateund delete-Befehle. Für auftraege gelten ebenfalls zwei Standardfilter: der Firmen- und der Applikationsfilter, die mit dem folgenden Code aktiviert werden: BEGIN DBMS_RLS.add_grouped_policy (object_schema => 'SCOTT', object_name => 'AUFTRAEGE', policy_group => 'SYS_DEFAULT', policy_name => 'FIR_FILTER', function_schema => 'SCOTT_SEC', policy_function => 'AW_BASIC_FUNCTION' ); DBMS_RLS.add_grouped_policy (object_schema => 'SCOTT', object_name => 'AUFTRAEGE', policy_group => 'SYS_DEFAULT', policy_name => 'APP_FILTER', function_schema => 'SCOTT_SEC', policy_function => 'AW_BASIC2_FUNCTION' ); END; / Listing 9.27: Standardrichtlinien für die Tabelle auftraege
Nach den Standardrichtlinien werden im Folgenden die Richtlinien angelegt, die exklusiv für die einzelnen Applikationen – SE und VE – gelten sollen. Hier wurden im Feinkonzept nur explizite Regel für VE vereinbart. Diese zusätzlichen, sich gegenseitig ausschließenden Richtlinien werden über jeweils eigene Richtliniengruppen gesteuert, die wechselweise zu den Standardrichtlinien zugeschaltet werden können.
456
Sicherheit
In einem ersten Schritt ist zunächst einmal festzulegen, dass das Attribut app des Kontextes scott_con für die Tabelle auftraege verantwortlich für das Zuschalten zusätzlicher Richtlinien ist: BEGIN DBMS_RLS.add_policy_context (object_schema => 'SCOTT', object_name => 'AUFTRAEGE', namespace => 'SCOTT_CON', attribute => 'APP' ); END; / Listing 9.28: Anlegen des Kontextes für Richtlinien
Im Anschluss daran können nun Richtliniengruppen angelegt werden, die den gleichen Namen wie die möglichen Werte des Attributs app von scott_con – nämlich VE und SE – haben: BEGIN DBMS_RLS.create_policy_group (object_schema object_name policy_group ); DBMS_RLS.create_policy_group (object_schema object_name policy_group ); END; /
=> 'SCOTT', => 'AUFTRAEGE', => 'VE' => 'SCOTT', => 'AUFTRAEGE', => 'SE'
Listing 9.29: Anlegen von Richtliniengruppen
Nun benötigen wir noch Funktionen, welche die where-Klauseln für die zusätzlichen Filter der Tabelle auftraege generieren. Für die VE-Applikation bedeutet dies nach der Feinspezifikation: CREATE OR REPLACE FUNCTION scott_sec.aw_ve_function ( owner VARCHAR2, objname VARCHAR2 ) RETURN VARCHAR2 IS BEGIN -- Filtern nach Position oder User - je nach Position IF SYS_CONTEXT ('SCOTT_CON', 'POS') = 'Manager' THEN RETURN ' a_abt = SYS_CONTEXT(''SCOTT_CON'',''ABT'')'; ELSIF SYS_CONTEXT ('SCOTT_CON', 'POS') = 'Verkäufer' THEN RETURN ' a_mitarb = user';
Virtual Private Database
457
ELSE RETURN ' 1 = 2'; END IF; END; / Listing 9.30: Filter für die VE-Applikation
Da die SE-Applikation für die Tabelle auftraege keine besonderen Regeln benötigt, generiert die Funktion eine nicht filternde Dummy-Klausel 1 = 1: CREATE OR REPLACE FUNCTION scott_sec.aw_se_function ( owner VARCHAR2, objname VARCHAR2 ) RETURN VARCHAR2 IS BEGIN RETURN ' 1 = 1'; END; / Listing 9.31: Filter für die SE-Applikation
Nun müssen die Tabelle auftraege, die neuen Richtliniengruppen und Funktionen über Richtlinien verbunden werden: BEGIN DBMS_RLS.add_grouped_policy (object_schema => 'SCOTT', object_name => 'AUFTRAEGE', policy_group => 'VE', policy_name => 'VE_FILTER', function_schema => 'SCOTT_SEC', policy_function => 'AW_VE_FUNCTION' ); DBMS_RLS.add_grouped_policy (object_schema => 'SCOTT', object_name => 'AUFTRAEGE', policy_group => 'SE', policy_name => 'SE_FILTER', function_schema => 'SCOTT_SEC', policy_function => 'AW_SE_FUNCTION' ); END; / Listing 9.32: Richtlinien für zusätzliche Richtliniengruppen
458
Sicherheit
Zum Schluss muss noch dafür gesorgt werden, dass die Initialisierung des Kontextes automatisch ausgeführt wird. In unserem Feinkonzept wurde hierfür ein LogonTrigger vorgesehen. Im Kernbereich dieses Triggers werden die jeweiligen Richtlinien dann wie folgt aktiviert: scott_sec.sec_init.init ( user_in => USER , application_in => lv_application ); Listing 9.33: Aktivierung der Richtlinien
Bei der Implementierung dieses Triggers ist zu beachten, dass die Plausibilitätsprüfungen innerhalb des aufgerufenen Paketes sec_init stark genug sind, um den jeweiligen Benutzer auf die richtige Anwendung zu lenken und Missbrauch auszuschließen. Darüber hinaus dürfen die Endbenutzer keinerlei Ausführungsprivilegien für das Initialisierungspaket – hier sec_init – haben! Diese Privilegien sind nur für den Benutzer notwendig, der den Logon-Trigger anlegt und in dessen Schema er gespeichert wird. Aus diesem Grunde wird der Logon-Trigger direkt im Schema scott_sec angelegt, um keine gefährdenden execute-Privilegien nach außen vergeben zu müssen. Damit auch scott_sec kein create any trigger-Privileg benötigt – was für das Anlegen von Logon-Triggern nötig wäre –, wird der Trigger von system für scott_sec aufgebaut: CREATE TRIGGER scott_sec.set_vpd ....
Ist der Kontext initialisiert, werden alle relevanten Richtlinien und die mit ihnen verbundenen Where-Klauseln für Zugriffe auf die Tabellen über AND-Verknüpfungen bereitgestellt. Für das Anlegen und Verwalten von Richtlinien und Anwendungskontexten steht alternativ auch ein Java-Client-Werkzeug, der Oracle Policy Manager, zur Verfügung. Das Werkzeug wird im Rahmen einer Client-Installation bereitgestellt und kann wie folgt aufgerufen werden: oemapp opm
Es versteht sich, dass die Funktionen und Pakete, die für die Richtlinien benötigt werden, nicht über dieses Werkzeug aufgebaut werden können. In der Regel empfiehlt sich das Werkzeug weniger zum Aufbau als vielmehr zur Verwaltung von VPD-Umgebungen, um beispielsweise bestehende Richtlinien zu aktivieren oder deaktivieren. Die folgende Abbildung zeigt die in unserem Beispiel angelegte VPD-Konfiguration in Ausschnitten aus der Sicht von OPM:
Virtual Private Database
459
Abbildung 9.25: Anwendungskontext im Oracle Policy Manager
Die folgende Grafik fasst noch einmal die komplexen Beziehungen aller beschriebenen VPD-Objekte zusammen.
Appl-Context
Paket Attribut
Policy-Function
Policy-Context Tabelle DML-Type
P Policy-Group
P
= Policy
Abbildung 9.26: Beziehungsgeflecht der VPD-Objekte
460
Sicherheit
Richtlinien: Typen und Caching Die Funktionen, die für die Generierung von Prädikaten verantwortlich sind, werden standardmäßig bei jeder parse- oder execute-Phase eines zugehörigen SQLBefehls zur Ausführung gebracht. Diese Strategie ist überall dort notwendig und sinnvoll, wo die Möglichkeit besteht, dass sich die für die Generierung nötigen Attributwerte sehr häufig ändern und daraus unterschiedliche Where-Klauseln resultieren. Diese Strategie kann aber unnötige Ressource kosten, wenn die Ergebnisse der VPD-Funktionen eher statischen Charakter haben. Aus diesem Grunde wurden bereits in der Version 9 unterschiedliche Richtlinientypen eingeführt, die in der Version noch erweitert wurden. Ziel dieser Typen ist es, die Dynamik der VPD-Funktionen genau konfigurieren zu können. Die Richtlinientypen werden beim Anlegen einer Richtlinie definiert über dbms_rls.add_policy oder dbms_rls.add_grouped_policy. Dort gibt des den IntegerParameter policy_type. Der boolesche Parameter static_policy wird nur noch aus Gründen der Rückwärtskompatibilität unterstützt und nur ausgewertet, falls policy_type auf dem Standardwert null belassen wurde. Die Angaben zu policy_type werden über die in der folgenden Übersicht angegebenen Konstanten definiert. Derzeit werden die folgenden Typen unterstützt: Dynamic (dbms_rls.DYNAMIC) – Standardwert. Die VPD-Funktion wird bei jedem parse oder execute ausgeführt. Static (dbms_rls.STATIC) – die VPD-Funktion wird einmalig ausgeführt und das resultierende Prädikat – zentral für alle Sessions – in der SGA gespeichert. Shared Static (dbms_rls.SHARED_STATIC) – wie static, nur kann die Funktion von mehreren Objekten genutzt werden. Shared Static (dbms_rls.SHARED_STATIC) – VPD-Funktionen, die für mehrere Objekte zum Einsatz kommen, werden nur einmalig ausgeführt. Context Sensitive (dbms_rls.CONTEXT_SENSITIVE) – nutzt das Caching von VPD-Funktionen, bis ein Applikationskontext verändert wird. Shared Context Sensitive (dbms_rls.SHARED_CONTEXT_SENSITIVE) – wie Context Sensitive, nur können VPD-Funktionen von mehreren Objekten genutzt werden. Views und Privilegien Das oben dargestellte VPD-Konzept wird wegen der umschaltbaren Kontexte auch Partitioned Fine Grain Access Control genannt. Für Informationen zu den oben angelegten Objekten stehen verschiedene DDViews zur Verfügung: dba_context, dba_policies, dba_policy_contexts und dba_policy_groups, v$vpd_policy, dba_global_context, v$context, v$globalcontext. Über das Systemprivileg EXEMPT ACCESS POLICY lässt sich VPD pauschal für einen Benutzer deaktivieren, so dass für den Betreffenden keine where-Klauseln generiert werden!
Virtual Private Database
461
Die oben geschilderten Beispiele funktionieren nur auf der Basis individueller Sessions. Beim Einsatz von Applikationsservern, in deren Kontext unterschiedliche Anwendungsbenutzer über einen Datenbankbenutzer eine Session aufbauen, werden verfeinerte Konzepte benötigt. Diese »globalen« Anwendungskontexte existieren. Die Darstellung dieser Möglichkeiten sprengt jedoch den Rahmen dieser Abhandlung. Tracing von VPD Werden VPD-Funktionen und Richtlinien nicht sehr sorgfältig geplant und umgesetzt, kann es oft zu unerwarteten und schwer zu diagnostizierenden Fehlern kommen. Für die Fehlersuche kann es hilfreich sein, die betreffende VPD-Funktion isoliert über einen SQL-Befehl abzufragen, etwa in der Form: SELECT vpd_function(......) FROM DUAL;
Für eine eingehendere Analyse dagegen sei an dieser Stelle kurz der Event 10730 erwähnt, der über die folgende Syntax innerhalb einer Session aktiviert werden kann: ALTER SESSION SET EVENTS '10730 trace name context forever, level 12'; Listing 9.34: Setzen des Events 10730
Der Event listet dann in einer Trace-Datei, die im Verzeichnis user_dump_dest gespeichert wird, die im Rahmen von VPD ergänzten Prädikate. Das folgende Beispiel enthält einen Ausschnitt aus einer solchermaßen generierten Trace-Datei. Auslöser war der SQL-Befehl SELECT * FROM scott.auftraege; ------------------------------------------------------------Logon user : P10 Table/View : SCOTT.AUFTRAEGE Policy name : APP_FILTER Policy function: SCOTT_SEC.AW_BASIC2_FUNCTION RLS view : SELECT "A_NR","A_DATUM","A_KUNDE","A_MITARB","A_ABT","KONTEXT","FIRMA" FROM "SCOTT"."AUFTRAEGE" "AUFTRAEGE" WHERE ( kontext = SYS_CONTEXT('SCOTT_CON','APP')) ------------------------------------------------------------Logon user : P10 Table/View : SCOTT.AUFTRAEGE Policy name : FIR_FILTER Policy function: SCOTT_SEC.AW_BASIC_FUNCTION RLS view : SELECT "A_NR","A_DATUM","A_KUNDE","A_MITARB","A_ABT","KONTEXT","FIRMA" FROM "SCOTT"."AUFTRAEGE" "AUFTRAEGE" WHERE ( firma = SYS_CONTEXT('SCOTT_CON','FIR')) -------------------------------------------------------------
462
Sicherheit
Logon user : P10 Table/View : SCOTT.AUFTRAEGE Policy name : VE_FILTER Policy function: SCOTT_SEC.AW_VE_FUNCTION RLS view : SELECT "A_NR","A_DATUM","A_KUNDE","A_MITARB","A_ABT","KONTEXT","FIRMA" FROM "SCOTT"."AUFTRAEGE" "AUFTRAEGE" WHERE ( a_abt = SYS_CONTEXT('SCOTT_CON','ABT')) Listing 9.35: Ausgabe des Events 10730
9.9
Labels
9.9.1
Überblick
In den vorangehenden Abschnitten wurde gezeigt, wie mit Hilfe von Privilegien Zugriffe auf Tabellen und Views für bestimmte Benutzer freigeschaltet werden können. Diese Objektprivilegien können entweder direkt vom Besitzer des betreffenden Objektes oder durch einen von diesem Besitzer explizit privilegierten Dritten38 vergeben werden. Neuerdings gibt es auch das Systemprivileg grant any object privilege, das dem Begünstigten die Zuteilung von Objektprivilegien an Dritte erlaubt! Bei Zugriffen über Labels dagegen entscheiden nicht die vergebenen Objektprivilegien alleine darüber, ob ein Benutzer eine bestimmte Tabelle und deren Daten abfragen und verändern darf. Label-Systeme erfordern darüber hinaus die Übereinstimmung des jeweiligen Benutzer- oder Session-Labels mit den Daten-Labeln, die jedem Datensatz zugeordnet sind. Anders ausgedrückt: Jeder Benutzer kann nur die Daten sehen, deren Label mit dem ihm zugeordneten Label kompatibel sind. Labels werden von Administratoren zentral im Rahmen von Richtlinien (Policies) für jede Datenbank konfiguriert. Einmal angelegt, können sie auf der einen Seite Sessions (Session Label) und auf der anderen Seite Tabellenzeilen (Row Label) zugeordnet werden. Nur wenn der Label eines Benutzers oder einer Session mit dem Label einer Tabellenzeile vereinbar ist und entsprechende Objektprivilegien vorliegen, kann der Zugriff erfolgen. Label-Systeme werden aufgrund dieses »übergreifenden« Kriteriums auch MAC-Systeme (Mandatory Access control) genannt, weil der Eigentümer alleine nicht über den Zugriff entscheiden kann. Im Gegensatz zu MAC-Systemen steht bei DAC-Systemen (Discretionary Access Control) der jeweilige Besitzer im Mittelpunkt, indem er eigenmächtig die Zugriffe per Grant-Befehl vergeben kann. Für die meisten Tabellenobjekte genügen DAC-Zugriffskriterien. DACPrivilegien können dort, wo es die Sicherheit der Daten erfordert, durch MACLabel ergänzt werden. Typische MAC-Objekte sind in der Regel solche, bei denen die Entscheidung darüber, wer zugreifen darf, nicht dem Besitzer des betreffenden Objektes alleine anvertraut werden darf. Objekte, bei denen die Privilegierung auf Zeilenebene nicht über bestimmte vorgegebene Spaltenwerte – Benutzer X sieht alle Daten von Abteilung 10 – oder feststehende Unterabfragen geregelt werden kann, sondern über komplexe, nicht standardisierbare Mechanismen entschieden 38 Die WITH GRANT OPTION Klausel des GRANT-Befehls
Labels
463
wird, sind ebenfalls für den Einsatz von Labels prädestiniert. Ein großer Vorteil des Label-Systems ist darüber hinaus, dass es nicht pauschal konfiguriert werden muss, sondern individuell für einzelne Tabellenobjekte im Rahmen von Richtlinien zuschaltbar ist. Neben Select-Operationen können auch Insert-, Update- und DeleteBefehle das Label-System nutzen. Bisher erforderte der Einsatz des Label-Systems im Kontext von Oracle-Datenbanken auf der einen Seite ein speziell zertifiziertes Betriebssystem (B-Level) und auf der anderen Seite eine für dieses System zertifizierte Version von Trusted Oracle. Labels sind unter Oracle9i nun auch ohne B-Betriebssystem und ohne entsprechende trusted-Version der Datenbank zu realisieren. Oracle Label Security (OLS) baut intern auf dem VPD39-Konzept auf, das in Abschnitt Virtual Private Database beschrieben wurde. Für den Aufbau und die Verwaltung von Label-Systemen stehen einige Pakete mit entsprechenden Prozeduren und Funktionen zur Verfügung. Darüber hinaus lassen sich die wichtigsten Aufgaben auch über die grafische Oberfläche des Oracle Policy Managers40 realisieren.
9.9.2
Die Grundlagen
Ein Label-System im Rahmen einer Oracle-Datenbank aufzubauen bedeutet im Einzelnen: 1. Richtlinien (Policies) anzulegen, die vorgeben, in welchem operativen Kontext Label-Operationen prinzipiell zur Anwendung kommen sollen. Der Kontext von Richtlinien wird über Optionen festgelegt. Mögliche Optionen sind auszugsweise in der folgenden Tabelle dargestellt: Option
Bedeutung
READ_CONTROL
Aktiviert die Richtlinien für alle Abfragen, auch für implizite Abfragen im Kontext von Update-, Insert- und Delete-Befehlen.
WRITE_CONTROL
Aktiviert die Richtlinien für Insert-, Update- und Delete-Operationen
ALL_CONTROL
Aktiviert die Richtlinien in jedem möglichen Kontext.
Tabelle 9.5: Auszüge aus den Policy-Optionen
Neben den Optionen spezifiziert jede Richtlinie auch den Namen der LabelSpalte. Label-Spalten enthalten die Daten-Labels und werden für alle Tabellen angelegt, die im Rahmen des Label-Systems verwaltet werden. 2. Sind Richtlinien spezifiziert, müssen im Kontext dieser Richtlinien die Komponenten geplant und definiert werden, aus denen letztendlich die Labels zusammengesetzt werden können. Die Planung der Label-Komponenten wie auch der Labels selbst erfordert große Sorgfalt und orientiert sich an den spezifischen Sicherheitsbedürfnissen der betreffenden Datenbank. Jeder Label kann sich prinzipiell aus ein bis drei unterschiedlichen Komponenten zusammensetzen:
39 VPD = Virtual Private Database 40 Aufruf im Unix-Umfeld über oemapp opm
464
Sicherheit
– Level: Jeder Label muss aus einer Level-Komponente bestehen. Levels sind hierarchisch organisiert und ermöglichen dadurch eine Klassifizierung der zugeordneten Daten hinsichtlich ihrer Sensibilität. Beispielsweise lassen sich die Level u (unbedenklich), g (geheim) und sg (streng geheim) definieren. Die hierarchische Ordnung wird über numerische Angaben erreicht. Je höher der numerische Wert, desto sensibler der Level. – Compartment: Compartments erlauben zusätzlich die Unterteilung der Daten in operationale Bereiche. Beispielsweise lassen sich die Compartments vk (Verkauf) oder mk (Marketing) anlegen. Jeder Label kann ein oder mehrere Compartments enthalten. – Group: Auch Gruppen sind für Labels optional. Sie lassen sich wie Level hierarchisch definieren, können aber, im Gegensatz zu diesen, jedem Label mehrfach zugewiesen werden. Über Gruppen können beispielsweise Organisationsbereiche implementiert werden: rw (westliche Region) oder rs (Region Süd). Die hierarchische Staffelung kann durch eine jeder Gruppe zuzuweisende Parent Group zum Ausdruck gebracht werden. 3. Aus den einzeln definierten Label-Komponenten können schließlich gültige Daten-Labels zusammengesetzt werden: g:vk,mk:rs steht beispielsweise für den Level geheim mit den Compartments Verkauf und Marketing sowie der Gruppe Region Süd, wobei die Komponenten über Doppelpunkt voneinander getrennt werden. Ein weiterer gültiger Label könnte sein: sg für »streng geheim«, Compartments und Gruppen sind hier – als optionale Komponenten – nicht zugewiesen worden. Jedem Label wird bei seiner Erstellung entweder explizit oder implizit ein numerischer Bezeichner (Tag) zugewiesen. Dieser Bezeichner ist es, der intern in der Label-Spalte der einzelnen Benutzertabellen gespeichert wird. 4. Die Richtlinien, in deren Kontext die Labels definiert wurden, müssen im nächsten Schritt einzelnen Tabellen, Prozeduren oder ganzen Schemata zugewiesen werden. Die Optionen der Richtlinien, die den operativen Kontext festlegen – z.B. WRITE_CONTROL –, werden entweder implizit auf die Objekte übertragen oder können dort nochmals alternativ spezifiziert werden. Darüber hinaus lassen sich bei der Zuweisung auch Label-Funktionen angeben, die individuell kodiert für die automatisierte Generierung von Labels bei insert-Operationen zuständig sein können. Es lassen sich hier ebenfalls Prädikate spezifizieren, die zusätzlich zu den Labels die Zugriffe steuern können. 5. Damit Benutzer auf die im Rahmen des Label-Systems verwalteten Tabellen Zugriff erhalten können, müssen jedem Benutzer entweder so genannte BenutzerLabels (User Label, Session Label) oder einzelne Levels, Compartments oder Groups zugewiesen werden. Im letzteren Fall werden für jeden Benutzer folgende Autorisierungen festgelegt: – Der maximale Level, den der Betreffende lesen und schreiben darf. Wird ein Benutzer beispielsweise für den Level g (geheim) freigegeben, darf er alle hierarchisch tieferen Levels lesen, allerdings nur bis zu seinem minimalen Level schreiben. – Sein Default-Level schließlich gibt den Level an, unter dem er standardmäßig operiert.
Labels
465
– Der Default Row Level schließlich ist der Level, der beim Einfügen von Datensätzen übertragen wird, sofern für die Tabelle keine Label-Funktion angegeben wurde. – Gleichermaßen werden dem Benutzer Compartments und Gruppen zugeordnet, für die er Berechtigungen erhalten soll. Für jede der beiden letztgenannten Komponenten kann separat angegeben werden, ob der Benutzer Schreibrechte erhält und ob die genannte Komponente Bestandteil seines standardmäßigen Session-Labels (Default) sowie Daten-Labels (Row) wird.
Abbildung 9.27: Zuordnung von Label-Komponenten zu Benutzern (1)
Ein Beispiel soll den vorangehenden Abschnitt verdeutlichen. Dem Benutzer scott werden der minimale Level g und der maximale Level sg zugewiesen. Er erhält darüber hinaus den Default-Level g und auch den Row-Level g. Ihm werden das Compartment mk (Marketing) zugeteilt und die Gruppe rs (Region Süd). Auf beiden Komponenten erhält er Schreibrechte, und beide werden auch Bestandteil seiner Session- und Row-Labels. Meldet sich scott im Folgenden an der Datenbank an, arbeitet er unter dem Level g, dem Compartment mk und der Gruppe rs als Session-Label (g:mk:rs). Er kann mit diesen Einstellungen alle Datensätze lesen, die maximal den Level g in ihrem RowLabel haben, mindestens die Gruppe rs oder keine Gruppe sowie ausschließlich das Compartment mk oder kein Compartment haben. Daten, die andere oder zusätzliche Compartments enthalten, stehen scott nicht zum Lesen zur Verfügung! Da er maximal für den Level sg autorisiert wurde, kann Scott im laufenden Betrieb seinen Session-Label ändern, z.B. in sg:mk:rs. Damit hat er Zugriff auf weitere Daten. Wenn er Daten einfügt, gibt er diesen – sofern er die Einstellungen seiner Session nicht ändert – seinen Default-Row-Label g:mk:rs mit. Zusätzlich darf er alle die
466
Sicherheit
Abbildung 9.28: Zuordnung von Label-Komponenten zu Benutzern (2)
Datensätze ändern, die mindestens seinem minimalen Level g entsprechen, die mindestens die Gruppe rs sowie maximal das Compartment mk enthalten.
Tabelle T1 Row-Label
Session-Label G:MK:RS
G
MK,VK
RS
G
MK
RS
SG
MK
RS,RN
G
RS,RN
level compartment group
Abbildung 9.29: Kompatibilität von Session Labels und Row Labels
Labels
467
6. Neben den Label-Komponenten können den Benutzern zusätzlich noch spezielle Systemprivilegien zugeteilt werden, die den Betreffenden erlauben, sich über bestimmte Label-Autorisierungen hinwegzusetzen. Die folgende Tabelle enthält einige Beispiele: Systemprivilegien
Berechtigungen
WRITEUP
Gestattet die Veränderung der Level-Komponente von Row-Labeln bis zum maximalen Level des ausführenden Benutzers
WRITEDOWN
Gestattet die Veränderung der Level-Komponente von Row-Labeln bis zum minimalen Level des ausführenden Benutzers
READ
Gibt dem Betreffenden volles Leserecht auf alle Daten der betreffenden Richtlinie
Tabelle 9.6: Systemprivilegien im Label-Kontext (Auszug)
Die wenigen Beispiele zeigen bereits, wie mächtig diese Systemprivilegien ausfallen. Es ist daher dringend anzuraten, sie nur in Ausnahmefällen zu vergeben, beispielsweise an Administratoren, die einen vollständigen Export von LabelDaten durchführen müssen (READ).
9.9.3
Konfiguration eines Label-Systems
Im Folgenden wird der Aufbau eines Label-Systems unter Verwendung der Beispiele des vorangehenden Abschnittes im Einzelnen durchgeführt. Alle Arbeitsschritte sind über den Oracle Policy Manager grafisch und interaktiv durchführbar, gleichwohl werden in unserem Beispiel entsprechende Prozeduraufrufe benutzt, die für den Aufbau umfangreicher Label-Umgebungen unverzichtbar sind. Im ersten Schritt ist bekanntlich eine Richtlinie zu definieren. Die Richtlinie soll in unserem Beispiel den Namen test_policy erhalten. Der Name der – für Row-Labels notwendigen – verdeckten Spalte soll labtest_col sein. Dieser Spaltenname muss unter allen angelegten Richtlinien eindeutig sein. Die Richtlinie soll darüber hinaus sämtliche Label-Optionen aktivieren (all_control). BEGIN sa_sysdba.create_policy( policy_name => 'TEST_POLICY', column_name => 'LABTEST_COL', default_options => 'ALL_CONTROL'); END; /
Erstellte Richtlinien können über die View dba_sa_policies selektiert werden: POLICY_NAME COLUMN_NAME STATUS --------------------- -------------------- -------TEST_POLICY LABTEST_COL ENABLED POLICY_OPTIONS -------------------------------------------------------------READ_CONTROL, INSERT_CONTROL, UPDATE_CONTROL, DELETE_CONTROL, LABEL_DEFAULT, LABEL_UPDATE, CHECK_CONTROL
468
Sicherheit
Die Spalte Status ENABLED verdeutlicht bereits, dass Richtlinien im Kontext von Tabellen auch »ausgeschaltet« werden können. Es versteht sich, dass Zugriffe in diesem Fall ohne die Kontrollen des Label-Systems erfolgen. Im Rahmen dieser Richtlinien werden nun die Label-Komponenten einzeln definiert. BEGIN sa_components.create_level( policy_name => 'TEST_POLICY', level_num => 5, short_name => 'G', long_name => 'geheim'); sa_components.create_level( policy_name => 'TEST_POLICY', level_num => 10, short_name => 'SG', long_name => 'streng geheim'); END; /
Das vorangehende Beispiel zeigt den Aufbau der Levels g und sg. Die numerischen Angaben (Parameter level_num) werden für die hierarchische Gruppierung benötigt. Der Kurzname dient der Anzeige über entsprechende Funktionen oder über den Policy Manager, die Langform hat rein dokumentarischen Charakter. Die View dba_sa_levels gibt alle vorhandenen Levels mit den ihnen zugeordneten Richtlinien aus. Compartments und Gruppen werden analog angelegt: BEGIN sa_components.create_compartment( policy_name => 'TEST_POLICY', comp_num => 10, short_name => 'MK', long_name => 'Marketing'); sa_components.create_compartment( policy_name => 'TEST_POLICY', comp_num => 20, short_name => 'VK', long_name => 'Verkauf'); END; /
Für Gruppen steht eine entsprechende Prozedur create_group zur Verfügung, bei der über den zusätzlichen Parameter parent_name eine Master-Gruppe angegeben werden kann. Die Parameter policy_name bzw. group_name haben in beiden Fällen keine hierarchisierende Funktion. Die Views dba_sa_groups und dba_sa_compartments geben die vorhandenen Komponenten aus.
Labels
469
Sind alle Komponenten angelegt, lassen sich die Daten-Label definieren: BEGIN sa_label_admin.create_label( policy_name => 'TEST_POLICY', label_tag => 101010, label_value => 'G:MK:RS'); sa_label_admin.create_label( policy_name => 'TEST_POLICY', label_tag => 201010, label_value => 'SG:MK:RS'); END; /
Die numerischen Bezeichner der Labels (label_tag) werden in der Label-Spalte der Tabellen gespeichert und nicht etwa die entsprechenden Kurznamen sg:mk_rs usw. Sie können explizit vergeben werden oder werden – wenn dies nicht geschieht – implizit generiert. Es ist in jedem Fall empfehlenswert, Label-Bezeichner nach einem bestimmten Konzept explizit vorzuschreiben. In unserem Beispiel wurden jeweils zwei Ziffern für jede Komponente vergeben: 10 für den Level g, 20 für sg usw. Nur bei einem solchen Vorgehen ist es möglich, die Daten nach dem Sensibilisierungsgrad zu gruppieren oder gar zu partitionieren. Angelegte Labels können über die View dba_sa_labels selektiert werden. Im nächsten Schritt ist nun die Richtlinie test_policy mit Tabellen oder Schemata zu verknüpfen. Das folgende Beispiel zeigt die Verknüpfung mit der Tabelle emp von scott: BEGIN sa_policy_admin.apply_table_policy ( policy_name => 'TEST_POLICY', schema_name => 'SCOTT', table_name => 'EMP'); END; /
Im Zuge dieser Verknüpfung wird die in der Richtlinie angegebene Spalte labtest_col für die Tabelle emp angelegt. Zusätzlich kann die Hide-Option gesetzt werden, die bewirkt, dass die Labelspalte labtest_col nicht sichtbar41 ist. Allerdings enthält die Label-Spalte in unserem Beispiel für vorhandene Datensätze noch keine Label-Angaben. Entsprechend sind abschließend die Altdaten von emp explizit mit einem Label zu versehen. Hierzu steht die Funktion char_to_label zur Verfügung, die den alphanumerischen Wert eines Labels in die numerische Entsprechung umsetzt. In unserem Beispiel werden die Angestellten der Abteilung 20 mit dem Label g:mk:rs versehen. UPDATE scott.emp SET labtest_col = char_to_label('TEST_POLICY', 'G:MK:RS') WHERE deptno = 20;
41 Nicht sichtbar für DESCRIBE- und SELECT *-Befehle. Die Spalte kann allerdings explizit selektiert werden.
470
Sicherheit
Wie bereits erwähnt, speichert die Label-Spalte nur numerische Daten: SELECT empno, labtest_cal FROM scott.emp WHERE deptno = 20; EMPNO LABTEST_COL ---------- ----------7369 101010 7566 101010 7788 101010 7876 101010 7902 101010
Nicht vergessen werden darf die Autorisierung der einzelnen Benutzer. Die Prozeduren erlauben dabei sowohl die Angabe einzelner Komponenten als auch die Spezifikation über fertige Labels. In den folgenden Beispielen wird der Benutzer Scott über die einzelnen Label-Komponenten autorisiert. BEGIN sa_user_admin.set_levels ( policy_name => 'TEST_POLICY', user_name => 'SCOTT', max_level => 'SG', min_level => 'G', def_level => 'G', row_level => 'G'); END; /
Zunächst werden für Scott die Hierarchiestufen (Level) bestimmt, in deren Kontext er Operationen ausführen darf. min_level gibt dabei die unterste Hierarchiestufe für Schreiboperationen an, max_level analog die höchste Stufe für Schreib- und Leseoperationen. def_level gibt die Stufe an, auf der sich der Benutzer nach dem Connect bewegt. row_level setzt den Standard für INSERT-Operationen. Auf ähnliche Weise werden im Folgenden die Compartments und die Gruppen für scott vorgegeben: BEGIN sa_user_admin.set_compartments ( policy_name => 'TEST_POLICY', user_name => 'SCOTT', read_comps => 'MK', write_comps => 'MK', def_comps => 'MK', row_comps => 'MK'); END; /
Labels
471
BEGIN sa_user_admin.set_groups ( policy_name => 'TEST_POLICY', user_name => 'SCOTT', read_groups => 'RS', write_groups => null, def_groups => 'RS', row_groups => 'RS'); END; /
Über die in den vorangehenden Beispielen gemachten Angaben werden entsprechende Labels generiert, die für die Zugriffe von scott relevant sind. Die folgende Abbildung zeigt diese generierten Labels:
Abbildung 9.30: Generierte Benutzer-Labels
In wenigen, wohl begründeten Fällen kann es notwendig sein, einem Benutzer spezielle Privilegien im Rahmen des Label-Systems zu erteilen. Im folgenden Beispiel erhält scott das WRITEUP-Privileg, mit dem ihm erlaubt wird, die Level-Komponente eines Daten-Labels bis zu seinem eigenen, maximalen Level – in unserem Beispiel sg – zu erhöhen. BEGIN sa_user_admin.set_user_privs ( policy_name => 'TEST_POLICY', user_name => 'SCOTT', privileges => 'WRITEUP'); END; /
472
Sicherheit
Die erteilten Label-Komponenten und Privilegien lassen sich auch für den Endbenutzer über die Views all_sa_users und all_sa_user_labels abfragen. Ist die LabelSpalte der betreffenden Tabelle offen gelegt, können darüber hinaus die DatenLabels direkt abgefragt werden: SELECT empno, deptno, FROM emp; EMPNO DEPTNO ---------- ---------7369 20 7876 20
label_to_char(labtest_col) label LABEL ---------G:MK:RS G:MK:RS
Im vorangehenden Beispiel sieht der Benutzer scott nur die Daten mit dem Label g:mk:rs, weil sein Standard-Session-Label auf g:mk:rs eingestellt wurde. Der Benutzer kann dieses Session-Label allerdings im Rahmen der ihm zugeteilten Privilegien über die Prozedur sa_session.set_label abändern und erhält – je nachdem, wie die Daten-Labels vergeben sind – andere Treffermengen. SET SERVEROUTPUT ON DECLARE dum VARCHAR2(100); BEGIN -- entweder über den alphanumerischen Label sa_session.set_label('TEST_POLICY', 'SG:MK:RS'); -- oder alternativ numerisch -- sa_utl.set_label('TEST_POLICY', 201010); -- zur Kontrolle den aktuellen Session-Label noch einmal ausgeben dum := sa_session.label('TEST_POLICY'); dbms_output.put_line(dum); END; /
Neben Tabellen und Benutzern können auch Programmeinheiten mit Label-Privilegien versehen werden. Auf diese Weise lassen sich außergewöhnliche Zugriffe über geprüfte Programmeinheiten realisieren. Im folgenden Beispiel wird der Funktion zaehl_test, welche die Anzahl der Datensätze in einer Tabelle mit Namen Test ausgibt, das READ-Privileg zugeteilt. Dieses Privileg erlaubt der Funktion das vollständige Lesen der Tabelle Test, unabhängig von den eingestellten Label-Privilegien des aufrufenden Benutzers. Die Label-Privilegien von Programmeinheiten werden aus verständlichen Gründen mit jeder Kompilierung zurückgenommen und müssen entsprechend neu zugeteilt werden. BEGIN sa_user_admin.set_prog_privs ( policy_name => 'TEST_POLICY', schema_name => 'BLA', program_unit_name => 'ZAEHL_TEST', privileges => 'READ'); END; /
Profile
9.10
473
Profile
Die Benutzerprofile haben zwei Aufgaben: erstens die Einschränkung von Ressourcen und des Weiteren die Möglichkeit des Managements von Passwörtern. Jedem Benutzer wird durch den Befehl CREATE USER automatisch ein Standardprofil zugewiesen. Dieses Profil mit dem Namen DEFAULT setzt zunächst alle Begrenzungen auf UNLIMITED bzw. schaltet alle Parameter für das Passwortmanagement aus. Es kann aber jederzeit durch einen Administrator mit Grenzen versehen werden. In der Regel wird das Standardprofil jedoch nicht angepasst, sondern es werden für bestimmte Benutzergruppen eigene Profile angelegt, die diesen dann zugeordnet werden. Dabei ist zu beachten, dass dem Benutzer automatisch das Standardprofil zugewiesen wird, wenn ein Profil gelöscht wird.
9.10.1 Management von Ressourcen Mit den Ressourcenparametern sind grobe Grenzen für die CPU-Benutzung oder das EA-Verhalten einstellbar, des Weiteren können Beschränkungen hinsichtlich Anzahl gleichzeitiger Sessions und die maximale idle-Zeit eingestellt werden. In der Praxis haben sich einige dieser Parameter als nützlich erwiesen, während andere, wie zum Beispiel PRIVATE_SGA, so gut wie nie eingesetzt werden. ALTER SYSTEM SET RESOURCE_LIMIT = TRUE;
In diesem Beispiel wird zunächst die Ressourcenlimitierung aktiviert. Dies kann entweder über den o.g. Befehl ALTER SYSTEM geschehen oder über den Initialisierungsparameter resource_limit = true. Damit werden mit dem Anmelden einer Session die Parameter überwacht. Im Folgenden werden die einzelnen Parameter beschrieben: session_per_useranamen mit der Datenbank arbeiten. cpu_per_sessionrten. Wird während der Ausführung eines Befehls diese Limitierung überschritten, wird er mit einer Fehlermeldung abgebrochen. Da kaum jemand erfassen kann, wie viel CPU-Verbrauch eine Session hat, wird dieser Wert selten gesetzt. cpu_per_callPARSE, EXECUTE, FETCH) gemessen werden. Das macht oft dann Sinn, wenn auf einem sehr ausgelasteten OLTP-System gelegentliche Abfragen durchgeführt werden, da diese bei Erreichen des Limits abgebrochen werden. Somit kann mit dem Befehl ALTER USER einem Benutzer für den Tagesbetrieb ein Profil mit einem niedrigen Wert und bei Nachtbetrieb mit großem oder unlimitiertem Wert zugewiesen werden. logical_reads_per_sessioncpu_per_session. Da die Menge der Datenbankblöcke, die für die Dauer einer Verbindung gelesen werden, nur schwer fassbar ist, wird dieser Wert selten gesetzt. logical_reads_per_callPARSE, EXECUTE, FETCH) festgelegt. Ebenso wie der Parameter cpu_per_call kann dieser Wert sinnvoll in Hochlastsystemen sein, um bestimmte Abfragen abzublocken. Leider wird die Abfrage zunächst aber gestartet und erst mit der Erreichung der Grenze abgebrochen.
474
Sicherheit
idle_timeatenbank anmelden und somit Ressourcen blockieren, aber nicht mit der Datenbank arbeiten. Wenn der Benutzer eine Zeit lang (im Beispiel 30 Minuten) keine Eingabe vornimmt, wird die Session als beendet gekennzeichnet. Ein Abmelden des Prozesses erfolgt jedoch erst mit der nächsten Eingabe des Benutzers, so dass hier der erzieherische Effekt im Vordergrund steht. connect_timeine geeignete Anwendung zu finden. Sicherlich kann es als erzieherische Maßnahme sinnvoll sein, dass jeder beim Nachhausegehen seine offenen Verbindungen zur Datenbank beendet, aber der gleiche Effekt kann auch mit der idle_time erzielt werden und dort, durch die Einschränkung des »Nichtstuns«, wesentlich effektiver. private_sgacomposite_limitService Units beschränkt. Damit werden sowohl CPUZeit als auch lesende Zugriffe gemessen und entsprechend gewichtet. Mit dem Befehl ALTER RESOURCE COST kann die Gewichtung eingestellt werden. Im folgenden Beispiel wird ein Profil mit dem Namen p_verwaltung erstellt. Dann wird für das composite_limit die Gewichtung eingestellt. Danach können die Benutzer das Profil über den Befehl ALTER USER zugewiesen bekommen, oder neue Benutzer können wie im Beispiel direkt das neue Profil erhalten. CREATE PROFILE p_verwaltung LIMIT SESSIONS_PER_USER 2 CPU_PER_SESSION unlimited CPU_PER_CALL 6000 LOGICAL_READS_PER_SESSION unlimited LOGICAL_READS_PER_CALL 100 IDLE_TIME 30 CONNECT_TIME 480 COMPOSITE_LIMIT 20000; ALTER RESOURCE COST CPU_PERS_SESSION 1 LOGICAL_READS_PER_SESSION 50; CREATE USER heyo IDENTIFIED BY heyo DEFAULT TABLESPACE USERS PROFILE p_verwaltung; GRANT CONNECT, RESOURCE TO heyo; Listing 9.36: Erstellen und Zuweisen eines Profils
Profile
475
9.10.2 Password-Management Neben der Limitierung von Ressourcen ist ein weiteres Thema der Profile die Überwachung von Kennwörtern. Damit existiert die Möglichkeit, ähnlich wie auf Betriebssystemebene, Vorgaben bezüglich der Passwörter zu machen. Im Gegensatz zu den Ressourcen müssen diese Parameter nicht erst über den ALTER SYSTEM-Befehl oder einen Initialisierungsparameter aktiviert werden, sondern sind immer aktiv. failed_login_attemptspassword_lock_time-Tagen oder durch den Administrator wieder freigegeben. password_lifetimePASSWORD eingegeben werden. Vorher wird der Benutzer eine Zeit lang (password_grace_time) aufgefordert, ein neues Kennwort einzugeben. password_reuse_timerwendet werden kann. password_reuse_maxpassword_reuse_time wird hiermit die Wiederverwendbarkeit eines Kennwortes geregelt. In diesem Fall wird allerdings die Anzahl der Kennwortwechsel festgelegt. Beide Parameter können nur alternativ genutzt werden. password_lock_timeeder freigegeben wird. password_grace_timefgefordert werden. Dieser Parameter ist nur in Verbindung mit password_life_time sinnvoll. password_verify_functionutlpwdmg.sql im Verzeichnis $ORACLE_HOME/rdbms/admin wird eine Routine für die Überprüfung der Komplexität eines Kennwortes mitgeliefert. Mit der Funktion verify_function wird überprüft, ob eine Mindestlänge von vier Zeichen mit mindestens einem Sonderzeichen eingegeben wurde, ob bestimmte einfache Passwörter wie z.B. »manager« eingegeben wurden und ob das Passwort sich in mindestens drei Zeichen vom vorherigen unterscheidet. @?/rdbms/admin/utlpwdmg.sql ALTER PROFILE p_verwaltung LIMIT PASSWORD_LIFE_TIME 60 PASSWORD_GRACE_TIME 5 PASSWORD_REUSE_TIME 180 PASSWORD_REUSE_MAX UNLIMITED FAILED_LOGIN_ATTEMPTS 3 PASSWORD_LOCK_TIME 7 PASSWORD_VERIFY_FUNCTION verify_function; Listing 9.37: Password-Management
Mit diesem Beispiel wird zunächst die Funktion verify_function erstellt und anschließend dem Profil p_verwaltung zusammen mit anderen Passwortmechanismen zugewiesen. Für alle Profile gilt, dass sie nur zu Beginn einer Session ausgewertet werden und somit anschließende Änderungen keine Auswirkungen auf bestehende Verbindungen haben. Eine Übersicht über die vorhandenen Profile und Einstellungen gibt die View dba_profiles. In der View dba_users kann überprüft werden, welche Benutzer wel-
ches Profil verwenden.
476
9.11
Sicherheit
Management von Ressourcen mit dem Resource Manager
9.11.1 Überblick Seit der Version 8i der Oracle-Datenbank gibt es den Database Resource Manager, mit dessen Hilfe es möglich ist, bestimmte System- und Datenbankressourcen einzelnen Benutzern sinnvoll zuzuteilen. Dadurch, dass die Zuteilung der Ressourcen über interne Mechanismen der Datenbank und nicht allein über das Betriebssystem durchgeführt werden kann, ergeben sich zusätzliche und verfeinerte Möglichkeiten für den Datenbankverwalter. Im Einzelnen lassen sich die folgenden Ressourcen hinsichtlich ihrer maximalen Nutzung vorgeben: Zuteilung von maximalen CPU-Zeiten Begrenzung des Parallelisierungsgrades für Datenbankoperationen Begrenzung der Anzahl gleichzeitig aktiver Datenbanksitzungen Vorgaben für die Nutzung von Speicherplatz in Rollback-Segmenten (undo pool) Der Database Resource Manager ergänzt derzeit noch die im vorangehenden Abschnitt besprochenen Profile und geht im Funktionsumfang weit über diese hinaus. Die bewusste Aufteilung von Ressourcen ist überall dort sinnvoll, wo eine Vielzahl von Benutzern und Anwendungen mit unterschiedlichen Anforderungen untereinander um die Nutzung von CPU-Zyklen, Rollback-Segmenten und ParallelServerprozessen konkurrieren. Der Database Resource Manager operiert im Kontext von Konsumentengruppen (Consumer Groups) und Ressourcenplänen. Für die Einstellung der Vorgaben können entweder die API-Prozeduren der PL/SQL-Pakete dbms_resource_manager und dbms_resource_manager_privs oder die grafische Oberfläche des Enterprise Managers42 genutzt werden. Zum Aufbau komplexer Umgebungen ist auf jeden Fall die Nutzung des PL/SQL-API zu empfehlen. Kleinere Verwaltungsarbeiten können dagegen komfortabel über die Oberfläche des Enterprise Managers erledigt werden. Die folgenden Arbeitsschritte sind zum Aufbau eines Ressourcenmanagements notwendig: Zunächst müssen analog zu den gegebenen Prioritäten Konsumentengruppen angelegt werden. Diesen Konsumentengruppen sind dann einzelne Benutzer oder Rollen zuzuweisen. Gleichzeitig werden Ressourcenpläne angelegt. Die Konsumentengruppen und die Ressourcenpläne werden anschließend über so genannte Direktiven miteinander verknüpft. Die Direktiven bestimmen hierbei die konkreten Vorgaben für die Nutzung der oben aufgelisteten Ressourcentypen. Es können unterschiedliche Pläne mit unterschiedlichen Anforderungen erstellt werden. Jeder Plan kann hierarchisch aufgebaut sein, d.h., er kann aus einem oder mehreren Unterplänen bestehen. Die Vorgaben der Ressourcenpläne werden allerdings erst dann wirksam, wenn der betreffende Plan aktiviert wurde. Zu einem 42 In der Version 9.0.1 des Enterprise Manager sind nicht alle Einstellungen über die grafische Oberfläche möglich.
Management von Ressourcen mit dem Resource Manager
477
bestimmten Zeitpunkt lässt sich immer nur ein Plan aktivieren, die Umschaltung auf einen alternativen Plan kann allerdings dynamisch, möglicherweise über eine Zeitsteuerung, erfolgen. Einmal aktiviert, regelt der Plan die maximale Nutzung von Ressourcen auf der Basis der Konsumentengruppen. Benutzer, welche die Vorgaben ihrer Gruppe über Gebühr beanspruchen, können dabei dynamisch im laufenden Betrieb einer alternativen Konsumentengruppe mit möglicherweise geringeren Prioritäten zugewiesen werden. Im folgenden Abschnitt wird dieses Konzept anhand eines konkretes Beispiels erläutert.
9.11.2 Der Aufbau einer Beispielumgebung Vorgaben Wir administrieren die fiktive Datenbank mit dem globalen Namen versand.ganzbillig.de. Diese Datenbank wird sowohl von OLTP-Transaktionen als auch von Batch-Programmen genutzt. Gleichzeitig testen zwei Entwicklungsteams ihre Anwendungen in separaten Schemata. In der Vergangenheit gab es immer wieder Beschwerden darüber, dass OLTP-Transaktionen, die Kundenbestellungen verwalten, aufgrund von Batch-Programmen oder Testläufen des Entwicklungsteams nicht genügend CPU-Ressourcen für die effiziente Auftragsbearbeitung zur Verfügung standen. Dies wollen wir mit Hilfe des Resource Managers optimieren. Die folgenden Regeln sollen aus diesem Grund auf Wunsch der Geschäftsleitung implementiert werden: Allen OLTP-Transaktionen sollen während der Geschäftszeiten zwischen 8 und 19 Uhr mindestens 80 % der CPU-Zeiten gesichert zur Verfügung stehen. Die restlichen 20 % sollen im Verhältnis 60 : 40 an die Entwicklungsteams team_a und team_b aufgeteilt werden. Batch-Programmen sollen während dieser Zeit nur die ungenutzten CPU-Ressourcen zufallen. Während der Nacht dagegen erhalten Batch-Programme 90 % der CPU, für die Entwicklungsteams stehen die restlichen 10 %, wieder im Verhältnis 60 : 40 zur Verfügung. OLTP-Transaktionen dagegen werden in dieser Zeit nur mit ungenutzten CPU-Zyklen abgespeist. Diese Anforderungen lassen sich wie folgt tabellarisch darstellen, wobei die »Schichtung« der oben beschriebenen Vorgaben über unterschiedliche Planungsebenen erreicht wird. Gruppe
CPU-Level 1
CPU-Level 2
CPU-Level 3
OLTP-Transaktionen
80
0
0
team_a
0
60
0
team_b
0
40
0
Batch-Programme
0
0
100
Tabelle 9.7: Tagesplan
478
Sicherheit
Gruppe
CPU-Level 1
CPU-Level 2
CPU-Level 3
OLTP-Transaktionen
0
0
100
team_a
0
60
0
team_b
0
40
0
Batch-Programme
90
0
0
Tabelle 9.8: Nachtplan
Zusätzlich zu diesen CPU-Anforderungen sollen auch weitere Vorgaben hinsichtlich des Parallelisierungsgrades und der Nutzung der Rollback-Segmente implementiert werden. Für die Entwickler soll darüber hinaus sichergestellt werden, dass nicht mehr als zehn aktive Sitzungen pro Team während des Tages existieren. Für den Fall, dass Sitzungen von Entwicklern mehr als 300 Sekunden aktiv sind, sollen sie in die Gruppe der Batch-Programme zurückgestuft werden. Privilegien erteilen Benutzer, welche die oben beschriebene Umgebung aufbauen und verwalten wollen, benötigen das Systemprivileg ADMINISTER RESOURCE MANAGER. Dieses Privileg ist bereits in der vordefinierten Rolle DBA enthalten, kann aber auch explizit mit dem folgenden Prozeduraufruf vergeben werden: BEGIN dbms_resource_manager_privs.grant_system_privilege( grantee_name => 'Guenter', privilege_name => 'ADMINISTER_RESOURCE_MANAGER', admin_option => FALSE); END; /
Im Gegensatz zu den meisten anderen Systemprivilegien kann ADMINISTER RESOURCE MANAGER nur in dieser Form und nicht über einen GRANT-Befehl zugeteilt werden. Es ist keinesfalls notwendig und auch nicht wirksam, den betreffenden Benutzern die Execute-Rechte für das Paket dbms_resource_manager zuzuteilen. Im vorangehenden Beispiel erhält der Benutzer guenter die Privilegien zur Arbeit mit dem Resource Manager. Er darf diese Privilegien allerdings nicht an Dritte weitergeben (admin_option => false). Erteilte Privilegien können über die View dba_rsrc_manager_system_privs abgefragt werden. Pending Area anlegen Einfache Ressourcenpläne, die sich nur auf die Zuteilung von CPU-Zeiten auf bis zu acht Ebenen beschränken, lassen sich vollständig über die Prozedur create_simple_ plan des Paketes dbms_resource_manager zusammen mit ihren Konsumentengruppen und Direktiven anlegen. Für komplexere Umgebungen, so wie in unserem Beispiel vorgesehen, sind unterschiedliche Prozeduraufrufe notwendig, die alle im Kontext eines Arbeitsbereiches (Pending Area) ablaufen müssen. Dieser Arbeitsbereich kann separat validiert und muss schließlich – nachdem alle Aufrufe abgesetzt werden
Management von Ressourcen mit dem Resource Manager
479
konnten – explizit übermittelt werden, um die Änderungen festzuschreiben. Der folgende Aufruf initiiert diesen Arbeitsbereich: BEGIN dbms_resource_manager.create_pending_area; END; /
Eine Validierung kann über die Prozedur validate_pendig_area, das Löschen über clear_pending_area erreicht werden, was einem Rollback gleichkommt. Sind alle Aufrufe durchgeführt worden, wird der Arbeitsbereich mit submit_pending_area aktiviert. Konsumentengruppen und Ressourcenpläne anlegen Nachdem der Arbeitsbereich initialisiert wurde, können als Nächstes die notwendigen Konsumentengruppen angelegt werden. Im folgenden Beispiel geschieht dies für die im Abschnitt Vorgaben geplanten Gruppen. Jeder Gruppe wird eine entsprechende Kommentarzeile beigefügt: BEGIN dbms_resource_manager.create_consumer_group ( consumer_group => 'OLTP', comment => 'Gruppe für OLTP-Anwendungen'); dbms_resource_manager.create_consumer_group ( consumer_group => 'Batch', comment => 'Gruppe für Batch-Anwendungen'); dbms_resource_manager.create_consumer_group ( consumer_group => 'Team_A', comment => 'Gruppe für Entwicklungsteam A'); dbms_resource_manager.create_consumer_group ( consumer_group => 'Team_B', comment => 'Gruppe für Entwicklungsteam B'); END; /
create_consumer_group bietet noch den Parameter cpu_mth (CPU-Methode), der die Strategie bei der Verteilung der CPU-Zeiten innerhalb einer Gruppe regelt. Der einzige mögliche Wert (round-robin) ist gleichzeitig auch der Standardwert und daher hier nicht explizit aufgeführt.
Ähnlich lassen sich die geplanten Ressourcenpläne anlegen: BEGIN dbms_resource_manager.create_plan ( plan => 'Tagesplan', comment => 'Plan für die Tageszeit von 8 bis 19 Uhr'); dbms_resource_manager.create_plan( plan => 'Nachtplan', comment => 'Plan für die Nacht von 19 bis 8 Uhr'); END; /
480
Sicherheit
Auch hier lassen sich über zusätzliche Parameter die Methoden für die Zuteilung der verschiedenen Ressourcenbereiche (CPU, Anzahl der aktiven Sessions, Parallelisierung und Nutzung der Warteschlange) regeln. Die eingestellten Standardwerte sind jedoch auch in diesem Fall die einzig möglichen Werte. Über die Views dba_rsrc_consumer_groups und dba_rsrc_plans können Ressourcenpläne und Konsumentengruppen ausgegeben werden. Grenzwerte vorgeben Nachdem nun die Konsumentengruppen und die Ressourcenpläne angelegt wurden, können die erforderlichen Grenzwerte definiert werden, die für bestimmte Gruppen in bestimmten Plänen gelten sollen. BEGIN dbms_resource_manager.create_plan_directive ( plan => 'Tagesplan', group_or_subplan => 'OLTP', comment => 'OLTP-Ressourcen während des Tages', cpu_p1 => 80, parallel_degree_limit_p1 => 4, undo_pool => 500000); END; /
Im vorangehenden Beispiel wird festgeschrieben, dass alle aktiven Sitzungen der Gruppe oltp im Rahmen des Planes Tagesplan zusammen maximal 80 % der CPUZeit und für jede parallelisiert ausgeführte Operation maximal vier Serverprozesse verbrauchen darf. Der Speicherplatz aller in dieser Gruppe aktiven Sitzungen darf in den Rollback-Segmenten (undo pool) 500.000 KByte nicht überschreiten. Die Gruppe oltp ist die einzige Gruppe der ersten Schicht. Die verbleibenden oder nicht genutzten Ressourcen, für den Fall, dass oltp keine aktiven Sitzungen vorzuweisen hat, werden der nächstfolgenden Schicht, in diesem Falle der Schicht 2, zugeführt. Auf diese Weise erhält die zweite Schicht in unserem Beispiel mindestens 20 %. Im folgenden Beispiel werden dementsprechend die Ressourcen für die Gruppe team_a zugeteilt. Gemäß der im Abschnitt Vorgaben vorgegebenen Planung darf
diese Gruppe von den mindestens verbleibenden 20 % CPU-Zeit der ersten »Schicht« maximal 60 % nutzen. Nicht genutzte CPU-Zeit geht auch hier an die nächstfolgende und nicht etwa an andere Gruppen derselben Schicht. Zusätzlich wird festgelegt, dass jede Sitzung dieser Gruppe maximal 300 Sekunden CPU-Zeit verbrauchen darf, bevor sie auf die Gruppe batch heruntergestuft wird. Die Herunterstufung kann auch schon dann erfolgen, wenn die Statistiken eine entsprechend lange Laufzeit erwarten (switch_estimate => true). BEGIN dbms_resource_manager.create_plan_directive ( plan => 'Tagesplan' group_or_subplan => 'Team_A', comment => 'Ressourcen für Entwicklungsteam A während des Tages', cpu_p1 => 0, cpu_p2 => 60,
Management von Ressourcen mit dem Resource Manager active_sess_pool_p1 switch_time switch_group switch_estimate parallel_degree_limit_p1 undo_pool
=> => => => => =>
481
10, 300, 'Batch', TRUE, 4, 500000);
END; /
Dementsprechend werden alle geplanten Direktiven angelegt. Es ist darauf zu achten, dass jeder Plan auch Direktiven für die vordefinierte Gruppe other_groups enthält, damit Benutzern, deren Gruppen nicht explizit in den betreffenden Plan miteingeschlossen wurden, restliche CPU-Zeiten zugeteilt werden können. In unserem Beispiel erhält diese Gruppe in der vierten Schicht alle verbleibenden CPU-Ressourcen. BEGIN dbms_resource_manager.create_plan_directive ( plan => 'Tagesplan', group_or_subplan => 'Team_B', comment => 'Ressourcen für Entwicklungsteam B während des Tages', cpu_p1 => 0, cpu_p2 => 40, active_sess_pool_p1 => 10, switch_time => 300, switch_group => 'Batch', switch_estimate => TRUE, parallel_degree_limit_p1 => 4, undo_pool => 500000); dbms_resource_manager.create_plan_directive ( plan => 'Tagesplan', group_or_subplan => 'Batch', comment => 'Ressourcen für Batch-Verarbeitung während des Tages', cpu_p1 => 0, cpu_p2 => 0, cpu_p3 => 100); dbms_resource_manager.create_plan_directive ( plan => 'Tagesplan', group_or_subplan => 'OTHER_GROUPS', comment => 'Diese Gruppe muss aufgeführt werden', cpu_p1 => 0, cpu_p2 => 0, cpu_p3 => 0, cpu_p4 => 100); -- Nachtzeit dbms_resource_manager.create_plan_directive ( plan => 'Nachtplan', group_or_subplan => 'OLTP', comment => 'Ressourcen für OLTP-Verarbeitung während der Nacht' cpu_p1 => 0,
482
Sicherheit
cpu_p2 => 0, cpu_p3 => 100); dbms_resource_manager.create_plan_directive ( plan => 'Nachtplan', group_or_subplan => 'Team_A', comment => 'Ressourcen für Entwicklungsteam A während der Nacht', cpu_p1 => 0, cpu_p2 => 60, active_sess_pool_p1 => 10); dbms_resource_manager.create_plan_directive ( plan => 'Nachtplan', group_or_subplan => 'Team_B', comment => 'Ressourcen für Entwicklungsteam B während der Nacht', cpu_p1 => 0, cpu_p2 => 40, active_sess_pool_p1 => 10); dbms_resource_manager.create_plan_directive ( plan => 'Nachtplan', group_or_subplan => 'Batch', comment => 'Ressourcen für Batch-Programme während der Nacht', cpu_p1 => 90); dbms_resource_manager.create_plan_directive ( plan => 'Nachtplan', group_or_subplan => 'OTHER_GROUPS', comment => 'Diese Gruppe muss aufgeführt werden', cpu_p1 => 0, cpu_p2 => 0, cpu_p3 => 0, cpu_p4 => 100); END; /
Pläne und Direktiven stellt die View dba_rsrc_plan_directives dar. Zum Schluss darf nicht vergessen werden, die durchgeführten Aktionen aus dem Arbeitsbereich heraus zu übertragen: BEGIN dbms_resource_manager.submit_pending_area; END; /
Konsumentengruppen und Benutzer Nachdem nun die Pläne mit Leben gefüllt wurden, müssen die Konsumentengruppen auf die Benutzer verteilt und für jeden Benutzer eine Standardgruppe definiert werden, in deren Kontext er nach dem Connect operiert. Im Einzelnen ist hierzu jedem Benutzer das Privileg zum Umschalten auf eine oder mehrere Gruppen zu erteilen, dann kann eine dieser Gruppen zur Standardgruppe gemacht werden. Die Grant-Option – falls gesetzt – ermöglich es dem Betreffenden, dieses Recht weiterzugeben:
Management von Ressourcen mit dem Resource Manager
483
BEGIN dbms_resource_manager_privs.grant_switch_consumer_group ( grantee_name => 'SCOTT', consumer_group => 'OLTP', grant_option => FALSE); dbms_resource_manager.set_initial_consumer_group( user => 'SCOTT', consumer_group => 'OLTP'); END; / BEGIN dbms_resource_manager_privs.grant_switch_consumer_group ( grantee_name => 'DEV_A', consumer_group => 'Team_A', grant_option => FALSE); dbms_resource_manager_privs.grant_switch_consumer_group ( grantee_name => 'DEV_A', consumer_group => 'BATCH', grant_option => FALSE); dbms_resource_manager.set_initial_consumer_group( user => 'DEV_A' consumer_group => 'Team_A'); END; /
Im vorangehenden Beispiel wird der Benutzer dev_a den Konsumentengruppen team_a und batch zugeteilt. Seine Standardgruppe wird team_a, auf batch wird er umgesetzt, falls – wie oben beschrieben – seine CPU-Zeiten zu hoch liegen. Die Prozeduraufrufe dieses Abschnittes lassen sich im Übrigen direkt, ohne Initialisierung eines Arbeitsbereiches, durchführen. Die View dba_rsrc_consumer_group_ privs gibt Auskunft über die erteilten Privilegien. Pläne aktivieren Nun sind alle Pläne und Gruppen wie geplant angelegt worden. Die Überprüfung der angegebenen Grenzwerte erfolgt jedoch erst dann, wenn ein Plan aktiviert wird. Diese Aktivierung kann entweder über den Serverparameter resource_manager_plan oder dynamisch über den Befehl ALTER SYSTEM erfolgen. Im folgenden Beispiel wird der Plan Tagesplan aktiviert: ALTER SYSTEM SET resource_manager_plan = 'TAGESPLAN';
Die in unserem Beispiel geforderte Umschaltung um 19 Uhr lässt sich leicht mit Hilfe eines Datenbankjobs und der Prozedur dbms_resource_manager.switch_plan erreichen. v$rsrc_plan gibt den jeweils aktiven Plan und seine Unterpläne aus.
484
Sicherheit
9.11.3 Monitoring Im laufenden Betrieb lassen sich Statistiken über die tatsächliche Verteilung der CPU-Zeiten über die View v$rsrc_consumer_group abrufen: SELECT name, active_sessions, consumed_cpu_time FROM v$rsrc_consumer_group; NAME ACTIVE_SESSIONS CONSUMED_CPU_TIME -------------------------------- --------------- ----------------TEAM_A 1 11091 TEAM_B 0 0 BATCH 1 106606 OTHER_GROUPS 0 1002 OLTP 2 283984
Der hohe CPU-Anteil der Gruppe batch in diesem Beispiel wurde dadurch verursacht, dass die Sitzung der Gruppe team_a erst später startete.
9.12
Auditing
Die beste Sicherheitstechnik ist nutzlos, wenn nicht überprüft werden kann, ob sie auch funktioniert. Somit muss es (auch nach den Bestimmungen des NCSC C2Standards) eine Möglichkeit geben, die Nutzung von Privilegien zu protokollieren und auszuwerten. Mit Auditing können die drei Bereiche Objekte, Kommandos und Privilegien überwacht werden, und somit ist es möglich, von fehlerhaften Anmeldungen bis zu Abfragen auf bestimmte Tabellen oder sogar nur bestimmte Spalten alle Informationen zu protokollieren. Diese Protokollierung kann natürlich bei übermäßigem Gebrauch zu einer Performance-Verschlechterung führen. Außerdem muss darauf geachtet werden, dass die gesammelte Information von Zeit zu Zeit gelöscht wird, da das Auditing ein zwingender Vorgang ist. Kann zum Beispiel das »Session Login« nicht mehr überwacht werden, weil die Audit-Tabelle in der Datenbank voll ist (maximale Anzahl Extents erreicht oder Ähnliches), dann ist es für einen Standardbenutzer nicht mehr möglich, sich anzumelden. Gleiches gilt auch für die Überwachung von DML-Befehlen, d.h., unter Umständen steht eine Anwendung, weil kein Protokoll mehr geschrieben werden kann. Generell sollte Auditing nur verwendet werden, wenn ein Grund zur Annahme besteht, dass Missbrauch betrieben wird oder es nur sehr wenige Operationen, z.B. den Zugriff auf bestimmte Tabelleninformationen, betrifft. Es ist über das BefehlsAuditing möglich, die zu protokollierenden Aktionen auf ganz bestimmte Zeilen oder Spalten einer Tabelle zu beschränken.
Auditing
485
9.12.1 Zwanghaftes Auditing Das Starten und Stoppen von Instanzen und Datenbanken sowie die Authentifizierung von Benutzern der Rollen sysdba und sysoper gehören zu den Operationen, die ohne Ausnahme immer protokolliert werden. Neben der bekannten ALERTDatei steht zu diesem Zweck das Unterverzeichnis $ORACLE_HOME/rdbms/audit zur Verfügung43. Die Audit-Einträge werden dort in eine einzelne Datei mit Namen ora_.aud geschrieben, wobei für die Prozessnummer des betreffenden Serverprozesses steht. Das oben genannte Audit-Verzeichnis kann über den Systemparameter audit_file_dest angepasst werden. Das folgende Fragment enthält einen Ausschnitt aus einer Audit-Datei: Instance name: test10 Redo thread mounted by this instance: 1 Oracle process number: 10 Unix process pid: 4892, image: oracle@NandaDevi (TNS V1-V3) Mon Sep 5 09:18:06 2005 ACTION : 'CONNECT' DATABASE USER: '/' PRIVILEGE : SYSDBA CLIENT USER: oracle CLIENT TERMINAL: pts/1 STATUS: 0 Listing 9.38: Ausschnitt aus der Audit-Datei ora_4892.aud
Für das Auditing von weiteren Aktionen, die unter dem Benutzer SYS oder den Rollen sysoper oder sysdba ablaufen, steht der Serverparameter audit_sys_operations zur Verfügung, der wie folgt aktiviert werden kann: ALTER SYSTEM SET audit_sys_operations=TRUE SCOPE=SPFILE;
Für diesen Parameter ist – aus Sicherheitsgründen – ein Neustart der Instanz erforderlich. In der Folge werden dann alle Aktionen, die über SQL- oder PL/SQLBefehle ausgeführt werden, in dem oben genannten Audit-Verzeichnis und dort in eigenen Dateien protokolliert. Das folgende Beispiel zeigt einen kleinen Ausschnitt dieser Datei: Mon Sep 5 14:54:04 2005 ACTION : 'select to_char(taddr) from sys.v_$session where audsid = userenv('SESSIONID')' DATABASE USER: 'SYS' PRIVILEGE : SYSDBA CLIENT USER: Administrator CLIENT TERMINAL: STATUS: 0 Listing 9.39: Auditing von SYS-Operationen
43 Unter Windows werden Audit-Sätze dieser Art in das Event-Log geschrieben.
486
Sicherheit
9.12.2 Aktivieren von Auditing Zur Nutzung des Auditings sind – mit Ausnahme der im vorangehenden Abschnitt genannten Fälle – zwei Schritte notwendig: Erstens muss der DBA über den Systemparameter audit_trail die Datenbank für das Auditing vorbereiten, zweitens muss konfiguriert, werden, welche Aktionen oder Statements im Rahmen des Auditings protokolliert werden sollen. Für den ersten Schritt ist ein Neustart der Instanz notwendig, der zweite Schritt kann im laufenden Betrieb unternommen werden. Der Parameter audit_trail kann die folgenden Werte haben: os – speichert die Audit-Protokolle über das Betriebssystem. db oder true – speichert die Protokolle in der Datenbank, dort in der SYS-Tabelle aud$.
db_extended – ist eine Neuerung unter der Version 10g, speichert in der Datenbank wie db oder true, legt aber zusätzlich noch die genutzten SQL-Befehle sowie die Werte der darin enthaltenen Bindevariablen in den Spalten SQLBIND und SQLTEXT der Tabelle aud$ ab. none oder false – (der Standardwert) schaltet das Auditing aus. Die Konfiguration dessen, was protokolliert werden soll, erfolgt dann mit dem Befehl: AUDIT
Als Optionen gelten: BY SESSION / BY ACCESS WHENEVER SUCCESSFUL / WHENEVER NOT SUCCESSFUL Ausgeschaltet werden kann das Auditing, wenn es nicht über die Änderung des Initialisierungsparameters audit_trail erfolgt, über den Befehl: NOAUDIT
Beim Auditing auf Betriebssystemebene (audit_trail=os) gibt es Unterschiede zwischen MS-Windows und anderen (z. B. Unix oder VMS). Bei Unix gibt es den Initialisierungsparameter audit_file_dest, der angibt, in welches Verzeichnis die AuditDateien geschrieben werden sollen (standardmäßig ist dies das Verzeichnis $ORACLE_HOME/rdbms/audit). Das Verzeichnis sollte also überwacht werden, da es stark anwachsen kann. Bei MS-Windows gibt es diesen Parameter nicht, sondern alle Audit-Informationen werden an die Ereignisanzeige übergeben und sind über das Anwendungsprotokoll einsehbar. Das Auditing in der Datenbank legt alle Informationen im Schema SYS in der Tabelle aud$ ab. Diese Tabelle wird bei der Erstellung der Datenbank angelegt und gehört zum internen Data Dictionary. Diese Tabelle ist die einzige des Data Dictionarys, die mit DML-Befehlen geändert werden darf, da nur hierüber die alten Einträge gelöscht werden können. Bei einem umfangreichen Gebrauch dieser Tabelle ist es zu empfehlen – was ebenfalls nur für diese Tabelle erlaubt ist –, die Storage-Klauseln zu ändern44. Zwar ist als Standardeinstellung PCTINCREASE 50 und MAXEXTENTS 256
Auditing
487
gesetzt, so dass nicht davon auszugehen ist, dass es zu einem Fehler aufgrund fehlender Extents kommt, der SYSTEM-Tablespace kann aber durch diese Einstellung stark anwachsen. Es empfiehlt sich also zum Beispiel folgende Änderung: ALTER TABLE aud$ STORAGE (NEXT 1M PCTINCREASE 0 MAXEXTENTS 100)
Unabhängig davon, ob das Auditing ein- oder ausgeschaltet ist, gibt es jeweils Protokolle für das Hoch- und Herunterfahren der Datenbank sowie das Login als SYSDBA oder SYSOPER. Diese Information wird immer auf Betriebssystemebene abgelegt, da beim Hochfahren der Datenbank ja noch keine Tabellen zur Verfügung stehen. Unter MS-Windows wird dabei jeder Prozess in der Ereignisanzeige eingetragen, was dazu führt, dass bei häufigem Hoch- und Herunterfahren der Datenbank dieses Protokoll stark anwächst.
9.12.3 Kommando-Auditing Das Kommando-Auditing befasst sich mit der Überwachung einzelner Kommandos oder Kommandogruppen, die zu einem bestimmten Bereich der Datenbank gehören. Hiermit kann z.B. überprüft werden, ob eine Einschränkung von Benutzern auf eine PL/SQL-Schnittstelle eingehalten wird. Die Protokollierung von Kommandooperationen im Administrationsbereich (ALTER SYSTEM) kann für die Rekonstruktion von Problemsituationen interessant sein. Der einfachste Fall für ein Kommando-Auditing ist der Befehl: AUDIT SESSION;
Damit wird jeder Login und jeder Logout an der Datenbank mitprotokolliert. Da dies für eine große Datenbank bzw. eine umfangreiche Anzahl von Benutzern unübersichtlich wird, wird in vielen Fällen ein Schemaname mitgegeben. AUDIT SESSION BY gerd, anna;
Dieser Befehl schränkt die Protokollierung auf die Benutzer gerd und anna ein. Das folgende Beispiel zeigt die Ausgabe der View dba_audit_trail. SQL> SELECT os_username, username, terminal, timestamp, action_name, returncode FROM dba_audit_trail; OS_USERNAM USERNAME TERMINAL TIMESTAM ACTION_NAME RETURNCODE ---------- ---------- ---------- -------- ------------ ---------jahrends GERD HLLAP33 10.09.01 LOGON 1017 jahrends ANNA HLLAP33 10.09.01 LOGOFF 0 jahrends GERD HLLAP33 10.09.01 LOGON 0 Listing 9.40: Kommando-Auditing
Der RETURNCODE 1017 gibt die Oracle-Fehlermeldung an, sie kann über oerr ora 1017 oder in der Dokumentation nachgelesen werden. In diesem Fall handelt es sich um den Fehler invalid username/password; logon denied. Neben den hier dargestellten Spalten ist noch die Spalte comment_text interessant, da hier die Netzwerkkonfiguration abgespeichert wird. 44 Der Tablespace darf nicht geändert werden, da dies bei Upgrades zu Problemen führen könnte.
488
Sicherheit
Insgesamt gibt es 144 mögliche Kommando-Auditing-Befehle, angefangen beim UNKNOWN bis zum ALTER OPERATOR, so dass hiermit alle möglichen DDL-Befehle überwacht werden können. Eine komplette Liste kann in der View audit_actions nachgesehen werden. Die Abfrage der eingestellten Audit-Funktionen erfolgt über die View dba_stmt_ audit_opts.
9.12.4 Privilegien-Auditing Mit dem Kommando-Auditing steht die Objektart im Vordergrund, z.B. werden mit dem Befehl AUDIT TABLE alle DDL-Befehle bezüglich der Erstellung, Änderung oder Löschung einer Tabelle überwacht. Beim Privilegien-Auditing kann hingegen eine einzelne Operation, für die z. B. das Privileg CREATE ANY TABLE notwendig ist, gezielt überwacht werden. In einem uns bekannten Beispiel existierte das Problem, dass bestimmte Views immer wieder gelöscht wurden. Durch ein gezieltes Auditing (AUDIT DROP VIEW) konnte das Problem gefunden und beseitigt werden. Da eine Überschneidung zwischen dem Kommando-Auditing und dem PrivilegienAuditing besteht, existieren zwar zwei Views, dba_priv_audit_opts und dba_stmt_ audit_opts, der Inhalt ist jedoch identisch. Mit der Tabelle system_privilege_map können die möglichen Audit-Optionen abgefragt werden.
9.12.5 Objekt-Auditing Während Kommando- und Privilegien-Auditing die generelle Nutzung von Befehlen und Rechten ohne Objektbezug überwachen, ist mit dem Objekt-Auditing die gezielte Überwachung bestimmter Objekte möglich. Damit können Zugriffe auf bestimmte Objekte oder DML-Operationen überwacht werden. Über die weitere Einschränkung BY <user> und BY ACCESS ist es möglich, die anfallende Menge an Informationen einzuschränken. Mit dem Befehl AUDIT INSERT, UPDATE, DELETE ON demo.kunden ist es möglich, die Verwendung von DML-Operationen zu überwachen, z.B. weil sichergestellt werden soll, dass nur über eine PL/SQL-Funktion auf diese Tabelle zugegriffen wird. SQL> SELECT terminal, username, timestamp#, owner, action_name, returncode FROM dba_audit_trail; TERMINAL USERNAME TIMESTAM OWNER ACTION_NAME RETURNCODE -------- -------- -------- ------ ----------- ---------HLLAP33 ANNA 11.09.01 DEMO INSERT 2004 HLLAP33 GERD 11.09.01 DEMO UPDATE 0 Listing 9.41: Objekt-Auditing
Auditing
489
Die Fehlermeldung ORA-02004 security violation im Falle einer insert-Operation des Benutzers anna ist ein spezieller Eintrag in die Audit-Trail-Tabelle, der Benutzer bekommt die Meldung ORA-00942: Table or view does not exist zurückgeliefert. Die eingestellten Objektüberwachungen können mit der View dba_obj_audit_opts überprüft werden.
9.12.6 Fine-Grain-Auditing Das generelle Auditing von Objekten kann unter Umständen zu aufwändig bzw. zu unübersichtlich sein. Als Beispiel sei eine Kundentabelle genannt, die natürlich alle relevanten Informationen des Kunden enthält, vielleicht aber auch seine Liquidität. Diese darf – und so ist es in der Anwendung auch implementiert – nur von bestimmten Personen eingesehen und geändert werden. Genutzt wird die Tabelle natürlich von sehr vielen Anwendungen. Hier ist es also nur interessant zu protokollieren, welche Zugriffe auf die Spalte liquiditaet erfolgten. Für diesen Zugriff gibt es ein Datenbankpaket dbms_fga, mit dem es möglich ist, eine Spalte oder eine Bedingung mitanzugeben. BEGIN dbms_fga.add_policy( object_schema => 'DEMO', object_name => 'KUNDEN2', policy_name => 'CHECK_LIQ', audit_condition => 'LIQUIDITAET > 400000', audit_column => 'LIQUIDITAET'); END; / SQL> SELECT timestamp#, dbuid, osuid, obj$schema, obj$name, policyname, sqltext FROM sys.fga_log$; TIMESTAM DBUID OBJ$SCHEMA OBJ$NAME POLICYNAME SQLTEXT -------- ------ ---------- -------- ---------- -------------11.09.01 DEMO DEMO KUNDEN2 CHECK_LIQ select * from kunden2 11.09.01 DEMO DEMO KUNDEN2 CHECK_LIQ select nachname, vorname from kunden2 where liquiditaet = 100000 Listing 9.42: Fine-Grain-Auditing
Die Information kann dann über die Tabelle sys.fga_log$ abgefragt werden. Diese mit der Version 9i eingeführte Variante des Auditings ermöglicht ein viel gezielteres Überwachen von Statements inklusive Abfragen. Ab der Version 10g ist diese Art des Auditings für alle DML-Befehle zulässig. Mit weiteren Prozeduren des Packages dbms_fga kann das Auditing an- oder ausgeschaltet bzw. gelöscht werden.
490
Sicherheit
9.12.7 Audit-Trigger Neben den beschriebenen Verfahren des Auditings darf die Verwendung von Triggern zur Überwachung nicht vergessen werden. Durch den Einbau eines Triggers auf eine Tabelle kann zum Beispiel jede DML-Operation in einer anderen Tabelle mit Datum, Uhrzeit, Benutzer und anderen Informationen festgehalten werden. Im Folgenden werden alle alten Werte der Tabelle kunden mit dem Benutzer und dem Systemdatum festgehalten. CREATE TABLE audit_kunden ( kdnr NUMBER (10) NOT NULL, anrede_alt VARCHAR2 (5), vorname_alt VARCHAR2 (50), nachname_alt VARCHAR2 (50), adresse_alt VARCHAR2 (50), ort_alt VARCHAR2 (50), plz_alt NUMBER (6), telefon_alt VARCHAR2 (20), benutzer VARCHAR2(10), systemdatum DATE); CREATE OR REPLACE TRIGGER audit_kunden AFTER INSERT OR DELETE OR UPDATE ON kunden FOR EACH ROW BEGIN INSERT INTO audit_kunden VALUES ( :new.kdnr, :old.anrede, :old.vorname, :old.nachname, :old.adresse, :old.ort, :old.plz, :old.telefon, user, sysdate ); END; Listing 9.43: Trigger-Auditing
Dies ist sicher ein einfaches Beispiel, erlaubt es aber, alle relevanten Informationen in einer eigenen separaten Tabelle abzulegen. Es ist jedoch nicht möglich, in dieser Form auf SELECT-Anweisungen zu reagieren.
Auditing
491
9.12.8 Empfehlungen Die beim Auditing zur Verfügung stehenden Optionen erlauben die Beobachtung der Datenbankaktivität in verschiedenen Stufen. Die Granularität der Beobachtungen sollte sich dabei an den Anforderungen ausrichten: Generell sollten sie mit sehr allgemeinen Optionen beginnen, so dass der Einfluss auf die Performance gering bleibt und wenig Platz verwendet wird. Erst wenn konkrete Verdachtsmomente für einen unbefugten Zugang zum System vorliegen, sollten aufwändigere Optionen eingeschaltet werden. Im Datenbankkonzept sollte zunächst eine Strategie zum Auditing festgelegt werden, die dann konkret in eine Audit-Konfiguration umgesetzt wird. Die Strategie sollte auch Maßnahmen festlegen, wie bei der Entdeckung von nicht zulässigen Zugriffen verfahren werden soll. In vielen Unternehmen wird es außerdem notwendig sein, Audit-Konzepte mit Unternehmensgremien wie z.B. dem Betriebsrat abzustimmen. Besonders dann, wenn nicht nur versuchte Eingriffe ins System oder nicht gestattete Operationen, sondern auch die tägliche Arbeit eines Anwenders nachvollzogen werden können, kann es zu Konflikten mit den Betriebsvereinbarungen kommen.
Wiederherstellungstechniken Die Sicherung von Oracle-Datenbanken gehört sicherlich zum Standardrepertoire eines Datenbankadministrators. Bedingt durch diese immer wiederkehrende Aktion hat sich bei vielen Oracle-Spezialisten ein bestimmtes Vorgehen eingeschliffen, das in einigen Fällen auf Erfahrungen aus der Oracle-Zeit der Version 6 herrührt. Damals gab es zum Teil hitzige Diskussionen über Online- oder Offline-Backups, Export und Import von Daten, Sicherung auf Band oder Festplatte oder die generelle Aktivierung der Oracle-Redo-Log-Archivierung. Leider gab es zu dieser Zeit von Oracle und auch später keine Werkzeuge bzw. technische Unterstützung für die Sicherung – alle Sicherungsverfahren beruhten im Wesentlichen auf mehr oder weniger optimalen Skripten. Nicht wenige Datenbanken werden noch heute nach dem Verfahren gesichert: Instanz herunterfahren und entsprechendes Laufwerk sichern. Dieses Vorgehen birgt große Gefahren in sich: Datenbanken werden immer größer und somit die Zeit für die Sicherung immer länger. Da die Datenbank während der Sicherung nicht zur Verfügung steht, besteht die Gefahr, dass während der Sicherung die Datenbank wieder gestartet werden muss. Weitaus größer ist allerdings das Risiko, nicht alle Datenbankdateien zu sichern, weil z.B. aus Platzmangel Datenbankdateien auf andere Platten gelegt wurden, die im Backup-Skript nicht enthalten sind. Wenn man dann noch die Frage stellt, wann denn das letzte Mal eine Sicherung überprüft, d.h., wieder eingespielt wurde, dann bekommt man eventuell zur Antwort: »Als wir die Datenbank damals neu aufgebaut haben.«
10.1
Planung
10.1.1 Generelles Für die Planung einer Sicherungs- und Wiederherstellungsstrategie müssen folgende Punkte beachtet werden: Welche Server-Hardware wird benutzt? Auf welchem Medium wird gesichert? Gibt es Redundanzen? Wie schnell muss die Datenbank wieder zur Verfügung stehen? Wie groß sind Gefahren durch fehlerhafte Anwendungen?
494
Wiederherstellungstechniken
Wie groß ist die Datenbank? Welche Komponenten müssen zusätzlich gesichert werden? Gibt es Abhängigkeiten zu anderen Systemen? Wann wird was gesichert?
10.1.2 Hardware Zur Server-Hardware zählt im Wesentlichen die eingesetzte Speicherarchitektur, z.B. die Spiegelung der Festplatten. Aber natürlich spielt auch die Anzahl der CPUs und die Bandbreite des I/O-Systems eine entscheidende Rolle. Es muss darauf geachtet werden, dass die Sicherung den normalen Betrieb nicht zu sehr stört. Sicherungsmedium Wenn über Sicherungen nachgedacht wird, denkt man zunächst natürlich an die Bandsicherung. Sicherlich ist es sinnvoll, mit diesem Verfahren eine Historisierung der Sicherungen zu betreiben; allerdings sind Bandsicherungen oft problematischer als alleinige Absicherung, da die Rücksicherung zumindest bei großen Datenbanken zu viel Zeit in Anspruch nimmt. Ähnliches gilt für optische Medien. Immer häufiger trifft man daher auf mehrstufige Verfahren, bei denen zunächst auf weitere Festplatten gesichert wird – natürlich möglichst physisch unabhängig von den Festplatten, auf denen die Datenbankdateien liegen. Von diesem Sicherungsplattenpool aus werden dann weitere Sicherungen, z.B. auf Bändern, angefertigt. Dieses Verfahren kann auch indirekt betrieben werden, indem man die Sicherungen z.B. auf einer Schattendatenbank, die auf Redo-Log-Shipping basiert, durchführt. Auch der Recovery Manager unterstützt solche indirekten Verfahren.
10.1.3 Archivierung Wie Sie schon im Kapitel 3 erfahren haben, sind die wichtigsten Dateien der Datenbank die Redo-Log-Dateien, da in diesen alle Transaktionsinformationen hinterlegt sind. Wenn es also um die Verfügbarkeit eines Systems geht, dann ist es die primäre Aufgabe eines Datenbankadministrators, dafür zu sorgen, dass keine abgeschlossenen Transaktionen verloren gehen. Dies wird zunächst über die Spiegelung der Redo-Log-Dateien geschehen, zusätzlich ist es aber notwendig, jede Redo-LogDatei zu sichern. Mit dieser Sicherung, im Oracle-Umfeld Archivierung genannt, lässt sich jede abgeschlossene Transaktion als roll forward aus einer Sicherung wieder herstellen. Das gilt sowohl für Sicherungen einer nicht aktiven (offline) als auch einer aktiven (online) Datenbank. Diese Archivierung der Redo-Log-Dateien bilden somit die notwendige Grundlage für jede Art der Online-Sicherung.
Planung
495
Man könnte jetzt auf die Idee kommen, die Archivierung mit Betriebssystemmitteln durchzuführen. Hierbei sind aber folgende Punkte zu beachten: Eine zyklisch beschriebene Redo-Log-Datei darf erst dann überschrieben werden, wenn der alte Inhalt archiviert worden ist. Wenn eine Archivierung nicht mehr möglich ist, z.B. weil kein Platz mehr im Filesystem zur Verfügung steht, darf keine Transaktion mehr durchgeführt werden, da sonst ein Datenverlust bei Fehlern droht. Da diese Punkte vom Betriebssystem kaum bewältigt werden können, bietet Oracle die optionale Konfiguration der Archivierung aus der Datenbank heraus. Dabei sorgen ein oder mehrere Archivierungsprozesse dafür, dass mit dem Logswitch die beschriebene Redo-Log-Datei in ein anderes Verzeichnis kopiert wird. Das bedeutet, dass es im Wesentlichen zwei Parameter für die Archivierung gibt: Soll archiviert werden oder nicht? Der Name der Datei bzw. des Verzeichnisses, in das archiviert werden soll. 1. Zu bedenken gibt es allerdings, dass das Archivierungsverzeichnis nicht mehr zum Oracle-Datenbankkontext gehört, d.h. aus der Oracle-Datenbank heraus nicht administriert bzw. überwacht werden kann. 2. Eine Ausnahme bildet hierbei die in Oracle 10g eingeführte Flash-Recovery Area, die später noch näher besprochen wird. Archivierung aktivieren Die Aktivierung erfolgt in zwei Schritten. Zunächst wird über Initialisierungsparameter festgelegt, wohin die Dateien gesichert werden bzw. wie die Dateien heißen sollen. Dafür stehen folgende Parameter zur Verfügung: 1. log_archive_dest Dieser seit der Version 6 gültige Parameter setzt das Verzeichnis und optional ein Präfix des Dateinamens für die Archivierung. Beispiel: log_archive_dest = F:\oracle\archive\WIN10G\
2. log_archive_dest_1 bis log_archive_dest_10 Diese Parameter sind nur in der Enterprise Edition erlaubt. Im Unterschied zu log_archive_dest werden sie immer als Zeichenkette angegeben, da sie aus verschiedenen Optionen und Werten zusammengesetzt sind. Man beachte, dass die Angabe eines Verzeichnisses über die LOCATION-Option erfolgt. Neben einem Verzeichnis kann hier auch ein Net-Aliasname angegeben werden, so dass eine Archivierung über Oracle Net auf eine andere Datenbank möglich ist. Dies wird für Schattendatenbanken mit Data Guard genutzt. Daneben sind zusätzliche Parameter möglich, wie z.B. ob diese Archivierung zwingend (MANDATORY) oder nur optional (OPTIONAL) ist. Das bietet sich dann an, wenn aus Verfügbarkeitsgründen mehrfach archiviert wird.
496
Wiederherstellungstechniken
Beispiel: log_archive_dest_1 = 'LOCATION=/ora_arch/LINUX10G/ MANDATORY' log_archive_dest_2 = 'SERVICE = STDY10G OPTIONAL REOPEN=60'
Weitere Parameter sind für die Data-Guard-Funktionalität möglich und werden im entsprechenden Kapitel besprochen. Die gleichzeitige Verwendung von log_archive_dest und log_archive_dest_n ist nicht möglich. 3. log_archive_dest_state_1 bis log_archive_dest_state_10 Für diese Parameter gibt es drei unterschiedliche Werte: – ENABLE (Standardwert):
Der Parameter wird benutzt.
– DEFER:
Ist belegt, wird aber (noch) nicht benutzt.
– ALTERNATE:
Wird benutzt, wenn eine andere Lokation nicht benutzt werden kann.
4. log_archive_duplex_dest Für die Standard Edition ist es mit diesem Parameter möglich, eine doppelte Archivierung (allerdings nur lokal) aufzusetzen. 5. log_archive_format Dateiformat der archivierten Redo-Log-Dateien. Folgende Parameter können gesetzt werden: – %s bzw. %S:
Log-Sequenznummer (groß, 8-stellig)
– %t bzw. %T:
Instanz-Thread-Nummer (groß, 4-stellig)
– %a:
Activation-ID der Datenbank
– %d:
Datenbank-ID (nicht ORACLE_SID)
– %r:
Reset-Logs-ID
Die Parameter %s, %t und %r, optional in der Großbuchstabenvariante, sollten grundsätzlich angegeben werden! Beispiel: log_archive_format = 'log_%t_%S_%r.arc'
6. log_archive_max_processes [1 … 10] Maximale Anzahl der Archivierungsprozesse 7. log_archive_min_succeed_dest [1 … 10] Bei mehrfacher Archivierung kann hierdurch gesteuert werden, wann eine Online-Redo-Log-Datei wiederverwendet werden kann. D.h., wenn dieser Parameter auf 2 steht, aber auf drei unterschiedliche Lokationen (log_archive_dest_1, log_archive_dest_2, log_archive_dest_3) gesichert wird, kann es vorkommen, dass die Archivierung auf eine der drei Lokationen noch nicht beendet ist, die Redo-Log-Datei aber dennoch überschrieben wird. Dies ist z.B. dann sinnvoll, wenn eine Lokation über ein Netzwerk angebunden ist, das keine hohe Verfügbarkeit hat.
Planung
497
Der nächste Schritt ist dann die eigentliche Aktivierung des Archivierens. Hierfür muss die Instanz heruntergefahren und im Mount-Status gestartet werden. Nur in diesem Zustand kann die Archivierung aktiviert oder deaktiviert werden. Die komplette Aktivierung der Archivierung kann also wie folgt aussehen: SQL> SQL> SQL> SQL> SQL> SQL>
ALTER SYSTEM SET log_archive_dest_1 = 'LOCATION = /app/oracle/ora_arch/LINUX10G/'; ALTER SYSTEM SET log_archive_format = 'log_%t_%S_%r.arc' scope = spfile; SHUTDOWN IMMEDIATE; STARTUP MOUNT; ALTER DATABASE ARCHIVELOG; ALTER DATABASE OPEN;
Listing 10.1: Aktivierung der Archivierung
Wichtig ist, dass die Datenbank konsistent heruntergefahren wird (also mit der Option NORMAL, IMMEDIATE oder TRANSACTIONAL), ansonsten kann die Archivierung nicht aktiviert werden. Tipp: Setzen Sie immer ans Ende der Zeichenfolge für das Archivierungsziel ein »/« bzw. »\«. Damit vermeiden Sie, wenn das Verzeichnis nicht existiert, dass die archivierten Redo-Log-Dateien im übergeordneten Verzeichnis landen. Bei der Festlegung des Namens wird der Dateiname einfach durch eine Konkatinierung von Destination und Format erstellt. Wichtig ist dies vor allen Dingen bei Unix-Systemen, wenn als Archivierungsverzeichnis ein Mount-Point benutzt wird. Überprüfen der Archivierung Zunächst bietet es sich an, nach dem Einschalten der Archivierung die Funktion zu testen. Am einfachsten geschieht dies durch einen Logswitch. Dabei wird jede Online-Redo-Log-Gruppe einmal archiviert. Im Beispiel für 3 Online Redo-Log-Gruppen wird also folgender Befehl ausgeführt: SQL> ALTER SYSTEM SWITCH LOGFILE; SQL> ALTER SYSTEM SWITCH LOGFILE; SQL> ALTER SYSTEM SWITCH LOGFILE; Listing 10.2: Testen der Archivierung
Nach dem dritten Logswitch sollte der SQL-Prompt nach kurzer Zeit wieder erscheinen. Ansonsten wird in der Alert-Datei ein entsprechender Eintrag protokolliert. Folgende Befehle zeigt die Informationen der Archivierung: SQL> SELECT archiver FROM v$instance; ARCHIVE ------STARTED Listing 10.3: Archiver gestartet
498
Wiederherstellungstechniken
SQL> SELECT log_mode FROM v$database; LOG_MODE -----------ARCHIVELOG Listing 10.4: Archivierung aktiviert
Über SQL*Plus kann, wenn man mit AS SYSDBA angemeldet ist, auch folgender Befehl ausgeführt werden: SQL> ARCHIVE LOG LIST; Datenbank-Log-Modus Archive-Modus Automatische Archivierung Aktiviert Archivierungsziel /app/oracle/ora_arch/JAUX10G/ Älteste Online-Log-Sequenz 75 Nächste zu archivierende Log-Sequenz 77 Aktuelle Log-Sequenz 77 Listing 10.5: Archivierungsinformation
Überprüfen kann man die archivierten Redo-Log-Dateien über die View v$archived_log z.B. in der Form: SQL> SELECT name, sequence#, archived, completion_time, ROUND((blocks*block_size)/1024/1024) MByte FROM v$archived_log WHERE completion_time > sysdate - 1; NAME SEQUENCE# ARC COMPLETION_TIME MBYTE -------------------------------------------------- ---------- --- ------------------- ---------E:\ORA_ARCH\JA10G\LOG_1_00157_522936157.ARC E:\ORA_ARCH\JA10G\LOG_1_00158_522936157.ARC E:\ORA_ARCH\JA10G\LOG_1_00159_522936157.ARC D:\ORACLE\ORAARCH\JA10G\LOG_1_00160_522936157.ARC D:\ORACLE\ORAARCH\JA10G\LOG_1_00161_522936157.ARC D:\ORACLE\ORAARCH\JA10G\LOG_1_00162_522936157.ARC D:\ORACLE\ORAARCH\JA10G\LOG_1_00163_522936157.ARC D:\ORACLE\ORAARCH\JA10G\LOG_1_00164_522936157.ARC E:\ORA_ARCH\JA10G\LOG_1_00165_522936157.ARC E:\ORA_ARCH\JA10G\LOG_1_00166_522936157.ARC E:\ORA_ARCH\JA10G\LOG_1_00167_522936157.ARC
157 158 159 160 161 162 163 164 165 166 167
YES YES YES YES YES YES YES YES YES YES YES
21.05.2004 21.05.2004 21.05.2004 21.05.2004 21.05.2004 21.05.2004 21.05.2004 21.05.2004 21.05.2004 21.05.2004 21.05.2004
17:21:04 17:21:10 17:21:13 17:22:39 17:22:40 17:22:41 17:24:33 17:24:37 17:25:48 17:25:53 17:25:56
10 10 10 10 10 10 10 10 10 10 10
Listing 10.6: Überprüfung der archivierten Redo-Log-Dateien
Hier
sieht
man,
dass
temporär
die
Archivierung
in
das
Verzeichnis
D:\oracle\oraarch\JA10G erfolgte. Vorher und nachher wurde das Verzeichnis E:\ora_arch\JA10G gewählt.
Planung
499
Ressourcenproblemlösung Die laufende Archivierung kann anhand der Redo-Log-Dateien abgefragt werden. Hierdurch ist es frühzeitig möglich zu erkennen, ob ein Ressourcenproblem vorliegt, also bevor die Instanz stehen bleibt. SQL> SELECT group#, sequence#, bytes, archived, status FROM v$log; GROUP# SEQUENCE# BYTES ARCHIVED STATUS ---------- ---------- ---------- ---------- ---------------1 149 10485760 NO CURRENT 2 148 10485760 NO ACTIVE 3 147 10485760 NO INACTIVE Listing 10.7: Überprüfung Archivierung
Der Wert »NO« in der Spalte archived gibt an, dass keine der Online-Redo-LogDateien archiviert worden ist. Das bedeutet, so lange, bis die Redo-Log-Datei mit status »CURRENT« noch Platz für weitere Redo-Log-Daten hat, haben Sie Zeit für eine Überprüfung der Archivierung – danach sind keine weiteren Transaktionen mehr möglich. Das Verzeichnis der archivierten Redo-Log-Dateien kann, wie das Beispiel zeigt, im laufenden Betrieb geändert werden. Damit kann, wenn ein Verzeichnis voll ist, auf ein anderes Verzeichnis umgeschaltet werden. Das dabei angegebene Verzeichnis muss allerdings vorher existieren. Ansonsten erhalten Sie die Fehlermeldung: ORA-02097: ORA-16032: ORA-09291: OSD-04018: O/S-Error:
Parameter kann nicht verändert werden, da angegebener Wert ungültig ist Zielzeichenfolge von Parameter LOG_ARCHIVE_DEST_1 kann nicht übersetzt werden sksachk: Ungültiges Verzeichnis für Archivierungsziel angegeben Auf das angegebene Verzeichnis oder Gerät kann nicht zugegriffen werden. (OS 2) Das System kann die angegebene Datei nicht finden.
Listing 10.8: Fehlerhaftes Archivverzeichnis
Hier ein MS-Windows-Beispiel: Ein Anwender meldet das Problem, dass ein DML-Befehl nicht beendet wird. Ein Abbruch bleibt ohne Erfolg. Alternativ meldet eine Monitoring-Software, dass es neue Fehlermeldungen in der Alert-Datei gibt. Eine Überprüfung der Alert-Datei bringt folgende Information: ARC1: Archiving not possible: No primary destinations ARC1: Failed to archive log 1 thread 1 sequence 127 (4) Fri May 21 16:19:43 2004 ARC0: Evaluating archive log 1 thread 1 sequence 127 Fri May 21 16:19:43 2004 Errors in file d:\oracle\admin\ja10g\bdump\ja10g_arc1_3420.trc: ORA-16014: Log 1 Sequenz-Nr. 127 nicht archiviert, keine verfügbaren Ziele ORA-00312: Online-Log 1, Thread 1: 'D:\ORACLE\ORADATA\JA10G\REDO01.LOG' Listing 10.9: Fehlermeldung in der Alert-Datei
500
Wiederherstellungstechniken
Als Lösung könnte man die archivierten Redo-Log-Dateien löschen. Aber Vorsicht, wenn dann die Datenbank einen Fehler produziert, fehlen Ihnen für eine Wiederherstellung die notwendigen archivierten Redo-Log-Dateien. Besser ist es zu schauen, ob auf einer anderen Platte bzw. einem anderen Filesystem noch ausreichend Platz ist, und dann die Archivierung auf dieses Verzeichnis umzuhängen. Dies geschieht im Beispiel durch folgenden Befehl: SQL> ALTER SYSTEM SET log_archive_dest_1 = 'LOCATION=D:\oracle\oraarch\JA10G\'; Listing 10.10: Neues Archivierungsverzeichnis
In der Alert-Datei stellt sich das wie folgt dar: ARC1: Evaluating archive log 1 thread 1 sequence 127 Fri May 21 16:19:46 2004 Committing creation of archivelog 'D:\ORACLE\ORAARCH\JA10G\LOG00128_0522936157_001.arc' Archiver process freed from errors. No longer stopped Fri May 21 16:19:48 2004 Private_strands 7 at log switch Thread 1 advanced to log sequence 130 Current log# 2 seq# 130 mem# 0: D:\ORACLE\ORADATA\JA10G\REDO02.LOG Fri May 21 16:19:49 2004 Committing creation of archivelog 'D:\ORACLE\ORAARCH\JA10G\LOG00127_0522936157_001.arc' Fri May 21 16:19:49 2004 Listing 10.11: Wiederanlauf der Archivierung
Jetzt kann das alte Archivverzeichnis gesichert werden, die archivierten Redo-LogDateien werden gelöscht, und zum Schluss wird die Archivierung wieder auf das alte Verzeichnis zurückgesetzt. Vergessen Sie aber nicht, die archivierten Redo-Log-Dateien des temporären Verzeichnisses auch noch zu sichern oder in das alte Verzeichnis zu kopieren. Enterprise Manager Alternativ kann die Konfiguration auch über den Enterprise Manager durchgeführt werden. Bild 10.1 zeigt die Übersichtsinformation über die Archivierung (in diesem Fall ausgeschaltet).
Abbildung 10.1: Übersicht Archivierung und Flashback
Planung
501
Wenn man den Hyperlink »Deaktiviert« anwählt, kommt man in ein zweites Menü, in dem die Archivierung eingeschaltet und konfiguriert werden kann (siehe Bild 10.2)
Abbildung 10.2: Einschalten der Archivierung
Das Archive-Log-Ziel log_archive_dest_10 ist standardmäßig mit dem Initialisierungsparameter USE_DB_RECOVERY_FILE_DEST vorbelegt. Das bedeutet, wenn Sie bei der Installation der Datenbank eine Flash-Recovery Area angegeben haben, wird automatisch in dieses Verzeichnis archiviert (siehe auch Kapitel 10.1.4).
10.1.4 Flash-Recovery Area In den Oracle-Versionen vor 10g gab es eine strikte Trennung zwischen Datendateien und Sicherungen. Das bedeutet auch, dass das Verzeichnis, in das die archivierten Redo-Log-Dateien gesichert werden, nicht zur Datenbank gehört und somit nicht mit Datenbankmitteln überprüft werden kann. Trotzdem ist dieses Verzeichnis kritisch, da die Datenbank keine Transaktionen mehr zulässt, wenn dieses Verzeichnis voll ist.
502
Wiederherstellungstechniken
Mit Version 10g führt Oracle einen zusätzlichen Datenbankbereich – die FlashRecovery Area – ein, der für unterschiedliche Zwecke genutzt werden und damit auch die Verwaltung der archivierten Redo-Log-Dateien übernehmen kann. Dieser Bereich wird über zwei Variablen parametriert: db_recovery_file_dest legt das Verzeichnis fest. Es sollte sich hierbei immer um ein eigenes Filesystem handeln. db_recovery_file_dest_size gibt die maximale Größe des von Oracle kontrollierten Verzeichnisinhalts an. Der Füllgrad bzw. das Vorhandensein dieses Verzeichnisses wird jetzt von der Datenbank aus kontrolliert, und bei entsprechenden Schwellenwerten wird ein Eintrag in der Alert-Datei generiert. Das Verzeichnis kann jetzt für folgende Aktionen genutzt werden: Archivierung Sicherung der Datenbank Flashback Database Aus diesen Informationen kann leicht die benötigte Größe des Verzeichnisses und damit der Parameter db_recovery_file_dest_size bestimmt werden: Anzahl noch nicht gesicherter archivierter Redo-Log-Dateien Anzahl notwendiger Backup-Sets (Retention) Flashback-Größe Für jede der oben genannten Aktionen werden automatisch eigene Unterverzeichnisse generiert. Außerdem wird darunter wiederum ein Verzeichnis für jeden Tag angelegt. Folgendes Beispiel zeigt die Nutzung der Flash-Recovery Area. Dabei wurde die Archivierung eingeschaltet, jedoch nicht der Parameter log_archive_dest bzw. log_archive_dest_n gesetzt. SQL> ALTER SYSETM SET db_recovery_file_dest = '/oraflash'; SQL> ALTER SYSTEM SET db_recovery_file_dest_size = 1G; SQL> SELECT * FROM v$recovery_file_dest; NAME SPACE_LIMIT SPACE_USED SPACE_RECLAIMABLE NUMBER_OF_FILES --------------- ----------- ---------- ----------------- --------------/oraflash 1073741824 882509824 3872768 31 Listing 10.12: Flash-Recovery-Area-Parameter und Abfrage
Die archivierten Redo-Log-Dateien heißen jetzt: /oraflash/JAUX10G/archivelog/2004_08_06/o1_mf_1_1_0k75gyfc_.arc /oraflash/JAUX10G/archivelog/2004_08_06/o1_mf_1_2_0k75tjg1_.arc Listing 10.13: Archivierte Redo-Log-Dateien in der Flash-Recovery Area
Sicherung und Wiederherstellung
503
Es wird schon in diesem einfachen Fall deutlich, dass mit der Zeit einige Verzeichnisse entstehen werden, und auch die Namen der archivierten Redo-Log-Dateien (Oracle Managed Files) sind gewöhnungsbedürftig. Wenn jetzt eine Sicherung mit dem Recovery Manager durchgeführt wird, wird standardmäßig auch diese in die Flash-Recovery Area geschrieben (siehe folgendes Kapitel). Obwohl die Flash-Recovery Area auch für die Standard Edition gesetzt werden kann, ist es nicht möglich, die archivierten Redo-Log-Dateien in dieses Verzeichnis zu sichern, da die Parameter log_archive_dest bzw. log_archive_duplex_dest für die Flash-Recovery Area nicht benutzt werden können.
10.2
Sicherung und Wiederherstellung
Bei der Wiederherstellung einer Datenbank unterscheidet man zwischen dem Rücksichern der Datenbankdateien und dem Wiederherstellen des Datenbankinhalts. Beim Rücksichern werden die betroffenen Dateien (Daten-, Kontroll-, Redo-LogDateien) aus einer physikalischen Sicherung heraus an die entsprechende Stelle eingespielt. Die Dauer dieser Aktion ist also ausschließlich von der I/O-Zeiten (Festplatte, Controller, Bandlaufwerk) abhängig. Bei der Wiederherstellung wird über die Informationen aus den Redo-Log-Dateien zunächst ein roll forward aller Transaktionen durchgeführt. Da in den Redo-LogDateien auch nicht abgeschlossene Transaktionen gespeichert werden, erfolgt danach ein Rollback aller offenen Transaktionen. Die hierzu notwendigen Informationen sind in den Undo-Segmenten vorhanden, die durch den roll forward ebenfalls wiederhergestellt worden sind. Im Folgenden sollen die Schritte dargestellt werden, die im Fehlerfall vom Datenbankadministrator durchzuführen sind. Das Oracle-System bietet vielfältige Möglichkeiten der Wiederherstellung, die in den meisten Fällen alternativ angewendet werden können. In der Regel wird man die Variante wählen, welche die kürzeste Ausfallzeit der Datenbank bei größter Fehlertoleranz mit sich bringt. Dazu ist, trotz der sicherlich herrschenden Eile im Fehlerfall, eine genaue Fehleranalyse notwendig, um die geeignete Strategie zur Wiederherstellung festlegen zu können. Verschiedene Fehlerfälle, die in der Praxis sicherlich auch in Kombination auftreten, werden anschließend mit entsprechenden Lösungen erläutert.
504
Wiederherstellungstechniken
10.2.1 Fehleranalyse Um das Ziel der schnellstmöglichen Fehlerbehebung zu erreichen, dürfen nur die Komponenten der Datenbank zurückgespielt werden, die auch tatsächlich durch einen Plattenfehler oder einen Anwenderfehler beschädigt worden sind. Dazu bedarf es einer eingehenden Fehleranalyse. Der Datenbankadministrator wird einen Fehler sehr wahrscheinlich vom Anwender gemeldet bekommen. Die Qualität der Fehlermeldung kann dabei sehr unterschiedlich sein, von »die Datenbank läuft nicht mehr« bis zu einer konkreten Oracle-Fehlermeldung. Aufgabe des DBA ist es nun zu überprüfen, ob die Datenbank noch läuft, ob eventuell »nur« Probleme mit dem Archivieren aufgetreten sind oder aber tatsächlich eine Beschädigung einer Platte vorliegt. Prinzipiell kann man davon ausgehen, dass bei einem Plattenfehler eine entsprechende Fehlermeldung in der Alert-Datei der Datenbank existiert und z.B. über die Enterprise-Manager-Konsole angezeigt wird.
Abbildung 10.3: Fehlermeldung im Enterprise Manager
Wenn man den entsprechenden Link anwählt, erhält man einen Auszug aus der Alert-Datei mit allen relevanten Fehlereinträgen.
Abbildung 10.4: Auszug aus der Alert-Datei
Sicherung und Wiederherstellung
505
In diesem Beispiel ist zu erkennen, dass die Datei /oradata/JAUX10G/ts_demo01.dbf korrupt ist. Als Nächstes muss herausgefunden werden, warum dieser Fehler aufgetreten ist. Der Ausfall einer Festplatte ist wesentlich leichter zu beheben als die in diesem Fall aufgetretene Korruption einer Datei. In diesem Fall muss zunächst eine eingehende Untersuchung des Filesystems (in dem vielleicht noch andere Datenbankdateien liegen) erfolgen. Erst wenn diese Untersuchung ein Resultat liefert (z.B. Fehler des I/O-Controllers, Festplattenfehler oder logischer Fehler), kann eine entsprechende Lösung erfolgen (z.B. eine neue Festplatte einbauen, Dateien auf ein anderes Filesystem verschieben oder durch Einschränkung von Rechten im Dateisystem dafür sorgen, dass kein Benutzer unbeabsichtigt eine Datenbankdatei zerstören kann). Wenn die Instanz nicht mehr zur Verfügung steht und eine Platte ausgefallen ist, muss herausgefunden werden, welche Komponenten auf dieser Platte lagen. Sobald die Instanz in den Status MOUNT gestartet werden kann, kann dies über die Views v$datafile und v$tablespace geschehen. Bei einem laufenden System können fehlerhafte Tablespaces auch über die View v$recover_file geprüft werden. Ein weiterer Anlass für die Wiederherstellung einer Datenbank kann ein Anwenderfehler oder ein Programmfehler sein. So könnte zum Beispiel versehentlich eine Tabelle gelöscht worden sein. Da es sich hierbei um logische Fehler handelt, ist eine Lösung in diesem Fall komplexer. Für die reine Wiederherstellung der Datenbank werden durch die Flashback-Funktionalität und den LogMiner entsprechende Hilfsmittel bereitgestellt.
10.2.2 Wiederherstellungsstrategie Ist der Fehler eingekreist, kann eine Wiederherstellungsstrategie festgelegt werden. Dafür sind folgende Punkte zu berücksichtigen: 1. Welche Teile der Datenbank müssen von Band zurückgespeichert werden? 2. Ist von diesen Komponenten der Tablespace SYSTEM oder ein Tablespace mit aktiven Undo-Segmenten betroffen? 3. Sind alle Voraussetzungen für eine vollständige Wiederherstellung gegeben? 4. Soll eine vollständige Wiederherstellung durchgeführt werden, oder muss die Datenbank auf einen früheren Zeitpunkt zurückgesetzt werden? 5. Können Teile der Datenbank auf einen früheren Zeitpunkt zurückgesetzt werden? Nach der Beantwortung dieser Fragen kann die Wiederherstellung gestartet werden. Verschiedene Fehlerfälle werden im Folgenden behandelt, wobei immer nur der Verlust einzelner Komponenten besprochen wird. Da es in der Praxis häufig zu Kombinationen dieser Fehler kommt, muss die Wiederherstellung auf die Komponente der Datenbank ausgerichtet werden, welche die meisten Einschränkungen mit sich bringt. Um die Datenbank möglichst schnell wieder verfügbar zu machen, auch wenn eventuell ein einzelner Tablespace dann noch nicht zugreifbar ist, kann sich auch eine Wiederherstellung in mehreren Schritten anbieten.
506
Wiederherstellungstechniken
10.2.3 Instanzwiederherstellung, Prozess- und Netzwerkfehler Das Oracle-System besitzt interne Mechanismen, die eine Wiederherstellung einer Datenbank nach Fehlersituationen wie Stromausfall, Netzwerkfehler oder Absturz eines einzelnen Prozesses automatisch bereinigen. Der Hintergrundprozess SMON ist für die Konsistenz der Datenbank insgesamt verantwortlich. Nach einem Systemabsturz, egal ob durch Stromausfall, Fehlbedienung oder Hardware-Fehler bedingt, ist es beim Neustart des Oracle-Systems Aufgabe des SMON, Inkonsistenzen festzustellen und automatisch eine Instanzwiederherstellung durchzuführen. Dazu werden zunächst in der »Roll Forward Phase« alle Transaktionen aus den noch nicht abgeschlossenen Redo-Log-Dateien nachzufahren. Anschließend wird die Datenbank geöffnet und steht wieder zur Verfügung. Noch offene Transaktionen werden als dead gekennzeichnet und im Folgenden in der »Rollback Phase« durch den SMON oder einen Benutzerprozess, der auf entsprechende Einträge trifft, zurückgerollt. In der Alert-Datei stellt sich dieser Vorgang wie folgt dar: ALTER DATABASE OPEN Sat May 22 14:47:55 2004 Beginning crash recovery of 1 threads Sat May 22 14:47:56 2004 Started first pass scan Sat May 22 14:47:56 2004 Completed first pass scan 2256 redo blocks read, 413 data blocks need recovery Sat May 22 14:47:56 2004 Started redo application at Thread 1: logseq 125, block 17823, scn 0.0 Recovery of Online Redo Log: Thread 1 Group 2 Seq 125 Reading mem 0 Listing 10.14: Alert-Eintrag für Instanzwiederherstellung
Der Hintergrundprozess PMON übernimmt diese Aufgabe für einzelne Serverprozesse. Sollte der Vordergrundprozess eines Anwenders abbrechen, z.B. durch eine »allgemeine Schutzverletzung ...«, wird dieser Fehler durch den Prozess PMON entdeckt. PMON terminiert den Serverprozess, offene Transaktionen werden zurückgerollt, und Sperren auf Datensätzen werden aufgehoben. Das gleiche Verfahren deckt in Verbindung mit der Dead Connection Detection von Oracle Net auch die Problematik abgebrochener Netzwerkverbindungen ab. Bei den hier beschriebenen Fehlertypen ist also keine weitere Aktivität des Datenbankadministrators nötig, sondern die Wiederherstellung wird automatisch durchgeführt.
Sicherung und Wiederherstellung
507
10.2.4 Wiederherstellung von Medienfehlern Der Begriff Wiederherstellung von Medienfehlern beschreibt die Wiederherstellung von Datenbanken oder einzelnen Dateien nach Beschädigung einer Platte bzw. einer Datenbankdatei. In diesen Fällen muss oft zunächst ein Hardware-Fehler behoben werden, und dann müssen über ein Restore die fehlenden oder fehlerhaften Dateien aus einer Sicherung zurückgelesen werden. Alternativ kann eine Wiederherstellung auf ein anderes Filesystem bzw. eine andere Festplatte erfolgen. Nachdem die Dateien zurückgespielt worden sind, kann dann die entsprechende Wiederherstellung durchgeführt werden. Zu diesen Medienfehlern gehören: Verlust von Dateien eines Daten-Tablespaces oder des SYSAUX Tablespaces Der Verlust der Dateien eines Daten-Tablespaces führt nicht zum Absturz der Instanz, jedoch wird ein Anwender, der auf Daten aus diesem Tablespace zugreift, eine Fehlermeldung bekommen, die einen Schreib-/Lesefehler für die Datei anzeigt. Ähnliches gilt für das SYSAUX-Tablespace. Jobs, wie zum Beispiel die automatische Generierung von Statistikinformationen, werden fehlschlagen, und diese Information wird in der Alert-Datei protokolliert. Die Wiederherstellung des Tablespace kann im laufenden Betrieb des OracleSystems durchgeführt werden. Anwendungen, die auf andere Bereiche der Datenbank zugreifen, können dabei ohne Einschränkung weiterarbeiten. Die Wiederherstellung kann für den kompletten Tablespace oder eine spezifische Datendatei erfolgen. Verlust von Dateien eines Index-Tablespaces Prinzipiell ist es für ein Restore und Recovery unerheblich, ob es sich um Daten oder Indizes handelt. Dennoch kann es u.U. bei einem Index-Tablespace sinnvoller sein, den Tablespace neu anzulegen und die Indizes mit den entsprechenden »CREATE INDEX«-Befehlen neu anzulegen. Dafür müssen natürlich die entsprechenden Skripte vorhanden sein. Verlust von Dateien des SYSTEM-Tablespaces Der Tablespace SYSTEM beinhaltet das Data Dictionary und damit zentrale Informationen, ohne die ein Oracle-System nicht lauffähig ist. Die Instanz ist so nicht mehr nutzbar und wird, so sie noch nicht von einem internen Prozess beendet wurde, durch ein SHUTDOWN ABORT heruntergefahren. Nachdem die Datenbank wieder gemountet wurde (STARTUP MOUNT), kann eine Wiederherstellung auf Tablespace- oder Datendateiebene durchgeführt werden. Anschließend kann die Datenbank wieder geöffnet werden. Verlust von Dateien des Undo-Tablespace Dieser Tablespace ist ebenso kritisch wie der SYSTEM-Tablespace. Hinzu kommt, dass Fehler in diesem Tablespace leicht zu einer Korruption der gesamten Datenbank führen können. Nur über die Informationen der Undo-Segmente kann ein fehlerfreies Rollback offener Transaktionen durchgeführt werden.
508
Wiederherstellungstechniken
Prinzipiell gilt für den Undo-Tablespace die gleiche Vorgehensweise wie beim SYSTEM-Tablespace. Da der Tablespace offene Undo-Segmente enthält, ist eine Fehlerbehebung im laufenden System nicht möglich. Die Datenbank muss heruntergefahren und die Wiederherstellung im Mount-Status durchgeführt werden. Verlust der Online-Redo-Log-Dateien Der Verlust der Online-Redo-Log-Dateien ist einer der schlimmsten Fälle. Die Instanz stürzt ab, da der LGWR-Prozess Informationen aus dem Log-Puffer nicht mehr auf Platte schreiben kann. Alle Transaktionen, die in einer aktiven Redo-Log-Datei protokolliert sind, gehen verloren. Es ist einer der Fälle, die zu einer unvollständigen Wiederherstellung der Datenbank führen. Werden lediglich so viele Member aus Redo-Log-Gruppen verloren, so dass jede Gruppe noch mindestens ein verbleibendes und intaktes Member hat, zählt dies nicht unmittelbar als Verlust – die Instanz wird weiter funktionieren, und die Datenbank bleibt konsistent. Erst wenn eine Gruppe vollständig verloren ist, tritt der hier betrachtete Worst Case ein. Fehlermeldung z.B.: Tue Jun 1 10:26:03 2004 Errors in file /app/oracle/admin/JAUX10G/bdump/jaux10g_lgwr_3143.trc: ORA-00316: log 1 of thread 1, type 26997 in header is not log file ORA-00312: online log 1 thread 1: '/oradata/JAUX10G/redo01.log' Tue Jun 1 10:26:03 2004 LGWR: terminating instance due to error 316 Instance terminated by LGWR, pid = 3143
Zur Vermeidung dieses Falles ist es, wie bei der Vorbereitung der Datenbank beschrieben, unbedingt anzuraten, die Redo-Log-Dateien entweder mit OracleMitteln (mehrere Member pro Gruppe) oder über das Betriebssystem bzw. Controller zu spiegeln. Verlust der archivierten Redo-Log-Dateien Der Verlust der archivierten Redo-Log-Dateien ist zunächst nicht kritisch. Diese werden ja nur für den Fall gebraucht, dass die Datenbank durch Beschädigung einer Komponente wiederhergestellt werden muss. Kritisch würde die Situation, wenn zudem Teile der Datenbank beschädigt würden. Bemerkt wird diese Beschädigung wahrscheinlich durch einen Stillstand der Datenbank, da ein Archivierungsprozess ARCn nicht mehr in sein Verzeichnis schreiben kann. Die Platte sollte so schnell wie möglich instand gesetzt werden. In der Zwischenzeit kann die Archivierung auf eine andere Platte umgeleitet werden. SQL> alter system set log_archive_log_dest_1 = 'LOCATION=/oraarch2/JAUX10G/arch/';
Kein Stillstand tritt auf, wenn die Archivierung gespiegelt und die minimale Anzahl der erfolgreichen Destinationen nicht unterschritten wird oder nicht mandatorische Destinationen ausfallen.
Sicherung und Wiederherstellung
509
Sollte zu dem Verlust der archivierten Redo-Log-Dateien noch eine Beschädigung der Datenbank hinzukommen, kann nur eine unvollständige Wiederherstellung ausgeführt werden, da dann keine ununterbrochene Kette seit der letzten Sicherung mehr verfügbar ist. Aus diesem Grunde muss sofort eine Sicherung der Datenbank angestoßen werden, sobald die Archivierung umgeleitet ist oder die Archivierungsplatte ersetzt wurde.
10.2.5 Anwenderfehler Anwenderfehler sind aus Sicht der Wiederherstellung sehr problematisch. Bezeichnet wird damit das unbeabsichtigte Löschen, Ändern oder Hinzufügen von Tabellen oder Datensätzen. Je nachdem, ob und wie die Datenbank auf die Wiederherstellung vorbereitet ist, ist ein solcher Fehler schneller oder langsamer zu beheben. Es muss aber immer damit gerechnet werden, dass sich durch diesen Fehler logische Inkonsistenzen ergeben. Als Beispiel sei eine Anwendung genannt, welche die Anwendungslogik vollständig in einem Applikationsserver abbildet und daher in der Datenbank auf die Verwendung von Constraints verzichtet (z.B. SAP/R3). Das unbeabsichtigte Leeren einer Tabelle (TRUNCATE TABLE) kann nur über eine Rücksicherung der Tabelle wieder hergestellt werden. Dieses Backup ist jedoch nicht zeitaktuell, so dass abhängige Tabellen unter Umständen Einträge haben, die auf nicht mehr existierende Daten dieser Tabelle verweisen. Bei diesem Beispiel wird wieder einmal deutlich, wie wichtig die Verwendung von Constraints ist. Die Lösung des Problems hängt im Wesentlichen von der Zeit und den zur Verfügung stehenden Ressourcen ab. Fehlerhafte Batch-Jobs Bei Batch-Jobs (inklusive Spezialfällen von Batch-Jobs wie Datenmodell-Upgrades) kann es zu schwer korrigierbaren Fehlern kommen. Oft weiß man schon im Vorfeld, dass diese Gefahr besteht. Daher empfiehlt es sich, in diesem Fall vorsorglich Exports der betroffenen Tabellen zu machen oder Kopien an anderer Stelle in der Datenbank. In diesem Fall ist eine Rücksicherung sehr einfach durch ein RENAME möglich und der alte Zustand schnell wieder hergestellt. Die weiter unten besprochene Flashback-Database-Funktion kann hier ebenfalls weiterhelfen. Anwenderfehler DML-Operationen Der Zustand von Datensätzen vor DML-Operationen wird im Undo-Tablespace für eine gewisse Zeit in Form der Before Images gespeichert, so dass über die Flashback-Table-Funktion der alte Zustand wieder hergestellt werden kann. Sind die Daten nicht mehr im Undo-Tablespace, kann alternativ der LogMiner benutzt werden, um die Daten aus den Redo-Log-Dateien zu lesen.
510
Wiederherstellungstechniken
Anwenderfehler DROP TABLE Mit Oracle 10g wird mit dem Befehl DROP TABLE die Tabelle in der Regel nicht gelöscht, sondern umbenannt, und landet im Recyclebin. Wie beim Papierkorb von MS-Windows steht die Tabelle damit weiterhin zur Verfügung und kann über die Flashback-Table-Funktion wieder hergestellt werden. Anwenderfehler TRUNCATE TABLE Dieser Befehl wird zurzeit nicht über den Recyclebin abgesichert, so dass in diesem Fall, genau wie bei einem DROP TABLE ohne Recyclebin, eine aufwändige Wiederherstellung durchgeführt werden muss. Das kann z.B. ein TablespacePoint-in-Time-Recovery, ein Flashback-Database oder aber der Export der Tabelle aus einer Clone-Datenbank sein. Die Verfahren für Flashback-Database und Tablespace-Point-in-Time-Recovery werden im Folgenden beschrieben.
10.3
Der Recovery Manager
Nachdem Oracle viele Jahre keinerlei Werkzeuge für die Sicherung der Datenbank mitgeliefert hatte, gibt es seit Oracle8 den Recovery Manager.1 Mit ihm ist es möglich, alle relevanten Datendateien aus der Sicht der Datenbank heraus zu sichern und wiederherzustellen. Dabei unterstützt er alle möglichen Konfigurationen, z.B. Online- oder Offline-Sicherung, inkrementelle Sicherung, vollständige Wiederherstellung (bis zur letzten Transaktion) sowie unvollständige Wiederherstellung. Bedient wird der Recovery Manager über eine grafische Erweiterung des Enterprise Managers oder über das Kommandozeilenwerkzeug rman, das sich auch für die Batch-Verarbeitung über die crontab unter Unix oder den MS-Windows-AT-Befehl eignet. Die Eingabe von Kommandos erfolgt entweder interaktiv oder in Form von Skripten, die beim Aufruf mit dem Parameter CMDFILE angegeben werden können. Zur Verarbeitung stehen dann diverse Kommandos zum Erstellen und Zurückspielen von Sicherungen, für die Wiederherstellung, zum Abgleich der gespeicherten Informationen über Datenbankdateien mit der Situation auf dem Server sowie zur Erstellung von Listen und Berichten zur Verfügung. Ursprünglich wurden Kommandos zur Sicherung bzw. Rücksicherung immer in RUN-Blöcke zusammengefasst, die alle erforderlichen Aktionen zusammengefasst haben. Durch die Möglichkeit, diverse Optionen mit CONFIGURE-Befehlen für den Standardfall festzulegen, reduziert sich die Durchführung solcher Aktionen in den allermeisten Fällen auf einen einzigen Befehl. Da eine Blockstruktur hier keinen Sinn mehr macht, wird der RUNBlock denn auch als optional angesehen. Eine Eingabe von Befehlen wie STARTUP, SHUTDOWN und ALTER DATABASE ist ebenfalls im Recovery Manager möglich.
1
Das mit Oracle7 eingeführte Enterprise Backup Utility erwähnen wir absichtlich nur am Rande.
Der Recovery Manager
511
Die Sicherung erfolgt entweder auf die Festplatte oder über eine Media Management Library (MML2) auf ein Bandgerät. Es wird von Oracle hierfür der Legato Networker in einer Application Specific License (ASL3) mitgeliefert. Diese Version ist eingeschränkt dadurch, dass z.B. ausschließlich lokal angeschlossene Bandlaufwerke unterstützt werden. Der entscheidende Vorteil des Recovery Managers gegenüber selbst geschriebenen Sicherungsmethoden (Shell-Skripte usw.) ist zum einen die Integration in die Oracle-Datenbank, d.h., es werden alle datenbankrelevanten Informationen direkt aus den Kontrolldateien gelesen und zum anderen die Schnittstelle zur Sicherungssoftware. Dadurch kann zum Beispiel nach der erfolgreichen Sicherung der archivierten Redo-Log-Dateien ein automatisches Löschen dieser Dateien veranlasst werden. Außerdem ermöglicht der Recovery Manager die Online-Sicherung einer Datenbank, ohne die einzelnen Tablespaces in den BEGIN BACKUP-Modus setzen zu müssen. Erreicht wird dies durch eine Checksumme für die einzelnen Datenbankblöcke, so dass eine Konsistenz jederzeit gewährleistet ist. Das aufwändige Full Block Logging, das gerade in großen Datenbanken für erheblich mehr Redo-Log-Informationen sorgt, entfällt somit.
Abbildung 10.5: Recovery-Manager-Architektur
2 3
MML = Media Management Library, eine Laufzeitbibliotheken zur Ansteuerung von Media-ManagementWerkzeugen, wie Tivoli Storage Manager mit Tivoli Data Protection for Oracle, Legato Networker usw. ASL = Application Specific License ist die Lizenzierung eines Produktes nur für einen ganz bestimmten Einsatz.
512
Wiederherstellungstechniken
10.3.1 Architektur Die Sicherung und das Wiedereinspielen einer Datenbank oder von Teilen davon geschieht mit dem Befehl rman und zusätzlichen Parametern. Als Kommandozeile kann dieser Befehl von jedem Client aus gestartet werden, in der Regel wird er jedoch auf dem gleichen System gestartet, auf dem die zu sichernde Datenbank liegt. Alternativ kann über den Oracle Enterprise Manager das Werkzeug BACKUPMANAGEMENT aufgerufen werden, und über die mitgelieferten Wizards können dann unterschiedliche Konfigurationen durchgeführt werden. Für eine einfache Sicherung einer Oracle-Datenbank, die sich im Archive-LogModus befindet, ist der Enterprise Manager allerdings zu aufwändig. Hier genügt die Eingabe: rman target system/manager@<SID> RMAN> BACKUP DATABASE PLUS ARCHIVELOG DELETE INPUT; Listing 10.15: Recovery-Manager-Sicherung einer einfachen Datenbank
Damit wird die gesamte Datenbank inklusive der angefallenen archivierten RedoLog-Dateien in zwei Backup-Sets (eines für die archivierten Redo-Log-Dateien und eines für die Datenbankdateien) gesichert, und es können beliebige Teile wieder hergestellt werden. Als Target (Ziel) wird dabei die Datenbank bezeichnet, von der ein Backup durchgeführt werden soll. Die Anmeldung an die entsprechende Datenbank erfolgt automatisch mit dem Systemprivileg SYSDBA. Durch die DELETE INPUTKlausel werden alle archivierten Redo-Log-Dateien nach der Sicherung automatisch gelöscht. Da während des Backups der Datenbank an dieser auch Strukturänderungen durchgeführt werden können, muss vom Recovery Manager sichergestellt werden, dass es einen definierten Zustand zum Sicherungszeitpunkt gibt. Dies erfolgt durch eine Kopie der Kontrolldatei als Snapshot-Kontrolldatei. Standardmäßig ist der Name der Snapshot-Kontrolldatei %ORACLE_HOME%\DATABASE\SNCF.ora unter MSWindows und $ORACLE_HOME/dbs/snapcf_.f unter Unix; dieser kann über den Befehl CONFIGURE SNAPSHOT CONTROLFILE NAME TO ... geändert werden. Damit ist für die Dauer der Sicherung bekannt, welche Datenbankdateien, Kontrolldateien, Online- und archivierten Redo-Log-Dateien zur Datenbank gehören. Außerdem enthält die Kontrolldatei Informationen über die Historie des Recovery Managers, um zum Beispiel eine inkrementelle Sicherung durchzuführen. Die Informationen über zu sichernden Dateien, aber auch über bereits gesicherte archivierte Redo-Log-Dateien, erhält der Recovery Manager in diesem Fall aus den Kontrolldateien. Da bei der ersten Sicherung oftmals nicht alle archivierten RedoLog-Dateien vorhanden sind (weil sie z.B. aufgrund von Platzmangel gelöscht wurden), ist es erforderlich, zunächst eine Prüfung der noch vorhandenen archivierten Redo-Log-Dateien vorzunehmen. Dies geschieht mit dem Befehl: RMAN> CROSSCHECK ARCHIVELOG ALL; Listing 10.16: Überprüfung der vorhandenen archivierten Redo-Log-Dateien
Der Recovery Manager
513
Damit wird ein Abgleich der Backup-Informationen in den Kontrolldateien hergestellt. Voraussetzungen Um eine Datenbank mit dem Recovery Manager sichern zu können, muss es möglich sein, sich mit dem SYSDBA-Privileg an der Datenbank anzumelden. Das bedeutet, dass für Anmeldungen über Oracle Net der Serverparameter remote_login_passwordfile auf exclusive oder shared gesetzt sein muss, und es muss eine Passwortdatei existieren. In der zu sichernden Datenbank wird dann einem Benutzer (z.B. SYSTEM) mit dem Befehl GRANT SYSDBA TO SYSTEM das SYSDBA-Recht zugewiesen. Damit kann man sich mit dem Recovery Manager an der entsprechenden Datenbank anmelden, zum Beispiel mit dem Befehl: rman TARGET system/manager@SUNDB
Der Aufruf des Recovery Managers lokal unter einem privilegierten Benutzer (Mitglied der Gruppe dba unter Unix oder Mitglied der Gruppe ORA_DBA unter Windows) funktioniert wie folgt: % rman taget / Listing 10.17: Lokaler Recovery-Manager-Aufruf
Der Recovery Manager ist abwärtskompatibel, d.h., Sie können mit dem Recovery Manager der Version 10 ältere Datenbanken sichern, nicht jedoch mit dem Recovery Manager der Version 9 eine Oracle 10g-Datenbank. Was wird gesichert? Mit dem Recovery Manager können verschiedene Objekte einer Datenbank entweder als einzelnes Objekt oder in einem Backup-Set gesichert werden. Je nach Verfahren (online oder offline, full oder incremental, Datafile-Copy oder Backup-Set) werden damit mehr oder weniger Dateien erstellt, die entweder auf eine andere Platte oder auf ein Bandlaufwerk gesichert werden. In den meisten uns bekannten Unternehmen wird die Datenbank insgesamt gesichert, und zusätzlich werden von Zeit zu Zeit die archivierten Redo-Log-Dateien und die Kontrolldateien gesichert. Es kann aber auch Szenarien geben, in denen es Sinn macht, Teile der Datenbank zu unterschiedlichen Zeiten zu sichern, also zum Beispiel einen sehr kritischen Tablespace einmal täglich, aber den Rest der Datenbank wöchentlich. Folgende Befehle stehen für das Backup zur Verfügung: RMAN> RMAN> RMAN> RMAN> RMAN> RMAN> RMAN> RMAN>
BACKUP BACKUP BACKUP BACKUP BACKUP BACKUP BACKUP BACKUP
ARCHIVELOG ALL; CURRENT CONTROLFILE FOR STANDBY; DATABASE; DATABASE PLUS ARCHIVELOG; DATAFILE ; RECOVERY AREA; SPFILE; TABLESPACE ;
Listing 10.18: Backup-Beispiele
514
Wiederherstellungstechniken
Dies sind nur einige Beispiele, die miteinander kombinierbar und erweiterbar sind. Anstelle der Namen für Datendateien und Tablespaces können auch deren Nummern (aus v$datafile bzw. v$tablespace) angegeben werden. Sicherungstypen Der Recovery Manager kennt zwei unterschiedliche Sicherungsverfahren: zum einen die einfache Kopie der Datendateien, z.B. für den Aufbau einer StandbyDatenbank, und zum anderen den Aufbau von Backup-Sets. Ein Backup-Set stellt sich auf Betriebssystemebene als einzelne Datei dar und enthält meist mehrere Daten- oder Redo-Log-Dateien. Der Inhalt eines Backup-Sets ist zwar nicht komprimiert, seine Größe ist aber oft viel kleiner als die Gesamtgröße der enthaltenen Dateien. Das kommt daher, dass in Backup-Sets ausschließlich mit Daten-, Indexoder sonstigen wichtigen Strukturen belegte Blöcke gespeichert werden. Leere Blöcke oder Blöcke aus Temporär-Segmenten werden nicht gespeichert. Die Sicherung erfolgt entweder als Full Backup oder in verschiedenen Stufen als inkrementelles Backup. Full Backup Mit einem Full Backup ist in diesem Fall keine Sicherung der gesamten Datenbank gemeint, sondern die Sicherung aller genutzten Blöcke der zu sichernden Einheit (Datei, Tablespace usw.). Inkrementelles Backup Beim inkrementellen Backup werden nur die Datenbankblöcke gesichert, die sich seit einem bestimmten Zeitpunkt (z.B. letzte inkrementelle oder letzte volle Sicherung) geändert haben. Damit können die Dauer der Sicherung sowie die notwendigen Kapazitäten (Bandbreite des Netzwerkes oder Anzahl Bänder) minimiert werden. Die inkrementelle Sicherung bezieht sich nur auf Datendateien, nicht jedoch auf Kontroll- oder Redo-Log-Dateien. Beim inkrementellen Backup können unterschiedliche Backup-Level aufgebaut werden, um damit den notwendigen Speicherplatz zu minimieren, aber auch um zum Beispiel bei der Sicherung über ein Netzwerk die Netzwerkressourcen nicht zu sehr zu belasten. Diese inkrementellen Backups können entweder als differenzielle oder als kumulative Backups aufgebaut werden. Differenz bedeutet, dass alle Änderungen seit dem letzten Backup der gleichen Ebene oder einer tieferen Ebene gesichert werden. Kumulative Backups sichern alle geänderten Blöcke seit der letzten Sicherung der nächsthöheren Ebene. Inkrementelle Backups haben den Vorteil, dass sie am wenigsten Platz beanspruchen, allerdings kann unter Umständen ein Wiedereinspielen der Sicherung recht lange dauern, da alle vorher angefallenen Sicherungen der gleichen Stufe eingespielt werden müssen.
Der Recovery Manager
515
Das folgende Beispiel zeigt den Aufbau eines inkrementellen Backups, das für die meisten größeren Datenbanken ausreichend sein sollte. Am Wochenende wird ein Full Backup (INCREMENT LEVEL 0) und jeden Tag ein kumulatives Backup (INCREMENT LEVEL 1 CUMULATIVE) durchgeführt. Mit den zugehörigen archivierten Redo-Log-Dateien sollte so ein guter Kompromiss zwischen dem verwendeten Platz für das Backup und der Zeitdauer für das Recovery gefunden sein. Sonntag: BACKUP INCREMENATL LEVEL = 0 DATABASE PLUS ARCHIVELOG;
Montag bis Samstag: BACKUP INCREMENATL LEVEL = 1 CUMULATIVE DATABASE PLUS ARCHIVELOG;
Bei einem Totalverlust der Datenbank oder beim Verlust einer Datendatei benötigt man dann drei unterschiedliche Sicherungen: 1. Full Backup des letzten Sonntags 2. Inkrementelles Backup des letzten Wochentags vor dem Crash 3. Archivierte Redo-Log-Dateien seit dem letzten Backup 4. Bei der Sicherung auf Festplatten sollten Sie beachten, dass zunächst eine Kopie der Datenbankdateien entsteht und erst zum Schluss das Backup-Set aufgebaut wird. FOR RECOVER OF COPY
5. Dem Vorteil der inkrementellen Sicherung – der Platzbedarf – steht der Nachteil gegenüber, dass für eine Rücksicherung bzw. Wiederherstellung eine Vollsicherung sowie eine oder mehrere inkrementelle Sicherungen eingespielt werden müssen. Mit der angegebenen Option ist es möglich, die Vollsicherung »vorzurollen«, d.h., wenn eine inkrementelle Sicherung erfolgt, wird diese mit der bestehenden Vollsicherung zu einer neuen, aktuellen Vollsicherung verbunden. Allerdings muss die Sicherung als Datendateikopie, also nicht als Backup-Set, erfolgen. Das folgende Beispiel soll dies verdeutlichen: RMAN> RUN { RMAN> RECOVER COPY OF DATABASE WITH TAG 'JAUX10G_inkrementell'; RMAN> BACKUP INCREMENTAL LEVEL 1 FOR RECOVER OF COPY WITH TAG 'JAUX10G_inkrementell' DATABASE; RMAN> } Listing 10.19: Datenbankkopie mit inkrementeller Sicherung
Bei der ersten Ausführung dieses Befehls wird eine Vollsicherung erstellt, d.h., der Befehl RECOVER COPY ... hat keinen Effekt. Bei der zweiten Ausführung wird eine inkrementelle Sicherung erstellt. Auch hier hat der Befehl RECOVER COPY ... keinen Effekt. Ab der dritten Ausführung wird die vorhergehende inkrementelle Sicherung mit der Vollsicherung zu einer neuen Vollsicherung zusammengeführt. Damit wird für das Rücksichern und Wiederherstellen lediglich die Vollsicherung und die letzte inkrementelle Sicherung benötigt.
516
Wiederherstellungstechniken
Change Tracking Für die Ermittlung der geänderten Datenbankblöcke ist es in der Regel erforderlich, die gesamte Datenbank zu durchsuchen, da für jeden Block die höchste SCN gesucht und mit der letzten Sicherung verglichen werden muss. Alternativ kann eine Datei erzeugt werden, in der die Liste der geänderten Blöcke gespeichert wird. Eingeschaltet wird Change Tracking mit folgendem Befehl: SQL> ALTER DATABASE ENABLE BLOCK CHANGE TRACKING USING FILE '/oradata/JAUX10G/change_tracking.ctf’; Listing 10.20: Einschalten von Change Tracking
Damit wird ein zusätzlicher Prozess4 gestartet, der die Informationen über geänderte Blöcke in die entsprechende Datei protokolliert. Die Datei hat anfangs eine Größe von 10 MB und erweitert sich bei Bedarf um weitere 10 MB. Laut Oracle ist die Größe von 10 MB für eine Datenbankgröße bis zu 1 TB und acht Stufen der inkrementellen Sicherung ausreichend. Backup-Sets Backup-Sets sind ein Oracle-eigenes Sicherungsformat, das entweder die Sicherung von einer oder mehreren Datenbankdateien oder eine Anzahl archivierter RedoLog-Dateien enthält, wobei leere Blöcke nicht mitgesichert werden. Während der Sicherung führt der Recovery Manager damit gleichzeitig eine Überprüfung der Blöcke durch. Eine Komprimierung der Backup-Sets mit Werkzeugen wie ZIP oder COMPRESS ist nicht zu empfehlen. Wenn ein Backup komprimiert werden soll, kann dies über die Option AS COMPRESSED BACKUPSET geschehen. Bei Komprimierungsfunktionen einer Tape-Library ist dieses der Recovery-Manager-Komprimierung vorzuziehen. Backup-Sets können aus einer oder mehreren Dateien (Backup-Pieces) bestehen, je nachdem, wie groß die Datenbank ist. Es werden jedoch immer die Datenbankdateien und die archivierten Redo-Log-Dateien in unterschiedlichen Backup-Sets gespeichert. Die Informationen, die in einem Backup-Set enthalten sind, werden in den Kontrolldateien der Datenbank und optional in einem Recovery-Katalog abgelegt. Das impliziert, dass eine komplette Sicherung der Datenbank immer auch eine Sicherung der Kontrolldateien enthalten sollte. Die Wiederherstellung der Kontrolldateien aus einem Backup-Set, die z.B. in einem Desasterfall notwendig ist, ist nur dann möglich, wenn ein Recovery-Katalog vorhanden ist, und auch in diesem Fall nur mit einer recht komplexen Vorgehensweise. Daher bietet es sich an, die Kontrolldateien getrennt zu sichern, so dass sie schnell wieder herstellbar sind. Die effektivste Möglichkeit hierfür ist, über den Parameter CONTROLFILE AUTOBACKUP ON diese Funktion generell einzuschalten. Hiermit werden nach jeder Sicherung sowohl die Kontrolldateien als auch das SPFILE in einer eigenen Einheit gesichert. In diesem Fall entfällt die Sicherung innerhalb des Backup-Sets.
4
Unter UNIX: ora_ctwr_
Der Recovery Manager
517
Der Befehl: BACKUP DATABASE PLUS ARCHIVELOG sichert die Datenbank standardmäßig in einem Backup-Set und die archivierten Redo-Log-Dateien in zwei weiteren (vor und nach der Datenbanksicherung). Über den Parameter PARALLELISM oder über explizite Allokation von Channels kann das Backup der Datenbank auch auf mehrere Backup-Sets erfolgen. Über den Befehl: RMAN> BACKUP NOT BACKED UP SINCE TIME ’SYSDATE – 7’ DATABASE;
ist es außerdem möglich, automatisch die Datenbankdateien zu sichern, die seit einer Woche nicht mehr gesichert wurden. Ohne die Angabe SINCE werden die Datendateien gesichert, die noch nie gesichert wurden. Die Alternative zum Aufbau von Backup-Sets sind Image Copies, d.h. die ein Einszu-eins-Sicherung der physikalischen Dateien. RMAN> BACKUP DATABASE AS COPY; Listing 10.21: Erstellen einer Backup-Kopie der Datenbank
Channels Die Kommunikation mit einem externen Sicherungswerkzeug, aber auch die Speicherung auf einer anderen Platte erfolgt über Channels. Mit dem Channel wird festgelegt, welches Sicherungsmedium (DISK oder TAPE/SBT) angesprochen wird, welches Format die Sicherung haben soll (z.B. das Verzeichnis und der Name des Backup-Sets) und ob eine Parallelisierung über mehrere Kanäle erfolgen soll. Ab der Version 9 ist es möglich, die Geräte und Channel einmalig zu konfigurieren, um dann ohne zusätzliche Angabe von Parametern eine Sicherung durchzuführen. Diese automatische Konfiguration wird einmal im Recovery Manager durchgeführt und gilt dann für alle Sicherungen der entsprechenden Zieldatenbank. 1. Automatische Konfiguration eines Standardgerätes Wenn Sie das erste Mal mit dem Recovery Manager arbeiten, sollten Sie einfach den Befehl BACKUP DATABASE eingeben. Sie werden feststellen, dass Sie keinen Channel angeben müssen, sondern es wird als Standard ein Channel vom Typ Disk genutzt, und die Sicherung erfolgt je nach Konfiguration in das Standardverzeichnis (MS-Windows %ORACLE_HOME\database) oder in die Flash-Recovery Area. Mit dem Befehl: CONFIGURE DEFAULT DEVICE TYPE TO sbt ändern Sie das Gerät auf den Type sbt, so dass in Zukunft beim gleichen Befehl eine Sicherung auf das Bandgerät erfolgt. 2. Automatische Konfiguration der Geräte Der Befehl: CONFIGURE DEVICE TYPE DISK PARALLELISM 3 stellt bei der Verwendung des Gerätes Disk drei Kanäle für die Sicherung zur Verfügung. Damit erfolgt jede Sicherung fortan in drei statt in ein Backup-Set. Genau so kann natürlich auch eine Konfiguration für den Typ sbt erfolgen. Der Parameter PARALLEL bedeutet allerdings, dass jedem Kanal etwa die gleiche Anzahl Datendateien zugewiesen wird, was aufgrund der unterschiedlichen Dateigrößen dazu führen kann, dass die Backup-Sets ebenfalls unterschiedlich groß werden
518
Wiederherstellungstechniken
3. Automatische Konfiguration der Channels Um noch zusätzliche Möglichkeiten bei der Namensgebung der Backup-Sets oder der Verwendung der Bandgeräte zu haben, kann man die einzelnen Kanäle separat konfigurieren. Mit dem Befehl: CONFIGURE CHANNEL DEVICE TYPE DISK FORMAT=“E:\TEMP\%d_%s_%T“ wird ein neues Format für die Speicherung auf Disk angegeben, dabei können folgende Variablen genutzt werden: – %a
Aktivierungs-ID der Datenbank
– %c
Nummer eines Backup-Pieces bei Verwendung von Duplex Backups
– %d
Name der Datenbank
– %D
Tag des Monats
– %F
Datenbank-ID (DBID) plus Tag, Monat, Jahr und fortlaufender Nummer
– %I
Datenbank-ID
– %M
Monat
– %n
Name der Datenbank (mit x aufgefüllt auf acht Zeichen)
– %p
Nummer des Backup-Pieces
– %s
Nummer des Backup-Sets
– %t
Zeitstempel des Backup-Sets (4 Byte)
– %T
Datum (Jahr, Monat, Tag im Format YYYYMMDD)
– %u
8 Zeichen langer Name aus Backup-Set und Zeit
– %U
Zusammengesetztes eindeutiges Format (%u_%p_%c)
– %Y
Jahr
– %%
%
4. Wie auch in den Vorgängerversionen kann die automatische Konfiguration mit dem Befehl ALLOCATE CHANNEL im RUN-Block übersteuert werden. Sie hat die gleichen Konfigurationsparameter wie die automatische Konfiguration, eine Parallelisierung erfolgt hier jedoch nicht über den Parameter PARALLEL, sondern es müssen alle Devices getrennt angegeben werden. RUN { ALLOCATE CHANNEL disk1 DEVICE TYPE DISK; ALLOCATE CHANNEL disk2 DEVICE TYPE DISK; ALLOCATE CHANNEL disk3 DEVICE TYPE DISK; BACKUP DATABASE; ) Listing 10.22: Beispiel: Manuelle Channel-Allokation
Der Recovery Manager
519
5. Die hier aufgeführten Beispiele können um zusätzliche Kontrollfunktionen erweitert werden. So kann zum Beispiel die maximale Größe eines Backup-Pieces (MAXPIECESIZE) oder die maximale I/O-Bandbreite (RATE) angegeben werden. Weitere Parameter finden Sie in der Dokumentation (Oracle Database Recovery Manager Reference). Hier werden auch die möglichen Formate beschrieben (Kapitel: RMAN Commands; Backup). Recovery-Katalog In komplexeren Umgebungen ist es sinnvoll, einen Recovery-Katalog anzulegen, da dieser eine einfachere Verwaltung der Sicherungen und einer eventuellen Wiederherstellung sowie die Speicherung von Skripten ermöglicht. Dabei werden alle relevanten Informationen (Lage und Name der Datendateien, Informationen über die archivierten Redo-Log-Dateien etc.) in einem Repository abgelegt und regelmäßig mit der zu sichernden Datenbank abgeglichen (siehe auch Abbildung 10.6: Recovery-Manager-Architektur). Für diesen Katalog sollte eine eigene Datenbank aufgebaut werden, die dann natürlich ebenfalls gesichert werden muss. Der Benutzer kann beliebig gewählt werden, es sollte jedoch nicht SYS oder SYSTEM sein, um den Bezug zum Recovery Manager zu bewahren. Oftmals findet man in Beispielen als Schemanamen für den Recovery-Katalog den Namen RMAN. Da es hierbei aber leicht zu Verwirrungen zwischen dem Befehl und dem Benutzer kommt, werden wir im Weiteren den Benutzer RMC (RMAN-Catalog) als Benutzer wählen. Das folgende Beispiel legt diesen Benutzer mit den erforderlichen Rechten an und erstellt dann den Katalog. SHELL% sqlplus system/manager@rmandb SQL> CREATE USER rmc IDENTIFIED BY mypwd DEFAULT TABLESPACE TOOLS; SQL> ALTER USER rmc QUOTA UNLIMITED ON TOOLS; SQL> GRANT RECOVERY_CATALOG_OWNER TO rmc; SHELL% rman CATALOG rmc/mypwd@rmandb RMAN> CREATE CATALOG; Listing 10.23: Erstellen eines Recovery-Katalogs
Zu beachten ist bei der Verwendung eines Recovery-Katalogs, dass die DatenbankID (DBID) eindeutig sein muss. Diese wird beim Aufbau der Datenbank generiert und ist somit bei allen Kopien, die z.B. für Data-Guard-Datenbanken erstellt werden, identisch. Eine solche Datenbank kann nur mit der FOR STANDBY-Option des Befehls DUPLICATE in das Repository eingetragen werden. Um eine Datenbank über den Recovery-Katalog zu verwalten, ist es somit notwendig, sich sowohl an der zu sichernden Datenbank als auch an dem Repository anzumelden. Dabei muss die Datenbank zunächst registriert werden, und von Zeit zu Zeit muss ein Abgleich der tatsächlichen Datenbankstruktur mit der im RecoveryKatalog verwalteten erfolgen (RESYNC).
520
Wiederherstellungstechniken
Das folgende Beispiel zeigt die Anmeldung sowie die Registrierung der Datenbank. Anschließend wird (überflüssigerweise) ein RESYNC durchgeführt. SHELL% rman catalog rmc/rmc@rmandb target sys/manager@JA10G RMAN> REGISTER DATABASE; RMAN> RESYNC CATALOG; Listing 10.24: Anmeldung an den Recovery-Katalog
Der Recovery-Katalog ändert sich mit der Datenbankversion. Daher kann er mit Hilfe des UPGRADE CATALOG-Befehls angepasst werden. Die Version des Recovery-Katalogs muss immer größer oder gleich der Version der zu sichernden Datenbank sein. Dabei kann er ohne Probleme in einer Datenbank liegen, deren Version wiederum unterschiedlich ist. Automatische Kontrolldateisicherung Diese Funktionalität beim Recovery Manager ab Version 9.0 erstellt automatisch eine Sicherung der Kontrolldatei nach jeder Sicherung mit dem Befehl BACKUP oder COPY. Falls vorhanden, wird das SPFILE dabei automatisch mitgesichert. Die beiden Dateien werden dann in einer eigenen Struktur gesichert. Diese Struktur ist kein Backup-Set. Standardmäßig ist die automatische Kontrolldateisicherung ausgeschaltet, sie kann aber jederzeit mit folgendem Befehl aktiviert werden: RMAN> CONFIGURE CONTROLFILE AUTOBACKUP ON;
Mit dieser Option ist es möglich, eine Datenbank wieder zurückzusichern, wenn weder eine Kontrolldatei noch ein Recovery-Katalog existieren. Die Informationen für die notwendige Rücksicherung werden dann aus der automatischen Kontrolldateisicherung gewonnen, die als Erstes zurückzusichern ist. Die wiederhergestellte Kontrolldatei ist genau deshalb vollständig, weil sie genau nach der Erstellung des letzten Backup-Sets kopiert wurde! Es ist in jedem Fall anzuraten, die automatische Kontrolldateisicherung zu konfigurieren! Die Kontrolldatei wird standardmäßig in das Verzeichnis $ORACLE_HOME/dbs (Unix) bzw. %ORACLE_HOME%\database (MS-Windows) gesichert. Als Name wird dann einzig das Format %F verwendet, das sich aus diversen Parametern zusammensetzt. Um diese Datei mit zu sichern, ist es daher sinnvoll, die Lage und den Namen der Kontrolldateisicherung mitzukonfigurieren. RMAN> CONFIGURE CONTROLFILE AUTOBACKUP FORMAT FOR DEVICE TYPE DISK TO ’e:\temp\control%F.ctl’;
Die Variable %F ist beim Namen der Kontrolldatei zwingend erforderlich. Überprüft werden kann die Konfiguration mit dem Befehl: RMAN> SHOW CONTROLFILE AUTOBACKUP FORMAT;
Der Recovery Manager
521
10.3.2 Sicherung Um das geeignete Sicherungsverfahren zu wählen, müssen zunächst die Randbedingungen geklärt werden. Diese sind im Folgenden: Größe der Datenbank Zeitraum der Sicherung Größe der Sicherung Online- oder Offline-Sicherung Recovery-Katalog Durch diese Parameter wird das Verfahren bestimmt, mit dem die Sicherung durchgeführt werden soll. Im Folgenden werden exemplarisch einige Beispiele beschrieben, wobei nicht darauf eingegangen wird, ob ein Recovery-Katalog benutzt wird, da dies für die eigentliche Sicherung ohne Belang ist. Lediglich der Aufruf des Befehls rman erhält dann als Zusatz den Parameter CATALOG .... Vollständige Online-Sicherung der Datenbank Der einfachste Befehl für eine komplette Sicherung der Datenbank ist: RMAN> BACKUP DATABASE PLUS ARCHIVELOG DELETE INPUT;
Hierdurch wird automatisch vor und nach der Sicherung ein ALTER SYSTEM ARCHIVE LOG CURRENT durchgeführt. Die während der Sicherung angefallenen archivierten Redo-Log-Dateien werden zum Schluss ebenfalls gesichert. Danach werden alle gesicherten Redo-Log-Dateien gelöscht (DELETE INPUT). In diesem Fall stehen also keine archivierten Redo-Log-Dateien mehr auf dem System für eine schnelle Wiederherstellung zur Verfügung. Oftmals ist aber das Archivverzeichnis so eingerichtet, dass es möglich ist, die archivierten Redo-LogDateien für mehrere Tage online zur Verfügung zu halten, was im Bedarfsfall die Wiederherstellung natürlich wesentlich beschleunigt, da die Dateien nicht erst von Tape zurückgesichert werden müssen. In einer solchen Konstellation empfiehlt es sich, die Redo-Log-Dateien ein- oder zweimal zu sichern und nach einigen Tagen über den entsprechenden RMAN-Befehl zu löschen. Oracle bietet dazu folgende Möglichkeiten: 1. CONFIGURE BACKUP OPTIMIZATION ON; Mit diesem Parameter stellt der Recovery Manager sicher, dass nur noch die Dateien gesichert werden, die sich seit der letzten Sicherung verändert haben (sofern die RETENTION_POLICY auf 1 gesetzt ist) . 2. Explizite Angabe der zu archivierenden und zu löschenden Dateien
522
Wiederherstellungstechniken
RMAN> BACKUP ARCHIVELOG ALL NOT BACKED UP 2 TIMES; RMAN> DELETE ARCHIVELOG ALL COMPLETED AFTER ‘SYSDATE – 3’; Listing 10.25: Sicherung der archivierten Redo-Log-Dateien
Das folgende Beispiel konfiguriert den Recovery Manager für eine Sicherung auf Festplatte und führt anschließend die eigentliche Sicherung durch. Die Konfiguration wird nur einmal durchgeführt, da die entsprechenden Informationen in den Kontrolldateien abgelegt werden. Wenn anschließend ein Recovery-Manager-Katalog aufgebaut wird, werden die Informationen automatisch übernommen. rman target=system/manager@SUN10G RMAN> CONFIGURE DEFAULT DEVICE TYPE TO DISK; RMAN> CONFIGURE DEVICE TYPE DISK PARALLELISM 3; RMAN> CONFIGURE CHANNEL DEVICE TYPE DISK FORMAT = "/oradata2/backup/%d_%s_%T"; RMAN> CONFIGURE CONTROLFILE AUTOBACKUP ON; RMAN> CONFIGURE CONTROLFILE AUTOBACKUP FORMAT FOR DEVICE TYPE DISK TO '/oradata2/backup/ %F.ctl'; RMAN> BACKUP DATABASE; RMAN> BACKUP ARCHIVELOG ALL NOT BACKED UP 2 TIMES; RMAN> DELETE ARCHIVELOG ALL COMPLETED AFTER ‘SYSDATE – 3’ Listing 10.26: Konfiguration und Sicherung einer Datenbank
Anschließend werden für die Sicherungen auf diese Art nur noch die letzten drei Befehle verwendet. Tipp: Mit dem Befehl SHOW ALL wird die Konfiguration des Recovery Managers angezeigt. Mit Drag & Drop kann man sich daraus die notwendigen Konfigurationsbefehle erstellen. Einzig der Befehl für die Konfiguration des Channels ist hier nicht abgelegt. Oracle empfiehlt, bei der Sicherung auf Platte immer eine Datenbankkopie zu erstellen und nicht mit Backup-Sets zu arbeiten. Der Hintergrund ist, dass dann ein RECOVER OF COPY genutzt werden kann. Es ist aber zu bedenken, dass eine Datenbankkopie mehr Platz beansprucht als ein Backup-Set. Sicherung mit Flash-Recovery Area Die Sicherung in die Flash-Recovery Area ist die Standardeinstellung des Recovery Managers, insofern diese konfiguriert ist. Es müssen dann keine weiteren Konfigurationen durchgeführt werden. Sollten Sie bereits mit dem Recovery Manager bestimmte Parameter eingestellt haben und wollen die Flash-Recovery Area nutzen, so ist es sinnvoll, diese Konfiguration wieder zurückzusetzen. RMAN> CONFIGURE CONTROLFILE AUTOBACKUP clear; RMAN> CONFIGURE CONTROLFILE AUTOBACKUP FORMAT clear; RMAN> CONFIGURE CHANNEL DEVICE TYPE DISK clear; Listing 10.27: Zurücksetzen von Recovery-Manager-Parametern
Jetzt kann die Sicherung in die Flash-Recovery Area erfolgen.
Der Recovery Manager
523
RMAN> BACKUP DATABASE PLUS ARCHIVELOG;
Im Verzeichnis /oraflash befinden sich jetzt folgende Dateien und Verzeichnisse: ./JAUX10G/archivelog/2004_08_06/o1_mf_1_1_0k75gyfc_.arc ./JAUX10G/archivelog/2004_08_06/o1_mf_1_2_0k75tjg1_.arc ./JAUX10G/archivelog/2004_08_06/o1_mf_1_3_0k7693bh_.arc ./JAUX10G/archivelog/2004_08_06/o1_mf_1_4_0k76j9b1_.arc ./JAUX10G/archivelog/2004_08_06/o1_mf_1_5_0k76nj14_.arc ./JAUX10G/archivelog/2004_08_06/o1_mf_1_6_0k773yd7_.arc ./JAUX10G/archivelog/2004_08_06/o1_mf_1_7_0k777qpn_.arc ./JAUX10G/archivelog/2004_08_06/o1_mf_1_8_0k77cfm1_.arc ./JAUX10G/autobackup/2004_08_06/o1_mf_s_533495072_0k77j3tx_.bkp ./JAUX10G/backupset/2004_08_06/o1_mf_annnn_TAG20040806T170207_0k7ckj8_.bkp ./JAUX10G/backupset/2004_08_06/o1_mf_nnndf_TAG20040806T170224_0k7d9p9_.bkp ./JAUX10G/backupset/2004_08_06/o1_mf_annnn_TAG20040806T170424_0k7ht5w_.bkp Listing 10.28: Sicherung in Flash-Recovery Area
Warum ist die Verwendung einer Flash-Recovery Area sinnvoll? In Kapitel 10.1.4 wurde die Größe der Recovery-Area auf 1 GByte festgelegt. Was passiert, wenn diese Grenze erreicht wird? Zunächst einmal überprüft der Archivierungsprozess, ob noch genügend Platz in der Recovery-Area vorhanden ist, ist dies nicht der Fall, werden ältere Sicherungen (Backup-Sets), die aufgrund der RETENTION POLICY nicht mehr gebraucht werden, gelöscht. JAUX10G; ARC1: Creating local archive destination LOG_ARCHIVE_DEST_1: '/oraflash/ JAUX10G/archivelog/2004_08_06/o1_mf_1_14_%u_.arc' (thread 1 sequence 14) ARCH: Connecting to console port... Deleted Oracle managed file /oraflash/JAUX10G/backupset/2004_08_06/ o1_mf_annnn_TAG20040806T164743_0k76jlc5_.bkp Deleted Oracle managed file /oraflash/JAUX10G/backupset/2004_08_06/ o1_mf_annnn_TAG20040806T164743_0k76jt7c_.bkp Deleted Oracle managed file /oraflash/JAUX10G/backupset/2004_08_06/ o1_mf_nnndf_TAG20040806T164801_0k76k4lr_.bkp Deleted Oracle managed file /oraflash/JAUX10G/backupset/2004_08_06/ o1_mf_ncsnf_TAG20040806T164801_0k76n615_.bkp Deleted Oracle managed file /oraflash/JAUX10G/backupset/2004_08_06/ o1_mf_annnn_TAG20040806T164953_0k76nmrm_.bkp Deleted Oracle managed file /oraflash/JAUX10G/backupset/2004_08_06/ o1_mf_annnn_TAG20040806T165807_0k7741xt_.bkp Deleted Oracle managed file /oraflash/JAUX10G/backupset/2004_08_06/ o1_mf_nnndf_TAG20040806T165818_0k774dwc_.bkp Fri Aug 6 17:55:22 2004 JAUX10G; ARC1: Closing local archive destination LOG_ARCHIVE_DEST_1: '/oraflash/ JAUX10G/archivelog/2004_08_06/o1_mf_1_14_0k7bhbjh_.arc' ARCH: Connecting to console port... Committing creation of archivelog '/oraflash/JAUX10G/archivelog/2004_08_06/ o1_mf_1_14_0k7bhbjh_.arc' Created Oracle managed file /oraflash/JAUX10G/archivelog/2004_08_06/ o1_mf_1_14_0k7bhbjh_.arc Listing 10.29: Löschen der Backup-Sets durch den Archive-Prozess
524
Wiederherstellungstechniken
Umgekehrt überwacht auch der Recovey-Manager-Prozess die Flash-Recovery Area und löscht alte Backup-Sets. Dabei werden in der Alert-Datei entsprechende Einträge generiert, die aufgrund ihres umfangreichen Textes und der immer wiederkehrenden Warnungen (weniger als 15% verfügbarer Platz) bzw. Fehlermeldungen (weniger als 3% verfügbarer Platz) dazu führen können, dass diese Datei sehr groß wird. Sie sollte also von Zeit zu Zeit geleert werden. Mit der View dba_outstanding_alerts können diese Einträge außerdem ausgelesen werden. Die Einträge sehen z.B. folgendermaßen aus: ORA-19815: WARNING: db_recovery_file_dest_size of 1048576000 bytes is 99.63% used, and has 3872768 remaining bytes available. ************************************************************* You have the following choices to free up space from flash recovery area: 1. Consider changing your RMAN retention policy. If you are using dataguard, then consider changing your RMAN archivelog deletion policy. 2. Backup files to tertiary device such as tape using the RMAN command BACKUP RECOVERY AREA. 3. Add disk space and increase the db_recovery_file_dest_size parameter to reflect the new space. 4. Delete unncessary files using the RMAN DELETE command. If an OS command was used to delete files, then use RMAN CROSSCHECK and DELETE EXPIRED commands. ************************************************************* Deleted Oracle managed file /oraflash/JAUX10G/backupset/2004_08_06/ o1_mf_nnndf_TAG20040806T175900_0k7bp7z3_.bkp Listing 10.30: Auszug aus Alert-Datei für Flash-Recovery Area
Hier sieht man auch, dass der Recovery Manager nicht mehr aktuelle Sicherungen selbstständig löscht. Damit wird dieser Bereich jetzt sowohl vom Recovery Manager als auch vom Archive-Prozess überwacht und die Gefahr, dass das Verzeichnis nicht mehr ausreicht, minimiert. Sicherung der Flash-Recovery Area Es ist durchaus sinnvoll, eine Bandsicherung mit einer Sicherung in die Flash-Recovery Area zu kombinieren. Dabei wird zunächst eine Sicherung mit dem Recovery Manager in die Flash-Recovery Area durchgeführt und anschließend ebenfalls mit dem Recovery Manager die Flash-Recovery Area auf Band gesichert. Damit wird erreicht, dass der Plattenplatz optimal ausgenutzt wird (es stehen möglichst viele Informationen für eine schnelle Rücksicherung direkt zur Verfügung) und trotzdem eine regelmäßige Sicherung auf Bänder erfolgt. Außerdem ist es bei der Verwendung von inkrementellen Sicherungen oder der Verwendung der Komprimierung für Sicherungen sinnvoll, zunächst auf Festplatte zu sichern, da bei Bändern ein optimaler Durchsatz nur dann erreicht wird, wenn ein kontinuierlicher Datenstrom verfügbar ist.
Der Recovery Manager
525
Die Sicherung der Flash-Recovery Area auf ein Band erfolgt mit dem Befehl: RMAN> BACKUP RECOVERY AREA;
Damit ist diese Information im Recovery-Katalog bzw. in den Kontrolldateien der Datenbanken verfügbar. Damit können Sicherungen, die bereits auf Band ausgelagert worden sind, bei Bedarf überschrieben werden. Ein explizites Löschen der Backup-Sets in der Flash-Recovery Area kann also entfallen. Offline-Sicherung Bisher war die Rede davon, dass ein spezieller Befehl (z.B. BACKUP) ausgeführt wird und dieser eine Datenbank inklusive der archivierten Redo-Log-Dateien sichert. Um eine Offline-Sicherung bzw. die Sicherung einer Datenbank ohne archivierte Redo-Log-Dateien durchzuführen, muss zunächst einmal die Datenbank heruntergefahren werden. Anschließend wird sie in den MOUNT-Zustand hochgefahren, um die Kontrolldatei zu lesen, und dann können die bereits erwähnten Befehle für die Sicherung genutzt werden. SHELL% RMAN> RMAN> RMAN> RMAN>
rman system/manager@JA10G SHUTDOWN IMMEDIATE; STARTUP MOUNT; BACKUP DATABASE; ALTER DATABASE OPEN;
Listing 10.31: Offline-Sicherung
Wie in dem Beispiel ersichtlich, ist es nicht notwendig, die SQL-Befehle als solche zu definieren; der Recovery Manager kennt die Standardbefehle STARTUP, SHUTDOWN und ALTER DATABASE. Zusätzlich steht allerdings auch noch der Befehl SQL zur Verfügung, der die Ausführung von DDL-Befehlen oder PL/SQL-Prozeduren erlaubt, einzig SELECT-Befehle sind nicht möglich. Datenbankkopie Für kleine Datenbanken oder für den Aufbau einer zweiten identischen Datenbank kann es sinnvoll sein, statt der Backup-Sets direkte Kopien der Datenbankdateien zu erstellen. Der Vorteil bei der Verwendung des Recovery Managers anstelle eines normalen Kopierbefehls ist der, dass die Datendateien direkt validiert werden und damit auch ein Full Block Logging entfallen kann. Dieses findet immer dann automatisch über den LGWR statt, wenn Datendateien mit anderen Mitteln online kopiert und die entsprechenden Tablespaces in den dafür erforderlichen BEGIN BACKUP-Modus gesetzt werden. Eine sehr effektive Methode zur Erstellung von Kopien einer kompletten Datenbank ist der Recovery-Manager-Befehl DUPLICATE. Damit wird die gesamte Datenbank auf dem Zielsystem aufgebaut, es wird eine neue Datenbank-ID vergeben, und es kann ein neuer Datenbankname benutzt werden. Die Datenbank wird automatisch wiederhergestellt und anschließend mit RESETLOGS-Option geöffnet. Voraussetzung hier für, dass es eine Revovery-Manager-Sicherung der Quelldatenbank gibt und diese auf dem Zielsystem eingelesen werden kann.
526
Wiederherstellungstechniken
Im Folgenden wird auf dem Zielsystem hltest eine Datenbank mit dem Namen WIN10G aus einer Produktionsdatenbank WIN10G auf dem Rechner hlserver erstellt. Es wird kein Recovery-Katalog benutzt. Auf dem Zielsystem liegen die Datenbankdateien in einer ASM-Instanz. Auf dem Quell- und Zielsystem wird die Datei tnsnames.ora so angepasst, dass auf beide Datenbanken zugegriffen werden kann. WIN10G = (DESCRIPTION = (ADDRESS_LIST = (GLOBAL_DBNAME = WIN10G) (ADDRESS = (PROTOCOL = TCP)(HOST = hlserver)(PORT = 1521)) ) (CONNECT_DATA = (SERVICE_NAME = WIN10G))) WIN10GDUP = (DESCRIPTION = (ADDRESS_LIST = (GLOBAL_DBNAME = WIN10G) (ADDRESS = (PROTOCOL = TCP)(HOST = hltest)(PORT = 1521)) ) (CONNECT_DATA = (SERVICE_NAME = WIN10G))) Listing 10.32: tnsnames.ora für DUPLICATE DATABASE
Jetzt wird auf dem Quellsystem eine Initialisierungsparameterdatei angelegt und auf das Zielsystem kopiert. Dort wird der Parameter für die Benutzung von ASM z.B. wie folgt angepasst: *.db_create_file_dest = '+WIN10G_ASM'
Auf dem Zielsystem (hltest) wird die Instanz jetzt im NOMOUNT-Status hochgefahren. Bei MS-Windows-Systemen muss vorher noch der entsprechende Dienst mit dem Befehl oradim erstellt werden. Für eine einfache Kopie ist es sinnvoll, dass das Backup-Verzeichnis für Quell- und Zielsystem identisch sind. Unter Unix-Systemen kann dies durch ein NFS-Mount sichergestellt werden, bei MS-Windows-Systemen durch ein Netzwerklaufwerk oder eine physikalische Kopie. Damit steht der Duplizierung der Datenbank nichts mehr im Wege. Zunächst erfolgt dafür die Anmeldung an die beteiligten Instanzen und dann der Aufruf des DUPLICATE-Befehls: % rman target sys/manager@WIN10G auxiliary sys/manager@WIN10GDUP connected to target database: WIN10G (DBID=4027871133) connected to auxiliary database: WIN10G (not mounted) RMAN> DUPLICATE TARGET DATABASE TO WIN10G;
Damit existiert eine neue Datenbank mit dem gleichen Inhalt wie die Produktionsdatenbank. Das gleiche Verfahren kann auch für die Erstellung einer StandbyDatenbank verwendet werden, dort muss dann Option FOR STANDBY beim DUPLICATEBefehl verwendet werden. In diesem Fall liegen die Kontrolldateien weiterhin in einem »normalen« Filesystem, also nicht unter einer ASM-Instanz. Die Methode, die im Verfahren Migrating a Database into ASM im Oracle Database Backup and Recovery Advanced User’s Guide
Der Recovery Manager
527
beschrieben ist, funktioniert in diesem Fall nicht. Wenn beim Anlegen der Initialisierungsdatei der Parameter control_files weggelassen wird, bricht der Kopierprozess bei dem Befehl CREATE CONTROLFILE ab mit der Oracle-Fehlermeldung ora-01276 Cannot add file .... File has an Oracle Managed Files file name. Es empfiehlt sich daher, nach erfolgreicher Duplizierung die Datenbank herunterzufahren. Danach wird der Parameter aus der Initialisierungsparameterdatei gelöscht und die Datenbank mit NOMOUNT hochgefahren. Mit dem Befehl RESTORE CONTROLFILE FROM kann dann eine ASM-Datei angelegt werden.
10.3.3 Rücksicherung und Wiederherstellung Solange es keine Probleme mit dem MML gibt, ist eine Wiederherstellung der Datenbank oder von Teilen davon sehr einfach. Mit dem Befehl RESTORE kann jeder beliebige Teil der Datenbank zurückgesichert werden. Im Folgenden werden exemplarisch einige Szenarien beschrieben. 1. Verlust eines Tablespaces Solange es sich nicht um den SYSTEM-Tablespace, einen Tablespace mit aktiven Rollback-Segmenten oder einen aktiven Undo-Tablespace handelt, kann die Wiederherstellung im laufenden Betrieb geschehen. RMAN> RMAN> RMAN> RMAN>
SQL "ALTER TABLESPACE users OFFLINE IMMEDIATE"; RESTORE TABLESPACE users; RECOVER TABLESPACE users; SQL "ALTER TABLESPACE users ONLINE";
Listing 10.33: Wiederherstellung eines Tablespace
2. Verlust einer Datendatei Auch hier gilt, dass die Wiederherstellung im laufenden Betrieb erfolgen kann, solange es sich nicht um den SYSTEM-Tablespace, einen Tablespace mit aktiven Rollback-Segmenten oder einen aktiven Undo-Tablespace handelt. SQL>
ALTER DATABASE DATAFILE 'e:/oradata/JA10G/users01.dbf' OFFLINE IMMEDIATE; RMAN> RESTORE DATAFILE 'e:/oradata/JA10G/users01.dbf'; RMAN> RECOVER DATAFILE 'e:/oradata/JA10G/users01.dbf'; SQL> ALTER DATABASE DATAFILE 'e:/oradata/JA10G/users01.dbf' ONLINE; Listing 10.34: Wiederherstellung einer Datendatei
3. Verlust einer Kontrolldatei Sollte die Datenbank nicht gestartet werden können und der Fehler ORA-00205: Fehler beim Identifizieren der Kontrolldatei auftreten, kann über die Alert-Datei ermittelt werden, welche Kontrolldatei fehlerhaft ist. ORA-00202: Kontrolldatei: 'D:\ORACLE\ORADATA\JA10G\CONTROL03.CTL' ORA-27041: Offnen der Datei nicht möglich
528
Wiederherstellungstechniken
OSD-04002: Datei kann nicht geöffnet werden O/S-Error: (OS 2) Das System kann die angegebene Datei nicht finden.
Wenn die Datenbank mit mehreren Kontrolldateien aufgebaut wurde, reicht es in der Regel, eine noch vorhandene an die entsprechende Position der fehlerhaften zu kopieren. Sollten jedoch alle Kontrolldateien verloren gegangen sein, ist es notwendig, eine Rücksicherung mit anschließender unvollständiger Wiederherstellung durchzuführen. Da die Datenbank mit der Option RESETLOGS geöffnet werden muss, sollte anschließend eine neue Sicherung der Datenbank erfolgen. % sqlplus / as sysdba SQL> STARTUP NOMOUNT % rman target / RMAN> set DBID=4027871133 RMAN> SET CONTROLFILE AUTOBACKUP FORMAT FOR DEVICE TYPE DISK TO 'D:\orabackup\JA10G\JA10G_%F.ctl'; RMAN> RESTORE CONTROLFILE FROM AUTOBACKUP; RMAN> ALTER DATABASE MOUNT; RMAN> RECOVER DATABASE; RMAN> ALTER DATABASE OPEN RESETLOGS; Listing 10.35: Wiederherstellung der Datenbank nach Verlust aller Kontrolldateien
Wenn die Kontrolldateien nicht mehr vorhanden sind und kein Recovery-Katalog benutzt wird, muss die Datenbank-ID (DBID) bekannt sein und mit dem SET-Befehl gesetzt werden. Daher ist es sinnvoll, sich diese als Parameter mit abzuspeichern. In unserem Fall wurde diese ID als Bestandteil des Namens (%F) des Backups der Kontrolldatei gesichert. % dir D:\orabackup\JA10G JA10_C-4027871133-20040806-01.CTL
4. Verlust der gesamten Datenbank Es wird jetzt angenommen, dass die gesamte Datenbank inklusive der Kontrolldateien, archivierten Redo-Log-Dateien und Parameterdatei nicht mehr zur Verfügung steht. Wenn die Sicherung mit dem Recovery Manager durchgeführt wurde und der Parameter CONTROLFILE AUTOBACKUP ON gesetzt war, können alle Datenbankdateien und die Parameterdatei wieder hergestellt werden. Natürlich kommt es zu einem Datenverlust, da die Online-Redo-Log-Dateien nicht mehr zur Verfügung stehen. Zunächst wird eine Initialisierungsparameterdatei mit mindestens folgenden Parametern benötigt 5: db_name = JAUX10G control_files = /tmp/control01.ctl compatible = 10.1.0.2.0 Listing 10.36: Minimale Initialisierungsparameterdatei für die Rücksicherung
5
init.ora im Verzeichnis $ORACLE_HOME/dbs (Unix) bzw. %ORACLE_HOME%\DATABASE (MS-Windows)
Der Recovery Manager
529
Der Parameter control_files kann auf ein beliebiges Verzeichnis zeigen, da er zu einem späteren Zeitpunkt mit dem echten Parameter überschrieben wird. Leider muss der Parameter compatible so gesetzt werden, wie er als Initialisierungsparameter ursprünglich angegeben war. Ein fehlerhafter Eintrag führt zum Abbruch der Rücksicherung des SPFILES, dann erhält man aber den richtigen Wert und muss die Prozedur nochmals durchführen. Eine gute Empfehlung ist die getrennte Aufbewahrung der Initialisierungsparameterdatei bzw. des SPFILEs – dies erspart in hektischen Situationen fehleranfälliges Ausprobieren. Auch das »Merken« der DBID (vielleicht als Kommentar zu db_name) gehört dazu. Als Nächstes wird die Minimalinstanz gestartet und die Wiederherstellung der Kontrolldatei und des SPFILEs ausgeführt. % sqlplus "/ as sysdba" SQL> STARTUP NOMOUNT % rman target / RMAN> SET DBID=3291768378 RMAN> SET CONTROLFILE AUTOBACKUP FORMAT FOR DEVICE TYPE DISK TO '/orabackup/JAUX10G/ %F.ctl'; RMAN> RESTORE SPFILE FROM AUTOBACKUP; Listing 10.37: Wiederherstellung der Parameterdatei (SPFILE)
Danach muss die Instanz noch einmal beendet und mit den neuen Parametern gestartet werden. Dieser Vorgang sollte aus dem Recovery Manager heraus durchgeführt werden, denn dadurch behält man die eingestellten Werte (DBID und CONTROLFILE AUTOBACKUP). Ist dies geschehen, kann das Rücksichern der Datenbank und die Wiederherstellung erfolgen. RMAN> RMAN> RMAN> RMAN> RMAN> RMAN> RMAN>
SHUTDOWN; STARTUP NOMOUNT; RESTORE CONTROLFILE FROM AUTOBACKUP; ALTER DATABASE MOUNT; RESTORE DATABASE; RECOVER DATABASE; ALTER DATABASE OPEN RESETLOGS;
Listing 10.38: Wiederherstellung der Datenbank mit Recovery Manager
Abschließend sollte natürlich sofort eine neue Sicherung erstellt werden. 5. Wiederherstellung von Blöcken Neben der Möglichkeit, die gesamte Datenbank oder bestimmte Objekte (Tablespace oder Datendatei) wiederherzustellen, ist es seit der Version 9 möglich, auch einen einzelnen Block wiederherzustellen, wobei nur dieser Block während der Wiederherstellung gesperrt wird und die übrige Datenbank unangetastet bleibt. Dieser Vorgang ist dann sinnvoll, wenn durch einen Hardware- oder Betriebssystemfehler einige wenige Blöcke korrupt sind.
530
Wiederherstellungstechniken
Bei einer Sicherung mit dem Recovery Manager wird automatisch geprüft, ob Blöcke korrupt sind. Sollte ein solcher Fehler vorliegen, kann es zum Beispiel zu folgender Fehlermeldung kommen: RMAN-00571: ========================================== RMAN-00569: ====== ERROR MESSAGE STACK FOLLOWS ======= RMAN-10035: exception raised in RPC: ORA-19566: exceeded limit of 0 currupt block for file /oradata1/SUN10G/users01.dbf Listing 10.39: Blockkorruption
Natürlich macht es keinen Sinn, jetzt die Sicherung weiterlaufen zu lassen. Zunächst wird man sich um die Beseitigung des Fehlers kümmern und froh sein, dass noch keine Anwendung davon betroffen ist. Es gilt also, den schnellstmöglichen Weg zu finden, die fehlerhaften Blöcke wiederherzustellen. Dafür muss zunächst einmal ermittelt werden, welche Blöcke tatsächlich fehlerhaft sind. Normalerweise führen Zugriffe auf fehlerhafte Blöcke zu Trace-Dateien, die im Verzeichnis, das durch den Parameter user_dump_dest bestimmt wird, erstellt werden. Eine solche Trace-Datei kann dann folgenden Eintrag haben: ORA-01578: ORACLE data block corrupted (file # 7, block # 3) ORA-01110: data file 7: ’/oradata1/SUN10G/users01.dbf’ Listing 10.40: Fehlermeldung Blockkorruption
Damit steht fest: Der Block Nummer 3 in der Datenbankdatei Nummer 7 ist korrupt und muss repariert werden. Dies geschieht dann mit dem Befehl: RMAN> BLOCKRECOVER DATAFILE 7 BLOCK 3;
Alternativ kann man auch den Recovery Manager benutzen, um den korrupten Block zu ermitteln. Dafür lässt man eine Sicherung durchlaufen, und der Recovery Manager protokolliert alle korrupten Blöcke im Data Dictionary. Voraussetzung ist, dass der Parameter maxcorrupt gesetzt wird. Im obigen Fall könnte also eine Sicherung wie folgt aussehen: RMAN> run { set maxcorrupt for datafile 7 to 999; backup datafile '/oradata1/SUN10G/users01.dbf'; } Listing 10.41: Backup fehlerhafter Blöcke
Über die View v$backup_corruption kann jetzt die Information über die fehlerhaften Blöcke gefunden werden. Der Befehl BLOCKRECOVER gestaltet sich jetzt einfacher, weil eine Liste der korrupten Blöcke im Data Dictionary existiert. RMAN> BLOCKRECOVER CURRUPT LIST;
Dieser Befehl stellt alle fehlerhaften Blöcke wieder her. Für die Wiederherstellung der Blöcke muss eine Komplettsicherung existieren, eine inkrementelle Sicherung reicht nicht aus. Außerdem kann der Header-Block einer Datei über diesen Mechanismus nicht wieder hergestellt werden.
Der Recovery Manager
531
10.3.4 Berichte und Überprüfung Berichte Es gibt zwei wesentliche Befehle für die Erstellung von Berichten mit dem Recovery Manager. 1. REPORT Mit diesem Befehl kann überprüft werden, welche Datendateien noch nicht gesichert wurden oder in welchen Dateien UNRECOVERABLE Operationen durchgeführt wurden und die deshalb gesichert werden sollten. Der Standardbefehl REPORT SCHEMA listet die Datenbankdateien mit der entsprechenden Größe auf. 2. LIST Mit diesem Befehl können Informationen über die bereits durchgeführten Backups, archivierte Redo-Log-Dateien etc. ausgegeben werden. Der Befehl LIST BACKUP gibt dabei eine vollständige Liste aller Backups aus. Natürlich kann auch direkt auf die entsprechenden Views zugegriffen werden. Folgender Befehl eignet sich zum Einbau in Überwachungsskripte: COLUMN COLUMN COLUMN COLUMN SELECT
FROM WHERE ORDER
set_stamp FORMAT 999G999G999 HEADING 'Id' backup_type FORMAT a20 HEADING 'Backup Art' start_time HEADING 'Startzeit' completion_time HEADING 'Beendet' set_stamp, decode(backup_type, 'D','Full', 'I','Incremental Level ' || incremental_level, 'L','Redologs', null) backup_type, start_time, completion_time v$backup_set start_time >= trunc(sysdate) - 7 BY start_time;
Listing 10.42: Überwachungsskript für den Recovery Manager
Überprüfung Es gibt beim Recovery Manager drei Arten der Überprüfung: 1. Datendateien und archivierte Redo-Log-Dateien können auf Fehler untersucht werden (z.B. korrupte Blöcke oder fehlende archivierte Redo-Log-Dateien) mit dem Befehl: RMAN> BACKUP VALIDATE DATABASE ARCHIVELOG ALL;
2. Die Sicherungen können mit dem Rücksicherungstest überprüft werden: RMAN> RMAN> RMAN> RMAN>
RESTORE RESTORE RESTORE RESTORE
DATABASE VALIDATE; TABLESPACE VALIDATE; ARCHIVELOG ALL VALIDATE; CONTROLFILE VALIDATE;
532
Wiederherstellungstechniken
3. Die Backup-Sets können überprüft werden: RMAN> VALIDATE BACKUPSET ;
10.3.5 Aufräumen Unter dem Namen Retention Policies versteht man die Angaben bezüglich des Aufbewahrens oder Löschens von Datensicherungen. Dabei muss unterschieden werden, ob die Steuerung über den Recovery Manager oder eine Media-ManagementSoftware durchgeführt wird. Die heute gebräuchlichen Media Manager sind im Normalfall in der Lage, entsprechende Strategien aufzubauen und auszuführen. Das Problem in der Vergangenheit war nun, dass der Recovery Manager bzw. der Recovery-Manager-Katalog von solchen Aufräumaktionen nichts mitbekam. Durch die in Oracle9i eingeführte Retention Policy kann diese Strategie zum einen komplett an den Recovery Manager übergeben werden, zum anderen kann mit den Befehlen CROSSCHECK BACKUP und DELETE EXPIRED BACKUPS eine Überprüfung und Synchronisierung der Backups zwischen Recovery Manager und Media Manager erfolgen. Beim Recovery Manager gibt es hierfür zwei Kategorien: 1. Anzahl Tage, die ein Backup aufbewahrt werden soll RMAN> CONFIGURE RETENTION POLICY TO RECOVERY WINDOW OF 60 DAYS;
2. Anzahl Kopien, die aufbewahrt werden sollen RMAN> CONFIGURE RETENTION POLICY TO REDUNDANCY 7;
3. Bei einer Sicherung kann von dieser Policy abgewichen werden, zum Beispiel um bestimmte Sicherungen für einen längeren Zeitraum – oder sogar für immer – aufzubewahren. Die optionale Angabe KEEP UNTIL oder KEEP FOREVER mit dem BACKUP-Befehl ermöglicht dies. 4. Das KEEP FOREVER ist allerdings nur möglich, wenn ein Recovery-Katalog verwendet wird, da die Informationen in den Kontrolldateien über den Serverparameter controlfile_record_keep_time gesteuert werden.
10.3.6 Verwaltung im Oracle Enterprise Manager Natürlich ist es auch möglich, den Recovery Manager über den Oracle Enterprise Manager zu nutzen. Zunächst einmal ist dafür erforderlich, dass man sich als SYSDBA an die zu sichernde Datenbank anmeldet. Dann stehen die folgenden Menüpunkte unter der Option WARTUNG zur Verfügung.
Der Recovery Manager
533
Abbildung 10.6: Oracle Enterprise Manager, Backup/Recovery
Über den Menüpunkt BACKUP-EINSTELLUNGEN KONFIGURIEREN wird die Konfiguration für Sicherungen vorgenommen.
Abbildung 10.7: Backup-Einstellungen
534
Wiederherstellungstechniken
Hierbei ist es direkt möglich, eine Sicherung zu testen. Unter dem Menüpunkt POLICY können weitere Konfigurationseinstellungen vorgenommen werden.
Abbildung 10.8: Konfigurationseinstellungen
Unter dem Menüpunkt BACKUP PLANEN kommt man zu einem Wizard, der ein Recovery-Manager-Skript für die tägliche Sicherung der Datenbank über den Enterprise Manager aufbaut.
Flashback Database
535
Abbildung 10.9: Backup planen
Damit wird eine physikalische Sicherung (kein Backup-Set) der Datenbank erstellt mit der inkrementellen Sicherung des letzten Tages und des »Vorwärtsrollens« der letzten Vollsicherung. Andere Sicherungsmethoden sind natürlich einstellbar, wie auch der Zeitpunkt, zu dem die Sicherung erfolgen soll.
10.4
Flashback Database
In einigen – hoffentlich seltenen – Fällen ist es notwendig, die gesamte Datenbank auf einen älteren Zustand zurückzusetzen. Dies kann zum Beispiel erforderlich sein, wenn ein Batch-Job Fehler produziert hat oder wenn ein beteiligtes System Inkonsistenzen feststellt, so dass ein gemeinsamer Wiederaufsetzpunkt gefunden werden muss. Oft wird auch das Zurücksetzten der gesamten Datenbank notwendig, wenn ein Update auf die Datenbankstrukturen eines Anwendungsschemas, z.B. im Rahmen eines Software-Updates, durchgeführt wird und fehlschlägt, weil etwa Constraints oder Indizes nicht wie geplant aufgebaut werden können.
536
Wiederherstellungstechniken
In der Vergangenheit war dies bei der Oracle-Datenbank nur durch ein vollständiges Rücksichern der Datenbank mit unvollständiger Wiederherstellung möglich. Da dieses Verfahren für große Datenbanken durchaus einige Stunden in Anspruch nehmen kann, stellt sich die Frage nach einer alternativen Methode, bei der nur die geänderten Blöcke wieder zurückgesetzt werden. Von Hardware-Herstellern gibt es schon länger die Möglichkeit, einen so genannten Snapshot von logischen Bereichen (LUNs) zu erstellen, die bei Bedarf den alten Zustand wieder herstellen. Dieses Verfahren ist allerdings recht teuer und nur bei bestimmten Hardware-Herstellern (z.B. EMC) möglich. Über die Flash-Recovery Area verfügt die Oracle 10g-Datenbank über eine Möglichkeit, alte Datenbankzustände zu speichern und im Zusammenspiel mit den archivierten Redo-Log-Dateien daraus jeden beliebigen Zeitpunkt wieder herzustellen, insofern dieser noch durch die Flash-Recovery Area abgedeckt wird. Voraussetzung für die Verwendung ist, dass eine Flash-Recovery Area konfiguriert ist und die Datenbank im Archive-Log-Modus arbeitet. Außerdem ist die Funktionalität auf die Enterprise Edition beschränkt. Mit dem Parameter db_flashback_retention_target wird angegeben, wie weit in die Vergangenheit die Änderungen aufbewahrt werden sollen. Dieser Parameter wird in Minuten (!) angegeben und steht standardmäßig auf 1440 (entspricht einem Tag). Flashback Database kann jetzt wie folgt eingeschaltet werden: SQL> SQL> SQL> SQL> SQL> SQL> SQL>
ALTER SYSTEM SET db_file_recovery_dest = '/oraflash'; ALTER SYSTEM SET db_file_recovery_dest_size = 10G; ALTER SYSTEM SET db_flashback_retention_target = 1440; SHUTDOWN IMMEDIATE; STARTUP MOUNT; ALTER DATABASE FLASHBACK ON; ALTER DATABASE OPEN;
Listing 10.43: Aktivieren der Flashback-Database-Funktion
Hierdurch wird ein zusätzlicher Prozess gestartet6, der den alten Zustand von geänderten Datenbankblöcken in die Flash-Recovery Area schreibt. Dieser Prozess wird bei der ersten Änderung eines Blockes aktiv sowie in regelmäßigen Abständen, wenn ein Block mehrfach geändert wird. Dadurch wird erreicht, dass eine Wiederherstellung mit wenigen Informationen aus den archivierten Redo-Log-Dateien möglich ist. Ein Flashback-Database-Szenario kann jetzt wie folgt aussehen: SQL> TRUNCATE TABLE kunden;
Der Anwender hat durch diesen Befehl die Applikation unbrauchbar gemacht. Eine Wiederherstellung mit Flashback-Query oder Flashback-Table ist nicht möglich, da sich die Struktur geändert hat. Die verbleibenden Möglichkeiten sind ein Tablespace-Point-in-Time-Recovery oder eben ein Flashback Database. 6
Unter Unix: ora_rvwr_
Flashback Database
537
Da für die Anwendung die Tabelle eine zentrale Rolle spielt und keine anderen Anwendungen mit dieser Datenbank arbeiten, entscheiden wir uns dafür, die Datenbank auf einen Stand vor diesem fatalen Befehl zurückzusetzen. Die erste Aufgabe besteht jetzt darin festzustellen, um welche Zeit (die SCN zu kennen ist unwahrscheinlich) der Befehl ausgeführt wurde. SQL> ALTER SESSION SET nls_date_format = 'DD.MM.YYYY HH24:MI:SS'; SQL> SELECT object_name, last_ddl_time FROM dba_objects WHERE object_name = 'KUNDEN'; OBJECT_NAME LAST_DDL_TIME ------------------------------ ------------------KUNDEN 11.08.2004 13:54:16 Listing 10.44: Ermitteln der Zeit des TRUNCATE-Befehls
Das funktioniert gut, wenn der Anwender nicht anschließend noch einen anderen DDL-Befehl für die Tabelle abgesetzt hat. Jetzt wird die Datenbank heruntergefahren und mit Mount gestartet. Bei Oracle Real-Application-Clusters müssen beide Instanzen gestoppt, eine Instanz muss danach exklusiv gestartet werden. Danach erfolgt das Flashback Database. SQL> SHUTDOWN IMMEDIATE; SQL> STARTUP MOUNT; SQL> FLASHBACK DATABASE TO TIMESTAMP TO_DATE('11.08.2004 13:54:11','DD.MM.YYYY HH24:MI:SS'); Listing 10.45: Flashback Database
Ob der Zeitpunkt optimal gewählt wurde, kann jetzt überprüft werden, indem die Datenbank im READ ONLY-Modus geöffnet wird. SQL> ALTER DATABASE OPEN READ ONLY;
Jetzt kann geprüft werden, ob die Daten in Ordnung sind. Sollten Daten fehlen, kann ein weiteres Recovery der Datenbank durchgeführt werden. Sollte der Fehler mit eingespielt worden sein, muss ein weiteres Flashback Database auf einen älteren Stand erfolgen. Bei der Wahl des Zeitpunkts sollte beachtet werden, dass es eine Unschärfe gibt, die bei ca. drei Sekunden liegt. Im Zweifelsfall ist ein Sicherheitspolster von einigen zusätzlichen Sekunden einzuplanen. Wenn das Flashback Database erfolgreich war, wird die Datenbank mit RESETLOGS geöffnet. Das bedeutet auch, dass es an dieser Stelle keinen Weg zurück gibt. Ein nochmaliges Flashback Database ist jetzt nicht mehr möglich. Mit dem Öffnen der Datenbank werden alle »alten« Flashback Logs automatisch gelöscht. Die FLASHBACK-Befehle können, wie im Beispiel, aus SQL*Plus heraus aufgerufen werden. Alternativ kann auch der Recovery Manager verwendet werden. Dieser hat den Vorteil, dass eventuell notwendige archivierte Redo-Log-Dateien oder Sicherungen der Flash-Recovery Area automatisch von Band eingespielt werden. Ansonsten unterscheidet sich die Syntax nicht.
538
Wiederherstellungstechniken
Die Möglichkeit, die Datenbank auf einen beliebigen älteren Zustand zurückzusetzen, hat jedoch ihre Grenzen. So ist die mit dem Parameter db_flashback_retention_ target angegebene Zeitdauer nicht zwingend. Wenn der Platz in der Flash-Recovery Area für andere Objekte (z.B. archivierte Redo-Log-Dateien) benötigt wird, werden die Flashback-Logs gelöscht, und somit besteht keine Möglichkeit mehr, die Datenbank auf einen älteren Zustand zurückzusetzen. Natürlich spielt auch die Frage eine Rolle, ob ein Zurücksetzen der Datenbank aufgrund anderer Anwendungen, die ja auch davon betroffen wären, möglich ist. Die Alternative hierzu ist das Tablespace-Point-in-Time-Recovery, das im Folgenden besprochen wird.
10.5
Tablespace-Point-in-Time Recovery (TSPITR)
Es muss sicherlich gut abgewogen werden, ob ein Flashback Database oder ein Tablespace-Point-in-Time-Recovery durchgeführt wird. Wenn die Flashback-Database-Funktionalität nicht eingeschaltet ist, erübrigt sich natürlich die Diskussion. Ansonsten ist ein Flashback Database sicherlich schneller als ein TSPITR, da in diesem Fall eine zweite (Auxiliary-)Datenbank aufgebaut werden muss und erst aus dieser heraus der Tablespace wieder erstellt werden kann. Außerdem muss zunächst überprüft werden, ob es irgendwelche Abhängigkeiten außerhalb des zurückzuspielenden Tablespace gibt (z.B. Primary Key Constraint, Materialized Views, Partitionen). Des Weiteren ist ein TSPITR nicht möglich nach einem DROP TABLESPACE Befehl. Als Beispiel soll wieder der Befehl TRUNCATE TABLE dienen, da dieser Befehl nicht über eine andere Aktion rückgängig gemacht werden kann. SQL> TRUNCATE TABLE kunden;
Mit der in Kapitel 10.4 gezeigten SQL-Anweisung kann jetzt herausgefunden werden, zu welchem Zeitpunkt der Befehl abgesetzt worden ist. Jetzt ist die Entscheidung gefallen, dass ein TSPITR des Tablespace ts_data erfolgen soll, da nur ein geringer Teil der Datenbank betroffen ist. Daher muss zunächst herausgefunden werden, ob es Abhängigkeiten in andere Tablespaces gibt. Hierfür gibt es die View ts_pitr_check.
Tablespace-Point-in-Time Recovery (TSPITR) SQL> SELECT * FROM ts_pitr_check WHERE TS1_NAME = 'TS_DATA' OBJ1_OWNER -----------------------------OBJ1_SUBNAME -----------------------------OBJ2_NAME -----------------------------OBJ2_OWNER -----------------------------CONSTRAINT_NAME ------------------------------
539
OBJ1_NAME -----------------------------OBJ1_TYPE TS1_NAME ---------------- -----------------------------OBJ2_SUBNAME OBJ2_TYPE ------------------------------ --------------TS2_NAME ------------------------------
REASON -------------------------------------------------------------------------------PROD KUNDEN TABLE TS_DATA PK_KUNDEN INDEX PROD USERS Tables and associated indexes not fully contained in the recovery set; Listing 10.46: TSPITR-Check
In diesem Fall ist also der Primärschlüsselindex in einem anderen Tablespace gespeichert und müsste ebenfalls zurückgesichert werden. Wir entscheiden uns alternativ dafür, den Index zu löschen und anschließend neu anzulegen. Damit steht der Wiederherstellung nichts mehr im Wege. RMAN> RECOVER TABLESPACE ts_data UNTIL TIME "to_date('17.08.2004 10:16:00','DD.MM.YYYY HH24:MI:SS')" AUXILIARY DESTINATION 'D:\oraaux\JA10GX';
Mit diesem Befehl wird jetzt im Verzeichnis 'D:\oraaux\JA10GX' eine Minimaldatenbank mit einer Kontrolldatei, zwei Redo-Log-Dateien, dem SYSTEM- und dem UndoTablespace aufgebaut. In der Produktionsdatenbank (JA10G) wird der Tablespace ts_data offline gesetzt und die Datendatei 'D:\oracle\oradata\JA10G\ts_data01.dbf' aus der Sicherung überschrieben. Dies ist ein kritischer Punkt, denn dieser Tablespace muss jetzt in jedem Fall, auch wenn das TSPITR fehlschlägt, wiederhergestellt werden. db_name=JA10G compatible=10.1.0.2.0 db_block_size=8192 db_unique_name=tspitr_JA10G_CfsD large_pool_size=1M #No auxiliary parameter file used db_create_file_dest=D:\oraaux\JA10GX control_files=D:\oraaux\JA10GX/cntrl_tspitr_JA10G_CfsD.f Listing 10.47: TSPITR-Instanzparameter
540
Wiederherstellungstechniken
Anschließend wird die Interimdatenbank gestartet und bis zum TSPITR-Zeitpunkt wiederhergestellt. Aus dieser Datenbank wird dann ein Export der Objektinformationen durchgeführt. Dafür gibt es sowohl beim Export als auch beim Import einen Parameter point_in_time_recovery, der allerdings scheinbar nirgendwo dokumentiert ist. Mit dieser Exportdatei wird dann die Information im Data Dictionary der Produktionsdatenbank überschrieben. Als Letztes wird die Interimsdatenbank wieder heruntergefahren, und sämtliche Datendateien werden gelöscht. In der Produktionsdatenbank muss der entsprechende Tablespace allerdings manuell wieder online gesetzt werden. SQL> ALTER TABLESPACE ts_data ONLINE;
In unserem Fall müsste jetzt als letzter Punkt noch der Primärschlüsselindex neu angelegt werden. Durch diesen vollständigen Automatismus ist ein TSPITR sicherlich einfach durchzuführen. Dennoch sollte beachtet werden, dass es sich hierbei um eine absolute Notlösung handelt, da in der Regel nicht davon auszugehen ist, dass es keine Abhängigkeiten außerhalb eines Tablespace gibt. Außerdem dauert es natürlich bei großen Datenbanken einige Zeit, bis die Interimsdatenbank aufgebaut und bis zum vorgesehenen Punkt vorgespielt worden ist. Auch der zusätzliche Platzbedarf für die Interimsdatenbank sollte nicht unterschätzt werden. Alternativ zu dem hier beschriebenen Verfahren kann auch eine manuelle Konfiguration erfolgen. Dabei wird eine eigenständige Datenbank aufgebaut und dann über die Funktion der transportablen Tablespaces in der Produktion ausgetauscht. Dieses Verfahren bietet sich an, wenn es z.B. eine Data-Guard-Datenbank gibt.
10.6
Objektbasierte Techniken
10.6.1 Data Pump Data Pump ist ein neues Werkzeug, das direkt zur Datenbank-Software gehört. Es besteht aus einem serverseitigen Teil (dem Package dbms_datapump) sowie den beiden Kommandozeilenwerkzeugen expdp und impdp (Data Pump Export und Data Pump Import), die als Clients die Benutzerschnittstelle zum serverseitigen Teil bilden. Beide Werkzeuge sind stark an die schon länger existierenden Tools exp und imp (konventioneller Export und Import, siehe Abschnitt Export und Import) angelehnt. Data Pump ist als Nachfolger dieser Werkzeuge anzusehen. Mit Data Pump Export alleine können Sicherungen, in Zusammenarbeit mit Data Pump Import aber auch versions- und plattformübergreifende Migrationen und Reorganisationen einzelner Objekte, Benutzer, Tablespaces oder auch der ganzen Datenbank erstellt werden.
Objektbasierte Techniken
541
Unterschiede zum konventionellen Export/Import Während beim konventionellen Export/Import sämtliche I/O-Aktivität (Schreiben/Lesen von Dump-Dateien) clientseitig stattfindet, dient bei Data Pump der Client lediglich als Kommando-Schnittstelle für den Benutzer. Die eigentliche Arbeit (I/O-Aktivität) findet ausschließlich auf dem Server selbst statt. Dadurch müssen die Daten nicht mit Oracle Net über das Netzwerk übertragen werden, was ansonsten immer ein Performance-Problem darstellte. Soll in eine andere Datenbank importiert werden, müssen die Dump-Dateien mittels Betriebssystemkommandos wie ftp, scp usw. übertragen werden. Die Übertragung wurde also vollkommen vom Export/Import entkoppelt und ist somit davon unabhängig. Der Benutzer kann nicht zwischen konventionellem und direktem Pfad wählen. Sowohl für den Data-Pump-Export als auch für den Data-Pump-Import wird – soweit möglich – stets der direkte Pfad benutzt. Insbesondere für den Import stellt dies eine erhebliche Beschleunigung dar. Data Pump arbeitet joborientiert. Export- und Importvorgänge können unterbrochen, umparametriert und wieder aufgenommen werden. Eine Parallelisierung des Jobs durch mehrere Slave-Prozesse ist möglich. Diese Funktion ist allerdings auf die Enterprise Edition beschränkt. Metadaten werden nicht als DDL-Skript, sondern in einer XML-Darstellung abgespeichert. Dadurch werden Anpassungen beim Import (Änderung von Tabellennamen oder Tablespaces etc.) erleichtert. Bei der Parametrierung der Kommandozeilenwerkzeuge wurde »aufgeräumt«. Leider sind die Dump-Dateien von Data Pump bzw. konventionellem Export/ Import nicht miteinander kompatibel. Mit dem einen Werkzeug erstellte DumpDateien können also mit dem anderen Werkzeug nicht verwendet werden. Einige neue Features der Oracle-Version 10g werden nur von Data Pump unterstützt, wohingegen Export/Import seit Oracle9i nicht mehr weiterentwickelt wurde. Allerdings kann Data Pump wegen des serverseitigen Zugriffs auf das Package dbms_datapump auch ausschließlich mit Oracle 10g-Datenbanken verwendet werden. Architektur Data Pump ist jobgesteuert, d.h., es gibt eine Konfigurationsphase, in der ein Name für den Data-Pump-Job vergeben und festgelegt wird, was zu tun ist (Export oder Import, welche Daten etc.) sowie eine Ausführungsphase, während welcher der eigentliche Export/Import läuft. Letztere kann beliebig oft unterbrochen und wiederaufgenommen oder auch vorzeitig abgebrochen werden. Eine Fortschrittsanzeige steht ebenfalls zur Verfügung. Achtung: Data-Pump-Jobs sind unabhängig von benutzerdefinierten Datenbank-Jobs, die mittels dbms_job oder dem Scheduler definiert werden können (siehe Abschnitt 6.2).
542
Wiederherstellungstechniken
Die gesamte Konfiguration und Steuerung wird über die Client-Programme expdp und impdp durchgeführt. Datenbankseitig wird die eigentliche Arbeit durch so genannte Worker-Prozesse geleistet. Diese sind Oracle-Hintergrundprozesse mit den Bezeichnungen DWnn, wobei nn für eine Zahl von 00 bis 99 steht. Wie viele Worker-Prozesse an dem Job arbeiten, also der Parallelisierungsgrad des Jobs, kann jederzeit vor und während der Job-Ausführung eingestellt bzw. geändert werden. Für jeden Data-Pump-Job gibt es außerdem einen Master-Prozess DMnn, der in regelmäßigen Intervallen die aktuelle Job-Konfiguration ausliest und entsprechend die Arbeit der Worker-Prozesse koordiniert und protokolliert. Dieses Protokoll bildet auch die Grundlage für die Fortschrittsanzeige des Jobs. Technisch ist es als Tabelle implementiert, die bei der Definition des Jobs automatisch im Schema des aufrufenden Benutzers erstellt wird und für die Dauer des Jobs existiert. Diese Tabelle heißt auch Master-Tabelle und trägt denselben Namen wie der Job. Achtung: Dies bedeutet in der Tat, dass Tabellen und Data-Pump-Jobs in demselben Namensraum liegen, d.h., ein neu zu definierender Data-Pump-Job darf nicht den Namen einer bereits existierenden Tabelle tragen. Nach erfolgreicher Beendigung oder explizitem Abbruch des Jobs wird die MasterTabelle automatisch gelöscht. Bei einem automatischen Unterbrechen oder einem Absturz des Jobs bleibt sie hingegen erhalten und kann zum Wiederanstarten des Jobs genutzt werden. Ist Letzteres nicht gewollt, muss sie allerdings manuell gelöscht werden. expdp oder impdp
Client Server Master-Tabelle DataPump API (DBMS_ DATAPUMP)
- Tabellen - Views - etc.
DW01 DW02 DW03
LogDatei DumpDatei DumpDatei DumpDatei
...
Metadata API (DBMS_ METADATA)
DB-Objekte:
DM01
Worker-Pool
Vorbereitungen Da alle beteiligten Dateien im Dateisystem des Servers liegen bzw. dort erstellt werden, muss zunächst sichergestellt werden, dass Schreib- bzw. Leseberechtigungen für diese Dateien bestehen. Dabei handelt es sich in jedem Fall um die DumpDatei(en) mit den Daten sowie um Log-Dateien zur Protokollierung. Optional kann auch ein SQL-Skript geschrieben werden (siehe unten). Die Zugriffsrechteverwaltung hierfür geschieht über Directory-Objekte. Diese werden in der Datenbank definiert und stellen einfach einen Aliasnamen für ein Datei-
Objektbasierte Techniken
543
systemverzeichnis dar, über den das Verzeichnis aus der Datenbank heraus zugänglich gemacht wird. Für Directory-Objekte siehe auch Abschnitt 5.7. Ein entsprechendes Directory-Objekt muss zunächst durch einen DBA oder einen Benutzer mit dem Systemprivileg CREATE ANY DIRECTORY erstellt werden. Wenn regelmäßig Daten via Data Pump unter Benutzung derselben Dump-Datei übertragen werden, ist dies natürlich ein einmaliger Vorgang. SQL> CREATE DIRECTORY pumpdir AS 'C:\dpump';
Anschließend müssen dem Data-Pump-Aufrufenden Lese- bzw. Schreibrechte auf dem Directory zugewiesen werden. SQL> GRANT READ, WRITE ON DIRECTORY pumpdir TO schwanke;
Achtung: Für das Verzeichnis mit der Log-Datei werden in jedem Fall Schreibrechte benötigt, für das Verzeichnis mit den Dump-Dateien kann ggf. auf Nur-Lese- bzw. Nur-Schreib-Zugriff beschränkt werden. Für das Verzeichnis mit den Dump-Dateien kann auch ein ASM-Pfad angegeben werden, z.B.: SQL> CREATE DIRECTORY pumpdir AS '+DATAFILES/';
Sollen Objekte aus einem anderen Schema exportiert werden, wird außerdem die Rolle EXP_FULL_DATABASE benötigt. Beim Import wird entsprechend die Rolle IMP_FULL_DATABASE benötigt. Data Pump Export Der Data-Pump-Export kennt vier verschiedene Granularitäten: TABLE: In dieser Variante werden einzelne Tabellen und/oder Partitionen sowie abhängige Objekte, d.h. Indizes, Constraints, Trigger und Objektprivilegien, zu den betreffenden Tabellen exportiert. SCHEMA: Diese Granularität wird benutzt, um alle Datenbankobjekte eines Benutzers, also sein vollständiges Schema (Tabellen, Views, Synonyme, PL/SQL-Objekte etc.), zu exportieren. FULL: Mit dieser Variante wird die gesamte Datenbank exportiert, also alle Benutzer, aber auch beispielsweise Tablespace-Definitionen, Rollen, DirectoryObjekte und Public-Synonyme, also Objekte, die nicht einem bestimmten Benutzer zugeordnet werden können. Dieser Modus ist z.B. für plattformübergreifende Migrationen nicht zu großer Datenbanken interessant. TABLESPACE: Hiermit werden alle Tabellen eines Tablespace inklusive ihrer abhängigen Objekte exportiert. Welche Granularität benutzt wird und welche Objekte in der gewählten Einheit berücksichtigt werden, wird über die Parametrierung des Data Pump Exports ausgewählt, ebenso wie der Name der Export-Dump-Datei und einiges mehr. Ein Data-Pump-Export wird beispielsweise durch folgenden Aufruf gestartet: $ expdp schwanke@ps10 directory=pumpdir dumpfile=myexp.dmp logfile=myexp.log schemas=schwanke job_name=myexpjob
544
Wiederherstellungstechniken
Dieser Aufruf definiert einen Data-Pump-Job mit dem Namen myexpjob und konfiguriert diesen, alle Objekte des Benutzers schwanke in die Dump-Datei myexp.dmp im Verzeichnis pumpdir zu exportieren (das Directory-Objekt pumpdir muss existieren). Alle Bildschirmausgaben sollen in die Log-Datei myexp.log in demselben Verzeichnis geschrieben werden. Anschließend wird der Job gestartet. Die Liste aller Parameter, von denen einige Standardeinstellungen haben, bekommt man durch den Aufruf: $ expdp help=y
Data-Pump-Export kann wahlweise auf zwei verschiedene Arten gestartet werden: im Zeilenmodus oder unter Verwendung einer Parameterdatei. Im Zeilenmodus werden die Parameter direkt beim Aufruf eingegeben so wie im obigen Beispiel. Besonders für wiederkehrende Exports empfiehlt sich die Verwendung einer Parameterdatei. Dazu werden die Parameter in eine Datei geschrieben, die dann beim Exportaufruf als parfile spezifiziert wird. $ expdp parfile=parameterdatei.par
Im Folgenden werden die wichtigsten Exportparameter vorgestellt. Einige Parameter können nur die Werte 'Y' oder 'N' annehmen. In diesem Fall wird der Parameter als gesetzt oder nicht gesetzt bezeichnet. Exportparameter
Bedeutung
JOB_NAME
Der Name des Jobs wird als Handle für weitere Bezugnahmen auf den Job (via ATTACH, siehe unten) verwendet. Außerdem entspricht er dem Namen der Master-Tabelle. Die Maximallänge beträgt 30 Zeichen.
DUMPFILE
Eine feste Liste von Dump-Dateien der Form [:], ...
Der Default ist SYS_EXPORT__
Bspw. pumpdir:exp01.dmp, pumpdir:exp02.dmp Oder eine dynamische Liste unter Verwendung der Substitutionsvariablen %U (wird der Reihe nach in 00, 01 … 98, 99 expandiert). Z.B. liefert exp%U.dmp maximal 100 Dump-Dateien. FILESIZE
Maximale Größe jeder Dump-Datei (Suffixe K,M,G sind möglich). Beispiele: 100000000; 100M; 1G
LOGFILE, NOLOGFILE
Name der Log-Datei: [:] Ist NOLOGFILE gesetzt, wird keine Log-Datei geschrieben
DIRECTORY
Default-Directory-Objekt für DUMPFILE und LOGFILE
Tabelle 10.1: Parameter für den Data Pump-Export
Objektbasierte Techniken
545
Exportparameter
Bedeutung
TABLES
Liste zu exportierender Tabellen und/oder Partitionen, jeweils in der Form [Schema.]Tabelle[:Partition], z.B. (KUNDEN,AUFTRAEGE, AUFPOSITIONEN). Impliziert die Granularität TABLE. Für jede Tabelle werden auch zugehörige abhängige Objekte (Constraints, Indizes, Trigger, Grants) exportiert.
SCHEMAS
Liste der zu exportierenden Benutzer, z.B. (SCHWANKE,AHRENDS). Impliziert die Granularität SCHEMA.
TABLESPACES
Liste der zu exportierenden Tablespaces (nur bei Granularität TABLESPACE)
FULL
Granularität FULL, falls gesetzt
CONTENT
Umfang des Exports: METADATA_ONLY (Objektdefinitionen), DATA_ONLY (Daten) oder ALL (beides). ALL ist Default.
QUERY
Export einer Teilmenge der Daten (siehe unten)
INCLUDE, EXCLUDE
Export einer Teilmenge der Objekte (siehe unten)
Tabelle 10.1: Parameter für den Data Pump-Export (Forts.)
Einige der vorgestellten Parameter sollen an dieser Stelle noch genauer erläutert werden: QUERY
Um nur eine Teilmenge einer oder mehrerer Tabellen auszulesen, z.B. alle Produkte, die mit 'A' beginnen, kann pro Tabelle eine Filterbedingung in Form einer WHEREKlausel mitgegeben werden. $ expdp schwanke@ps10 directory=pumpdir dumpfile=myexp.dmp logfile=myexp.log schemas=schwanke job_name=myexpjob query=kunden:"WHERE kd_nr > 5" query=produkte:"WHERE prod_name LIKE 'A%'"
Die WHERE-Klausel wird in doppelte Hochkommata eingeschlossen, da Leerzeichen innerhalb der Klausel auftreten. Je nach Betriebssystem und verwendeter Kommando-Shell müssen die doppelten Hochkommata noch mit Escape-Zeichen versehen werden. Achtung: Aus der Exportdatei ist anschließend nicht mehr ersichtlich, dass der Export mit Filterbedingungen ausgeführt wurde. Außerdem verhindert dieser Parameter die Verwendung des direkten Pfads (siehe unten). INCLUDE, EXCLUDE
Mit diesen beiden Parametern kann genauer eingegrenzt werden, welche Objekte und/oder Objekttypen exportiert werden sollen. Damit wird die recht große Lücke zwischen dem feingranularen Tabellenexport und dem schon relativ groben Schemaexport geschlossen.
546
Wiederherstellungstechniken
Beispielsweise bewirkt folgende Parametrierung, dass ausschließlich Tabellen und Primärschlüsselindizes (per Konvention enden diese auf PK) exportiert werden: $ expdp ... INCLUDE=TABLE INCLUDE=INDEX:"LIKE '%PK'"
Um alles außer Constraints zu exportieren, genügt folgende Parametrierung: $ expdp ... EXCLUDE=CONSTRAINT
Die Dump-Datei(en) wird (werden) durch den Data-Pump-Export erstellt und dürfen vorher nicht existieren. Dies bedeutet, dass z.B. unter Unix keine Named Pipes als Dump-Datei verwendet werden können. Die Möglichkeit einer gleichzeitigen Komprimierung oder Übertragung via ftp oder scp (siehe konventioneller Export/ Import) ist mit Data Pump daher nicht gegeben. Eine Alternative, um zumindest Export- und Übertragungsvorgang zu parallelisieren, wird weiter unten beschreiben. Data-Pump-Import Import kann Data-Pump-Exportdateien lesen und logisch gesicherte Datenbankstrukturen und -objekte wiederherstellen. Genau wie Data-Pump-Export kann Data-Pump-Import im Zeilenmodus oder mit einer Parameterdatei betrieben werden. Der Import muss nicht durch denselben Benutzer durchgeführt werden, der den Export durchgeführt hat. Alle beschriebenen Exportparameter außer FILESIZE finden sich mit analoger Bedeutung auch beim Import. Einige wichtige importspezifische Parameter werden im Folgenden vorgestellt: Importparameter
Bedeutung
TABLE_EXISTS_ACTION
Was passiert, wenn eine zu importierende Tabelle bereits vorhanden ist? SKIP (keine Aktion, Default), APPEND (Daten werden eingefügt), TRUNCATE (der Tabelleninhalt wird ersetzt) oder REPLACE (die Tabelle wird gelöscht und neu erstellt)
REMAP_SCHEMA
REMAP_SCHEMA=SCHWANKE:AHRENDS bewirkt, dass alle exportierten Objekte des Benutzers SCHWANKE in das Schema AHRENDS importiert werden. Der Parameter kann beliebig oft vorkommen.
REMAP_TABLESPACE
REMAP_TABLESPACE=TOOLS:USERS bewirkt, dass alle TablespaceKlauseln entsprechend angepasst werden. Der Parameter kann beliebig oft vorkommen.
Tabelle 10.2: Zusätzliche Parameter für den Data-Pump-Import
Benutzung des direkten Pfads Beim so genannten Direct-Path-Export wird aus dem Buffer-Cache direkt in die Exportdatei geschrieben. Der Puffer für die Auswertung der Blöcke wird umgangen, wodurch der direkte Pfad des Exports signifikante Verbesserungen der Performance bringt. Wie groß die Performance-Vorteile sind, ist von der Datenbankblockgröße und der IO-Bandbreite abhängig.
Objektbasierte Techniken
547
Analog wird es bei einem Direct-Path-Import ermöglicht, direkt in freie Blöcke zu schreiben, ohne über die SGA zu gehen, auch hier mit deutlichen PerformanceGewinnen. Sowohl Data-Pump-Export als auch Data-Pump-Import benutzen – wenn möglich – den direkten Pfad, was insbesondere beim Import einen erheblichen Performance-Gewinn gegenüber dem konventionellen Import darstellt, der dazu nicht fähig ist. In einigen Fällen ist jedoch kein Direct-Path-Import möglich, nämlich bei: Tabellen mit aktiven (enabled) Fremdschlüssel-Constraints Tabellen mit aktiven (enabled) Triggern Tabellen mit Regeln für Fine Grained Access für Einfüge-Operationen Tabellen, die anders partitioniert sind als während des Exports Weitere, seltene Ausnahmen sind in der Dokumentation aufgeführt. Wenn eine dieser Ausnahmebedingungen erfüllt ist, wird die Dump-Datei als externe Tabelle behandelt. Der Zugriffstreiber ORACLE_DATAPUMP ist in der Lage, das Data-Pump-Dateiformat zu lesen. Anschließend wird der konventionelle Pfad für den Import benutzt. Der Benutzer hat keinen Einfluss darauf, welcher Pfad genutzt wird; Data Pump entscheidet dies autonom. Wegen des Performance-Verlusts sollte abgeklärt werden, ob es nicht möglich ist, Fremdschlüssel und Trigger vor dem Import und für die Dauer des Imports zu deaktivieren. Monitoring von Data-Pump-Jobs Alle
aktiven
Data-Pump-Jobs
können
über
die
Data-Dictionary-View
dba_datapump_jobs identifiziert werden. Hier sind alle Jobs zu sehen, solange sie
nicht erfolgreich beendet oder abgebrochen wurden, insbesondere also auch abgestürzte oder explizit unterbrochene Jobs. Die Spalte state gibt den aktuellen Status des Jobs wieder. SELECT FROM WHERE AND
operation, job_mode, state, degree dba_datapump_jobs owner_name = 'SCHULUNG' --Benutzer job_name = 'MYEXPJOB'; --Jobname
Während des eigentlichen Imports oder Exports wird außerdem eine Fortschrittsprotokollierung über die View v$session_longpos gepflegt. Die Spalten sofar und totalwork geben an, wie viele Daten schon übertragen wurden und wie viel insgesamt übertragen werden muss. SELECT FROM WHERE AND
target_desc, sofar, totalwork, units v$session_longops username = 'SCHULUNG' --Benutzer opname = 'MYEXPJOB'; --Jobname
548
Wiederherstellungstechniken
Administration laufender Data-Pump-Jobs Über die Client-Utilities expdp und impdp ist es auch möglich, sich jederzeit während der Lebenszeit eines Jobs in diesen Job »einzuklinken«, z.B. um festzustellen, warum der Job unterbrochen wurde, ggf. Umparametrierungen vorzunehmen und den Job anschließend wiederaufzunehmen. Durch den Aufruf $ expdp schwanke@ps10 attach=myexpjob
wird eine einfache Kommandozeilen-Shell gestartet, über die der Job mit dem Namen myexpjob jederzeit administriert werden kann. In diesem »interaktiven Modus« läuft der Job im Hintergrund weiter (sofern er nicht gerade gestoppt wurde), die üblichen Fortschrittsmeldungen werden jedoch nicht ausgegeben. Stattdessen stehen innerhalb dieser Shell folgende Kommandos zur Verfügung: STOP_JOB, START_JOB, KILL_JOB: Damit lässt sich der Job anhalten, wiederaufnehmen bzw. endgültig abbrechen. PARALLEL= ändert den Parallelisierungsgrad des Jobs ADD_FILE=[:] ist nur für Export-Jobs verfügbar und bewirkt, dass eine weitere Dump-Datei zur Ausgabe benutzt werden kann. Dieses Kommando wird z.B. benutzt, nachdem ein Job wegen Platzmangels in den Dump-Dateien unterbrochen ist. STATUS gibt den aktuellen Status des Jobs aus. Über STATUS= wird dies alle Sekunden ausgegeben. Über das Kommando EXIT_CLIENT wird die Shell wieder verlassen. Alternativ kann mit dem Befehl CONTINUE_CLIENT die Job-Ausführung wieder in den Vordergrund geholt werden, d.h., es werden wieder Fortschrittsmeldungen angezeigt, Kommandos können jedoch nicht eingegeben werden. Dies ist derselbe Zustand, der auch beim ursprünglichen Start eines Data-Pump-Jobs vorliegt. Mittels CTRL+C kann wieder in den interaktiven Modus und damit die Kommando-Shell zurückgewechselt werden. Data Pump und Globalization Support Data Pump benutzt die Einstellungen der Umgebungsvariablen NLS_LANG lediglich für die Interaktion mit dem Benutzer. Als Zeichensatz für den Data-Pump-Export wird der Datenbankzeichensatz verwendet und in der Dumpdatei vermerkt. DataPump-Import vergleicht dann den Zeichensatz aus der Dump-Datei mit dem Zeichensatz der Zieldatenbank und führt entsprechende Konvertierungen automatisch durch. Parallelisierung von Export und Dateitransfer Wenn Data Pump für eine Übertragung von Daten zwischen zwei Datenbanken genutzt werden soll, fällt nach der bisherigen Beschreibung eine dreistufige Vorgehensweise an: der Export auf dem Quellserver, die Übertragung der Dump-Dateien (z.B. mittels ftp oder scp) und abschließend der Import auf dem Zielserver.
Objektbasierte Techniken
549
Aus Performance-Gründen kann der Übertragungsvorgang mit einem der beiden anderen Schritte zusammengefasst werden. Im Folgenden wird beschrieben, wie Export und Dateitransfer auf diese Weise »gepipelined« werden können. Dazu wird der Export des Quellservers vom Zielserver aus durchgeführt. Alle zu exportierenden Daten werden via Datenbank-Link vom Quellserver gelesen und in DumpDateien auf den Zielserver geschrieben. Diese können anschließend ganz normal importiert werden. Voraussetzung hierfür ist lediglich, dass auf dem Zielserver ein Datenbank-Link zum Quellserver existiert, über den die Daten gelesen werden können. Ggf. muss dieser zuvor erstellt werden. Existiert ein entsprechender Datenbank-Link mit dem Namen SUNDB, wird der Export z.B. wie folgt parametriert: $ expdp schwanke@ps10 directory=pumpdir dumpfile=myexp.dmp logfile=myexp.log schemas=schwanke job_name=myexpjob network_link=sundb
Alle Objekte werden nun von der Datenbank gelesen, auf die der Datenbank-Link SUNDB zeigt, die Dump-Dateien werden ins Dateisystem der zum TNS-Namen PS10 gehörigen Datenbankservers geschrieben und können von dort aus importiert werden. Alternativ kann auf dem Quellsystem der Export normal durchgeführt und anschließend ebenfalls auf dem Quellserver via Datenbank-Link direkt in den Zielserver importiert werden. Bei dieser Variante muss der Datenbank-Link offenbar »in die entgegengesetzte Richtung zeigen«. In beiden Varianten entfällt der Dateitransfer vollständig, stattdessen werden die eigentlichen Daten über einen Datenbank-Link, also via Oracle Net, übertragen. Daher bilden diese zwei Varianten auch Lösungen für restriktive Umgebungen, in denen der Dateitransfer aus Sicherheitsgründen nicht möglich ist (z.B. bei gesperrten ftp- und scp-Ports). Bei der Übertragung via DB-Link findet natürlich auch eine Zeichensatzkonvertierung statt. Bei der ersten Variante enthält die Dump-Datei daher die NLS-Einstellungen des Zielservers. Auch hier gilt aber, dass während des gesamten Ablaufs eine korrekte NLS-Konvertierung automatisch und unabhängig von Client-Einstellungen erfolgt. Leider ist mit diesem Verfahren kein Export bzw. Import aus/in Datenbanken älterer Versionen möglich. Beide beteiligten Datenbanken müssen Oracle 10g-Datenbanken sein.
550
Wiederherstellungstechniken
Spezialfunktionen Mit Data Pump können auch Migrationen vom Datentyp LONG in die Datentypen CLOB oder NCLOB durchgeführt werden. Beispielsweise sei die Tabelle artikel betrachtet: SQL> DESCRIBE artikel Name -----------------ARTIKEL_NR NAME BESCHREIBUNG
Null? -------NOT NULL NOT NULL
Typ ----------------------NUMBER VARCHAR2(100) LONG
Eine Umwandlung der Spalte beschreibung in den Datentyp CLOB kann mittels Data Pump wie folgt realisiert werden: Export der alten Tabelle: $ expdp schwanke@ps10 directory=pumpdir dumpfile=longtab.dmp logfile=longtab.log tables=artikel job_name=longexp
Ersetzen der alten Tabelle durch eine neue, leere Tabelle mit Datentyp CLOB statt LONG. SQL> ALTER TABLE artikel RENAME TO artikel_old; SQL> 2 3 4
CREATE SELECT FROM WHERE
TABLE artikel AS artikel_nr, name, EMPTY_CLOB() AS beschreibung artikel_old 0 = 1;
Import in die neue Tabelle: $ impdp schwanke@ps10 directory=pumpdir dumpfile=longtab.dmp logfile=longtab.log tables=artikel job_name=lobimp table_exists_action=append
10.6.2 Export und Import Export und Import sind ein Paar von Werkzeugen, die zur Datenbank-Software gehören. Gemeinsam stellen sie den Vorgänger des mit Oracle 10g eingeführten Tools Data Pump dar (siehe Abschnitt Data Pump). Während Data Pump ausschließlich auf Oracle 10g-Datenbanken anwendbar ist, können mit Export und Import auch Datenbanken älterer Versionen angesprochen werden, insbesondere sind Migrationen oder Datentransfer zwischen Oracle 10g- und älteren Datenbanken damit möglich. Zur besseren Unterscheidung werden die beiden Tools Export und Import auch als konventioneller Export/Import bezeichnet.
Objektbasierte Techniken
551
Mit dem Exportwerkzeug alleine können Sicherungen, in Zusammenarbeit mit dem Importwerkzeug aber auch versions- und plattformübergreifende Migrationen und Reorganisationen einzelner Objekte, Benutzer, Tablespaces oder auch der ganzen Datenbank erstellt werden. Dabei werden neben den Daten auch die Befehle zur Erstellung der Datenbankobjekte, wie Tablespaces, Tabellen, Indizes, Benutzer usw., in einem Oracle-eigenen Binärformat in einer Exportdatei, auch Dump-Datei genannt, abgelegt. Dieses Format kann ausschließlich über das Werkzeug Import, das Gegenstück zum Export, gelesen und verarbeitet werden, um die Strukturen und Daten wieder in eine vorhandene Datenbank einzuspielen. Eine Kompatibilität zum Dump-Dateiformat von Data Pump besteht leider nicht. Export kennt vier verschiedene Granularitäten: TABLE: In dieser Variante werden einzelne Tabellen und/oder Partitionen sowie optional auch abhängige Objekte, d.h. Indizes, Constraints, Trigger sowie Objekt-Privilegien, zu den betreffenden Tabellen exportiert. Es kann auch ausgewählt werden, ob lediglich die Tabellenstruktur oder auch der Inhalt exportiert werden soll. USER (OWNER): Diese Granularität wird benutzt, um alle Datenbankobjekte eines Benutzers, also sein vollständiges Schema (Tabellen, Views, Synonyme, PL/SQLObjekte etc.), zu exportieren. FULL: Mit dieser Variante wird die gesamte Datenbank exportiert, also alle Benutzer, aber auch beispielsweise Tablespace-Definitionen, Rollen, DirectoryObjekte und Public-Synonyme, also Objekte, die nicht einem bestimmten Benutzer zugeordnet werden können. Dieser Modus ist aber zumeist nur im Rahmen von Migrationen kleinerer Datenbanken zu empfehlen, da der zugehörige Import ansonsten sehr zeitaufwändig wird. TABLESPACE: Diese Variante bildet einen Sonderfall, da ausschließlich Meta-Informationen über einen Tablespace exportiert werden. Die eigentlichen Daten werden durch ein Kopieren der zugehörigen Datendateien auf Betriebssystemebene übertragen. Das »Einhängen« des Tablespace in eine andere wird auf diese Weise ermöglicht, indem auf der Zieldatenbank ein entsprechender Import im TABLESPACE-Modus durchgeführt wird. Für nähere Informationen und Anwendungen hierzu siehe Abschnitt 15.1.1 (Transportable Tablespaces). Welche Granularität benutzt wird und welche Objekte in der gewählten Einheit berücksichtigt werden, wird über die Parametrierung des Exportbefehls ausgewählt, ebenso wie der Name der Exportdatei, Puffergrößen, Konsistenzanforderungen und einiges mehr. Jeder Anwender kann seine eigenen Daten, also Objekte seines Schemas, exportieren. Soll ein Export eines anderen Benutzers, ein Tablespace-Export oder ein Export der gesamten Datenbank ausgeführt werden, so muss der Anwender, unter dessen Namen der Export ausgeführt wird, entsprechende Privilegien besitzen, um die fremden Objekte lesen zu können. Dazu existiert eine vorgefertigte Rolle exp_full_ database.
552
Wiederherstellungstechniken
Die Liste aller Parameter, von denen einige Standardeinstellungen haben, bekommt man durch den Aufruf: $ exp help=y
Export kann in drei verschiedenen Modi ausgeführt werden: Interaktiv Zeilenmodus Verwendung einer Parameterdatei Im interaktiven Modus werden vom Anwender Eingaben für die wichtigsten Parameter verlangt. Jedoch können hier nicht alle möglichen Parameter spezifiziert werden. Im Zeilenmodus werden die Parameter positionell, d.h. in der vom Export vorgegebenen Reihenfolge, oder, was üblicher ist, über die Parameternamen direkt beim Aufruf eingegeben. $ exp system file=export_full_04112001.dmp full=y consistent=y
Besonders für wiederkehrende Exports empfiehlt sich die Verwendung einer Parameterdatei. Dazu werden die Parameter in eine Datei geschrieben, die dann beim Exportaufruf als parfile spezifiziert wird. $ exp parfile=parameterdatei.par
Im Folgenden werden die am häufigsten benutzten Exportparameter vorgestellt. Einige Parameter können nur die Werte Y oder N annehmen. In diesem Fall wird der Parameter als gesetzt oder nicht gesetzt bezeichnet. Exportparameter
Bedeutung
USERID
Benutzername/Kennwort@NetAlias. Das Kennwort kann weggelassen werden und wird dann interaktiv abgefragt.
FILE
Liste von Ausgabedateien, z.B. (file1.dmp,file2.dmp)
FILESIZE
Maximale Größe jeder Dump-Datei
LOG
Name der Log-Datei
TABLES
Liste zu exportierender Tabellen und/oder Partitionen, jeweils in der Form [Schema.]Tabelle[:Partition], z.B. (KUNDEN,AUFTRAEGE,AUFPOSITIONEN). Impliziert die Granularität TABLE.
GRANTS, INDEXES, TRIGGERS, CONSTRAINTS
Falls gesetzt, werden die zu den Tabellen gehörenden Privilegien, Indizes, Trigger bzw. Constraints ebenfalls exportiert
ROWS
Falls gesetzt, werden auch die Inhalte von Tabellen exportiert
QUERY
Export einer Teilmenge aller Zeilen entsprechend der angegebenen WHERE-Klausel (siehe unten)
OWNER
Liste der zu exportierenden Benutzer, z.B. (HLADMIN). Impliziert die Granularität USER.
FULL
Granularität FULL, falls gesetzt
Tabelle 10.3: Parameter für den konventionellen Export
Objektbasierte Techniken
553
Exportparameter
Bedeutung
COMPRESS
Falls gesetzt, werden beim nachfolgenden Import alle Daten in ein einziges Extent geladen (siehe unten)
DIRECT
Falls gesetzt, direktes Lesen aus den Datendateien unter Umgehung der Instanz (siehe unten)
CONSISTENT
Falls gesetzt, werden alle Daten mit demselben Konsistenzzeitpunkt gelesen (siehe unten)
TRANSPORT_TABLESPACE
Falls gesetzt, Export mit der Granularität TABLESPACE
TABLESPACES
Liste der zu exportierenden Tablespaces (nur bei Granularität TABLESPACE)
Tabelle 10.3: Parameter für den konventionellen Export (Forts.)
Einige der vorgestellten Parameter sollen an dieser Stelle noch genauer erläutert werden: COMPRESS
Dieser Parameter (Standardeinstellung Y) bewirkt, dass der initiale Extent der zu exportierenden Tabelle abhängig vom Füllgrad der jetzigen Tabelle neu berechnet wird. Der ungefähre Wert ergibt sich aus der Summe der zurzeit allokierten Extents. Das bedeutet, dass beim Import ein einzelnes Extent mit der Gesamtgröße der jetzigen Tabelle angelegt wird. Dies kann bei großen Tabellen zu Problemen führen, weil z.B. eine einzelne Datendatei nicht ausreichend Platz bietet. Vor dem Hintergrund der Tatsache, dass seit Oracle8i die Problematik großer Extentzahlen durch Locally-Managed Tablespaces beseitigt wurde, empfehlen wir, diesen Parameter stets explizit auf N zu setzen. Diese Empfehlung gilt auch für Dictionary-Managed Tablespaces. CONSISTENT
Bei einem Export, der bei laufendem Oracle-System ausgeführt wird, wird jede Tabelle für sich lesekonsistent exportiert. Bei Fremdschlüsselbeziehungen der Tabellen untereinander kann es passieren, dass z.B. Auftragsdatensätze exportiert werden, deren zugehöriger Kunde nicht exportiert wurde, weil er beim Export der Kundentabelle noch nicht existierte. Durch Setzen des Parameters CONSISTENT werden alle Tabellen konsistent exportiert. Der Nachteil hierbei ist, dass die Anforderungen an die Undo-Segmente bei lange laufenden Exports und gleichzeitig hoher Transaktionslast auf dem System entsprechend groß sind. Es besteht die Gefahr eines ORA-01555: Snapshot too old. QUERY
Um nur eine Teilmenge einer oder mehrerer Tabellen, z.B. alle Aufträge des Kunden mit der Kunden-Nr. 100, auszulesen, kann eine Filterbedingung in Form einer WHERE-Klausel mitgegeben werden. $ exp hladmin/hladmin file=exp_schwanke.dmp tables=auftraege query="where kdnr=100"
Die WHERE-Klausel wird in doppelte Hochkommata eingeschlossen, da Leerzeichen innerhalb der Klausel auftreten. Je nach Betriebssystem und verwendeter Kom-
554
Wiederherstellungstechniken
mando-Shell müssen die doppelten Hochkommata ggf. noch mit Escape-Zeichen versehen werden. Der Parameter kann nur bei der Granularität TABLE angegeben werden. Die angegebene Filterbedingung muss auf alle spezifizierten Tabellen anwendbar sein. Dies ist leider immer dann ein Problem, wenn z.B. die Kunden-Nr. in verschiedenen Tabellen leicht unterschiedliche Namen hat (z.B. kd_kdnr in der Kundentabelle, auf_kdnr in der Aufträgetabelle) Achtung: Aus der Exportdatei ist anschließend nicht mehr ersichtlich, dass der Export mit Filterbedingungen ausgeführt wurde. DIRECT
Beim so genannten Direct-Path-Export wird aus dem Buffer-Cache direkt in die Exportdatei geschrieben. Der Puffer für die Auswertung der Blöcke wird umgangen, wodurch der direkte Pfad des Exports signifikante Verbesserungen der Performance bringt. Wie groß die Performance-Vorteile sind, ist von der Datenbankblockgröße und der IO-Bandbreite abhängig. Außerdem können keine Filterbedingungen angegeben werden (Parameter QUERY). Achtung: Im Rahmen von Virtual Private Database und Oracle Label Security (siehe Abschnitt 9.6) definierte Zugriffsrechte auf einzelnen Tabellenspalten werden beim Direct-Path-Export nicht (!) berücksichtigt, da diese ebenfalls auf Filterbedingungen beruhen. Komprimieren von Exportdateien Oftmals stellt sich die Frage, ob es möglich ist, die Exportdatei(en) während des Exportierens zu komprimieren, um Zeit und Platz zu sparen. Unter dem Betriebssystem Unix kann dies über sog. Named Pipes realisiert werden. Mit dieser Methode ist es möglich, vom Export aus in die Pipe zu schreiben und z.B. mit einem GZip-Befehl aus dieser zu lesen: $ /sbin/mknod /tmp/exp_pipe p $ exp demo/demo compress=n tables=kunden file=/tmp/exp_pipe > export.log 2>&1 & $ cat /tmp/exp_pipe | gzip -c > /tmp/exp_user.ora & Listing 10.48: Listing 10.1: Export mit gleichzeitiger Komprimierung der Dump-Datei
Das Ergebnis eines Exports ist also eine logische Sicherung der internen Strukturen der gesamten Datenbank oder von Objekten aus ausgesuchten Bereichen. Diese logische Sicherung kann gesamt oder partiell mit dem Importwerkzeug in eine Oracle-Datenbank zurückgespielt werden, eine Wiederherstellung aller nach dem Export erfolgter Transaktionen über die Redo-Log-Dateien kann jedoch nicht angeschlossen werden.
Objektbasierte Techniken
555
Import Import kann Exportdateien lesen und logisch gesicherte Datenbankstrukturen und -objekte wiederherstellen. Genau wie Export kann Import im interaktiven Modus, im Zeilenmodus oder mit einer Parameterdatei betrieben werden. Auch hier werden im interaktiven Modus nur die wichtigsten Parameter angeboten. Wollen Sie spezielle Parameter spezifizieren, so müssen Sie den Zeilenmodus oder die Parameterdatei nutzen. Import-Parameter
Bedeutung
USERID
Analog zu Export
FILE
Liste von Eingabedateien, z.B.(file1.dmp,file2.dmp)
FILESIZE
Beim Export angegebene Maximalgröße der Dump-Dateien
LOG
Log-Datei mit Inhalt der Bildschirmausgabe
TABLES
Liste zu importierender Tabellen und/oder Partitionen, Format analog zu Export
GRANTS, INDEXES, CONSTRAINTS
Falls gesetzt, werden die zu den Tabellen gehörenden Privilegien, Indizes bzw. Constraints ebenfalls importiert.
ROWS
Falls gesetzt, werden auch die Inhalte von Tabellen importiert
SHOW
Nur Inhalt der Dump-Datei, kein tatsächlicher Import
IGNORE
Fehler beim Erstellen von DB-Objekten ignorieren (siehe unten)
FULL
Falls gesetzt, gesamten Inhalt der Dump-Datei importieren
FROMUSER, TOUSER
Nur die Objekte der unter FROMUSER aufgelisteten Benutzer werden importiert, z.B. FROMUSER= (AHRENDS,SCHWANKE).Optional enthält TOUSER eine Liste der zugehörigen Zielschemata (siehe unten)
COMMIT, BUFFER
Einstellen eines Commit-Intervalls (siehe unten)
INDEXFILE
Schreibt ein Erstellungsskript für Tabellen und Indizes in die angegebene Datei (siehe unten)
RESUMABLE, RESUMABLE_NAME, RESUMABLE_TIMEOUT
Der Import wird als so genannte »Resumable Session« ausgeführt. Dies ist für umfangreichere Ladevorgänge im Rahmen von Data Warehouses interessant (siehe Kapitel 14).
Tabelle 10.4: Parameter für den konventionellen Import
556
Wiederherstellungstechniken
Auch hier seien wieder einige wichtige Parameter gesondert erläutert: IGNORE
Import erwartet, dass die zu importierenden Objekte, insbesondere Tabellen, nicht in der Zieldatenbank existieren. Folgt man jedoch dem Ratschlag, bei einer Reorganisation Tabellen vorher mit passenden Speicherplatzparametern anzulegen, so muss dem Importprozess mitgeteilt werden, dass die existierenden Objekte benutzt und Fehlermeldungen, die sich auf das Vorhandensein des Objekts beziehen, ignoriert werden sollen. FULL
Im Kontext des Imports bedeutet FULL, dass alle Objekte aus der angegebenen Exportdatei importiert werden sollen. FROMUSER/TOUSER
Über FROMUSER/TOUSER können Datenbankobjekte zwischen Schemata bewegt werden. Mit FROMUSER wird angegeben, unter welchem Schema die Objekte in der Exportdatei liegen, mit TOUSER, in welches Schema sie in die Zieldatenbank geschrieben werden sollen. Dazu sind entsprechende Privilegien des Prozesses nötig, der den Import ausführt. Anzuraten ist, solche Aktivitäten als DBA-Benutzer zu starten. Exports, die von einem DBA durchgeführt wurden, können auch nur von einem DBA wieder importiert werden. FROMUSER kann auch dazu verwendet werden, aus einem FULL-Export nur Objekte eines Schemas selektiv zu importieren. COMMIT
Import führt einen Commit-Befehl nach erfolgtem Import aller Daten einer Tabelle aus, was bei großen Tabellen zu extremen Anforderungen an die Undo-Segmente der Zieldatenbank führen kann. Über die Einstellung COMMIT=Y wird ein CommitBefehl nach jedem Puffer, dessen Größe über BUFFER=NNNNN eingestellt werden kann, ausgeführt. INDEXFILE
Mit dem Befehl: imp schwanke@hlsun1 file=expdat.dmp indexfile=create_index.sql
können Sie aus einer bestehenden Exportdatei ein SQL-Skript generieren lassen, das Befehle zum Anlegen der Indizes beinhaltet, die durch den Import erzeugt würden. Auch sämtliche Befehle zum Anlegen der Tabellen werden in die angegebene Datei geschrieben, sind jedoch als Kommentar gekennzeichnet. Der Sinn dieses Skripts ist es, den Import ohne Indizes durchführen und diese dann später mit einer speziell definierten sort_area_size, eventuell auch parallelisiert, anlegen zu können. Durch Setzen des Parameters CONSTRAINTS werden auch Indizes, die über einen Primärschlüssel definiert worden sind, hier berücksichtigt. Es ist so aber auch eine elegante Möglichkeit geboten, Skripte für den Neuaufbau einer Datenbank zu generieren und diese mit eventuell vorhandenen Skripten abzugleichen.
Objektbasierte Techniken
557
Globalization Support für Export und Import Frühere Versionen von Export und Import haben für den Datenstrom die Zeichensatzkomponente der Umgebungsvariablen NLS_LANG ausgewertet. Dies führte oft zu Fehlern, bei denen z.B. Umlaute verloren gegangen sind. Seit Oracle9i Release 2 verwendet der Export den Datenbankzeichensatz. Dieser Zeichensatz wird in der Exportdatei abgelegt. Import interpretiert dann den Zeichensatz aus der Exportdatei und führt entsprechende Konvertierungen (ebenfalls ohne Umweg über den Client-Zeichensatz) durch. Grundsätzlich ist zu empfehlen, sowohl für den Export als auch für den Import die Umgebungsvariable NLS_LANG auf den Zeichensatz der Quell-Datenbank zu setzen, auch wenn die Zieldatenbank einen anderen Zeichensatz hat. Export und Import über Named Pipes unter Unix Gerade bei der Migration von Datenbanken oder der Umstellung der Hardware auf einen neuen Anbieter stellt sich die Frage, wie die gesamte Anwendung übertragen werden kann. Ein Export in eine Datei mit nachfolgendem Import verbraucht aufgrund des seriellen Charakters unnötig Zeit und Platz. Wünschenswert ist hier eine Parallelisierung von Export und Import. Hier kann man unter Unix auf Named Pipes zurückgreifen, die sich vom Betriebssystem wie normale Dateien ansprechen lassen und somit zwei unterschiedlichen Prozessen ermöglichen, in die Pipe zu schreiben bzw. aus ihr zu lesen. Ein Export-/Import-Vorgang kann über dieses Hilfsmittel wie folgt realisiert werden. $ $ $ $ $
/sbin/mknod /tmp/exp_pipe p rsh hlsun1 -l oracle "/usr/sbin/mknod /tmp/exp_pipe p" cat /tmp/exp_pipe | rsh hlsun1 -l oracle "cat > /tmp/exp_pipe" & exp system/manager file=/tmp/exp_pipe parfile=exp.par & rsh hlsun1 -l oracle "imp system/manager file=/tmp/exp_pipe parfile=/tmp/imp.par log=/tmp/imp.log"
Listing 10.49: Export-/Import-Vorgang über Named Pipes unter Unix
Es soll nochmals deutlich darauf hingewiesen werden, dass ein Export immer nur eine Ergänzung zur physischen Sicherung sein kann. Der Datenbankadministrator übernimmt beim Import einer einzelnen Tabelle die Gewähr für die logische Konsistenz der Datenbank. Auch wenn mit einer Tabelle Constraints verbunden sind, lassen sich diese beim Import ausschalten. LONG- nach LOB-Migration Analog zu dem in Kapitel Data Pump vorgestellten Verfahren kann auch mit dem konventionellen Export/Import eine Migration vom Datentyp LONG nach CLOB oder NCLOB durchgeführt werden.
558
Wiederherstellungstechniken
10.6.3 LogMiner Mit Oracle8i hat Oracle den LogMiner eingeführt, mit dem die Informationen der Online- und Offline-Redo-Log-Dateien ausgelesen werden können. Das Werkzeug ist zunächst über eine Reihe von PL/SQL-Prozeduren realisiert und seit Oracle9i durch eine grafische Oberfläche im Enterprise Manager ergänzt worden. Damit besteht jetzt die Möglichkeit, ein Undo oder Redo einer Transaktion durchzuführen. Außerdem kann ein Audit erfolgen, da alle DDL- und DML-Befehle in den RedoLog-Dateien gespeichert sind. Die Quelldatenbank und die Mining-Datenbank können voneinander getrennt sein. In diesem Fall ist es möglich, aus einer Oracle 10g-Datenbank als MiningInstanz die Redo-Log-Dateien einer Oracle8-Datenbank (bis hinunter zu Version 8.0.6) zu verarbeiten. In Oracle8 muss hierzu das Package dbms_logmnr_d mit den entsprechenden Skripten aus $ORACLE_HOME/rdbms/admin einer neueren Datenbankversion erstellt werden. Der Aufbau des LogMiners basiert auf einem Daten-Repository, das die Struktur der zu analysierenden Datenbank enthält. Notwendig ist dies, um eine Beziehung zwischen den Objekt-IDs und den Objektnamen herzustellen. Dieses Repository muss in einer Oracle-Datenbankversion 8.1 oder höher installiert werden. Es ist zwar theoretisch möglich, auch ohne ein Repository zu arbeiten; da aber dann die Objektnamen fehlen, ist es schwierig, die ermittelte Information auszuwerten. Während dieses Repository in der Version 8.1 nur als einfache Datei zur Verfügung stand, gibt es ab der Version 9 auch die Möglichkeit, das Data Dictionary zu nutzen oder die Dictionary-Information in einer Redo-Log-Datei mit abzuspeichern. Folgende Vor- und Nachteile ergeben sich bei der jeweiligen Verwendung eines Dictionarys: Online Dictionary Das Online-Data-Dictionary wird bei der lokalen Anwendung des LogMiners (Quell-Datenbank und Mining-Instanz sind gleich) benutzt. SQL> EXECUTE DBMS_LOGMNR.START_LOGMNR( OPTIONS => DBMS_LOGMNR.DICT_FROM_ONLINE_CATALOG); Listing 10.50: LogMiner mit Online Dictionary
Dictionary als Datei Es ist notwendig, mit einem Befehl (PL/SQL-Prozedur oder Enterprise Manager LOGMINER VIEWER) eine solche Datei im Dateisystem zu erstellen. Diese Datei ist jedoch nur eine Momentaufnahme der Datenbank, so dass jede spätere Änderung an den Datenstrukturen zu einer Inkonsistenz zwischen Dictionary-Datei und tatsächlichem Data Dictionary führt. Als Vorteil muss jedoch gesehen werden, dass der Einfluss auf die Datenbank in diesem Falle am geringsten ist. Voraussetzung für die Verwendung einer externen Datei ist, dass der Initialisierungsparameter utl_file_dir gesetzt ist.
Objektbasierte Techniken
559
SQL> EXECUTE DBMS_LOGMNR_D.BUILD( 'dictionary.ora', 'D:\oracle\admin\udump\dictionary.ora', DBMS_LOGMNR_D.STORE_IN_FLAT_FILE); Listing 10.51: LogMiner mit Datei-Dictionary
Redolog Dictionary Hierbei wird die Information des Data Dictionarys in die Redo-Log-Dateien geschrieben und ist somit über den LogMiner wie auch die DML-Operationen verfügbar. Diese Operation kann je nach Anzahl zu sichernder Objekte die Performance der Datenbank stören und außerdem zu zusätzlichen archivierten RedoLog-Dateien führen. Der Vorteil liegt jedoch bei der besseren Performance des LogMiner Viewers bzw. der entsprechenden PL/SQL-Prozeduren gegenüber einer externen Datei. SQL> EXECUTE DBMS_LOGMNR_D.BUILD( OPTIONS=> DBMS_LOGMNR_D.STORE_IN_REDO_LOGS); Listing 10.52: Redo-Log Dictionary
Allen drei Konfigurationen ist aber gemeinsam, dass sie nur eine Momentaufnahme des Data Dictionarys ermöglichen. Das bedeutet speziell beim Zugriff auf archivierte Redo-Log-Dateien. dass es vorkommen kann, dass es das entsprechende Objekt gar nicht mehr in der Datenbank gibt. Im Weiteren werden wir uns auf die Verwendung des Online-Dictionarys beschränken. Zunächst wird der Umfang der Mining-Sitzung festgelegt. Dieser kann als Zeitdauer (starttime, endtime) oder als SCN (startscn, endscn) festgelegt werden. Während es in der Version 9 noch notwendig war, alle in Frage kommenden Redo-Log-Dateien anzugeben (dbms_logmnr.add_logfile), genügt in der Version 10 die Angabe (dbms_logmnr.continuous_mine), wodurch der LogMiner die notwendigen Online- und archivierten Redo-Log-Dateien selbstständig erkennt. Außerdem können bei dem Aufbau der Mining-Sitzung schon Optionen mitgegeben werden, so z.B. dbms_logmnr.committed_data_only, wodurch die erfasste Datenmenge eingeschränkt werden kann. Diese Option hat aber den Nachteil, dass zunächst die Datenmenge erfasst wird und erst anschließend die Einschränkung erfolgt. Dadurch kann es leicht zum Fehler out of memory kommen. Außerdem haben wir den interessanten Nebeneffekt festgestellt, dass durch diese »Einschränkung« die ermittelte Datenmenge (SELECT COUNT(*) FROM v$logmnr_contents WHERE commit_timestamp IS NOT NULL) teilweise größer war als ohne. Es ist daher oftmals sinnvoller, auf diese Option zu verzichten und erst bei der Darstellung der Ergebnismenge einzuschränken. Das Ergebnis einer Mining-Sitzung kann über die View v$logmnr_contents angezeigt werden. Wie aus dem Namen ersichtlich, handelt es sich hierbei um eine virtuelle Tabelle, die nur während der Mining-Sitzung existiert. Es ist daher erforderlich, die PL/SQL-Prozedur dbms_logmnr.start_logmnr und die Abfrage auf v$logmnr_contents in der gleichen Sitzung auszuführen. Neben den Informationen über die Transaktion (Zeitpunkt, SCN, Segment-Name) enthält diese View die Spalten sql_redo und
560
Wiederherstellungstechniken
sql_undo, womit Transaktionen noch einmal (sql_redo) durchgeführt werden können bzw. zurückgesetzt (sql_undo) werden können. Die Spalte sql_undo ist nur bei
DML-Befehlen gefüllt. In Beispiel wurden einige Tabellen fälschlicherweise geleert, gelöscht und neu angelegt, so dass ein Flashback nicht in Frage kommt. Die Ermittlung des TRUNCATEBefehls über dba_objects ist ebenfalls nicht möglich, da ja nur der letzte DDL-Befehl gespeichert wird. Es muss also herausgefunden werden, wann der erste Löschbefehl stattgefunden hat, eine grobe Zeitangabe gibt es hierbei (zwischen 10:30 Uhr und 11:30 Uhr). Außerdem ist bekannt, welcher Befehl zuerst abgesetzt worden ist (TRUNCATE TABLE kunden). SQL> ALTER SESSION SET NLS_DATE_FORMAT = 'DD.MM.YYYY HH24:MI:SS'; SQL> BEGIN DBMS_LOGMNR.START_LOGMNR( STARTTIME => '17.08.2004 10:30:00', ENDTIME => '17.08.2004 11:30:00', OPTIONS => DBMS_LOGMNR.DICT_FROM_ONLINE_CATALOG + DBMS_LOGMNR.CONTINUOUS_MINE + DBMS_LOGMNR.COMMITTED_DATA_ONLY); END; / SQL> SELECT table_name, timestamp, operation, sql_redo FROM V$LOGMNR_CONTENTS WHERE upper(sql_redo) like '%TRUNCATE TABLE KUNDEN%'; TABLE_NAME TIMESTAMP OPERATION SQL_REDO -------------------------------- ------------------- -------------------------------------------------------KUNDEN 17.08.2004 11:16:09 DDL truncate table kunden; Listing 10.53: Ermittlung der Zeit des ersten DDL-Befehls
In diesem Fall wurde also der Befehl TRUNCATE TABLE kunden um 11:16:09 Uhr ausgeführt, so dass jetzt ein Flashback Database oder ein TSPITR auf diesen Zeitpunkt (Minus 5 Sekunden) erfolgen kann. Natürlich ist es auch möglich, DML-Befehle über den LogMiner zurückzusetzen (Spalte sql_undo). Die Notwendigkeit hierfür hat aber durch die Flashback-Techniken in Oracle 10g an Relevanz verloren und wird daher hier nicht mehr besprochen.
10.6.4 Flashback Query Immer wieder kommt es vor, dass ein Benutzer oder ein Batch-Job fehlerhafte Änderungen durchführt. Ein sehr menschlicher Fehler ist beispielsweise das Vergessen einer WHERE-Klausel in einer UPDATE- oder DELETE-Anweisung. Wird dies erst nach dem COMMIT-Befehl bemerkt, stellt sich natürlich die Frage, wie die dadurch entstandene logische Datenkorruption wieder bereinigt werden kann. Der in Abschnitt 10.6.3 beschriebene LogMiner bietet hierfür eine Möglichkeit; das Verfahren ist jedoch etwas langwierig, da zunächst ein Skript generiert werden muss, das kompensierende Aktionen ausführt. Sind bis zur Ausführung dieses
Objektbasierte Techniken
561
Skripts bereits weitere Änderungen der betroffenen Tabelle eingegangen, verkompliziert dies die Bereinigung eventuell weiter. Ein einfacherer Weg steht bereits seit Oracle9i zur Verfügung, die so genannte Flashback Query. Im Gegensatz zum LogMiner wird hierbei nicht Redo-Log-Information, sondern Rollback-Information genutzt, die ja in Undo-Segmenten in den Datendateien oder sogar im Buffer-Cache steht. Bei näherer Betrachtung stellt man fest, dass Oracle diese Technik schon seit langem verwendet, um bei Abfragen konsistent Daten zu lesen. Flashback Queries stellen nun einfach ein Benutzer-Interface in Form einer bestimmten SQL-Syntax dar, um diese Technik explizit zu nutzen, also z.B. den Inhalt einer Tabelle vor einer Stunde zu sehen: SQL> SELECT * FROM kunden AS OF TIMESTAMP SYSDATE – 1/24;
Vorrausetzungen Damit diese Abfrage ausgeführt werden kann, ist die Verwendung von Automatic Undo Management (siehe Abschnitt 3.3.5) erforderlich. Außerdem müssen natürlich entsprechend alte Rollback-Informationen noch in den Undo-Segmenten vorhanden sind. Dies kann durch den Initialisierungsparameter undo_retention konfiguriert werden. Die Einstellung undo_retention = 7200
bedeutet beispielsweise, dass Rollback-Informationen für zwei Stunden (7200 Sekunden) aufbewahrt werden sollen, bevor sie überschrieben werden. Damit das auch tatsächlich funktionieren kann, muss der Undo-Tablespace ausreichend dimensioniert sein. Über den UNDO ADVISOR im Enterprise Manager kann der Platzbedarf für den Undo-Tablespace abgeschätzt werden. Eine gewisse Reserve, z.B. 10%, sollte von vornherein einkalkuliert oder zumindest über den Auto-ExtendMechanismus der Datendateien verfügbar sein. Ist der Undo-Tablespace zu klein, z.B. durch eine temporär sehr hohe Transaktionslast, werden letztlich auch Rollback-Daten, die jünger sind als undo_retention, überschrieben, damit die Transaktionen und damit die produktive Arbeit nicht unterbrochen werden muss. Eine entsprechende Flashback Query wird dann mit einer Fehlermeldung quittiert: ORA-01555: snapshot too old: rollback segment too small
Mit Oracle 10g ist es auch möglich, die durch undo_retention spezifizierte gewünschte Rückblickzeit zu garantieren: SQL> ALTER TABLESPACE RETENTION GUARANTEE;
Achtung: Dies führt dazu, dass Transaktionen mit einer Fehlermeldung abbrechen, wenn der Undo-Tablespace belegt ist. Daher sollte diese Einstellung nur in Ausnahmesituationen erfolgen und nach Zurückschaltung auf den Normalbetrieb unbedingt wieder deaktiviert werden (Klausel RETENTION NOGUARANTEE).
562
Wiederherstellungstechniken
Anwendung Alternativ zu der oben gezeigten Flashback Query kann statt eines Zeitpunkt auch eine SCN (die interne Änderungsnummer einer DML-Anweisung) angegeben werden. SQL> SELECT * FROM kunden AS OF SCN 312675424;
Da diese jedoch zumeist weniger bekannt ist als der Zeitpunkt, auf den zurückgeschaut werden muss, ist diese Variante für die Praxis weniger geeignet. Intern rechnet Oracle aber auch bei der Timestamp-Variante den angegebenen Zeitpunkt in eine SCN um. Diese Umrechnung geschah bei Oracle9i mit einer Granularität von fünf Minuten; das bedeutet, dass der tatsächliche Rückblick-Zeitpunkt bis zu fünf Minuten vor dem angeforderten Zeitpunkt liegen konnte. Die Flashback Query zu Anfang dieses Kapitels konnte also auch den Tabelleninhalt vor einer Stunde und fünf Minuten zurückliefern. Mit Oracle 10g ist diese Ungenauigkeit auf etwa drei Sekunden reduziert worden. Da der Zeitpunkt einer fehlerhaften DML-Operation im Allgemeinen zunächst nicht besser als ca. eine Minute bekannt ist, ist dies völlig ausreichend. Ist der letztmögliche Zeitpunkt vor der fehlerhaften Anweisung (z.B. durch Trial & Error) gefunden, kann dieser als Rückblick-Zeitpunkt zur Rekonstruktion der Tabelle verwendet werden (da eine Timestamp-Konstante durch das Schlüsselwort TIMESTAMP eingeleitet wird, muss dieses Wort hier tatsächlich zweimal stehen): SQL> CREATE TABLE kunden_vorher AS 2 SELECT * 3 FROM kunden AS OF TIMESTAMP TIMESTAMP '2004-08-10 16:25:30'; SQL> DROP TABLE kunden; SQL> ALTER TABLE kunden_vorher RENAME TO kunden; Listing 10.54: Wiederherstellung der Kundentabelle mit Flashback Query
Der Nachteil hierbei ist, dass abhängige Objekte (Indizes, Constraints, Trigger) manuell neu erstellt sowie Privilegien neu vergeben müssen werden. Dieses Problem tritt bei der Benutzung von Flashback Table (siehe Abschnitt Flashback Table) nicht auf. Die Flashback-Query-Funktion ist daher vor allem zum Einsehen des Tabelleninhalts zu einem bestimmten Zeitpunkt sowie zum Ermitteln eines geeigneten Rücksetz-Zeitpunkts bei logischen Fehlern interessant; für das Rücksetzen selbst sollte stattdessen die Flashback-Table-Funktionalität verwendet werden. Es kann auch nicht über ein TRUNCATE-Kommando, ein Löschen der Tabelle (DROP TABLE) oder irgendein Kommando, das die Spaltenstruktur der Tabelle ändert, hinweggeschaut werden. Für den Fall einer versehentlichen Löschung der Tabelle ist eine Wiederherstellung mittels der Flashback-Table-Funktion (siehe Abschnitt 10.6.5) möglich.
Objektbasierte Techniken
563
Sicherheit DBAs können mit dem Systemprivileg FLASHBACK ANY TABLE für alle Tabellen Flashback Queries ausführen. Andere Benutzer, die nur auf bestimmten Tabellen Flashback Queries ausführen müssen, benötigen neben dem SELECT-Recht auch das FLASHBACK-Privileg. SQL> GRANT SELECT, FLASHBACK ON kunden TO ahrends;
10.6.5 Flashback Table Was ist zu tun, wenn ein Benutzer irrtümlich eine Tabelle gelöscht hat, z.B. weil er zu spät bemerkt hat, dass er sich statt in einer Testumgebung gerade auf dem Produktionssystem befindet? Oder wenn er bei einem UPDATE- oder DELETE-Statement die WHERE-Klausel vergessen hat und dies erst nach dem COMMIT bemerkt? Für das erste Szenario gab es bis einschließlich Oracle9i keine einfache Lösung. Sowohl der Log-Miner (Abschnitt 10.6.3) als auch die Flashback-Query-Funktion (Abschnitt Flashback Query) sind nicht in der Lage, DDL-Operationen wie das Löschen einer Tabelle rückgängig zu machen. Stattdessen musste beispielsweise aus einer möglichst aktuellen Sicherung mittels Rücksicherung und Wiederherstellung zu einem bestimmten Zeitpunkt der Zustand kurz vor der versehentlichen Löschung wiederhergestellt und mittels Export und Import die Tabelle wieder in das Produktionssystem übertragen werden. Im zweiten Fall ist eine Wiederherstellung mit den beiden erwähnten Tools möglich, aber mit einem gewissen Aufwand verbunden. Mit Oracle 10g sind für beide Szenarien alternative, deutlich einfachere Lösungswege geschaffen worden. Beide laufen unter der Bezeichnung Flashback Table, stellen aber ganz unterschiedliche Mechanismen dar. Zurücksetzen von Transaktionen Nachdem z.B. mittels Flashback Queries (siehe Abschnitt 10.6.4) der korrekte Rücksetzzeitpunkt für eine fehlerhafte Transaktion gefunden wurde, kann das eigentliche Zurücksetzen am bequemsten mittels eines FLASHBACK TABLE-Kommandos erfolgen. Dabei werden intern entsprechende kompensierende DML-Operationen generiert und auf die Tabelle angewendet. Alle abhängigen Objekte (Constraints, Indizes, Trigger) sowie Objektprivilegien bleiben erhalten. Zuvor wird die Tabelle exklusiv gesperrt, während des Flashbacks können also keine Benutzer auf der Tabelle arbeiten. Lesende Zugriffe sind jedoch möglich. Voraussetzung ist, dass das so genannte ROW MOVEMENT für die Tabelle aktiviert ist (diese Eigenschaft erlaubt die Wiederherstellung von Zeilen unter einer anderen ROWID). Ist dies nicht der Fall, kann es einfach aktiviert werden: SQL> ALTER TABLE auftraege ENABLE ROW MOVEMENT;
Der Rücksetzzeitpunkt wird analog zu den Flashback Queries entweder als Timestamp oder als SCN angegeben. Bezüglich der Verfügbarkeit entsprechender Rollback-Informationen sowie Security-Regeln gilt ebenfalls das dort Gesagte. Für die auftraege-Tabelle sieht das z.B. so aus:
564
Wiederherstellungstechniken
SQL> FLASHBACK TABLE auftraege TO TIMESTAMP SYSDATE – 45/1440;
Existieren Abhängigkeiten zu anderen Tabellen, kann es natürlich zu Verletzungen von Fremdschlüssel-Constraints kommen. In diesem Fall schlägt das Kommando fehl. Als Ausweg ist hier nur das Deaktivieren des betreffenden Constraints möglich, oder aber es werden beide Tabellen gleichzeitig auf denselben Zeitpunkt zurückgesetzt: SQL> FLASHBACK TABLE auftraege, aufpositionen 2 TO TIMESTAMP SYSDATE – 45/1440;
Auf die Reihenfolge der Tabellen kommt es nicht an. Intern läuft diese Operation in einer Transaktion. Bei einem Fehlschlag bleiben also alle Tabellen auf dem Originalstand. Trigger auf den Tabellen werden standardmäßig für die Dauer der Flashback-Operation deaktiviert. Sollen beispielsweise Protokoll-Trigger dennoch aktiviert bleiben, kann dies (allerdings nur pauschal für alle Trigger) eingestellt werden: SQL> FLASHBACK TABLE auftraege TO TIMESTAMP SYSDATE – 45/1440 2 ENABLE TRIGGERS;
Eine Flashback-Table-Operation kann nicht zurückgerollt werden; jedoch kann durch ein weiteres Flashback Table mit einem etwas früheren Rücksetzzeitpunkt eine Art ROLLBACK simuliert werden. Das Zurücksetzen von Data-Dictionary-Tabellen (um DDL-Operationen rückgängig zu machen) ist nicht möglich. Hierfür muss stattdessen die Flashback-DatabaseFunktion genutzt werden (siehe Abschnitt 10.4). Auch für andere Objekte, die (versehentlich) im SYSTEM-Tablespace liegen, ist kein Flashback möglich. Es sollte z.B. durch die Definition eines datenbankweiter Default-Tablespace verhindert werden, dass Objekte einzelner Benutzer versehentlich im SYSTEM-Tablespace liegen. Wiederherstellen gelöschter Tabellen Zur Rekonstruktion einer gelöschten Tabelle wird derselbe Ansatz benutzt wie bei MS-Windows für Dateien. Oracle hat eine eingebaute Papierkorb-Funktion (»Recyclebin«). Das Löschen einer Tabelle führt bei Oracle 10g nicht mehr zu einem physischen Löschen, sondern die Tabelle wird umbenannt, und es wird ein Flag gesetzt, das indiziert, dass die Tabelle gelöscht ist. Der Speicherplatz wird zunächst nicht freigegeben. Zur Wiederherstellung wird das Flag einfach wieder zurückgesetzt. Natürlich kann auch ein echtes, physisches Löschen angefordert werden. Dieser Mechanismus braucht nicht konfiguriert zu werden, sondern ist von vornherein aktiviert, insofern Locally-Managed Tablespaces verwendet werden. Beispielhaft soll diese Funktionalität anhand der kunden-Tabelle demonstriert werden. Auf der Kundentabelle ist ein Primärschlüssel pk_kunden auf der Spalte kd_nr definiert sowie ein Trigger tr_neuer_kunde, der beim Einfügen eines neuen Kunden eine neue Kundennummer aus einer Sequenz zieht.
Objektbasierte Techniken
565
Nach einem versehentlichen Löschen der Kundentabelle liefert ein Blick in den Papierkorb Folgendes: SQL> SELECT object_name,original_name,type FROM recyclebin; OBJECT_NAME ORIGINAL_NAME TYPE ------------------------------ --------------- ------BIN$H94Oz1MiTs6mZc5CrlGHMQ==$0 PK_KUNDEN INDEX BIN$aHK64lpfTGC5OJtZqJTsXw==$0 TR_NEUER_KUNDE TRIGGER BIN$5gCoXywZQiyCGevvx/rJ4A==$0 KUNDEN TABLE Listing 10.55: Auflistung des Papierkorbinhaltes
Auch alle abhängigen Objekte (Trigger, Indizes, Constraints) sind also noch vorhanden. Die Spalte object_name gibt den (kryptischen) Recyclebin-Namen an. Welches ursprüngliche Objekt sich dahinter verbirgt, ist in den Spalten original_name und type aufgeschlüsselt. Falls dieselbe Tabelle abermals erstellt und gelöscht wurde, können zusätzlich die Spalten createtime und droptime hinzugezogen werden, um eine eindeutige Identifizierung zu ermöglichen. In SQL*Plus gibt es als Abkürzung das Kommando: SQL> SHOW RECYCLEBIN
Die Papierkörbe aller Benutzer können über die View dba_recyclebin abgefragt werden. Auch der Inhalt der gelöschten Tabelle kann abgefragt werden. Die gelöschte Tabelle wird dabei wie eine ganz normale Tabelle behandelt. Allerdings muss der Recyclebin-Name verwendet werden. Da dieser meistens Sonderzeichen und Kleinbuchstaben enthält, ist er in doppelte Hochkommata einzufassen: SQL> SELECT * FROM "BIN$5gCoXywZQiyCGevvx/rJ4A==$0";
Die Wiederherstellung der Tabelle inklusive aller abhängigen Objekte geht nun einfach durch folgenden Befehl: SQL> FLASHBACK TABLE kunden TO BEFORE DROP;
Die Tabelle wird dabei unter ihrem ursprünglichem Namen wiederhergestellt. Dies sollte auch für abhängige Objekte gelten, ein Bug führt jedoch dazu, dass Trigger, Constraints und Indizes unter ihrem Recyclebin-Namen wiederhergestellt werden (bis einschließlich 10.1.0.4 getestet). Hier ist leider ein manuelles Umbenennen mittels entsprechenden ALTER-Kommandos notwendig. Wichtig ist dabei, sich die Originalnamen vor der Wiederherstellung zu merken, da diese nach der Wiederherstellung nicht mehr in der Recyclebin stehen und somit nicht mehr verfügbar sind. Hinzu kommt, dass Constraints gelöschter Tabellen zwar in dba_constraints, nicht aber in dba_recyclebin aufgeführt sind. Befinden sich mehrere Objekte mit demselben Originalnamen im Papierkorb (die Recyclebin-Namen sind in jedem Fall unterschiedlich), wird das jüngste dieser Objekte wiederhergestellt. Alternativ kann explizit eine bestimmte Version des Objekts ausgewählt werden, indem beim Flashback-Kommando statt des Originalnamens der Recyclebin-Name eingesetzt wird, z.B. SQL> FLASHBACK TABLE "BIN$5gCoXywZQiyCGevvx/rJ4A==$0" 2 TO BEFORE DROP;
566
Wiederherstellungstechniken
Hat ein Benutzer vor dem versehentlichen Löschen einer Tabelle bereits DML-Operationen auf der Tabelle ausgeführt, müssen diese nach der Wiederherstellung der Tabelle noch zurückgesetzt werden. Außerdem müssen in jedem Fall Fremdschlüssel-Constraints manuell neudefiniert werden. Es sollte daher zunächst verhindert werden, dass Anwendungen oder Benutzer auf die frisch wiederhergestellte Tabelle zugreifen können. Um dies auszuschließen, wird die Tabelle zunächst unter einem anderen Namen wiederhergestellt. Anschließend wird mittels Flashback Queries ein geeigneter Rücksetzzeitpunkt ermittelt und auf diesen zurückgeschaltet. Zum Schluss wird wieder der Originalname eingesetzt. SQL> SQL> 2 SQL> SQL> SQL> 2 SQL> 2 SQL> 2 SQL>
FLASHBACK TABLE kunden TO BEFORE DROP RENAME TO kunden_fb; FLASHBACK TABLE kunden_fb TO TIMESTAMP TIMESTAMP '2004-08-10 16:25:30'; -- Fremdschlüssel neu definieren -- Ggf. ursprüngliche Namen abhängiger Objekte herstellen ALTER TABLE kunden_fb RENAME CONSTRAINT "BIN$A6ViryXMTIGjZFNgbKpewg==$0" TO kunden_pk; ALTER TRIGGER "BIN$aHK64lpfTGC5OJtZqJTsXw==$0" RENAME TO tr_neuer_kunden ALTER INDEX "BIN$H94Oz1MiTs6mZc5CrlGHMQ==$0" RENAME TO pk_kunden; ALTER TABLE kunden_fb RENAME TO kunden;
Listing 10.56: Beispielskript für die Wiederherstellung der kunden-Tabelle
Da der Speicherplatz gelöschter Tabellen und Indizes nicht mehr unmittelbar freigegeben wird, ist der belegte Platz in einem Tablespace zunächst höher als ohne Papierkorb. Dieser Platz wird auch als belegter Platz bezüglich der Benutzer-Quota gezählt. Dennoch ist der Papierkorb für den Benutzer bzw. die Applikation transparent, da Recyclebin-Objekte automatisch endgültig gelöscht werden, sobald durch CREATE- oder INSERT-Operationen eine Benutzer-Quota überschritten oder eine Datendatei vergrößert würde. Monitoring-Tools, die unter anderem den Füllgrad der Tablespaces bestimmen, bemerken den Papierkorb ebenfalls nicht, da die View dba_free_space, die als Basis für entsprechende Berechnungen benutzt wird, insofern angepasst wurde, dass Papierkorb-Objekte zum Freiplatz gezählt werden. Allerdings werden dadurch auch Abfragen auf diese View langsamer, wenn sich viele Objekte im Papierkorb befinden. In regelmäßigen Zeitabständen sollte der Papierkorb daher geleert werden. SQL> SQL> SQL> SQL>
PURGE TABLE kunden; -- löscht die Kundentabelle endgültig PURGE RECYCLEBIN; -- leert den eigenen Papierkorb PURGE DBA_RECYCLEBIN; -- leert Papierkörbe aller Benutzer DROP TABLE kunden PURGE; -- gar nicht erst in den Papierkorb
Listing 10.57: Verschiedene Kommandos zum endgültigen Löschen von Objekten
Die gesamte Papierkorb-Funktion kann deaktiviert werden, indem der undokumentierte Parameter _recyclebin auf FALSE gesetzt wird.
Ältere Techniken zur Sicherung
10.7
567
Ältere Techniken zur Sicherung
10.7.1 Offline-Sicherung Das einfachste Verfahren für die Sicherung einer Datenbank ist die Offline-Sicherung. Offline bedeutet, dass während der Sicherung keine Änderungen in der Datenbank möglich sind. Dies wird durch folgenden Befehle erreicht: SQL> SHUTDOWN [NORMAL | IMMEDIATE | TRANSACTIONAL];
Nachdem die Instanz heruntergefahren wurde, ist eine Sicherung aller Datenbankdateien im konsistenten Zustand möglich. Zur Offline-Sicherung gehören alle Dateien der Datenbank außer den Dateien der temporären Tablespaces, also Kontrolldateien, Redo-Log-Dateien und sämtliche Datendateien. Um eine aktuelle Liste der zu sichernden Dateien zu erhalten, ist es sinnvoll, die Datenbank in den MOUNT-Status hochzufahren und dann die Informationen aus den Kontrolldateien über entsprechende v$-Views abzufragen. SQL> SQL> SQL> SQL> SQL> SQL> SQL>
STARTUP MOUNT; SET trimspool on; SPOOL backuplist.lst; SELECT name FROM v$datafile; SELECT member FROM v$logfile; SELECT name FROM v$controlfile; SPOOL OFF;
Listing 10.58: Abfragen der v$-Informationen im MOUNT-Status
Hiermit ist sichergestellt, dass auch bei Strukturänderungen der Datenbank jederzeit alle erforderlichen Dateien gesichert werden. Die Dateien der temporären Tablespaces werden nicht gesichert, da sie zum einen keine wichtigen Informationen enthalten und zum anderen im laufenden Betrieb jederzeit wiederhergestellt werden können. Die eigentliche Sicherung erfolgt dann mit Betriebssystembefehlen, wie copy unter MS-Windows oder tar bzw. cpio bei Unix. Natürlich kann hierfür auch eine spezielle Software wie z.B. Veritas NetBackup, HP Omniback oder Brightstor Arcserve genutzt werden. Neben der Sicherung der Datenbankdateien sollte zusätzlich die Parameterdatei (SPFILE oder init.ora) regelmäßig gesichert werden. Nach der Sicherung kann die Datenbank mit einem der folgenden Befehle wieder aktiviert werden: Nach dem Herunterfahren der Instanz: SQL> STARTUP;
568
Wiederherstellungstechniken
Wenn die Instanz im MOUNT-Status war: SQL> ALTER DATABASE OPEN;
Der Nachteil dieses einfachen Verfahrens ist, dass die Datenbank für die Dauer der Sicherung nicht zur Verfügung steht. Außerdem wird die gesamte Datenbank gesichert, d.h. auch Dateien, die wenig oder gar nicht gefüllt sind. Der im Abschnitt 10.3 besprochene Recovery Manager vereinfacht die OfflineSicherung, so dass nur die gefüllten Blöcke weggeschrieben werden. Außerdem ermittelt der Recovery Manager selbstständig die zu sichernden Dateien. Offline-Rücksicherung und Wiederherstellung Die generelle Frage, die sich für ein Offline-Recovery stellt, ist: »Wurde archiviert oder nicht?« Keine Archivierung Wenn keine archivierten Redo-Log-Dateien zur Verfügung stehen, muss davon ausgegangen werden, dass die Datenbank nur auf den Zeitpunkt der letzten Sicherung zurückgesetzt werden kann. Das bedeutet, es gibt keine Wiederherstellung, sondern es werden die Dateien aus der Sicherung in die entsprechenden Verzeichnisse kopiert, und die Instanz wird mit dieser Information hochgefahren. Eine Ausnahme ist, wenn die Online-Redo-Log-Dateien noch zur Verfügung stehen und seit der letzten Sicherung noch keine (!) überschrieben worden ist. Es gibt Datenbanken, bei denen die Anzahl und Größe der Online-Redo-Log-Dateien so bemessen wird, dass diese Möglichkeit besteht. Wir möchten aber davor warnen, damit ein produktives Umfeld zu betreiben. Es reicht eine ungewöhnlich große Transaktion, um dieses Kartenhaus zum Einsturz zu bringen. Archivierung Wenn die Archivierung zum Zeitpunkt des Fehlers eingeschaltet war, kann eine Rücksicherung und eine anschließende Wiederherstellung durchgeführt werden. Die Vorgehensweise unterscheidet sich dabei nicht von derjenigen, die für die Wiederherstellung einer Online-Sicherung notwendig ist. Beispiel: Die Anwendung bricht mit folgender Fehlermeldung ab: ORA-00376: Datei 5 kann zur Zeit nicht gelesen werden ORA-01110: Datendatei 5: '/oradata/JAUX10G/ts_demo01.dbf' Listing 10.59: Fehlerhafte Datendatei
Zunächst wird der Tablespace (in diesem Fall ts_demo) offline gesetzt: SQL> ALTER TABLESPACE ts_demo OFFLINE IMMEDIATE;
Die Option IMMEDIATE muss angegeben werden, weil kein Checkpoint mehr geschrieben werden kann, da ja die zugehörige Datei nicht mehr verfügbar ist.
Ältere Techniken zur Sicherung
569
Die Datei /oradata/JAUX10G/ts_demo01.dbf wird jetzt vom Band wieder eingespielt. Danach erfolgt die Wiederherstellung, und der Tablespace wird wieder online gesetzt: SQL> ALTER DATABASE RECOVER AUTOMATIC DATAFILE '/oradata/JAUX10G/ts_demo01.dbf'; SQL> ALTER TABLESPACE ts_demo ONLINE; Listing 10.60: Offline-Wiederherstellung
10.7.2 Online-Sicherung Für die physikalische Sicherung muss nun ein Werkzeug verwendet werden, das geöffnete Dateien sichern kann. Die unter Unix verwendeten Werkzeuge wie cpio, tar oder dd bieten diese Möglichkeit, unter MS-Windows müssen Werkzeuge von Fremdanbietern benutzt werden, z.B. Arcserve oder Arkaia. Eher zum Testen geeignet ist das von Oracle mit der Datenbank-Software ausgelieferte OCOPY-Programm, das geöffnete Dateien kopieren kann. Während die physikalischen Dateien der Datenbanken gesichert werden, findet nach wie vor uneingeschränkter Schreibbetrieb statt. Aus diesem Grund ist der Stand, der gesichert wird, inkonsistent und kann nur mit Hilfe der Transaktionsprotokolle im Wiederherstellungsfall in einen konsistenten Zustand gebracht werden. Die einzelnen Tablespaces einer Datenbank müssen jeweils in einen Modus für die Online-Sicherung gesetzt werden. SQL> ALTER TABLESPACE users BEGIN BACKUP;
Das Kommando bewirkt drei Dinge: 1. Für die Dateien des Tablespaces wird ein Checkpoint ausgelöst. 2. Die Header-Informationen werden eingefroren. 3. Für Blöcke des Tablespace wird auf Full Block Logging umgeschaltet. Der Checkpoint stellt einen konsistenten Stand der Dateien des Tablespace her. Da zum gleichen Zeitpunkt die Header-Informationen der Dateien eingefroren werden, existiert also ein definierter Synchronisationszeitpunkt, der als Startpunkt einer Wiederherstellung dient. Dass auf Full Block Logging umgeschaltet werden muss, hat seinen Grund in der unterschiedlichen Blockung von Datenbank und Betriebssystem. So wird vom Sicherungswerkzeug nicht ein kompletter OracleBlock in einer Operation gesichert und kann sich vor dem Kopieren des restlichen Teils verändern, so dass er dann auf der Sicherung inkonsistent ist. Kompensiert wird das dadurch, dass komplette Inhalte von Oracle-Blöcken in die Redo-LogDateien geschrieben werden. Als Folge steigt die Menge der Redo-Log-Dateien, die zur Archivierung anstehen, an. Sie sollten also daher eine Online-Sicherung nicht in Zeitfenster legen, in denen sehr hohe Transaktionslasten liegen. Leseoperationen sind nicht problematisch. Zudem sollten Tablespaces nur nacheinander, solange die physikalische Sicherung läuft, in den Backup-Status gesetzt werden.
570
Wiederherstellungstechniken
Beendet wird der Status für die Sicherung durch das Kommando: SQL> ALTER TABLESPACE users END BACKUP;
Durch diesen Befehl werden die Header-Informationen wieder freigegeben, und das Full Block Logging wird ausgeschaltet. Geprüft werden kann der Status der Datendateien über folgenden Befehl: SQL> SELECT * FROM v$backup; FILE# STATUS CHANGE# TIME ---------- ------------------ ---------- ------------------1 NOT ACTIVE 375471 14.05.2004 19:30:34 2 NOT ACTIVE 375475 14.05.2004 19:30:53 3 NOT ACTIVE 375478 14.05.2004 19:31:16 4 NOT ACTIVE 375481 14.05.2004 19:31:56 5 ACTIVE 375467 14.05.2004 19:32:23 Listing 10.61: Backup-Status für Online-Sicherung
Die Online-Sicherung wird also auf Ebene der Tablespaces durchgeführt. Bei der Online-Sicherung sind die Redo-Log-Dateien nicht Bestandteil der Sicherung, da diese während des Sicherungsvorganges weiterhin beschrieben werden und auch Wechsel der Redo-Log-Gruppen auftreten können. Daher ist auch der Archivierungsmodus der Datenbank Voraussetzung für die Online-Sicherung. Die folgenden Schritte sind ein Vorschlag für eine Vorgehensweise, die eine Kontrolle und die Nachvollziehbarkeit der Sicherung ermöglicht. SQL> SPOOL protokoll.lis SQL> CONNECT / as sysdba
Als Erstes sollte ein Protokoll erstellt werden, das den aktuellen Stand der RedoLog-Dateien und der Archivierung anzeigt. Zudem werden alle Tablespaces und Datendateien aufgelistet. Aus diesen Abfragen sind auch die anschließend benötigten Schleifen zu füllen. SQL> SQL> SQL> SQL>
ARCHIVE LOG LIST SELECT name FROM v$controlfile; SELECT * FROM v$log; SELECT name FROM v$datafile;
Listing 10.62: Ermitteln der zu sichernden Dateien
Nun sollte eine Schleife über alle Tablespaces laufen, die diese auf den Status BACKUP setzt, und eine weitere, in der alle Dateien des Tablespaces gesichert werden. Anschließend muss das Ende des Backups für den Tablespace bekannt gegeben werden. SQL> ALTER TABLESPACE users BEGIN BACKUP; SQL> host cp /disk3/oracle/test/users_01.dbf /backup/oracle/test/users_01.dbf SQL> host cp /disk3/oracle/test/users_02.dbf /backup/oracle/test/users_02.dbf SQL> ALTER TABLESPACE users END BACKUP;
Ältere Techniken zur Sicherung
571
Um im Fehlerfall eine Online-Sicherung für die Wiederherstellung verwenden zu können, müssen mindestens alle Redo-Log-Dateien vom Start der Sicherung bis zu deren Ende vorhanden sein. Gesichert werden typischerweise die archivierten Redo-Log-Dateien, da diese nicht mehr geöffnet sind. Um am Ende der OnlineSicherung einen definierten Stand zu haben, der auch auf ein Band abgezogen werden kann, empfiehlt sich am Ende der Sicherung noch ein manuell initiierter Wechsel der Redo-Log-Gruppen, der eine Archivierung auslöst. Zusätzlich kann in diesem Zuge eine Online-Sicherung der Kontrolldatei erstellt werden. Ratsam ist es auch, sich eine Trace-Datei mit dem passenden CREATE CONTROLFILE-Befehl generieren zu lassen. SQL> ALTER SYSTEM SWITCH LOGFILE; SQL> ALTER DATABASE BACKUP CONTROLFILE TO '/backup/oracle/test/control.bck'; SQL> ALTER DATABASE BACKUP CONTROLFILE TO TRACE; Listing 10.63: Sichern der Kontrolldateien
Nun sollte der zu Ende der Sicherung aktuelle Status der Redo-Log-Dateien als Ende des Protokolls ausgegeben werden. SQL> ARCHIVE LOG LIST SQL> SPOOL OFF SQL> EXIT Listing 10.64: Protokollierung
Wichtig ist, dass diese Sicherung nur zusammen mit den während der Sicherung anfallenden Redo-Log-Informationen eine komplette Datenbanksicherung ergibt.
10.7.3 Spezielle Techniken Insbesondere Hersteller von Speicherlösungen verwenden zum Teil eigene Verfahren, um eine Datenbank bzw. beliebige Dateien möglichst komfortabel und schnell zu sichern. Das am weitesten verbreitete Verfahren ist hierbei die Business Copy (BC). Dabei wird im Prinzip die Spiegelung (Raid-1) der Plattensysteme aufgehoben und der abgetrennte Spiegelteil über ein beliebiges Werkzeug gesichert. Die Datenbank läuft während dieser Zeit ungespiegelt. Die Firma EMC erlaubt eine solche Kopie (BCV = Business Continuance Volume) nur, wenn ein zusätzlicher Spiegel vorhanden ist. Ziel dieses Verfahrens ist zunächst einmal die möglichst geringe Beeinflussung der Produktionsdatenbank. Nachteil ist jedoch, dass in jedem Fall nur auf physikalischer Ebene gesichert wird (LUN = Logical Unit), d.h., dass die unterschiedlichen Datenbereiche einer Oracle-Datenbank (Daten-Tablespace, Temporär-Tablespace, Undo-Tablespace, Redo-Log-Dateien, archivierte Redo-Log-Dateien, tatsächlich gefüllter Platz in der Datenbank) keine Rolle spielen. Das führt in der Regel dazu, dass die gesicherte Datenmenge wesentliche größer ist als erforderlich.
572
Wiederherstellungstechniken
Nach einer erfolgreichen Sicherung kann der Spiegel wieder eingeschaltet werden. Die während der Sicherung in der Produktion angefallenen Änderungen werden in eigenen Log-Dateien protokolliert, so dass nur geänderte Blöcke synchronisiert werden müssen. Aber Vorsicht: Auch hier sind Betriebssystemblöcke und nicht etwa Oracle-Blöcke gemeint. Für die Sicherung der Oracle-Datenbank bedeutet dieses Verfahren, dass die gesamte Datenbank kurzzeitig in den BACKUP-Modus gesetzt werden muss. Hierfür gibt es den Befehl: ALTER DATABASE BEGIN BACKUP;
Zusätzlich kann die Datenbank in den Suspend-Modus versetzt werden. In diesem Modus werden alle I/O-Operationen der Datenbank verhindert. Dieser Modus wird eingeschaltet durch den Befehl ALTER SYSTEM SUSPEND;
Der Suspend-Modus ist bei vielen Herstellern die Voraussetzung für das Aufbrechen von Spiegeln. Nun kann einerseits die Sicherung auf dem abgetrennten Spiegel gestartet werden. Die I/O-Operationen können praktisch gleichzeitig mit ALTER SYSTEM RESUME;
wieder aktiviert werden. Auch der BACKUP-Status der Datenbank kann mit ALTER DATABASE END BACKUP;
wieder aufgehoben werden. Es sei an dieser Stelle noch einmal darauf hingewiesen, dass es sich bei diesem Verfahren um ein generelles Backup-Verfahren handelt, das nicht auf die Eigenarten der Oracle-Datenbank eingeht. Daher sollte geprüft werden, ob eine Sicherung mit dem Recovery Manager nicht effektiver und eventuell sogar schneller ist. Beachten Sie dabei: Es geht nicht nur um die Sicherung der Datenbank, sondern insbesondere um eine möglichst schnelle Wiederherstellung. Und dazu gehört zum Beispiel, dass im Fehlerfall eventuell nur ein Tablespace zurückgesichert werden muss. Bei einer Business Copy und der bei großen Datenbanken üblichen RAID-10-Verteilung der Daten müssen Sie mit großer Wahrscheinlichkeit die gesamte Datenbank zurücksichern. Eine Rücksicherung der Datenbank aus einer Business Copy ist dabei eventuell noch schneller als die Rücksicherung einer Datendatei aus einer Recovery-Manager-Sicherung. Die anschließende Wiederherstellung der Datenbank über die archivierten Redo-Log-Dateien kann aber ein Vielfaches an Zeit dauern, je nachdem, ob Sie die gesamte Datenbank oder nur einen Tablespace wiederherstellen müssen.
Tuning Akzeptierte Antwortzeiten, gute Skalierbarkeit und eine ausreichende Verfügbarkeit sind die drei Säulen, die nach wie vor eine erfolgreiche Datenbankinstallation auszeichnen. Die Skalierbarkeit wird dabei durch einen sparsamen Umgang mit Datenbankressourcen erreicht, der garantiert, dass auch bei wachsenden Benutzerzahlen und Datenmengen die vorgegebenen Antwortzeiten eingehalten werden können. Bei der Vielzahl an Merkmalen und Funktionalitäten, die Oracle 10g mittlerweile bietet, ist es nicht immer leicht, diese drei Säulen dauerhaft und zuverlässig zu implementieren. Das vorliegende Kapitel »Tuning« konzentriert sich auf die ersten beiden – Antwortzeiten und Skalierbarkeit – und zeigt, wie Datenbankinstanzen und Anwendungen, die mit ihnen arbeiten, systematisch analysiert und erfolgreich optimiert werden können. In der Praxis ist es nicht immer leicht, »Tuning« von »Troubleshooting« zu unterscheiden. Ist beispielsweise die lange Laufzeit einer PL/SQL-Prozedur, die durch Wartezyklen und Hang-Situationen beim Locking verursacht wird, ein Problem, das durch Tuning- oder Troubleshooting-Maßnahmen behoben wird? Wie verhält es sich mit Verzögerungen bei Schreiboperationen, die zustande kommen, weil die betreffende Session auf die Fertigstellung eines Checkpoints warten muss und aus diesem Grunde kein Log Switch durchgeführt werden kann? Im Kontext dieses Buches verstehen wir »Tuning« als Summe aller Maßnahmen, welche die Optimierung der Antwortzeiten und die Verbesserung der Skalierbarkeit zum Ziele haben. Tuning-Maßnahmen legitimieren sich nicht durch auftretende Fehler. Im Gegensatz dazu bezeichnet »Troubleshooting« alle Aktivitäten zur Analyse und Behebung von konkreten Fehlersituationen. Fehlersituationen werden durch Fehlermeldungen im Kontext von Sessions oder in entsprechenden Log-, Trace- oder Alert-Dateien ausgewiesen. Ergänzend hierzu verstehen wir unter »Monitoring« alle Aktivitäten, die der bewertenden Erfassung diverser Datenbankressourcen dienen und als Ziel die frühzeitige Erkennung möglicher Fehlerquellen oder Performance-Engpässe haben. Den Themen »Troubleshooting« und »Monitoring« werden aus diesem Grunde eigene Kapitel gewidmet.
11.1
Strategie
Sorgfältig geplante und entsprechend entwickelte Systeme benötigen keine Tuning-Maßnahmen, sondern liefern im Rahmen der für sie definierten Kontexte zufrieden stellende Antwortzeiten und ausreichende Skalierungen. Diese Aussage ist zugegebenermaßen radikal, entbehrt jedoch nicht einer gewissen realistischen Grundlage. Trotz allem sind – wie wir alle wissen – Tuning-Maßnahmen häufig notwendig. Die Gründe hierfür können vielfältig sein: Die Realität hat sich geändert, und daraus resultieren neue Anforderungen an die Datenbank und Instanz.
574
Tuning
Die Implementierung einer Anwendung wurde nicht Oracle-spezifisch, sondern offen für unterschiedliche Datenhaltungssysteme konzipiert. Bei entsprechendem Datenvolumen oder entsprechender Last können daher vorgegebene Antwortzeiten nicht mehr eingehalten werden. Die Anwendung wurde ohne gründliche Funktions- und Anforderungsanalyse konzipiert und »heiß gestrickt«. Bei produktivem Einsatz offenbaren sich die konzeptionellen Schwachstellen. Allmähliche funktionale Erweiterungen haben eine vormals gut optimierte Anwendung über die Jahre ausgehöhlt. Eine Konsolidierung und Optimierung ist daher angesagt. Die Ressourcenanforderungen einer Anwendung sind (noch) unbekannt. Nach der Installation in eine bereits genutzte Instanz kommt es zu Performance-Problemen. Aus diesen wenigen Beispielen lassen sich bereits wichtige Maßnahmen ableiten, die den Tuning-Aufwand erheblich minimieren helfen und im Vorfeld schon gute Antwortzeiten und Skalierungen erwarten lassen: Das Feinkonzept sollte auf der Grundlage einer gründlichen Anforderungsanalyse erstellt werden, die – soweit möglich – zukünftige Entwicklungen mit berücksichtigt. Die physische Implementierung des Datenmodells sollte mit Blick auf die technischen Möglichkeiten einer Oracle-Datenbank erfolgen: Es werden mittlerweile vielfältige Tabellen- und Indextypen unterstützt, die – sinnvoll eingesetzt – erhebliche Performance-Vorteile bieten können. Eine sinnvolle Modularisierung sollte dafür sorgen, dass aufwändige Datenmanipulationen möglichst »datennah« realisiert werden und die Programmlogik effizient aufgesetzt wird. Bei der Konfiguration der Datenbank sollten konsequent neue Techniken, die sich bewährt haben, genutzt werden, so z.B. Locally Managed Tablespaces, automatisiertes Undo Management und automatisierte Platzverwaltung in Segmenten (ASSM). Gleichzeitig sollten die grundlegenden Ressourcen, wie z.B. die SGA und der Redo-Log-Bereich, ausreichend dimensioniert sein. Anwendungen mit derart konzipierter Basis lassen sich in der Regel mit vertretbarem Aufwand optimieren, wenn sich eine Veränderung des Zeitverhaltens abzeichnet. Tuning-Maßnahmen, die sich in den oben genannten Bereichen bewegen und beispielsweise Anpassungen am Datenmodell vornehmen müssen, sind entsprechend aufwändig, zeitintensiv und damit teuer. Bei der Optimierung von Instanzen lassen sich unterschiedliche Strategien anwenden: Mit Hilfe eines allgemeinen Health Check lassen sich allgemeine Kennzahlen ermitteln, die grobe Anhaltspunkte für den »Gesundheitszustand« der betreffenden Instanz liefern. Hierzu zählen beispielsweise die Trefferquoten im Buffer Pool und im Library Cache, eine Statistik der Wartezyklen und dergleichen mehr. Das im Abschnitt Monitoring und Engpassanalyse vorgestellte Werkzeug Statspack kann in diesem Kontext gut zum Einsatz kommen. Die gelieferten
Hilfsmittel
575
Kennzahlen können zu einer angepassten Parametrierung der Instanz führen, lassen aber nur wenige Rückschlüsse auf die Performance der einzelnen Anwendungen zu, welche die Datenbank nutzen. Tuning im engeren Sinne des Wortes kümmert sich um die Sicherstellung von akzeptablen Antwortzeiten für geschäftsrelevante Prozesse. Antwortzeiten lassen sich in CPU- und Wartezeiten untergliedern. CPU-Zeiten entstehen beispielsweise durch das Parsing von SQL-Befehlen oder die Ausführung von Prozeduren. Wartezeiten ergeben sich immer dann, wenn die Datenbank auf die Bereitstellung von Ressourcen oder die Fertigstellung »externer« Anforderungen – z.B. IO-Operationen – warten muss. Tuning reagiert in diesem Zusammenhang immer auf konkrete Probleme durch die Erstellung eines detaillierten Lastprofils, das die anfallenden CPU- und Wartezeiten im Kontext eines konkretes Programmmoduls oder SQL-Befehls auflistet. Die Optimierung des betreffenden Prozessen wird dann erreicht, indem die markantesten Problembereiche dieses Lastprofils analysiert und optimiert werden. Zeigt das Lastprofil einer Prozedur beispielsweise, dass 60% der Wartezeiten aufgrund von IO-Operationen entstehen und nur 5% durch Latch Contention, werden in erster Linie die IO-Operationen für eine Optimierung in Frage kommen, weil sie das größte Potenzial für die Verkürzung der Antwortzeit bergen. Da aggregierte Instanzstatistiken keine Möglichkeiten bieten, konkrete Rückschlüsse auf die Engpässe einzelner Anwendungen zu ziehen, ist der oben erwähnte Problembezug für das Tuning von enormer Bedeutung. Darüber hinaus ist Tuning immer auch Teamarbeit: Der DBA mit seiner detaillierten Kenntnis der Instanz und ihrer Interaktionen braucht in der Regel die Unterstützung eines »Anwendungsadministrators«, der die Datenstrukturen und Funktionsabläufe der betreffenden Anwendung kennt.
11.2
Hilfsmittel
11.2.1 Oracle Performance-Views Die Oracle-Datenbank stellt eine große Menge von Performance-Statistiken in so genannten Performance-Views (V$-Views) zur Verfügung. Dabei handelt es sich um vordefinierte Views im Schema SYS. Im Gegensatz zu den Data-DictionaryViews (USER_*, ALL_*, DBA_*) basieren diese jedoch nicht auf festen Tabellen, die den Inhalt der Datenbank beschreiben, sondern auf speziellen Performance-Tabellen (X$-Tabellen), die u.a. Speicherstrukturen der SGA – also des von Oracle benutzten Shared-Memory-Bereichs – abbilden. Auf diese Weise werden interne PerformanceWerte dem Benutzer in Tabellenform zugänglich gemacht. Diese Methode hat den Charme, dass komplexe SQL-Befehle zur Aufarbeitung der dargebotenen statischen Rohdaten eingesetzt werden können. Zu beachten ist, dass die X$-Tabellen zwar zugänglich sind, aber zumeist kryptischen Inhalt haben, nicht dokumentiert sind und auch die Struktur und Namensgebung sich jederzeit ändern kann. Diese sollten daher i.A. nicht verwendet werden (Oracle verwendet diese jedoch intern z.B. für das Füllen des Automatic Workload Repositorys). Stattdessen sollten Zugriffe über die V$-Views realisiert werden.
576
Tuning
In jeder Datenbankversion kommt stets eine nicht unerhebliche Zahl neuer Performance-Views hinzu, daher soll an dieser Stelle vorrangig eine strukturierte Übersicht über die unterschiedlichen Messzahlen gegeben werden. Außerdem werden die wichtigsten Views vorgestellt. Grundlegendes Es stehen Statistiken für zahlreiche Funktionskontexte der Datenbank zur Verfügung. Die wichtigsten dieser Kontexte sind: Sessions, z.B. Wartezeiten für jede einzelne Session Services, also beispielsweise verschiedene Anwendungen innerhalb einer Datenbank. Statistiken auf Service-Ebene stehen erst seit Oracle 10g zur Verfügung. Datendateien, z.B. Umfang und Performance von Lese- und Schreibzugriffen pro Datei Segmente, z.B. die Anzahl logischer oder physischer Lese- und Schreibzugriffe pro Tabelle, Index etc. SQL-Kommandos, die sich im Cursor-Cache (SQL-Area) befinden, die beispielsweise Anzahl der Ausführungen, die dadurch verursachten Lesezugriffe, der Ausführungsplan etc. Aktive Transaktionen, beispielsweise der Startzeitpunkt, I/O-Daten Undo-Segmente Sperrverhalten von Oracle, insbesondere Sperren für Datensätze (Enqueues) sowie interne Sperren (Latches) Außerdem gibt es Gesamtstatistiken (Systemebene), die Summenwerte über alle Sessions darstellen. In den Versionen bis einschließlich Oracle9i wurden ausschließlich kumulative Performance-Werte bereitgestellt, es handelte sich also um Gesamtstatistiken seit dem Start der Instanz. Eine Reinitialisierung dieser Performance-Werte ist nicht möglich, ohne die Instanz neu zu starten. Das bedeutet auch, dass kurzfristige Schwankungen, Ausreißer oder plötzliche Performance-Einbrüche, z.B. wenn eine Datendatei seit einer halben Stunde ein schlechteres I/O-Verhalten zeigt, sich in diesen Views nicht auf den ersten Blick zeigen. Die anomalen Werte werden durch die über Wochen oder Monate der Instanzlaufzeit gesammelten normalen Werte »weggemittelt«. Voraussetzung für ernsthafte Performance-Untersuchungen ist daher die Bildung von Snapshots, indem beispielsweise alle 30 Minuten ein Auszug dieser Performance-Werte ermittelt wird und anschließend die Differenzwerte zwischen Endund Anfangszeitpunkt eines solchen Intervalls gebildet werden. Erst dadurch zeigt sich das Verhalten innerhalb dieses Intervalls. Performance-Tools wie Statspack/ AWR oder Precise bauen auf dieser Snapshot-Technik auf. Außerdem sollten regelmäßig Baselines, also Performance-Daten über ein Intervall mit einer bestimmten Standardlast, erzeugt und archiviert werden, um längerfristige Entwicklungen zu erkennen und analysieren zu können. Auch dies wird durch entsprechende Tools geleistet (für Statspack/AWR siehe den Abschnitt Monitoring und Engpassanalyse).
Hilfsmittel
577
Einen Spezialfall bilden Sessions. Eine Session befindet sich stets in einem von drei Zuständen: Die Session ist inaktiv, d.h., sie wartet auf ein neues SQL-Kommando vom Client. Die Session ist aktiv und verbraucht CPU-Zeit. Die Session ist aktiv, aber befindet sich in einem Wartezustand, z.B. es wird auf die Beendigung einer physischen Lese-Operation gewartet. Anzahl und Dauer aller Wartezustände werden in V$SESSION_EVENT kumulativ protokolliert. Kumulativ bedeutet hierbei »seit Beginn der Session«. Die Statistiken auf Service- und Systemebene ergeben sich durch Aufsummierung der Statistiken aller entsprechenden Sessions. Für Wartezustände sowie für Block-Leseoperationen ist auch eine Histogramm-Darstellung, also eine Auftragung nach Wartezeit bzw. Zugriffszeit, verfügbar. Auch hier sind erst über die oben beschriebene Snapshot-Technik aktuelle Entwicklungen nachvollziehbar. Damit diese Histogramm-Daten verfügbar sind, muss der Serverparameter timed_statistics = TRUE gesetzt sein (dies ist der Default-Wert). Neuerungen in Oracle 10g Seit Oracle 10g sind nun auch direkt in der Datenbank einige Statistiken verfügbar, die sich auf ein aktuelles Intervall bzw. auf historische Intervalle beziehen. Diese werden als Metriken bezeichnet. Eine Nachbearbeitung mit Hilfe der SnapshotTechnik ist für diese Werte nicht mehr notwendig. Dabei wird als Intervalllänge meist eine Minute angesetzt. Ausnahmen davon bilden: Metriken auf Tablespace-Ebene (10-Minuten-Intervalle) Einige Metriken auf Session- und Systemebene, z.B. verbrauchte CPU-Zeit sowie Anzahl logsicher und physischer Lese-Operationen (15-Sekunden-Intervalle) Für einige Metriken existieren separate Views, die nicht nur das aktuelle, sondern auch die letzten historische Intervalle darstellen. Eine Übersicht über alle Metriken findet sich in der View V$METRICNAME. Die Implementierung in den einzelnen Performance-Views ist leider nicht einheitlich. Teilweise sind die einzelnen Metriken als Spalten abgebildet (z.B. in V$SESSMETRIC und V$EVENTMETRIC), teilweise als Zeilen mit der Join-Spalte metric_id (z.B. in V$SYSMETRIC). In V$METRICGROUP wird noch eine Kategorisierung der einzelnen Metriken vorgenommen. Die Kategorie einer Metrik entscheidet auch über die Intervalllänge und die Anzahl historischer Intervalle (Spalten interval_size und max_interval). Mit Oracle 10g werden auch die Wartezustände in Kategorien unterteilt (Spalte wait_class in V$EVENT_NAME). Dies ist insbesondere zur Aussortierung »unechter« Wartezustände – so genannter Idle Events – sehr nützlich. Darunter fällt beispielsweise das Warten auf SQL-Kommandos vom Client, das in den meisten Fällen nicht performance-relevant ist, aber auch eine ganze Reihe weiterer Zustände (wait_class = 'Idle'). Andere interessante Eingrenzungen sind:
578
Tuning
Physische Lese- und Schreiboperationen: (wait_class = 'User I/O') Wartezustände, die zunächst einmal durch reine Konfigurationsmaßnahmen entschärft werden können, z.B. kann das Warten auf Checkpoints durch mehr oder größere Redo-Log-Dateien beseitigt werden (wait_class = 'Configuration') Wartezustände wegen Cache- oder Sperrsynchronisation in RAC-Umgebungen (wait_class = 'Cluster') Netzwerk-Latenzen, z.B. das Lesen via DB-Link (wait_class = 'Network') Statistiken zur Beanspruchung von Betriebssystemressourcen werden erstmalig in Oracle 10g automatisch gesammelt. Diese Funktion ist unabhängig von dem bereits in älteren Datenbankversionen bekannten Serverparameter timed_os_statistics, der deutliche Performance-Auswirkungen hat und daher sehr vorsichtig benutzt werden sollte. Zur Bedeutung der einzelnen Statistiken wie OS-Statistiken siehe Dokumentation Oracle 10g Database Reference. Statistiken (kumulativ)
Wartezustände (kumulativ)
Sessions
V$SESSION V$SESSTAT V$MYSTAT V$SESS_IO
Services
Metrik (aktuelles Intervall)
MetrikHistorie (aktuelle und historische Intervalle)
V$SESSION_ EVENT V$SESSION_ WAIT V$SESSION_ WAIT_ CLASS
V$SESSMETRIC
V$ACTIVE_ SESSION_ HISTORY
V$SERVICE_ STATS
V$SERVICE_ EVENT V$SERVICE_ WAIT_CLASS
V$SERVICEMETRIC
V$SERVICE METRIC_ HISTORY
System
V$SYSSTAT
V$SYSTEM_ EVENT V$SYSTEM_ WAIT_CLASS
V$EVENT_ HISTOGRAM
V$EVENTMETRIC V$SYSMETRIC V$SYSMETRIC_ SUMMARY V$WAITCL ASSMETRIC
V$SYSMETRIC_ HISTORY V$WAIT CLASS METRIC_ HISTORY V$METRIC _HISTORY
Dateien
V$FILESTAT V$TEMPSTAT
V$FILE_ HISTORAM V$TEMP_ HISTORAM
V$FILEMETRIC
V$FILEMETRIC_ HISTORY
Segmente
V$SEGSTAT V$SEGMENT_ STATISTICS
Tabelle 11.1: V$Tabellen und Funktionskontexte
Histogramme (kumulativ)
Hilfsmittel
579
Statistiken (kumulativ)
SQL
V$SQL V$SQL_PLAN V$SQL_PLAN_ STATISTICS
Transaktionen
V$TRANSACTION
UndoSegmente
V$ROLLSTAT
Sperren (Enqueu es)
V$TRANSACTION_ ENQUEUE V$ENQUEUE_LOCK V$ENQUEUE_STAT V$LOCK V$LOCKED_OBJECT
Latches
V$LATCH V$LATCHHOLDER V$LATCH_MISSES
Betriebssystem
V$OSSTAT
Wartezustände (kumulativ)
Histogramme (kumulativ)
Metrik (aktuelles Intervall)
MetrikHistorie (aktuelle und historische Intervalle)
V$SQL_ WORKAREA_ HISTORAM
V$UNDOSTAT
Tabelle 11.1: V$Tabellen und Funktionskontexte (Forts.)
In manchen der aufgelisteten Performance-Views findet sich jeweils auch der Name der entsprechenden Statistik oder Metrik, manchmal ist jedoch nur ein Fremdschlüssel auf eine Referenztabelle vorhanden (z.B. Spalte statistic# in V$SESSTAT und V$SEGSTAT, Spalte event# in V$EVENTMETRIC etc.) Dann kann zumindest per Join mit der Referenztabelle der entsprechende Name dazugebunden werden. Die benutzten Referenztabellen sind: V$METRICNAME für Metriken. Die Spalte metric_id ist Join-Spalte, metric_name beschreibt die entsprechende Metrik. Über die Spalte metric_unit ist auch die Maßeinheit gegeben. Die Metrik-Kategorien sind in V$METRICGROUP zusammengefasst. V$EVENT_NAME für Wartezustände. Die Spalte event# ist Join-Spalte, name enthält die Bezeichnung des Wartezustands. Die Maßeinheit ist hier immer die Dauer des Wartezustandes in hundertstel Sekunden (Centisekunden). Eine Ausnahme bildet die Spalte time_waited_micro, die in Mikrosekunden (millionstel Sekunden) misst und ausschließlich für sehr kurze Wartezeiten einen sinnvollen Genauigkeitsvorteil bietet.
580
Tuning
V$STATNAME für Statistiken auf Session-, Service- und Systemebene. Die Spalte statistic# ist Join-Spalte, name enthält die Statistikbezeichnung. Die Spalte class gibt an, zu welcher Performance-Kategorie die Statistik gehört. Für diese Kategorien gibt es aber keine eigene Referenztabelle, sondern es gilt folgendes Schema: 1: Benutzer-Sessions 2: Redo-Log-Aktivität 4: Sperrverhalten (Enqueues) 8: Caching (physischer und logischer I/O) 16: Betriebssystem (diese Statistiken werden nur dann gepflegt und angezeigt, wenn der Serverparameter timed_os_statistics auf einen Wert größer 0 gesetzt ist) 32: RAC (Real Application Cluster) 64: SQL-Kommandos (Zugriffsmethoden auf Tabellen, Parsing, Sortierungen) 128: Debugging (interne Statistiken) Liegt eine Zugehörigkeit zu mehreren Kategorien vor, wird dieses Schema additiv verwendet. Zur Eingrenzung auf eine Kategorie muss also eine bitweise ANDVerknüpfung (Funktion BITAND) durchgeführt werden. V$SEGSTAT_NAME für Statistiken auf Segmentebene. Die Spalte statistic# ist JoinSpalte, name enthält die Statistikbezeichnung. V$LATCHNAME für Statistiken auf Latch-Ebene. Die Spalte latch# ist Join-Spalte, name enthält den Namen des Latches. Advisories Ein sehr nützliches Hilfsmittel für den Bereich Instance-Tuning stellen die so genannten Advisories dar. Dabei handelt es sich um Empfehlungen für die Dimensionierung von Buffer-Cache, Shared-Pool, Java-Pool und PGA-Pool. Die Advisories sind als Histogramme aufgebaut und geben für verschiedene Größen des entsprechenden Pools das Laufzeitverhalten an (beispielsweise Trefferraten im BufferCache, Sortieroperationen mit Auslagerung in Temporär-Segmente). Für den Buffer-Cache (Default-Buffer-Cache mit 8-K-Blockgröße) sieht das beispielsweise so aus: SQL> SELECT size_for_estimate ,size_factor ,buffers_for_estimate ,estd_physical_read_factor ,estd_physical_reads ,estd_physical_read_time FROM v$db_cache_advice WHERE name = 'DEFAULT' AND block_size = 8192;
AS AS AS AS AS AS
size_est factor buffers read_fct phy_reads phy_rtime
Hilfsmittel
581
SIZE_EST FACTOR BUFFERS READ_FCT PHY_READS PHY_RTIME ---------- ------ ---------- ---------- ---------- --------4 ,1 501 5,5853 125998 2397 8 ,2 1002 3,3464 75490 1347 12 ,3 1503 2,6664 60152 1029 16 ,4 2004 2,2532 50830 835 20 ,5 2505 2,0398 46016 735 24 ,6 3006 1,6026 36152 530 28 ,7 3507 1,3471 30389 410 32 ,8 4008 1,1751 26508 329 36 ,9 4509 1,0887 24559 289 40 1,0 5010 1 22559 247 44 1,1 5511 ,9437 21288 221 48 1,2 6012 ,8933 20152 197 52 1,3 6513 ,8467 19101 175 56 1,4 7014 ,7896 17813 148 60 1,5 7515 ,7596 17135 134 64 1,6 8016 ,7183 16203 115 68 1,7 8517 ,686 15474 100 72 1,8 9018 ,6469 14593 82 76 1,9 9519 ,6243 14085 71 80 2,0 10020 ,6108 13779 65
Es werden verschiedene Cache-Größen zwischen 10% und 200% der aktuellen Cache-Größe betrachtet. Die ersten drei Spalten geben die betrachtete Cache-Größe an, die folgenden Spalten geben absolute und relative Werte für physische Lese-Operationen an, beispielsweise gilt: Eine Verdopplung des Buffer-Caches führt zu einer Reduktion der physischen Lese-Operationen auf ca. 61% (gerechnet seit Instanzstart oder seit der letzten Änderung der Buffer-Cache-Größe). Um einen Eindruck von der tatsächlichen Zeiteinsparung zu bekommen, sollte auch die letzte Spalte betrachtet werden, welche die Gesamtzeit für physisches Lesen in hundertstel Sekunden angibt. Für den Shared Pool kann die Parsing-Zeit für SQL-Kommandos in Abhängigkeit von der Pool-Größe untersucht werden. Analog ist dasselbe für den Java-Pool möglich (V$JAVA_POOL_ADVICE) SQL> SELECT shared_pool_size_for_estimate ,shared_pool_size_factor ,estd_lc_load_time ,estd_lc_load_time_factor FROM v$shared_pool_advice;
AS AS AS AS
size_est factor load_time l_factor
Auch für den PGA-Pool (dimensioniert durch den Serverparameter pga_aggregate_ target) steht eine Advisory zur Verfügung. Die View V$PGA_TARGET_ADVICE_HISTOGRAM liefert für verschiedene Größen des PGA-Pools je ein Histogramm über die Anzahl von Operationen, die eine bestimmte PGA-Größe beansprucht haben. Ein Auszug aus dieser Performance-View soll dies verdeutlichen:
582 SQL> SELECT pga_target_for_estimate ,pga_target_factor ,low_optimal_size ,high_optimal_size ,estd_optimal_executions ,estd_onepass_executions ,estd_multipasses_executions FROM v$pga_target_advice_histogram;
Tuning AS AS AS AS AS AS AS
size_est factor lower_lim upper_lim in_memory pass_1 pass_n
SIZE_EST FACTOR LOWER_LIM UPPER_LIM IN_MEMORY PASS_1 PASS_N --------- ------ --------- --------- --------- ------ -----... 23592960 ,75 4194304 8388607 0 0 0 23592960 ,75 2097152 4194303 0 0 0 23592960 ,75 1048576 2097151 3 0 2 23592960 ,75 524288 1048575 223 0 8 23592960 ,75 262144 524287 40 0 0 23592960 ,75 131072 262143 18 0 0 23592960 ,75 65536 131071 47 0 0 23592960 ,75 32768 65535 0 0 0 23592960 ,75 16384 32767 0 0 0 23592960 ,75 8192 16383 0 0 0 23592960 ,75 4096 8191 0 0 0 23592960 ,75 2048 4095 16817 0 0 23592960 ,75 1024 2047 0 0 0 23592960 ,75 0 1023 0 0 0 ...
Dies bedeutet, dass bei einem PGA-Pool mit 75% der aktuellen Größe die meisten Operationen (Sortierungen, Hash-Joins sowie Aufbau und Merging von BitmapIndizes) weiterhin im Speicher hätten stattfinden können. Für die weitaus meisten – nämlich 16817 Operationen – genügt dafür sogar ein Arbeitsbereich zwischen 2 KB und 4 KB innerhalb des PGA-Pools. Allerdings hätten insgesamt zehn Operationen (mit Sortiervolumina zwischen 512 KB und 2 MB) auch eine mehrfache Auslagerung in Temporär-Segmente erfordert (Spalte pass_n). Der PGA-Pool sollte so dimensioniert werden, dass die meisten Operationen im Hauptspeicher ausgeführt werden können. Weniger als 10% aller Operationen sollten eine einzige Auslagerung in Temporär-Segmente benötigen (Spalte pass_1). Bei OLAP-Systemen kann diese Anforderung etwas gelockert werden. Mehrfach-Auslagerungen sollten aber in jedem Fall vermieden werden. Die von den Advisories projizierten Werte sind sehr verlässlich, da intern einfach ein entsprechend großer Pool-Bereich simuliert wird, ohne jedoch konkrete Inhalte (z.B. Blöcke im Buffer-Cache) abzuspeichern. Bei einer dynamischen Vergrößerung oder Verkleinerung eines Pools (manuell via ALTER SYSTEM-Kommando oder automatisch bei gesetztem Serverparameter sga_target) wird die zugehörige Advisory reinitialisiert.
Hilfsmittel
583
Persistente Performance-Daten Seit Oracle 10g werden im Rahmen des AWR (Automatic Workload Repository) Snapshots der meisten oben genannten Performance-Views regelmäßig in persistenten Tabellen gesichert. Damit sind beispielsweise bei den oben genannten Metrik-Historien auch ältere Versionen zugänglich. Über die AWR-Reports können dann auch gleich Auswertungen nach der Differenzmethode vorgenommen werden. Dieser Mechanismus ist nach Erstellung der Datenbank automatisch aktiviert. Für weitere Informationen zum AWR siehe auch Abschnitt Monitoring und Engpassanalyse.
11.2.2 Monitoring und Engpassanalyse Zur Unterstützung des Datenbankadministrators für das Monitoring von OracleSystemen bieten mehrere Hersteller Werkzeuge an, die Grafiken und Listen, zumeist unter MS-Windows-Oberflächen, erstellen. Zu diesen Werkzeugen zählen z.B. das Tuning-Pack des Oracle Enterprise Managers, Quest Spotlight on Oracle und SQLab Vision, BMC Patrol, Keeptool HORA oder Precise. Hinweise dazu sind in Kapitel 14 beschrieben, das sich generell mit dem Thema Monitoring auseinander setzt. Diesen Werkzeugen liegen unterschiedliche Ansätze zugrunde. Einige greifen auf die virtuellen Performance-Views (V$-Tabellen) zu, die Strukturen der Oracle-SGA abbilden. Diese Zugriffe erzeugen Last im Oracle-System und können bei nicht angepasster Parametrierung bezüglich der Überwachungsintervalle selbst eine Quelle erhöhten Ressourcenbedarfs sein. Andere greifen direkt SGA-Strukturen ab, so dass keine Last für die Oracle-Instanz erzeugt wird. Alle Werkzeuge müssen lizenziert werden. Die Lizenzgebühren leiten sich zumeist aus den Oracle-Lizenzstufen ab, so dass gerade für große Systeme mit erheblichen Kosten gerechnet werden muss. Die Informationen können aber auch durch SQL-Scripts über die V$-Tabellen abgegriffen werden. Im Laufe der Zeit wird ein Datenbankadministrator sich eine Sammlung solcher Skripte erstellen, die auch oft in der Literatur zum Thema Oracle-Tuning zu finden sind bzw. von Internetseiten der Autoren geladen werden können. Die Ausgabe solcher Scripts muss natürlich so formatiert werden, dass der Administrator schnell die wichtigen Informationen erkennen kann. Hierin ist sicher ein Nachteil zu den farbigen Grafiken der Werkzeuge zu sehen, jedoch sind die Ausgaben der Skripte im Gegenzug nicht grafisch überfrachtet und liefern direkt die gewünschten Informationen. In diesem Kapitel wird ausschließlich die Nutzung von SQL-Befehlen und Skripten aus dem Lieferumfang von Oracle 10g beschrieben, da wir nicht davon ausgehen können, dass jedem Leser ein zusätzliches Werkzeug zur Verfügung steht und wir auch keine Gebrauchsanweisungen für die genannten Werkzeuge liefern, sondern einen generellen Überblick über die Tuning-Möglichkeiten geben möchten.
584
Tuning
Statspack Statspack ist die Weiterführung des früheren Tools utlbstat/utlestat. Es besteht aus Skripten, die mit der Oracle Server-Software ausgeliefert werden. Beim Aufruf dieser Skripte werden in einem speziellen Schema Tabellen installiert, in die Abzüge aus den V$-Tabellen abgelegt werden, die aber in diesem Fall mit einer Snapshot ID versehen werden. Das bedeutet, dass zu bestimmten Zeitpunkten solche Snapshots gezogen werden können, die man dann zu einem späteren Zeitpunkt in verschiedenen Intervallen auswerten kann. Hervorzuheben ist, dass Statspack PerformanceDaten vornehmlich aus Sicht der Instanz darstellt, ein problemorientiertes Tuning von einzelnen Modulen daher nicht optimal unterstützt. Installation Zur Installation von Statspack startet man, als SYSDBA angemeldet, ein Skript, das einen Benutzer PERFSTAT anlegt. Das Skript verlangt nach der Angabe eines Passwortes für diesen Benutzer, eines Default Tablespace und eines Temporary Tablespace, wofür sich TOOLS und TEMP anbieten. Außerdem werden Packages installiert und Tabellen für die Abzüge aus den V$-Tabellen angelegt. SQL> connect / as sysdba SQL> @?/rdbms/admin/spcreate
Benutzung Nach der Installation der Packages können nun nach Anmeldung als Benutzer PERFSTAT-Snapshots erstellt werden, die jeweils einen Abzug der V$-Tabellen darstellen. SQL> connect perfstat/perfstat SQL> execute statspack.snap
Es bietet sich an, diese Snapshots in regelmäßigen Intervallen von 30 oder 60 Minuten zu erstellen, die natürlich wahlweise auch als Job eingestellt werden können, um auch für den nächtlichen Betrieb mit Batch-Jobs Statistiken zu sammeln. Oracle bietet hierfür das Skript spauto an, das über Oracle-Jobs Snapshots zu jeder vollen Stunde erstellt. SQL> connect perfstat/perfstat SQL> @?/rdbms/admin/spauto
Wenn Snapshots zu Verfügung stehen, können diese über verschiedene Intervalle ausgewertet werden. Für die Erstellung eines Reports wird ein SQL-Script aufgerufen, das die Eingabe eines Start- und eines Endpunktes verlangt und einen Namen für den Report vorschlägt, der aber auch verändert werden kann. Sie können nur Reports über Start- und Endpunkte bilden, zwischen denen die Instanz nicht gestoppt worden ist, da ja bei einem Start einer Instanz die V$-Tabellen neu initialisiert werden und daher eine Auswertung über ein solches Intervall unsinnig wäre. SQL> @?/rdbms/admin/spreport
Hilfsmittel
585
Einstellungen und Pflege der Tabellen Wie viele Informationen im Rahmen eines Snapshots gesammelt werden, hängt von dem so genannten »Snap-Level« ab. Standardeinstellung ist der Level 5. Diese Einstellung ist auch durchaus sinnvoll, da schon umfangreiche Informationen über die Instanz und auch ressourcenintensive SQL-Befehle geliefert werden. Möchte man dennoch weitergehende Informationen über SQL-Befehle mit Ausführungsplänen haben, kann die Einstellung des Levels über eine Prozedur verändert werden. Für eine einmalige Ausführung: SQL> execute statspack.snap(i_snap_level => 6);
Permanent: SQL> execute statspack.snap(i_snap_level => 6 ,i_modify_parameter => 'true');
Es existieren weitergehende Einstellungen, die Schwellenwerte für die Beobachtung der kritischen SQL-Befehle beinhalten und aus der Tabelle STATS$STATSPACK_ PARAMETER abgelesen werden können. Auch diese können über eine Prozedur modifiziert werden. Beispiel: SQL> execute statspack.modify_statspack_parameter( i_snap_level => 10 ,i_buffer_gets_th => 10000 ,i_disk_reads_th => 1000 );
Bei der Erstellung des Snapshots wirken die gesetzten Thresholds alternativ, d.h., ein SQL-Statement wird ausgegeben, wenn es mindestens einen der Thresholds überschreitet. Im obigen Beispiel würden also solche SQL-Statements ausgegeben, die mehr als 10000 Blöcke gelesen oder mehr als 1000 Blöcke physikalisch gelesen haben. Die Level 0 bis 4 haben identische Funktionalität. Unter den ausgegebenen Informationen sind vor allem folgende relevant (alle angegebenen Informationen beziehen sich auf den ausgewählten Zeitraum): Allgemeine Performance-Daten, insbesondere Lastprofil, Trefferraten im BufferCache, Library-Cache etc. Wartezustände Systemstatistiken I/O-Statistiken pro Tablespace und pro Datafile Statistiken über den Buffer-Cache-, Shared-Pool und PGAs der Serverprozesse, jeweils auch simulierte Statistiken für größere/kleinere Dimensionierung der jeweiligen Komponenten Statistiken über Undo-Segmente Veränderungen von Serverparametern
586
Tuning
Der Level 5 ergänzt diese Informationen um eine Liste der SQL-Statements mit dem höchsten Ressourcenverbrauch unter Benutzung der oben beschriebenen Thresholds. Level 6 gibt außerdem die Ausführungspläne dieser Statements aus. Level 7 speichert außerdem Segmentstatistiken, analog zu dem obigen Beispiel können auch hier Thresholds übergeben werden, z.B. für die Anzahl logischer oder physischer Reads (Parameter i_seg_log_reads_th und i_seg_phy_reads_th). Level 10 schließlich speichert außerdem detaillierte Informationen über Latches. Dies sollte jedoch nur in Ausnahmefällen verwendet werden, da es relativ aufwändig ist. Je mehr Informationen gesammelt werden, desto mehr Platz wird natürlich in den Tabellen zur Zwischenspeicherung benötigt. Daher sollten Sie den verfügbaren Platz im Default-Tablespace des Benutzers PERFSTAT überwachen und nach erfolgten Auswertungen nicht mehr benötigte Snapshots löschen. Dazu stehen wiederum SQL-Scripts zur Verfügung. SQL> @?/rdbms/admin/sptrunc
löscht die gesamten Inhalte der STATS$-Tabellen oder SQL> @?/rdbms/admin/sppurge
löscht einen anzugebenden Bereich von Snapshots. Es bietet sich an, in regelmäßigen Abständen, z.B. wöchentlich, einen Satz umfangreicherer Snapshots zu erzeugen (Level 6 oder Level 7) und diese aufzubewahren, um eine Referenz auch für langfristige Vergleiche zu haben. Da man aber meistens aus Gründen des Speicherplatzbedarfs nicht sämtliche Snapshots der letzten Monate behalten möchte, wird zumeist via DBMS_JOB ein automatisches Löschen älterer Snapshots eingerichtet. Eine Lösung bildet hier die Definition so genannter »Baselines«, darunter sind gewissermaßen »löschgeschützte« Snapshots zu verstehen, die durch oben beschriebenes Purge-Skript eben nicht gelöscht werden. SQL> execute statspack.make_baseline( i_begin_date => TRUNC(SYSDATE) ,i_end_date => SYSDATE );
etikettiert alle heute angelegten Snapshots als Baselines. Über die Prozedur CLEAR_BASELINE kann analog der Baseline-Status wieder aufgehoben werden. Interpretation der Ausgabe Die Präsentation der Ergebnisse ist recht übersichtlich, sämtliche Trefferraten oder sonstigen Werte sind aufbereitet und mit guten Überschriften und Kommentaren versehen. Auch werden WAIT-Events schon nach ihrer Relevanz geordnet als Top-5-Liste ausgegeben, ebenso wie I/O-Statistiken oder Undo-Segment-Statistiken.
Hilfsmittel
587
Da der Report gut lesbar ist, soll er hier nicht Zeile für Zeile besprochen werden. Zusätzlich werden in diesem Report SQL-Befehle aufgelistet, die als nicht effizient beurteilt werden. Die Beurteilung erfolgt in vier Bereichen: Anzahl der verarbeiteten Blöcke, Anzahl der von der Festplatte gelesenen Blöcke, Anzahl Ausführungen und Anzahl Parse Calls. Die Schwellenwerte dafür sind einstellbar. Damit liefert Statspack neben den wichtigen Kennzahlen für das Instanz-Tuning auch wertvolle Hinweise auf verbesserungswürdige SQL-Befehle, die einer Zugriffsoptimierung unterzogen werden sollten. Wichtiger Bestandteil der Ausgabe ist auch die Beschreibung des Snap-Intervalls. Bei der Interpretation des Reports sollten Sie immer berücksichtigen, dass es sich bei den kalkulierten Werten um ein Mittel über das Snap-Intervall handelt. So kann zum Beispiel die Trefferrate im Buffer-Cache der SGA über den Tag gesehen sehr gut sein, jedoch knickt diese in einem kleineren Zeitintervall im Laufe des Tages dramatisch ein und führt zu schlechter Performance. Gerade hierin liegt unter anderem die Stärke von Statspack, da Snapshots in regelmäßigen Intervallen abgesetzt werden können, Auswertungen sich aber über beliebige verfügbare Intervalle erstrecken können. Eine detaillierte Beschreibung der Statspack-Funktionen enthält die Datei rdbms\doc\spdoc.txt im Oracle Home-Verzeichnis.
Als weitere Auswertungsmöglichkeit hat sich die Webseite www.oraperf.com bewährt. Dort kann ein erzeugter Statspack-Report hochgeladen werden. Ein automatischer Analyse-Engine erzeugt daraus einen weiteren Report in HTML-Form, der noch mehr Übersichtlichkeit sowie zahlreiche Lösungsvorschläge insbesondere im Zusammenhang mit aufgetretenen Wartezuständen bietet. AWR (Automatic Workload Repository) Das mit der Oracle-Version 10g eingeführte AWR (Automatic Workload Repository) benutzt denselben Ansatz wie Statspack. Auch hier werden regelmäßig Auszüge aus verschiedenen Performance-Tabellen generiert und in Tabellen abgespeichert, um anschließend über beliebige Intervalle Auswertungen erstellen zu können. Allerdings braucht hierzu kein spezielles Schema angelegt zu werden, stattdessen werden die Snapshot-Daten in dafür vorgesehenen Tabellen im Schema SYS abgelegt. Da u.U. sehr viele Daten anfallen können, liegen diese Tabellen nicht im SYSTEM-, sondern im SYSAUX-Tablespace. Die gesammelten Daten können über Data-Dictionary-Views (DBA_HIST_*) abgefragt werden, die zugehörigen Data-Dictionary-Tabellen haben Namen der Form WRH$_* und WRM$_*. Außerdem wird aus Performance-Gründen für die AWRSnapshots überwiegend auf X$-Tabellen statt auf V$-Views zugegriffen.
588
Tuning
Benutzung Ein AWR-Snapshot kann manuell erstellt werden durch folgenden Aufruf: SQL> execute dbms_workload_repository.create_snapshot( flush_level => 'TYPICAL');
Der optionale Parameter flush_level bestimmt, welche Daten in den Snapshot mit einbezogen werden. Zurzeit sind zwei Werte erlaubt. TYPICAL ist der Default und unterscheidet sich vom alternativen Wert ALL nur dadurch, dass für Latch-Statistiken keine Daten über Child- und Parent-Latches extrahiert werden (dies entspricht dem Snapshot-Level 10 bei Statspack). Dies sollte nur dann genutzt werden, wenn bekannt ist, dass Latching-Probleme für die Performance der Datenbank entscheidend sind. In der View DBA_HIST_SNAPSHOT, die alle Snapshots im AWR anzeigt, steht in der Spalte snap_level der Wert 1 für einen TYPICAL-, 2 für einen ALL-Snapshot. Außerdem werden in regelmäßigen Abständen automatisch AWR-Snapshots erstellt (immer als TYPICAL-Snapshots), diese Erstellung geschieht aber anscheinend nicht im Rahmen eines Oracle-Serverprozesses oder eines Hintergrundprozesses. Voraussetzung hierfür ist, dass der Serverparameter statistics_level auf TYPICAL (Default) oder ALL steht. Die Intervalle, in denen diese automatischen Snapshots generiert werden, sowie die maximale Aufbewahrungszeit für AWR-Snapshots lassen sich ebenfalls konfigurieren: SQL> execute dbms_workload_repository.modify_snapshot_settings( 7*24*60,30);
Der erste Parameter gibt die maximale Aufbewahrungszeit in Minuten an (in diesem Fall also eine Woche). Im Gegensatz zu Statspack braucht also kein eigener Job zum automatischen Löschen älterer Snapshots eingerichtet zu werden. Der zweite Parameter stellt die Zeit zwischen zwei automatischen AWR-Snapshots in Minuten dar (in diesem Fall also eine halbe Stunde). Für beide Parameter kann NULL übergeben werden, wodurch der bisherige Wert beibehalten wird. Die aktuelle Konfiguration kann mittels SQL> SELECT snap_interval, retention FROM dba_hist_wr_control; SNAP_INTERVAL RETENTION ------------------------- ------------------------+00000 00:30:00.0 +00007 00:00:00.0
abgefragt werden. Ein explizites Deaktivieren der AWR-Automatik ist möglich, indem als SnapshotIntervall 0 gesetzt wird. Leider ist dann aber auch keine manuelle Snapshot-Erstellung mehr möglich. Stattdessen kann aber z.B. der Maximalwert (100 Jahre) benutzt werden, was praktisch einer Deaktivierung der AWR-Automatik gleichkommt, manuelle Snapshots aber weiterhin zulässt. Ein völliges Deaktivieren des AWR (sowohl automatisch als auch manuell) ist möglich, indem der undokumentierte Serverparameter _awr_restrict_mode auf TRUE gesetzt wird. Jeder Versuch, das AWR zu benutzen, wird anschließend mit einer Fehlermeldung quittiert. Der Parameter ist statisch, eine erneute Freigabe des AWR ist in diesem Fall also nur nach einem Neustart der Instanz möglich.
Hilfsmittel
589
Der momentane Speicherverbrauch für das AWR (in KBytes) kann durch folgende Abfrage kontrolliert werden: SQL> SELECT space_usage_kbytes FROM v$sysaux_occupants
Der zu erwartende Speicherbedarf im SYSAUX-Tablespace hängt natürlich von der Aufbewahrungszeit und dem Snapshot-Intervall und damit von der Anzahl aufzubewahrender Snapshots ab. Je nach Datenbank muss mit einem bis einigen MB Speicherbedarf pro aufzubewahrendem Snapshot gerechnet werden. Wie auch beim Statspack können ein oder mehrere Snapshots vor dem Löschen geschützt werden, indem sie als Baseline definiert werden. Dazu müssen zunächst die Snap-IDs der zu sichernden Snapshots ermittelt werden. Zum Beispiel können typische Performance-Daten für den Lauf eines täglichen Batch-Jobs gesichert werden. Dazu wird als Stichprobe der Batch-Lauf vom 02.10.2004 (02:00 Uhr bis 04:30 Uhr) herangezogen. SQL> SELECT MIN(snap_id), MAX(snap_id) FROM dba_hist_snapshotSQL> execute dbms_workload_repository.create_baseline( 92,96,'Täglicher Batch-Lauf');
Die beiden ersten Parameter geben ein Intervall von Snapshot-IDs an. Alle betreffenden Snapshots werden unter dem Namen »Täglicher Batch-Lauf« gesichert. Über die Prozedur DROP_BASELINE kann der Baseline-Status (Löschschutz) für die betreffenden Snapshots wieder aufgehoben werden. Genau wie bei Statspack können vorhandene Snapshots über verschiedene Intervalle ausgewertet werden. Für die Erstellung eines Reports wird ein SQL-Script aufgerufen, das die Eingabe eines Start- und eines Endpunktes verlangt und einen Namen für den Report vorschlägt, der aber auch verändert werden kann. Der Auswertungszeitraum darf keinen Neustart der Instanz beinhalten. Es kann auch gewählt werden, ob der Report als Text- oder HTML-Datei generiert werden soll. SQL> @?/rdbms/admin/awrrpt
Anders als bei Statspack liegt der eigentliche Report nicht als SQL*Plus-Skript vor, vielmehr ruft das oben angegebene Skript eine Tabellenfunktion auf, die den Report Zeile für Zeile zurückgibt. Die gesamte Report-Logik ist in dieser Funktion gekapselt und insbesondere nicht editierbar. Eine Übersicht über die einzelnen SQL-Abfragen des Reports kann allerdings durch ein SQL-Tracing gewonnen werden. Die direkte Erstellung eines AWR-Reports ist einfach durch einen direkten Aufruf besagter Tabellenfunktion möglich: SQL> SELECT output FROM TABLE(dbms_workload_repository.awr_report_text( 2744428495,1,92,96));
Die ersten beiden Parameter sind die DB-ID und Instanznummer. Falls diese sich seit der Erstellung der Snapshots nicht geändert haben (das dürfte meistens der Fall sein), können sie einfach aus V$DATABASE und V$INSTANCE entnommen werden. Ansonsten (z.B. nach einem Öffnen der Datenbank mit RESETLOGS-Klausel) finden sich historische Werte in DBA_HIST_DATABASE_INSTANCE.
590
Tuning
Für einen HTML-Report wird analog die Tabellenfunktion AWR_REPORT_HTML benutzt. Innerhalb des OEM 10g Database Control ist die AWR-Verwaltung im Abschnitt ADMINISTRATION und dort unter dem Link AUTOMATISCHES WORKLOAD REPOSITORY zu finden. Dort kann u.a. die so genannte »Erfassungsebene« geändert werden. Dies entspricht dem Serverparameter statistics_level. Baselines (Sequenzen löschgeschützter Snapshots) finden sich hier unter dem Link BEIBEHALTENE SNAPSHOT-SETS. Für eine Baseline oder für eine sonstige Snapshot-Sequenz kann aus einer Dropdown-Liste eine der oben beschriebenen Aktionen ausgewählt werden (Löschen der Snapshots, Erstellen eines AWR-Reports oder eines ADDM-Reports sowie Deklaration als Baseline), vorhandene Löschschutze via Baselines können natürlich aufgehoben werden. Migration Statspack AWR Es gibt keinen direkten Migrationspfad von Statspack nach AWR. Hier ist lediglich ein Umstieg vom einen auf das andere Tool möglich. Bei einem beabsichtigten Umstieg von Statspack auf AWR sollten für einen Übergangszeitraum (z.B. 1 Monat) beide Tools parallel gefahren werden. Auf diese Weise können im Zweifelsfall Daten aus beiden Repositories miteinander verglichen werden. Interpretationsprobleme die gesammelten Daten betreffend lassen sich so einfacher lösen. Eine Migration bestehender Statspack-Repositories auf Statspack 10g ist mit den mitgelieferten Skripten spup.sql möglich, z.B. Migration von Oracle9iR2: SQL> @?/rdbms/admin/spup92
Auf längere Sicht ist der alleinige Einsatz von AWR zu empfehlen, da das Erstellen eines AWR-Snapshots deutlich ressourcensparender ist als die Erstellung eines entsprechenden Statspack-Reports. Außerdem benutzt auch der Oracle Enterprise Manager 10g ausschließlich die Daten aus dem AWR, nicht die Statspack-Daten. Das neue Diagnose-Tool ADDM (siehe unten) baut ebenfalls auf dem AWR auf. Merkwürdig ist, dass Statspack, nicht jedoch AWR, auch Performance-Statistiken über Oracle Streams verarbeitet, so z.B. gestartete Capture-, Sender-, Receiver- und Apply-Prozesse, Subscriber, Streams-Regeln sowie Queue-Aktivitäten. Wird Oracle Streams eingesetzt und sind diese Informationen gewünscht, führt zurzeit (Stand: Version 10.1.0) kein Weg an der Benutzung von Statspack vorbei. Der zusätzliche Overhead durch Statspack kann hierbei jedoch gering gehalten werden, da diese Daten bereits durch einen Level 0-Snapshot extrahiert werden. Um Lastspitzen durch das Monitoring zu vermeiden, sollte bei einem – vorübergehenden oder dauerhaften – parallelen Einsatz von Statspack und AWR darauf geachtet werden, dass die Snapshot-Zeitpunkte nicht zusammenfallen, sondern versetzt laufen, also beispielsweise bei stündlichen Reports der AWR-Snapshot zur vollen Stunde und der Statspack-Snapshot jeweils eine halbe Stunde später läuft.
Hilfsmittel
591
ADDM (Automatic Database Diagnostic Monitor) Mit der Version Oracle 10g ist ein weiteres Diagnose-Tool hinzugekommen. ADDM baut auf den mittels AWR gesammelten Daten auf. Nach Angabe zweier SnapshotIDs wird ein Performance-Report über das zugehörige Intervall generiert. Im Gegensatz zu den oben beschriebenen AWR-Reports werden hier ausschließlich Informationen darüber ausgegeben, wie viel Datenbankzeit (elapsed Time) im Rahmen verschiedener Tuning-Ansätze eingespart werden könnte. Dazu gehören z.B.: Wie viel Einsparung (in Zeit) bringt eine Vergrößerung des Buffer-Cache, Shared-Pool oder der PGA? Gibt es bestimmte SQL- oder PL/SQL-Statements, die einen signifikanten Teil der Datenbankzeit verbrauchen, und, wenn ja, welche sind das? Wie viel Zeit wurde durch welches Wait-Event verbraucht? Wie ist die Performance des I/O-Systems gegenüber einer (durch den DBA vorzugebenden) »Norm«-Performance? Für die manuelle Erstellung eines Reports wird ein SQL-Skript aufgerufen, das die Eingabe eines Start- und eines Endpunktes verlangt und einen Namen für den Report vorschlägt, der aber auch verändert werden kann. Der Auswertungszeitraum darf keinen Neustart der Instanz beinhalten. In der Standardeinstellung wird jedoch bereits automatisch für jeden abgeschlossenen AWR-Snapshot (manuell oder automatisch) eine ADDM-Analyse für den Zeitraum seit dem vorigen AWRSnapshot durchgeführt. Da auch die AWR-Snapshots automatisch erzeugt werden, läuft der ganze Mechanismus, ohne dass irgendetwas konfiguriert wurde. Über das AWR-Snapshot-Intervall wird indirekt auch die Häufigkeit der ADDM-Analysen gesteuert. Bei jedem ADDM-Aufruf werden die Ergebnisse zunächst datenbankseitig persistent gespeichert. Die gesammelten Daten können über Data-Dictionary-Views (DBA_ADVISOR_*) abgefragt werden, die zugehörigen Data-Dictionary-Tabellen haben Namen der Form WRI$_*. Außerdem wird aus Performance-Gründen für die ADDMReports überwiegend direkt auf die WRH$_*- und WRM$_*-Tabellen des AWR zugegriffen. Sollten die automatischen ADDM-Analysen ein Performance-Problem darstellen oder sonstige Probleme verursachen, gibt es einen – allerdings nicht dokumentierten – Serverparameter, um den Automatismus zu deaktivieren. Dieser kann im laufenden Betrieb gesetzt werden: SQL> ALTER SYSTEM SET "_addm_auto_enable" = FALSE;
ADDM versucht auch, die Performance des I/O-Systems innerhalb des zugrunde liegenden Intervalls zu beurteilen. Dazu ist zuvor eine Eichung notwendig, indem eine »Sollzeit« für das Lesen eines einzelnen Oracle-Blocks definiert wird. Die einfachste, aber nicht immer einsetzbare Variante besteht darin, einen bestimmten Wert als Default für alle zukünftigen ADDM-Reports festzulegen, z.B. 9000 Mikrosekunden: SQL> execute dbms_advisor.set_default_task_parameter( 'ADDM','DBIO_EXPECTED',9000);
592
Tuning
Ein realistischer Durchschnittswert lässt sich aus den Systemstatistiken ablesen, wenn diese gesetzt sind (siehe Abschnitt Erstellung und Pflege von Statistiken): SQL> SELECT pval1*1000 FROM sys.aux_stats$ WHERE pname = 'SREADTIM';
-- Milli Mikro
Der so ermittelte Wert bezieht sich wohlgemerkt auf das Lastprofil, für das die Systemstatistiken erstellt wurden, und ist nicht ohne weiteres auf ein anderes Lastprofil übertragbar. Der Grund dafür ist, dass in den Durchschnittswert natürlich auch Latenzzeiten für die Positionierung des Schreib-/Lesekopfes eingehen, die bei wahlfreiem ganz anders aussehen können als beim Full-Table-Scan einer Tabelle. Diese Problematik kann jedoch umgangen werden, indem einmalig eine Systemstatistik für das Lastprofil eines betreffenden Jobs erstellt und der oben genannte Wert eingesetzt wird. Weiter unten wird gezeigt, wie der gesetzte Default-Wert für eine konkrete ADDM-Analyse überschrieben werden kann. In jedem Fall handelt es sich aber um einen Durchschnittswert über alle Datendateien. In der Praxis ist es jedoch nicht immer sinnvoll, von einem einzigen durchschnittlichen Wert auszugehen, insbesondere wenn ein bezüglich der Performance inhomogenes I/O-System verwendet wird, also unterschiedlich schnelle Platten oder Plattensysteme vorliegen. Eine genauere Aufschlüsselung in Form durchschnittlicher Lesezeiten pro Datendatei kann z.B. durch folgende Abfrage ermittelt werden: SQL> SELECT f.name ,s.singleblkrdtim/s.singleblkrds*10000 FROM v$datafile f ,v$filestat s WHERE f.file# = s.file#;
-- Zenti Mikro
Eine möglicherweise vorhandene Streuung der Performance-Werte über Datendateien hinweg kann im Rahmen von ADDM leider nicht berücksichtigt werden. ADDM-Berichte können wie folgt generiert werden: SQL> @?/rdbms/admin/addmrpt
Der aufrufende Benutzer benötigt hierzu EXECUTE-Recht auf dem Package DBMS_ADVISOR sowie das ADVISOR-Systemprivileg. Diese Rechte können bei Bedarf wie folgt zugewiesen werden: SQL> GRANT EXECUTE ON dbms_advisor TO perfstat; SQL> GRANT ADVISOR TO perfstat;
Falls während des betrachteten Intervalls sehr wenig Aktivität stattfand, d.h., der Gesamtverbrauch an Datenbankzeit zu gering ist, wird der Report mit einer Fehlermeldung abgebrochen: THERE WAS NOT ENOUGH INSTANCE SERVICE TIME FOR ADDM ANALYSIS.
Die gesamte Logik sowie die eigentliche Skripterstellung sind in dem Package DBMS_ADVISOR gekapselt. Durch den direkten Aufruf entsprechender Prozeduren kann ein ADDM-Report parametriert werden, insbesondere lässt sich eine »SollPerformance« für das I/O-System mitgeben (Parameter DBIO_EXPECTED):
Hilfsmittel
593
SQL> DECLARE id NUMBER; name VARCHAR2(20) := 'ADDM-Report Batch'; descr VARCHAR2(100) := 'ADDM-Report täglicher Batch-Lauf'; BEGIN dbms_advisor.create_task('ADDM',id,name,descr); dbms_advisor.set_task_parameter(name,'START_SNAPSHOT',2); dbms_advisor.set_task_parameter(name,'END_SNAPSHOT',3); dbms_advisor.set_task_parameter(name,'INSTANCE',1); dbms_advisor.set_task_parameter(name,'DB_ID',2749483799); dbms_advisor.set_task_parameter( name,'DBIO_EXPECTED',12000); dbms_advisor.execute_task(name); END; / SQL> SELECT dbms_advisor.get_task_report( 'ADDM-Report Batch', 'TEXT', 'TYPICAL') FROM dual;
11.2.3 Anwendungs-Tracing Anwendungs-Tracing, auch SQL-Tracing genannt, beschreibt die Aufzeichnung von SQL-Befehlen von Prozessen und deren Ausführungsstatistiken. AnwendungsTracing ist immer dann angezeigt, wenn Anwender sich über Antwortzeiten einer Anwendung beschweren und die Quelle der schlechten Performance lokalisiert werden muss, aber auch wenn ein Anwendungsentwickler oder ein Datenbankadministrator Ausführungspläne und Statistiken für SQL-Befehle ermitteln möchten. Anwendungs-Tracing kann auf unterschiedlichen Ebenen eingeschaltet werden: Für eine einzelne laufende Oracle-Session (Session-Tracing) Für einen oder mehrere Oracle-Clients. Dies ist immer dann erforderlich, wenn keine eindeutige Zuordnung zwischen Clients und Sessions möglich ist, z.B. wenn Clients lediglich indirekt (über einen Middle-Tier) auf die Datenbank zugreifen. Auch im Rahmen von Parallel-Query bzw. Parallel-DML ist dieses Vorgehen anzuraten, da hier mehrere PX-Slave-Prozesse für einen Client-Task arbeiten, die jeweils eigene Trace-Files erstellen (Client-Tracing). Für die gesamte Datenbank, d.h. für alle laufenden und neuen Sessions (Datenbank-Tracing) Außerdem gibt es verschiedene Ausbaustufen, die sich durch Art und Umfang der gesammelten Informationen unterscheiden: Beim Basis-Tracing werden Ausführungsstatistiken von SQL- und PL/SQL-Statements gesammelt. Beim erweiterten Tracing werden zusätzlich zu den Ausführungsstatistiken auch Informationen über Wait Events und/oder Bindevariablen gesammelt. Wait Events sind für die Erstellung eines genauen Lastprofils unerlässlich.
594
Tuning
Session-Tracing Für jede Oracle-Session kann das Basis-Tracing der SQL-Befehle über ein alter session-Kommando eingeschaltet werden. SQL> alter session set sql_trace = true;
Das Kommando kann auch aus beliebigen Anwendungen heraus abgesetzt werden, jedoch bietet sich in der Praxis das Problem, dass Anwendungen keinen Schalter besitzen, mit dem ein SQL-Tracing aktiviert werden kann und eine nachträgliche Implementierung gerade in Standardprodukte oder auch Individualsoftware nicht oder nur schwer möglich ist. Dieser Befehl wird daher vornehmlich vom Entwickler oder Datenbankadministrator genutzt werden, der SQL-Befehle, die er näher untersuchen möchte, in einem Script separiert hat. Für Anwendungen bietet sich auf der anderen Seite die Möglichkeit an, das SQLTracing »von außen« für eine Oracle-Session an- und auszuschalten. Dafür steht das Package DBMS_MONITOR mit der Prozedur SESSION_TRACE_ENABLE zur Verfügung. Für die Parametrierung der Prozedur müssen sid und serial# der Session bekannt sein. Sollte eine Session über username aus v$session nicht eindeutig identifiziert werden können, bietet es sich an, die Spalten terminal, program und module mit ausgeben zu lassen. SQL> select username, sid, serial# from v$session; USERNAME SID SERIAL# ------------------------------ ---------- ---------1 1 2 1 3 1 4 1 5 1 6 1 7 1 DEMO 8 30
Für die beschriebene Session des Benutzers DEMO wird ein erweitertes SQL-Tracing mit Wait-Event- und Bindevariablen-Informationen wie folgt aktiviert: SQL> execute dbms_monitor.session_trace_enable(8,30,TRUE,TRUE);
Die beiden booleschen Parameter geben an, ob Wait-Informationen (1. Parameter) bzw. Bind-Informationen (2. Parameter) gesammelt werden sollen. Beide Parameter sind optional, als Default wird dann ein erweitertes Tracing mit Wait-Event-Informationen durchgeführt. Das Basis-Tracing für die bezeichnete Session wird also wie folgt aktiviert: SQL> execute dbms_monitor.session_trace_enable(8,30,FALSE);
Nach einer gewünschten Beobachtungszeit wird deaktiviert über: SQL> execute dbms_monitor.session_trace_disable(8,30);
Sollte die Session vorher beendet werden, ist das Tracing automatisch beendet. Es ist jedoch darauf zu achten, dass entsprechende Trace-Dateien vom Server auch
Hilfsmittel
595
geschlossen werden. Der nachträgliche Aufruf von session_trace_disable stellt dies sicher. Das Protokoll des Tracings wird in das Verzeichnis geschrieben, das über den Serverparameter user_dump_dest eingestellt ist. Die Namen der erzeugten Trace-Dateien variieren je nach Betriebssystem. Bestandteil des Namens ist die BetriebssystemProzessnummer des Oracle-Serverprozesses. In der Praxis sucht man im Filesystem nach einer Datei mit der Endung .trc, die einen Zeitstempel zum Ende des Tracings trägt. Unter Unix kann dazu der Befehl ls –ltr verwendet werden. Über den Serverparameter tracefile_identifier lassen sich darüber hinaus markante Zeichenketten definieren, die als Infix Eingang in den Namen der generierten TraceDateien finden. Zu ergänzen ist noch: Erzeugung Trace-Statistiken, Cursor-Closing: Ausführungspläne werden erst dann schrieben, wenn der Cursor geschlossen wird – daher Tracing nicht explizit schließen, sondern nur Session beenden. Client- und anwendungsbasiertes Tracing Client- und anwendungsbasiertes Tracing nutzt die Möglichkeit, Oracle-Sessions seitens des Clients bzw. der Anwendung zu markieren, um diese datenbankseitig problemlos und automatisch identifizieren zu können. Dies geschieht mittels Prozeduren des Pakkages DBMS_APPLICATION_INFO (SET_MODULE und SET_ACTION) sowie DBMS_SESSION (Prozeduren SET_IDENTIFIER und CLEAR_IDENTIFIER). Über diese Prozeduren kann vom Client eine Identifikation an die Datenbank durchgereicht werden, die anschließend z.B. in V$SESSION (Spalten MODULE, ACTION und CLIENT_IDENTIFIER) sichtbar ist. Alle drei Werte können im Laufe einer Session beliebig oft verändert werden, die beabsichtigte Verwendung ist jedoch wie folgt: Achtung: Die Prozedur DBMS_APPLICATION_INFO.SET_CLIENT_INFO setzt eine ClientInformation, die über die Spalte CLIENT_INFO in V$SESSION abgefragt werden kann. Hierfür funktioniert das Client-Tracing jedoch nicht! Es besteht hier leider starke Verwechslungsgefahr. Über SET_IDENTIFIER werden Informationen über den Client mitgegeben, z.B. der Name der Anwendung oder – bei Connection-Pooling – der Name des authentifizierten Benutzers. Dies sollte möglichst unmittelbar nach der Anmeldung an die Datenbank geschehen, um im Rahmen eines Client-Tracings wirklich alle vom Client abgesetzten SQL-Statements zu erfassen. Mittels SET_MODULE und SET_ACTION kann der Eintritt in einen bestimmten Code-Abschnitt der Client-Anwendung mitgeteilt werden, z.B. ein bestimmtes Formular, ein Report oder ein Batch-Lauf. Entsprechende Bezeichner für Clients sowie Module oder einzelne Aktionen des Clients sollten auf Seiten der Anwendungsentwicklung definiert und dokumentiert werden. Erfahrungsgemäß ist diese Funktionalität in vielen Anwendungen leider noch nicht verwendet. Soll in diesem Fall dennoch Client-Tracing verwendet werden, ist dies nur über eine entsprechende Anpassung der Anwendung möglich. Dazu müssen im allgemeinen an den Einstiegs- und Ausstiegspunkten der Anwendungsmodule entsprechende Aufrufe des Packages DBMS_APPLICATION_INFO bzw. DBMS_SESSION einprogrammiert werden.
596
Tuning
Abbildung 11.1: Client- und anwendungsbasiertes SQL-Tracing
Verfügt eine Anwendung über diese Funktionalität, kann durch den DBA veranlasst werden, dass für alle Oracle-Sessions ein selektives Tracing durchgeführt wird in dem Sinne, dass jede Session nur in solchen Zeiträumen getracet wird, in denen entsprechende Client-Markierungen gesetzt sind. Bei entsprechender Verwendung dieser Markierungen wie oben beschrieben, führt dies im Resultat dazu, dass datenbankweit genau diejenigen SQL-Statements getracet werden, die zu den gewählten Anwendungsmodulen bzw. Code-Abschnitten gehören. Beispielsweise könnte ein in PL/SQL geschriebenes Reporting-Tool im Rahmen einer Report-Generierung folgenden Marker setzen: BEGIN dbms_application_info.set_module( module_name => 'Verkaufsbericht (heute)' ,action_name => 'Initialisierung' ); /* Erstellung des Reports … */
dbms_application_info.set_module( module_name => NULL ,action_name => NULL ); END;
Hilfsmittel
597
Der DBA kann vor der Erstellung des Reports wie folgt ein Client-Tracing für diesen und andere Reports vereinbaren, z.B.: SQL> execute dbms_monitor.serv_mod_act_trace_enable('SUN10G', 'Verkaufsbericht (Woche)'); SQL> execute dbms_monitor.serv_mod_act_trace_enable('SUN10G', 'Verkaufsbericht (heute)','Initialisierung');
Der erste Parameter ist ein Service-Name, unter dem die Datenbank erreichbar ist. Dies ist der einzige Parameter, der unbedingt erforderlich ist. Es werden nur solche Sessions getracet, die unter dem angegebenen Service-Namen auf die Datenbank zugreifen. Sessions, die nicht über einen Service-Namen, sondern lokal über eine SID angemeldet sind, werden mit dem speziellen Service-Namen SYS$USERS ausgestattet. Für Oracle-Hintergrundprozesse wird der spezielle Service-Name SYS$BACKGROUND benutzt. Damit kann also auch ein Tracing für Hintergrundprozesse (SMON, PMON etc.) durchgeführt werden, wenn Performance-Probleme an dieser Stelle vermutet werden. Im Zweifelsfall kann der Service-Name einer Session aus der Spalte SERVICE_NAME in V$SESSION abgelesen werden. Die ersten drei Parameter dieser Prozedur (service_name, module_name, action_name) bilden ein hierarchisches Schema zur Definition von Tracing-Regeln ab: Wird lediglich ein Service-Name übergeben, entspricht dies einem datenbankweiten Tracing mit der Einschränkung, dass nur solche Sessions getracet werden, die über den entsprechenden Service-Namen an die Datenbank angemeldet sind. Bedient eine Datenbank mehrere Anwendungen, sollte daher jeder Anwendung ein separater Service-Name zugeordnet sein, um auf diese Weise ein Tracing auf Anwendungsebene zu ermöglichen (siehe Abbildung). Wird außerdem ein Modulname angegeben, werden diese Sessions nur getracet, solange der entsprechende Modulname gesetzt ist. Damit kann eine bestimmte Komponente innerhalb einer Anwendung getracet werden. Wird außerdem ein Aktionsname angegeben, werden diese Sessions nur getracet, solange der entsprechende Modul- und Aktionsname gesetzt ist. Ein Tracing eines bestimmten Code-Abschnitts innerhalb einer Anwendung ist auf diese Weise möglich. Sowohl für den Modul- als auch für den Aktionsnamen kann NULL übergeben werden, dann wird jede Session nur getracet, solange kein Modul bzw. keine Aktion gesetzt ist. Vorsichtshalber sollte dies immer durchgeführt werden, wenn nicht sicher ist, dass die Anwendung diese beiden Marker setzt. Für jede Tracing-Regel kann außerdem angegeben werden, ob ein Basis-Tracing oder ein erweitertes Tracing durchgeführt werden soll (boolesche Parameter waits und binds). In RAC-Umgebungen (siehe Kapitel 13) kann auch eine Beschränkung auf eine Instanz erfolgen (Parameter instance_name), wenn bekannt ist, dass nur bei dieser Instanz Probleme auftreten. Service-Name, Modul und Aktion bilden, wenn sie wie oben beschrieben verwendet werden, eine hierarchisches Schema, das die Struktur der Anwendung auf Seiten der Datenbank bekannt macht. Davon unabhängig stellt die Client-Markierung Informationen über den Client auf Seiten der Datenbank bereit. Ein ClientTracing auf Basis der Client-Markierung wird daher wie folgt durchgeführt:
598
Tuning
Das oben erwähnte Reporting-Tool setzt nach der Anmeldung an die Datenbank eine Client-Markierung. Dabei wird die Login-Information des Clients sozusagen durchgereicht: BEGIN dbms_session.set_identifier( client_id => 'Ahrends' ); END;
Um nun alle von diesem Benutzer ausgelösten SQL-Statements zu tracen, ist folgender Aufruf notwendig: SQL> execute dbms_monitor.client_id_trace_enable('Ahrends');
Jeder Aufruf von DBMS_MONITOR.SERV_MOD_ACT_TRACE_ENABLE bzw. DBMS_MONITOR.CLIENT_ ID_TRACE_ENABLE definiert eine Tracing-Regel wie oben beschrieben. Es können beliebig viele Tracing-Regeln vereinbart werden. Diese wirken kumulativ, d.h. für jede Session wird getracet, solange mindestens eine Tracing-Regel erfüllt ist. Aktivierte Client-Tracings können über dba_enabled_traces abgefragt werden, aktivierte Session-Tracings aber leider nicht. Ob das Tracing auf Datenbankebene aktiviert ist, kann durch Inspektion des Parameterwerts für SQL_TRACE in V$PARAMETER ermittelt werden. SQL> SQL> SQL> SQL>
column primary_id format a10 column qualifier_id1 format a25 column qualifier_id2 format a15 SELECT trace_type,primary_id,qualifier_id1 ,qualifier_id2,waits,binds FROM dba_enabled_traces; TRACE_TYPE PRIMARY_ID QUALIFIER_ID1 QUALIFIER_ID2 WAITS BINDS --------------------- ---------- ------------------------- --------------- ----- ----SERVICE_MODULE_ACTION SUN10G Verkaufsbericht (heute) Initialisierung TRUE FALSE SERVICE_MODULE SUN10G Verkaufsbericht (Woche) TRUE FALSE CLIENT_ID Ahrends TRUE FALSE
Nach beendetem Tracing kann das Client-Tracing wieder deaktiviert werden, z.B.: SQL> execute dbms_monitor.serv_mod_act_trace_disable('SUN10G', 'Verkaufsbericht (Woche)'); SQL> execute dbms_monitor.serv_mod_act_trace_disable('SUN10G', 'Verkaufsbericht (heute)','Initialisierung'); SQL> execute dbms_monitor.client_id_trace_disable('Ahrends');
Achtung: Regeln für Client-Tracing werden in Datenbanktabellen abgespeichert und bleiben daher über den Neustart der Instanz hinweg erhalten. Eine explizite Deaktivierung solcher Tracing-Regeln wie oben gezeigt ist daher erforderlich!
Hilfsmittel
599
Datenbank-Tracing Für eine komplette Oracle-Instanz kann das Tracing aller SQL-Befehle über ein ALTER SYSTEM-Kommando eingeschaltet werden. SQL> ALTER SYSTEM SET sql_trace = TRUE;
Ist der Serverparameter gesetzt, wird jeder Prozess protokolliert. Dadurch kann es zu nicht unerheblichen Belastungen des Systems kommen, sowohl in Bezug auf die CPU als auch auf den I/O, besonders auf der Platte, auf die der Serverparameter user_dump_dest verweist. Zudem wird unter Umständen enorm viel Platz auf dieser Platte benötigt. Die Größe einer Trace-Datei lässt sich über den Serverparameter max_dump_file_size begrenzen. Die Auswertung einer solchen Menge von Trace-Dateien ist natürlich auch problematisch, da auch im Nachhinein eine Zuordnung zu Anwendungen und Anwendern schwierig ist. Diese Möglichkeit bietet sich also nur für Testsysteme an, auf denen festgelegte Anwendungen auf die Performance untersucht werden sollen. Konsolidierung von Trace-Dateien Da für jede Oracle-Session eine Trace-Datei geschrieben wird, werden insbesondere beim Client-Tracing i.A. mehrere Trace-Dateien generiert. Um diese mit ReportingTools wie TKProf (siehe unten) aufzubereiten, ist es zunächst erforderlich, sie zu einem einzigen Gesamt-Trace zu konsolidieren. Ein weiteres Problem erwächst aus dem Sachverhalt, dass die Namen von TraceFiles eindeutig gemacht werden, indem die Prozess-ID des Serverprozesses Teil des Dateinamens ist. Dies ist problematisch, wenn Connection-Pooling benutzt wird und die Serverprozesse somit sehr langlebig sind. Es ist dann durchaus wahrscheinlich, dass ein bestimmter Serverprozess schon einmal getracet wurde und in der zugehörigen Trace-Datei auch bereits alte Trace-Informationen liegen. Aber auch bei kurzlebigen Connections kann dieses Problem auftreten, nämlich wenn eine Prozess-ID zum wiederholten Male verwendet wird. Dann werden neue TraceInformationen einfach an die bestehende Trace-Datei angehängt. In beiden Fällen ist es also erforderlich, alte von neuen Trace-Einträgen zu trennen. Das Werkzeug TRCSESS löst einige der beschriebenen Probleme. Es konsolidiert mehrere Trace-Dateien. Gleichzeitig können unerwünschte Einträge auf Basis verschiedener Kriterien ausgefiltert werden. Das Aufruf-Skript befindet sich in $ORACLE_HOME/bin, das Werkzeug ist in JAVA geschrieben. Ein Aufruf ohne Parameter gibt eine Syntax-Hilfe aus. Aufruf: $ trcsess output=trace_cons.trc module="Verkaufsbericht (heute)" action="Initialisierung" ps10_ora_1452.trc ps10_ora_1556.trc ps10_ora_1640.trc
600
Tuning
output
Ausgabedatei für die Konsolidierung
module
Nur Einträge mit dem angegebenen Modul-Wert werden für die Konsolidierung berücksichtigt.
action
Nur Einträge mit dem angegebenen Action-Wert werden für die Konsolidierung berücksichtigt.
*.trc
Namen der Trace-Dateien, die konsolidiert werden sollen
Analog zu den Parametern module und action sind auch folgende Parameter möglich: service
Eingrenzung nach Service-Namen des Clients
clientid
Eingrenzung nach Client-ID
session
Eingrenzung nach Oracle-Session in der Form <SID>.<Serial#> Beispiel: session=146.78
Mindestens einer der Filter-Parameter muss angegeben werden. Leider gibt es keine Möglichkeit, nach dem Datum des Trace-Eintrags zu filtern. Das Abtrennen alter Einträge muss daher ggf. zuvor manuell erfolgen. Achtung: Die für das Filtern notwendigen Trace-Einträge (Module-, Action-Wert etc.) werden nicht in die Ausgabedatei übernommen. Daher kann die Ausgabedatei (trace_cons.trc im obigen Beispiel) nicht für einen weiteren Konsolidierungsschritt benutzt werden. Eine Konsolidierung in mehreren Stufen ist also nicht möglich. TKPROF Der Inhalt einer Trace-Datei ist kryptisch, kann also nicht einfach interpretiert werden. Für die Aufbereitung der Trace-Dateien wird ein Werkzeug mitgeliefert, TKPROF. Das ausführbare Programm ist unter $ORACLE_HOME/bin zu finden und kann über die Shell eines Unix-Systems oder über die MS-Windows-Kommandoebene aufgerufen werden. Wird das Werkzeug ohne Parameter aufgerufen, wird eine Hilfe mit der möglichen Parametrierung geboten. Aufruf: $ tkprof ora00391.trc out.tkp explain=username/passwd sort=fchqry
ora00391.trc
Name der Trace-Datei, die ausgewertet werden soll.
out.tkp
Ausgabedatei der Auswertung, hier muss auf die Schreibberechtigung geachtet werden.
explain
Gibt an, dass die Ausführungspläne der SQL-Befehle der Trace-Datei durch eine explizite Datenbankverbindung ermittelt werden sollen – statt sie direkt aus der Trace-Datei zu übernehmen. Es muss ein Benutzername und dessen Passwort angegeben werden. Hier sollten Sie darauf achten, dass es der Benutzer ist, unter dem auch die Anwendung während des Tracings ausgeführt worden ist, damit sichergestellt ist, dass es sich um die gleichen Schema-Objekte handelt. Der Ausführungsplan wird nicht aus der Trace-Datei gelesen,
Hilfsmittel
601
sondern wird zum Zeitpunkt des TKPROF-Aufrufs ermittelt. Vorsicht: Nach dem Tracing angelegte oder gelöschte Indizes können daher den Ausführungsplan verfälschen. Eine Methode, um garantiert an die korrekten Ausführungspläne zu kommen, wird weiter unten beschrieben. Wird explain nicht angegeben, generiert TKPROF die Pläne direkt aus den Angaben der Trace-Datei. sort
Die Befehle können in der Ausgabedatei nach verschiedenen Kriterien sortiert werden. Wird nichts angegeben, werden sie in der Reihenfolge der Ausführung dargestellt. Sortiert werden kann nach Zeitverbrauch oder der Anzahl von gelesenen Blöcken in den drei Phasen der SQL-Befehle: PARSE, EXECUTE oder FETCH.
Beispiele: prscpu
CPU-Zeitverbrauch für SQL-Parsing
exeela
Verweilzeit für Ausführung (meist bei DML)
fchqry
Anzahl gelesener Oracle-Blöcke (Select)
(prsela,fchela)
Summe der Gesamtzeiten für Parsing und Auslesen
Durch die optionale Angabe SYS=NO können rekursive Befehle des Benutzers SYS aus der Ausgabe herausgefiltert werden. Zusätzlich zu den Statistiken eines SQL-Befehls wird der Ausführungsplan dargestellt. Im dem unten aufgeführten Beispiel sollen diese Ausführungspläne nicht aus der rohen Trace-Datei, sondern direkt über eine Datenbankverbindung ermittelt werden. Die Interpretation von Ausführungsplänen wird im Abschnitt Ausführungspläne näher erläutert. Beispiel: tkprof ora00031.trc out1.tkp explain=demo/demo sys=no Optimizer goal: CHOOSE Parsing user id: 26 (DEMO) *************************************************************** SELECT k.kd_ort, SUM(p.pos_menge * p.pos_einzelpreis) AS umsatz FROM kunden k, auftraege a, positionen p WHERE k.kd_nr = a.auf_kdnr AND a.auf_nr = p.pos_aufnr AND UPPER(k.kd_nachname) = 'AHRENDS' AND UPPER(k.kd_vorname) = 'MARLIES' GROUP BY k.kd_ort call count cpu elapsed disk query current rows ------- ------ ----- -------- ------- ------- -------- -----Parse 1 0.04 0.02 0 15 0 0 Execute 1 0.00 0.00 0 0 0 0 Fetch 2 1.85 8.77 27771 28142 0 1 ------- ------ ----- -------- ------- ------- -------- -----total 4 1.90 8.79 27771 28157 0 1
602 Misses in library cache during parse: 1 Optimizer goal: CHOOSE Parsing user id: 26 (DEMO) Rows Row Source Operation ------- --------------------------------------------------1 SORT GROUP BY 27 HASH JOIN 9 HASH JOIN 1 TABLE ACCESS FULL KUNDEN 1000000 TABLE ACCESS FULL AUFTRAEGE 2502684 TABLE ACCESS FULL POSITIONEN Rows Execution Plan ------- --------------------------------------------------0 SELECT STATEMENT GOAL: CHOOSE 1 SORT (GROUP BY) 27 HASH JOIN 9 HASH JOIN 1 TABLE ACCESS GOAL: ANALYZED (FULL) OF 'KUNDEN' 1000000 TABLE ACCESS GOAL: ANALYZED (FULL) OF 'AUFTRAEGE' 2502684 TABLE ACCESS GOAL: ANALYZED (FULL) OF 'POSITIONEN' **************************************************************** ... *************************************************************** OVERALL TOTALS FOR ALL NON-RECURSIVE STATEMENTS call count cpu elapsed disk query current rows ------- ------ ----- -------- ------- ------- -------- -----Parse 6 0.04 0.02 0 15 0 0 Execute 7 0.00 0.00 0 6 9 7 Fetch 5 1.85 8.77 27771 28164 0 8 ------- ------ ----- -------- ------- ------- -------- -----total 18 1.90 8.80 27771 28185 9 15 Misses in library cache during parse: 5 Misses in library cache during execute: 1 OVERALL TOTALS FOR ALL RECURSIVE STATEMENTS call count cpu elapsed disk query current rows ------- ------ ----- -------- ------- ------- -------- -----Parse 18 0.03 0.01 0 0 0 0 Execute 45 0.00 0.01 0 2 8 7 Fetch 66 0.00 0.00 0 104 0 37 ------- ------ ----- -------- ------- ------- -------- -----total 129 0.03 0.02 0 106 8 44 Misses in library cache during parse: 14 Misses in library cache during execute: 1 8 user SQL statements in session. 17 internal SQL statements in session. 25 SQL statements in session. 5 statements EXPLAINed in this session. *************************************************************** Trace file: ora00031.trc Trace file compatibility: 9.00.01 Sort options: default 3 sessions in tracefile. 11 user SQL statements in trace file. 32 internal SQL statements in trace file.
Tuning
Hilfsmittel
603
25 20 5
SQL statements in trace file. unique SQL statements in trace file. SQL statements EXPLAINed using schema: DEMO.prof$plan_table Default table was used. Table was created. Table was dropped. 363 lines in trace file. Trace file: ora00031.trc Trace file compatibility: 9.00.01 Sort options: default 3 sessions in tracefile. 11 user SQL statements in trace file. 32 internal SQL statements in trace file. 25 SQL statements in trace file. 20 unique SQL statements in trace file. 5 SQL statements EXPLAINed using schema: DEMO.prof$plan_table Default table was used. Table was created. Table was dropped. 363 lines in trace file. Listing 11.1: Durch TKPROF formatierte Trace-Datei
Interpretationsproblematiken: Falsche Ausführungspläne durch implizite Datentypkonvertierungen TKPROF kennt nicht die Inhalte von Bindevariablen und daher auch nicht die verwendeten Datentypen. Es ist daher möglich, dass in der TKPROF-Ausgabe ein Ausführungsplan angezeigt wird, der nicht den tatsächlichen Ausführungsplan abbildet, weil sich durch implizite Datentypkonvertierungen, die immer auf Seite der Tabellenfelder ausgeführt werden, dieser Zugriff nicht realisieren lässt. Diese Diskrepanz ist nur anhand der Statistiken festzustellen, wenn z.B. trotz angezeigter Indexbenutzung die Anzahl der gelesenen Blöcke zu hoch erscheint. Anzahl gelesener Blöcke bei Lesekonsistenz Zu beachten ist, dass die Anzahl der gelesenen Blöcke im Konsistenzmodus in der Spalte query auch die gelesenen Undo-Segment-Blöcke beinhaltet, die für die Wahrung der Lesekonsistenz herangezogen werden mussten. So kann diese Zahl differieren, abhängig davon, ob gerade DML-Operationen von anderen Prozessen auf den beteiligten Tabellen der Abfrage durchgeführt werden. Falsche Ausführungspläne durch Änderungen am Schema Die Ausführungspläne der SQL-Befehle werden in der Regel1 mit in die Trace-Datei geschrieben, bei Nutzung der explain-Klausel jedoch neu aus der Datenbank generiert. In solchen Fällen ist es möglich, dass in der Zwischenzeit angelegte oder gelöschte Indizes einen vom Original abweichenden Ausführungsplan ausgeben. 1
Bei abnormaler Beendigung der Session kann es vorkommen, dass diese Pläne nicht in der rohen Trace-Datei erscheinen.
604
Tuning
Interpretation der elapsed time Die elapsed time wird von der CPU time häufig abweichen, gerade dann, wenn Wartezustände auf Plattenzugriffe auftreten oder der Prozess nicht permanent CPUZeit zugeteilt bekommen kann. Aber auch künstlich erzeugte Wartezustände auf Tabellen, wie z.B. eine exklusive Sperre auf einer Tabelle, können die Zeitinformationen ungewollt verfälschen. Darüber hinaus gehen die Ausführungszeiten rekursiver Calls mit in die Elapsed-Zeiten ihrer auslösenden Befehle ein. Höherer Ressourcenverbrauch durch Trigger In den Statistiken wird der komplette Ressourcenverbrauch eines Befehls kumuliert, so z.B. auch Aktivitäten, die durch Trigger auf den Tabellen erzeugt werden, auf die zugegriffen wird. Daraus können auf den ersten Blick nicht erklärbare Werte in den Statistikinformationen entstehen. Trace Analyzer (TRCA) Ein Nachteil von TKProf ist, dass insbesondere bei SQL-Befehlen mit Bindevariablen TKProf lediglich Summenwerte über alle Ausführungen des Kommandos liefert, die Performance jedoch in einigen Fällen von den konkreten Werten für Bindevariablen abhängt (z.B. bei schlecht ausbalancierten Indizes). Außerdem können Wartezustände einen Großteil der Gesamtzeit (elapsed Time) ausmachen bzw. die Ergebnisse verfälschen. Prinzipiell können Werte von Binde-Variablen sowie aufgetretene Wartezustände mittels erweitertem Tracing in die Trace-Datei mit einbezogen werden. Diese zusätzlichen Einträge werden jedoch von TKProf nicht vollständig interpretiert. Oracle stellt daher über die Metalink-Seite (Note 224270.1) das Werkzeug Trace Analyzer (TRCA) zur Verfügung, das alle Informationen im Rahmen des erweiterten Tracings interpretiert und ein detailliertes Last- und Ressourcenprofil der gemessenen Zeitspanne liefert. Im Gegensatz zu TKProf besteht TRCA aus einer Sammlung von SQL- und PL/SQL-Skripten und läuft vollständig in der Datenbank, wo auch ein Repository verwaltet wird. Die Skripte erlauben einen genauen Einblick in die Arbeitsweise des Tools und sind beliebig anpassbar und erweiterbar. Es wird zunächst ein Gesamtbericht generiert, der u.a. alle Informationen eines TKProf-Berichts beinhaltet. Über einen Drill-down-Mechanismus können weitere Detailberichte erzeugt werden (siehe Abbildung 11.2). Die zusätzlichen Funktionen von TRCA zusammen mit der Ad-hoc-Einsatzfähigkeit von TKProf führen dazu, dass beide Werkzeuge sich hervorragend ergänzen in dem Sinne, dass nach einer »groben Sichtung« mittels TKProf entschieden werden kann, ob eine genauere Analyse mittels TRCA angebracht ist. Beide Werkzeuge sind mithin als komplementär zu bezeichnen.
Hilfsmittel
605
Abbildung 11.2: Funktionsweise des Trace Analyzers
TRCA-Administration TRCA verwaltet ein Repository in der Datenbank, bestehend aus Tabellen und Indizes, deren Namen sämtlich mit TRCA$ beginnen, einem Package TRCA$ sowie einem Directory-Alias mit dem Namen udump. Sämtliche Skripte laufen im Schema des Aufrufenden ab (die Skripte führen kein CONNECT aus). Alle Skripte haben die Form TRCA*.sql, bspw. TRCACREA.sql: CREA, DROP: Erstellen/Löschen des Repositories. Alle Objekte werden im Default Tablespace des Aufrufenden erstellt. Der Directory-Alias udump zeigt auf das user_dump_ dest-Verzeichnis. GRNT, REVK <user>: Zuweisen/Entziehen von SELECT-Rechten auf einige DBA- und V$Views sowie des READ-Rechtes auf den Directory-Alias für den Benutzer <user>. Diese Rechte werden benötigt, um den Trace Analyzer auszuführen. TRNC: Leert alle Repository-Tabellen PURG : Löscht alle Repository-Einträge, die älter als Tage sind.
Generierung eines Gesamtberichts Ein Aufruf von TRCANLZR.sql liest zunächst zeilenweise die angegebene Trace-Datei und speichert den interpretierten Inhalt im Repository. Dabei wird eine Trace-ID zugewiesen, mittels derer im weiteren Verlauf auf den Inhalt dieser Trace-Datei Bezug genommen werden kann. Daran anschließend wird der Gesamtbericht erstellt. Beim Aufruf muss der Directory-Alias für das Verzeichnis angegeben werden, in dem die Trace-Datei liegt (standardmäßig udump) sowie der Name der TraceDatei. SQL> @TRCANLZR
udump
606
Tuning
Folgende Informationen werden in den Gesamtbericht geschrieben: Die Top 5 SQL-Cursor bezüglich CPU-Zeit, Elapsed-Zeit, Non-Idle- und IdleWartezustände (jeweils Gesamtwerte über alle Ausführungen). Der Übersicht halber werden zunächst nur die Cursor-ID (wird von TRCA analog zu tkprof vergeben), die User-ID des Ausführenden (0 für SYS) und der Oracle Command Type aufgelistet. Letzterer ist in der Trace-Datei als Eintrag oct codiert und wird über die Tabelle AUDIT_ACTIONS aufgelöst. Häufige Command Types sind SELECT, INSERT, UPDATE, DELETE, PL/SQL EXECUTE, ANALYZE TABLE. Für jeden Cursor, der nach mindestens einem Kriterium zu den Top 5 gehört, wird eine Zeile dargestellt. Aufgetretene ORA-Fehler während des Tracings. Gaps (Zeiträume ohne Aktivität) werden anhand des Vergleichs aufeinander folgender tim-Einträge im Trace-File ermittelt und ausgegeben. Abgeschlossene Transaktionen (XCTEND) im Trace-File, zusammen mit der Information, ob mit COMMIT oder ROLLBACK beendet wurde und ob DML-Aktivität stattfand oder nicht. Ausführungsstatistiken pro Benutzer, getrennt nach Recursive/Non-Recursive SQL. Dies erlaubt insbesondere eine Differenzierung zwischen »User Recursive SQL« (Inhalt von PL/SQL-Blöcken) und »System recursive SQL«. Jeweils eine Zeile für Parse-/Exec-/Fetch-Phase (analog zu TKProf) Eine Zeile pro Kommandotyp Wartezustandsstatistiken pro User, getrennt nach Recursive/Non-Recursive SQL. Idle-Waits stehen jeweils als Letztes. Außerdem werden jeweils Teilsummen-Zeilen für alle Idle-Waits bzw. Non-Idle-Waits ausgegeben. Für einige Non-Idle-Waits, z.B. db file {sequential | scattered} read werden außerdem Statistiken pro Datenbank-Objekt (z.B. Tabelle) ausgegeben. Die »Hottest 5 blocks« (die Blöcke mit der höchsten Wartezeit) und Cursor-IDs der entsprechenden Cursor. Kommandotyp, Ausführungsstatistiken (à la TKProf) sowie Non-Idle/Idle-Wartezeiten pro Cursor. Damit kann sehr schnell eine Vorauswahl relevanter SQLKommandos vorgenommen werden. Cursorliste: Dabei werden (analog zu TKProf) Gesamt-Ausführungsstatistiken und Wartezustandsstatistiken sowie der Ausführungsplan dargestellt. Außerdem werden die Substitutionswerte aller Bindevariablen pro Ausführung sowie Ausführungs- und Wartezustandsstatistiken pro Ausführung dargestellt. An dieser Stelle lassen sich sehr gut einzelne Ausreißer erkennen. In der Trace-Datei und auch in den TRCA-Reports sind leider nicht die Namen der Bindevariablen eingetragen. Stattdessen sind diese entsprechend der Reihenfolge ihres Vorkommens im SQL-Statement mit 0 beginnend aufsteigend durchnummeriert. Die Zuordnung zu entsprechenden evtl. mit sprechenden Namen versehenen Bindevariablen muss daher ggf. durch Abzählen der Positionen der Bindevariablen innerhalb des SQL-Kommandos vorgenommen werden. Falls eine Bindevariable mehrfach vorkommt, wird bei allen außer dem ersten Vorkommen als Substitutionswert NSBBE (no separate bind buffer exists) ausgegeben.
Hilfsmittel
607
Einige Obergrenzen sind in den TRCA-Skripten fest eingetragen. So werden maximal 2000 Cursor in den Gesamtbericht geschrieben. Pro Cursor werden maximal 100 Ausführungen (zehn bei Benutzer SYS) angezeigt. All diese Begrenzungen können natürlich angepasst bzw. aufgehoben werden. Ganz oben im Gesamtbericht ist auch die Trace-ID eingetragen, die für die Detailberichte verwendet werden muss. Generierung von Detailberichten Falls aufgrund der genannten Obergrenzen nicht alle Ausführungen eines Cursors im Gesamtbericht gelistet wurden, kann ein entsprechender Detailbericht erstellt werden, der sämtliche Ausführungen umfasst: SQL> @TRCACRSR
<cursor-id>
Ein entsprechendes Beispiel findet sich unterhalb der Ausführungsliste im Gesamtbericht in Form folgender Zeile, z.B.: REPORTING ONLY FIRST 100... (TO REPORT ALL: SQL> START TRCACRSR.sql 11 2; )
Hier muss lediglich die gewünschte Cursor-ID eingesetzt und per Copy and Paste ins SQLPlus-Fenster übertragen werden. Cursor-IDs werden im Gesamtbericht mit 1 beginnend aufsteigend vergeben. Durch Einsetzen von 0 als Cursor-ID werden alle Ausführungen für alle Cursor ausgegeben. Ein Bericht über den detaillierten Ablauf einer einzelnen Ausführung schließlich kann unter Angabe der Bind-Line erzeugt werden. Diese ist in den vorgenannten Berichten in der Spalte binds trc_line zu finden und entspricht der Zeilennummer im ursprünglichen Trace-File. SQL> @TRCAEXEC
<cursor-id>
Auch hier findet sich im Gesamtbericht unterhalb der Ausführungsliste eine entsprechende Beispielzeile. Durch Einsetzen von 0 als Bind-Line werden Detailinformationen über alle Ausführungen des betreffenden Cursors geliefert. Hier ein Ausschnitt aus einem solchen Bericht, der gewissermaßen eine lesbare Darstellung der entsprechenden Zeilen der Trace-Datei darstellt. Für Wartezustände, bei denen dies möglich ist, werden die Parameter p1, p2, p3 in Segmentname und Extent-Nummer aufgelöst, so dass unmittelbar erkennbar ist, worauf gewartet wurde.
608
Tuning
Abbildung 11.3: Ausschnitt aus einem Trace-Analyzer-Bericht
Tracing und Ausführungspläne Wie bereits erwähnt, ist das nachträgliche Erstellen eines Ausführungsplans (via explain-Parameter) mit Hilfe des TKProf-Werkzeugs problematisch, da der so gefundene Ausführungsplan nicht zwangsläufig dem tatsächlichen Ausführungsplan entspricht. Seit Oracle9i werden prinzipiell aber auch die Ausführungspläne jedes SQL-Kommandos in die Trace-Datei geschrieben. Die TKProf-Werkzeuge ab Oracle9i geben diese auch korrekt aus. Eigentlich besteht also gar keine Notwendigkeit mehr für das nachträgliche Generieren eines Ausführungsplans. Allerdings merkt man in der Praxis recht schnell, dass seltsamerweise nicht für alle SQL-Kommandos tatsächlich Ausführungspläne in die Trace-Datei geschrieben werden. Dies sorgt oftmals für Verwirrung, da auch scheinbar bei jedem Lauf andere Kommandos von diesem Umstand betroffen sind. Des Rätsels Lösung liegt darin, dass der Ausführungsplan eines SQL-Kommandos erst in dem Moment in die Trace-Datei geschrieben wird, in dem der zugehörige SQL-Cursor im Library-Cache geschlossen wird. Dies kann zeitlich weit hinter der eigentlichen Ausführung und sogar nach der Beendigung des Tracings liegen. In letzterem Fall tritt das beschriebene Problem auf. Da kaum vorherzusagen ist, wann der Cursor geschlossen wird, kann man sich – gerade bei häufig benutzten SQLKommandos – nicht auf diesen Mechanismus verlassen. Der einzige Weg, ein Schließen aller SQL-Cursor und damit das Schreiben aller Ausführungspläne in die Trace-Datei zu erzwingen, besteht darin, das Tracing nicht (!) sauber zu beenden, sondern einfach die Session zu beenden (via Disconnect oder SQL*Plus-Kommando quit). Bei einer Anwendung mit Connection-Pool ist das natürlich nicht immer so einfach, es stellt aber leider die einzige Lösung dar, die garantiert zum gewünschten Ergebnis führt.
Der Optimizer
11.3
609
Der Optimizer
Die Aufgabe des Optimizers ist die Ermittlung des optimalen Zugriffspfades für einen SQL-Befehl. Die Optimierung ist Teil des Parsings, der Übersetzung des SQLBefehls in eine ausführbare Form. Der Optimizer soll bei einem Zugriff auf eine Tabelle z.B. feststellen, ob ein Zugriff über einen Index aufgrund der WHERE-Klausel ausgeführt werden kann, bei mehreren vorhandenen Indizes auch über welchen. Bei Join-Operationen, also dem Zugriff auf zwei oder mehr Tabellen in einem SELECT-Befehl, muss ermittelt werden, welche Tabelle zuerst gelesen wird, also zur treibenden Tabelle wird, und in welcher Reihenfolge die weiteren Tabellen hinzugenommen werden. Zudem ist die Methode der Zusammenführung der Teilmengen der Tabellen entscheidend (merge join, nested loop, hash join). Der »regelbasierte Optimizer« (RBO), der in den vergangenen Oracle-Versionen stets noch unterstützt, wenn auch nicht mehr empfohlen wurde, wird mit dem Release Oracle 10g nicht mehr unterstützt und wird daher an dieser Stelle auch nicht behandelt. Die Funktionalität des RBO ist noch vorhanden, jedoch leistet Oracle keinen Support für deren Benutzung. Es sollte daher ausschließlich der kostenbasierte Optimizer (CBO) benutzt werden. Mit der Oracle-Version 10g ist dieser außerdem in »Query Optimizer« umbenannt worden. Der Query Optimizer ist ein Expertensystem, das die optimalen Zugriffspfade zu Oracle-Tabellen aufgrund statistischer Informationen, die für Tabellen, Indizes und Cluster erzeugt werden können, ermittelt. Neben den Statistiken der Objekte sind für die Pfade auch Instanzressourcen und Parametrierungen der Instanz relevant, die im Folgenden noch erläutert werden. Die Nachteile, die beim regelbasierten Optimizer festgestellt wurden, sollen durch den Query Optimizer eliminiert werden, da dieser die Größen der Tabellen ebenso wie die Selektivität der Indizes berücksichtigen kann. Zur Ermittlung des optimalen Pfades werden zunächst alle möglichen Permutationen von möglichen Zugriffen gebildet. Zu jedem Pfad werden dann auf Grundlage der Statistiken die entsprechenden Kosten errechnet, welche die Nutzung von Ressourcen beziffern, wie z.B. die Anzahl der I/O-Operationen, die Hauptspeichernutzung und die CPU-Zeit. Der Zugriffspfad mit den geringsten Kosten ist der optimale, insofern eine Parallelisierung außer Acht gelassen wird.
11.3.1
Die Ausführung von SQL-Code
Die Abarbeitung eines SQL-Befehls erfolgt nicht an einem Stück, sondern in mehreren Phasen. Die einzelnen Phasen werden im Folgenden kurz erklärt. Sie gelten im Wesentlichen für alle Arten von SQL-Befehlen. Eine Ausnahme ist lediglich die FETCH-Phase, die nur beim SELECT-Befehl existiert und dafür sorgt, dass die Ergebnisdatensätze vom Server zum Client übertragen werden.
610
Tuning
Der Cursor Um in den nachfolgend diskutierten Phasen Informationen zwischenzuspeichern, wird eine spezielle Datenstruktur benötigt. Diese wird, in Anlehnung an die Vorstellung eines Zeigers, der bei der Ausgabe der Datensätze die aktuelle Position angibt, als Cursor bezeichnet. Bezieht man sich auf die dort enthaltenen Informationen, so wird diese Struktur auch Context Area genannt. Der Cursor ist die Schaltzentrale für die Ausführung eines SQL-Befehls. Er enthält den betreffenden SQLBefehl als Zeichenkette sowie den Ausführungsplan des SQL-Befehls als Zeiger auf den Shared Pool sowie Zeitstempel- und Zustandsinformationen. Ein Anwendungsprogramm kann – bis auf die Beschränkungen des virtuellen Adressraums und des Serverparameters open_cursors – beliebig viele Cursors öffnen. Weiterhin werden in der Anwendung Variablen benutzt, um einerseits Parameter an SQL-Befehle zu übergeben (z.B. in WHERE-Klauseln) und um andererseits das Ergebnis eines SELECT-Befehls aufzunehmen. Diese Variablen werden als Bindevariablen bezeichnet und ebenfalls Cursor-spezifisch behandelt. Das Vorgehen zum Binden von Variablen unterscheidet sich nach Art des Clients (Embedded SQL, Forms, OCI usw.). Um die Arbeitsweise des Oracle-Servers zu verdeutlichen, muss noch auf eine spezielle Eigenschaft hingewiesen werden: Der Oracle-Server arbeitet ausschließlich nach einer Methode, die allgemein als dynamisches SQL bezeichnet wird. Dies bedeutet, dass die SQL-Befehle der Anwendungen dem Oracle-Server vor der Ausführung nicht bekannt sein müssen. Im Gegensatz dazu müssen bei Datenbankservern, die mit statischem SQL arbeiten, die Anwendungen vorher übersetzt werden, so dass beim Ablauf der Anwendungen alle SQL-Befehle bekannt sind und ein beim Übersetzen festgelegter Ausführungsplan benutzt wird. Das dynamische SQL des Oracle-Servers hat den Vorteil, dass die Anwendungen dadurch flexibler werden: Moderne SQL-Werkzeuge generieren SQL-Befehle aus den Eingaben des Benutzers in eine grafische Oberfläche, so dass permanent neue SQL-Befehle entstehen. Das Datenbank-Tuning wird dadurch vereinfacht, dass z.B. ein neu kreierter Index sofort von allen Anwendungen benutzt werden kann, wenn die Benutzung aus der Sicht des Optimizers Sinn macht. Um die Performance des dynamischen SQLs zu optimieren, wird beim Oracle-Server der einmal bestimmte Ausführungsplan in einem dafür vorgesehenen Teil der SGA, dem Shared Pool, abgelegt. Somit kann generell in der PARSE-Phase Zeit eingespart werden, indem zunächst überprüft wird, ob der Befehl bereits im Shared Pool abgelegt ist und vom aktuellen Benutzer ohne Verletzung der Zugriffsrechte benutzt werden kann. Die Suche des SQL-Befehls im Shared Pool erfolgt mit Hilfe eines Hash-Algorithmus recht schnell, so dass bei einem Nichtvorhandensein kein allzu großer Nachteil entsteht. Die größten Vorteile des Shared Pools entstehen aus der Verwendung des Oracle-Servers mit fest programmierten SQL-Befehlen in den Anwendungen im Mehrbenutzerbetrieb: Diese werden nur einmal übersetzt und dann immer wieder verwendet. Da aber auch die vom Oracle-Server intern generierten SQL-Befehle, so genannte rekursive SQL-Befehle, über den Shared Pool abgewickelt werden, können bei praktisch allen Anwendungen die Vorteile des Shared Pools genutzt werden.
Der Optimizer
611
Der Effekt eines gut gefüllten Shared Pools vereint die Vorteile von dynamischem und statischem SQL: Die Flexibilität des dynamischen SQL erreicht fast die Performance von statischem SQL. Die OPEN-Phase In der OPEN-Phase wird lediglich die Datenstruktur des Cursors bereitgestellt und initialisiert. In einigen Programmierumgebungen wird die nachfolgende PARSEPhase automatisch beim OPEN ausgeführt. Die PARSE-Phase Die PARSE-Phase dient zur Vorbereitung der Ausführung eines SQL-Befehls. In der PARSE-Phase wird der zu bearbeitende SQL-Befehl als Zeichenkette an den Oracle-Server geschickt und dort zunächst einmal analysiert. Wird der Befehl im Shared Pool gefunden und kann er verwendet werden, wird die PARSE-Phase sofort erfolgreich beendet (soft parse). Ansonsten erfolgt eine Syntaxprüfung (Ist der Befehl korrekt formuliert?), die Auswertung der betroffenen Datenbankobjekte (Tabellen, Views, Sequenzen usw.) inklusive einer Zugriffsprüfung (Darf der Benutzer auf die Objekte zugreifen?) sowie der Bestimmung eines Ausführungsplans durch den Optimizer (Welches Objekt wird zuerst gelesen, welche Indizes werden benutzt?). Der Ausführungsplan und der SQL-Befehl werden im Shared Pool abgelegt. Nach diesem hard parse ist der Befehl fertig zur Ausführung. Binden der Eingabevariablen Bevor der SQL-Befehl endgültig ausgeführt werden kann, müssen eventuell vorhandene Eingabevariablen an Werte gebunden werden, d.h., die Werte werden als Parameter an den Oracle-Server übertragen. Ein SQL-Befehl mit einer Bindevariablen kann z.B. wie folgt aussehen: SELECT name FROM kunde WHERE kdnr = :b1;
Vor der Ausführung des Befehls muss die Variable B1 mit einem Wert gefüllt werden. Die EXECUTE-Phase Die EXECUTE-Phase kann nur nach einer erfolgreichen PARSE-Phase durchgeführt werden. In allen SQL-Befehlen außer dem SELECT-Befehl verbirgt sich hier die komplette Befehlsausführung. Zunächst wird auf jeden Fall der Zeitpunkt der Lesekonsistenz gesetzt. Hierzu wird ein interner Zeitstempel, die System Change Number (SCN), im Cursor vermerkt, so dass die Möglichkeit besteht, die SCN mit derjenigen von eventuellen Änderungen an Datensätzen zu vergleichen. Sobald im späteren Verlauf der EXECUTE-Phase oder in der FETCH-Phase Datensätze gelesen werden, die nach der vermerkten SCN verändert worden sind, werden automatisch die Daten so rekonstruiert, wie sie zum Zeitpunkt der vermerkten SCN waren. Damit wird sichergestellt, dass ein SQLBefehl immer lesekonsistent arbeitet, d.h., aus Sicht des Befehls haben sich die Daten seit Befehlsstart nicht verändert. Dies ist notwendig, um nachvollziehbare, richtige Ergebnisse zu erhalten.
612
Tuning
Beim SELECT-Befehl hängt der Umfang der Arbeit, die zusätzlich in der EXECUTEPhase zu tun ist, von der Art des Befehls ab. Sind etwa Sortierungen oder Gruppierungen vorzunehmen, so erfolgen diese Operationen in der EXECUTE-Phase. Die aufbereitete Ergebnismenge wird dann in einem Temporärbereich so zur Verfügung gestellt, dass in der nächsten Phase sofort die ersten Datensätze übertragen werden können. Alle anderen Befehle werden nach dem Setzen des Lesekonsistenzzeitpunkts vollständig abgearbeitet. Die FETCH-Phase Diese Phase wird ausschließlich für SELECT-Befehle durchgeführt, da alle anderen Befehle mit der EXECUTE-Phase abgeschlossen sind. Bei SELECT-Befehlen werden in der FETCH-Phase die Ergebnisdatensätze an die Anwendung übertragen. Dabei wird entweder aus den Daten- und Indexblöcken oder aus dem in der EXECUTE-Phase vorbereiteten Temporärbereich gelesen. Eine Spezialität der Client-Server-Funktionalität des Oracle-Server ist der Array Fetch, bei dem ein Array von Ergebnisdatensätzen anstatt eines einzigen Datensatzes übertragen wird. Hierzu ist anzumerken, dass der ANSI-Standard die Übertragung eines Datensatzes pro FETCH vorsieht. In Netzwerkumgebungen ist jedoch die Optimierung des Übertragungsverhaltens von entscheidender Bedeutung – nicht nur in Bezug auf die Performance einer einzelnen Anwendung, sondern auch im Sinne aller Netzwerkbenutzer auf die gesamte Netzwerkauslastung. Somit ist die Verwendung des Array-Fetch-Mechanismus uneingeschränkt zu empfehlen. Die CLOSE-Phase Wenn der Cursor nicht mehr gebraucht wird, kann er durch ein CLOSE beendet und entfernt werden. Das Schließen eines Cursors sollte allerdings nur dann durchgeführt werden, wenn der Cursor mit Sicherheit nicht mehr benutzt wird. Ansonsten kann z.B. mit dem Binden anderer Werte an die Variablen neu eingestiegen werden, wenn der SQL-Befehl mit anderen Variablen nochmals ausgeführt werden soll. Damit kann die recht aufwändige PARSE-Phase eingespart werden.
11.3.2
Erstellung und Pflege von Statistiken
Es gibt zur Zeit zwei voneinander unabhängige Varianten, um Statistikinformationen zu erzeugen. Dabei handelt es sich um den ANALYZE-Befehl sowie um das Package DBMS_STATS. Die Funktionalität beider Tools überlappt sich zum Teil, andererseits gibt es auch Funktionen, die nur jeweils eines der beiden Tools beherrscht. Zur konkreten Anwendbarkeit ist Folgendes zu sagen: Alle Statistikinformationen, die vom Query Optimizer benutzt werden, sollten ausschließlich mit dem Package DBMS_STATS erzeugt und verwaltet werden, da es hierfür erheblich erweiterte Möglichkeiten im Vergleich zum ANALYZE-Kommando bietet.
Der Optimizer
613
Lediglich die weiter unten beschriebenen Spezialfunktionen sollten mit dem ANALYZE-Kommando durchgeführt werden. Die Ergebnisse dieser Analysen werden vom Optimizer ohnehin nicht verwendet, sondern geben beispielsweise Anhaltspunkte für bestimmte Reorganisationen von Tabellen oder Indizes: Die Statistikinformationen werden im Data Dictionary abgelegt. Sie sind über die folgenden Views abzurufen (hier dba_, aber auch all_ und user_):
dba_tables, dba_tab_partitions, dba_tab_subpartitions dba_indexes, dba_ind_partitions, dba_ind_subpartitions dba_tab_columns dba_ind_columns dba_tab_histograms, dba_subpart_histograms dba_clusters
Die Güte der Zugriffspfade wird durch den Detaillierungsgrad und die Aktualität der Statistiken bestimmt, aber auch durch die implementierten Algorithmen des Optimizers, die von Version zu Version verbessert werden. Statistikerstellung über DBMS_STATS Das Package DBMS_STATS bietet reichhaltige Möglichkeiten, Statistiken zu erzeugen und zu verwalten. Es ist sowohl aus administrativen als auch aus PerformanceGesichtspunkten dem ANALYZE-Kommando in der Erstellung relevanter Statistikinformationen überlegen. Im Folgenden soll ein Überblick über die wichtigsten Features und deren Funktionsweise gegeben werden: Erstellung der Statistiken Es ist möglich, Statistiken für einzelne Tabellen, Indizes oder Tabellenspalten (Histogramme) zu generieren bzw. zu verwalten (z.B. die Prozeduren GATHER_TABLE_STATS, GATHER_INDEX_STATS und GATHER_COLUMN_STATS). Alternativ können jedoch auch Statistiken für ein ganzes Schema oder für die gesamte Datenbank erzeugt werden (Prozeduren GATHER_SCHEMA_STATS und GATHER_DATABASE_STATS). Insbesondere das Arbeiten auf Schema-Ebene ist zu empfehlen, da so beim Anlegen neuer Tabellen keine Anpassung vorhandener Statistikskripte und/oder -jobs notwendig ist. Über entsprechende Prozeduren DELETE_*_STATS können Statistiken ersatzlos gelöscht werden. Statistikwerte schätzen Das Berechnen der genauen Statistiken kann bei großen Tabellen extrem zeitaufwändig sein und einen hohen Ressourcenverbrauch erzeugen. Daher können Statistikinformationen geschätzt werden. Dazu wird ein bestimmter Prozentsatz der Daten gelesen, und die daraus ermittelten Statistiken werden auf den gesamten Datenbestand hochgerechnet. Der Prozentsatz kann über den Parameter estimate_ percent eingestellt werden. In diesem Zusammenhang sollte auch das so genannte Block-Sampling benutzt werden (Parameter block_sample auf TRUE setzen), damit ein entsprechender Anteil aller Blöcke gelesen wird. Enthält für eine bestimmte Tabelle beispielsweise jeder Oracle-Block ca. 100 Zeilen, so würde eine Statistikschätzung
614
Tuning
mit 2% ohne Block-Sampling jede 50. Zeile lesen, also müsste wahrscheinlich jeder Block einmal geladen werden. Performance-technisch wäre gegenüber einer exakten Statistikberechnung nichts gewonnen. Bei einem Block-Sampling wird hingegen jeder 50. Block geladen, und alle Zeilen aus diesem Block werden gelesen. Parallelisierung Die Ermittlung exakter bzw. geschätzter Statistikwerte kann parallel durch mehrere Slave-Prozesse erfolgen. Hierzu kann über den Parameter degree z.B. ein konkreter Wert für den Parallelisierungsgrad übergeben werden. Weitere Varianten hierfür sind der Dokumentation zu entnehmen. Indexstatistiken und Histogramme Bei der Ermittlung von Statistiken auf Tabellen-, Schema- oder Datenbankebene kann eingestellt werden, dass neben den Tabellenstatistiken auch Statistiken für Indizes dieser Tabellen sowie Histogramme für Tabellenspalten generiert werden sollen. Dies ist stark anzuraten, da diese weitere essenzielle Informationen für den Optimizer darstellen. Indexstatistiken werden zusätzlich gesammelt, indem der Parameter cascade auf TRUE gesetzt wird. Histogramme größtmöglicher Genauigkeit werden erstellt, indem für den Parameter method_opt Folgendes übergeben wird: 'FOR ALL COLUMNS SIZE 254'. Beide Optionen sind sehr zu empfehlen. Gespeicherte Statistiken Es ist wünschenswert, dass SQL-Befehle auf ihre Performance hin getestet werden, bevor sie in den Produktionsbetrieb gehen. Insbesondere dann, wenn der kostenbasierte Optimizer genutzt wird, stellt sich diese Untersuchung auf dem Entwicklungs- oder Testrechner als sehr problematisch dar, da diese Rechner immer kleiner ausgelegt sind als das Produktionssystem und keinen kompletten Abzug der Produktionsdaten bieten. Ein solcher Aufwand ist meist aus Kostengründen nicht möglich und auch unter Datenschutzgesichtspunkten problematisch. Hier bieten die gespeicherten Statistiken einen Lösungsweg. Statistiken können aus dem Data Dictionary in eine so genannte Benutzer-Statistiktabelle exportiert werden. Dabei handelt es sich um eine normale Tabelle im Schema eines Benutzers, die zuvor über die Prozedur CREATE_STAT_TABLE erstellt werden muss. Anschließend kann über eine der Prozeduren EXPORT_*_STATS ein Statistikexport des Produktionsschemas durchgeführt werden. Als Ziel wird die soeben erstellte Benutzer-Statistiktabelle angegeben. Diese Statistiktabelle kann auf ein Testsystem übertragen werden, wo die Statistiken mittels einer der Prozeduren IMPORT_*_STATS in das DataDictionary übertragen werden. Über diesen Weg kann ohne physikalischen Platzbedarf eine große Datenbank für den Optimizer simuliert werden. Das Arbeiten mit gespeicherten Statistiken soll für Tabellenstatistiken an einem einfachen Beispiel erläutert werden. Das Schema bzw. der Datenbankbenutzer, mit dem in diesem Beispiel gearbeitet wird, sei hladmin.
Der Optimizer
615
Unter diesem Schema muss als Erstes auf der Produktionsdatenbank eine Statistiktabelle aufgebaut werden. SQL> execute dbms_stats.create_stat_table('HLADMIN','STAT_TAB');
Nun können die Statistikinformationen für eine Tabelle, z.B. kunden, in die Statistiktabelle exportiert werden. SQL> execute dbms_stats.export_table_stats ('HLADMIN','KUNDEN',NULL,'STAT_TAB','1',TRUE,'HLADMIN');
Parameter: HLADMIN
Eigentümer der Tabelle, deren Statistiken exportiert werden.
KUNDEN
Tabellenname
NULL
Partition; NULL, wenn die Tabelle nicht partitioniert ist
STAT_TAB
Name der Statistiktabelle
'1'
Optionaler Bezeichner für diesen Export
TRUE
CASCADE=TRUE, d.h., Statistiken für Indizes und Spalten werden mit-
exportiert HLADMIN
Eigentümer der Statistiktabelle, braucht nur angegeben zu werden, wenn sie vom aktuellen Schema abweicht
Die so gefüllte Statistiktabelle stat_tab kann nun über einen Datenbank-Link oder mit den Werkzeugen Data-Pump oder exp/imp auf das Testsystem übertragen werden. Hier können optional noch Statistikinformationen verändert werden, um andere Datenmengen oder Schlüsselverteilungen zu simulieren (siehe den folgenden Abschnitt 'Manipulierte Statistiken'). Nun können die Statistiken aus der Statistiktabelle in das Data Dictionary der Testdatenbank importiert werden. SQL> execute dbms_stats.import_table_stats ('HLADMIN','KUNDEN',NULL,'STAT_TAB','1',TRUE,'HLADMIN');
Manipulierte Statistiken Über die Prozeduren SET_*_STATS können Statistikinformationen auch explizit verändert werden, um andere Datenmengen oder Schlüsselverteilungen zu simulieren. Die Manipulation kann direkt am Data Dictionary ansetzen oder zunächst nur an einer Benutzer-Statistiktabelle, die erst anschließend importiert wird. SQL> execute dbms_stats.set_table_stats ('HLADMIN','KUNDEN',NULL,'STAT_TAB', '1',10000,1000,NULL,NULL,'HLADMIN');
Hier wird für die Benutzer-Statistiktabelle HLADMIN.STAT_TAB eingestellt, dass die Tabelle KUNDEN 10.000 Sätze hat, die auf 1.000 Blöcke verteilt sind. Die restlichen Statistikwerte werden nicht modifiziert.
616
Tuning
SQL> execute dbms_stats.set_table_stats ('HLADMIN','KUNDEN',NULL,NULL, '1',10000,1000,NULL,NULL,NULL);
Hier wird dieselbe Statistikinformation direkt ins Data Dictionary geschrieben. Die Parameter für den Namen und Eigentümer der Statistiktabelle wurden dazu auf NULL gesetzt. Automatische Statistiken Oracle 10g protokolliert automatisch DML-Aktivitäten für Tabellen (Voraussetzung dafür ist, dass der Serverparameter statistics_level auf TYPICAL oder ALL gesetzt ist. In Oracle9i musste diese Protokollierung für jede Tabelle aktiviert werden, in Oracle 10g gibt es lediglich einen versteckten Instanzparameter _dml_monitoring_enabled, der per Default auf TRUE steht). Dabei werden für jede Tabelle die Anzahl eingefügter, geänderter und gelöschter Zeilen nachgehalten. Diese Informationen können aus der View dba_tab_modifications abgelesen werden. Bei der Erstellung von Statistiken auf Schema- oder Datenbank-Ebene kann durch Setzen des Parameters options auf den Wert GATHER AUTO erreicht werden, dass nur für solche Tabellen neue Statistiken generiert werden, für die: die Gesamtzahl der Einfügungen, Änderungen und Löschungen seit der letzten Analyse 10% der Zeilenzahl überschreitet, seit der letzten Analyse ein TRUNCATE durchgeführt wurde oder noch keine Statistiken existieren. Dadurch kann insbesondere bei Datenbanken mit vielen Tabellen der Aufwand für die Statistikerstellung deutlich reduziert werden, da nur einige Tabellen gravierende Änderungen der Datenmengen aufweisen, viele hingegen relativ statisch sind. Auf diese Weise lässt sich das für die Statistikgenerierung benötigte Zeitfenster ohne negative Auswirkungen auf die Aktualität der Statistiken deutlich verringern. SQL> BEGIN dbms_stats.gather_schema_stats( ownname => 'HLADMIN' ,options => 'GATHER AUTO' ,estimate_percent => 5 ,block_sample => TRUE ); END;
Systemstatistiken Neben den beschriebenen Objektstatistiken kann der Optimizer auch Informationen über die Performance des CPU- und I/O-Systems berücksichtigen. Dazu gehören u.a. die unten aufgeführten Statistiken:
Der Optimizer
617
Statistik
Parametername (PNAME) in SYS.AUX_STATS$
Benötigt Lastprofil
Durchschnittliche Latenzzeit für Positionierung des Schreib-/Lesekopfes (in Millisekunden)
IOSEEKTIM
nein
CPU-Geschwindigkeit (in MHz)
CPUSPEED
nein
Durchschnittliche Wartezeit für das Lesen eines einzelnen Blocks (in Millisekunden)
SREADTIM
ja
Durchschnittliche Wartezeit für das Lesen einer Blocksequenz »Multi-Block-Read« (in Millisekunden)
MREADTIM
ja
Durchschnittliche Anzahl gelesener Blöcke bei Multi-Block-Reads (siehe auch Abschnitt Erstellung und Pflege von Statistiken)
MBRC
ja
Einige dieser Werte können nur bezüglich eines bestimmten Lastprofils sinnvoll ermittelt und verwendet werden. Da sich der Workload eines Systems aber permanent ändert, ist es sinnvoll, ein Intervall für die Messung anzugeben und die Messung zu unterschiedlichen Zeiten (Tagesbetrieb, Nachtbetrieb, eventuelle Spitzenzeiten) zu wiederholen. Um Systemstatistiken z.B. für einen bestimmten Batch-Job zu erstellen, wird vor dem Starten des Batch-Jobs die Statistiksammlung aktiviert: SQL> execute dbms_stats.gather_system_stats('START');
Nach Beendigung des Jobs wird die Statistiksammlung beendet. SQL> execute dbms_stats.gather_system_stats('STOP');
Ist der Zeitraum a priori bekannt, z.B. das Tagesgeschäft einer Anwendung, kann die Beendigung auch automatisiert werden. Dazu würde um 08:00 Uhr folgendes Kommando abgesetzt: SQL> execute dbms_stats.gather_system_stats('INTERVAL',9*60);
Der zweite Parameter gibt die Dauer der Statistiksammlung in Minuten an. Im Hintergrund wird ein Datenbank-Job erzeugt, der nach der angegebenen Zahl Minuten die Statistiksammlung beendet. Eine vorzeitige explizite Beendigung via 'STOP' ist jedoch ebenfalls problemlos möglich. Sind die Statistiken einmal gesammelt, sollten sie in eine Benutzer-Statistiktabelle exportiert werden (Prozedur EXPORT_SYSTEM_STATS). Wichtig ist hierbei, einen sprechenden Bezeichner für den Parameter statid zu verwenden (z.B. 'Tagesgeschäft'), um später die richtigen Statistiken für das jeweilige Lastprofil wiederzufinden. Anschließend wird ein Datenbank-Job definiert, der wochentags um 08:00 Uhr genau diese Statistiken unter Angabe der vergebenen statid wieder importiert (Prozedur IMPORT_SYSTEM_STATS).
618
Tuning
Analog wird für die übrigen Lastprofile verfahren. Dadurch wird automatisch zu bestimmten Zeiten gegenüber der Datenbank eine Laständerung mitgeteilt. Die aktuellen Statistiken können aus der Tabelle SYS.AUX_STATS$ abgefragt werden: SQL> SELECT pval1 FROM sys.aux_stats$
Im Gegensatz zu Objektstatistiken werden bei einem Wechsel der Systemstatistiken (z.B. durch Import) vorhandene Ausführungspläne betroffener SQL-Befehle nicht ungültig. Dies bedeutet, dass der beschriebene Lastwechsel auf bestehende Ausführungspläne zunächst keine Auswirkung hat, da keine Neubewertung der Kosten durch den Optimizer stattfindet. Dies erscheint auf den ersten Blick widersinnig (wozu werden dann überhaupt Systemstatistiken benutzt, wenn sie keinen Einfluss auf die Ausführungspläne haben?), wird jedoch in den meisten Situationen dadurch gelöst, dass ja nach einem Lastwechsel auch ganz andere SQL-Kommandos ausgeführt werden als zuvor. Für diese neuen Kommandos wird somit ohnehin ein erneutes Parsing inklusive Kostenabschätzung durchgeführt. Im Zweifelsfall kann für ein gegebenes SQL-Kommando in V$SQL unter der Spalte LAST_LOAD_TIME nachgeschaut werden, wann das letzte Parsing stattfand. Dieser Zeitpunkt sollte zeitlich nach dem Lastwechsel liegen. Ist dies für die meisten SQLKommandos nicht der Fall, bleibt als Ausweg nur das explizite Löschen aller Ausführungspläne via SQL> ALTER SYSTEM FLUSH SHARED_POOL;
Achtung: Dieser Befehl sollte erst dann ausgeführt werden, wenn auch sichergestellt ist, dass der Lastwechsel auch tatsächlich stattgefunden hat und somit die aktuellen SQL-Kommandos nicht mehr benötigt werden, da sonst kurzfristig ein erheblicher Performance-Einbruch für diese Kommandos zu erwarten ist. Mittels DELETE_SYSTEM_STATS können die vorhandene Systemstatistiken ersatzlos deaktiviert werden. Statistikhistorisierung Jede mittels DBMS_STATS-Prozeduren vollzogene Änderung der Statistiken im DataDictionary – nicht in Benutzer-Statistiktabellen – wird automatisch historisiert. Eine maximale Aufbewahrungszeit kann über die Prozedur ALTER_STATS_HISTORY_RETENTION definiert werden. Ältere Statistiken werden dann automatisch gelöscht. Sollten aus den neuen Statistiken Ausführungspläne mit schlechterer Performance resultieren, können über die Prozeduren RESTORE_*_STATS historische Statistiken (unter Angabe des gewünschten Zeitpunkts) reaktiviert werden. Ggf. kann zuvor mittels GET_STATS_ HISTORY_AVAILABILITY überprüft werden, ob für den betreffenden Zeitpunkt historische Statistiken gespeichert sind.
Der Optimizer
619
SQL> SELECT dbms_stats.get_stats_history_availability FROM dual; GET_STATS_HISTORY_AVAILABILITY ---------------------------------------------------------------01.04.04 18:19:36,635000000 +01:00 SQL> BEGIN dbms_stats.restore_schema_stats( ownname => 'SCHULUNG' ,as_of_timestamp => SYSTIMESTAMP - INTERVAL '2 00:00:00' DAY TO SECOND ); END;
Gesperrte Statistiken Sollen für eine oder mehrere Tabellen bestimmte Statistikinformationen verbindlich festgeschrieben werden, können diese eingetragen und anschließend mittels der Prozedur LOCK_TABLE_STATS gewissermaßen »schreibgeschützt« werden. Dabei werden auch Statistiken abhängiger Objekte (Indexstatistiken und Histogramme) schreibgeschützt. Bei extrem dynamischen Tabellen kann hierüber das so genannte »Dynamic Sampling« erzwungen werden, indem evtl. vorhandene Statistiken gelöscht werden und anschließend der Schreibschutz aktiviert wird. Werden anschließend auf Schema- oder Datenbankebene Statistiken erstellt, werden die so geschützten Objekte einfach übersprungen. Mit der Prozedur LOCK_SCHEMA_STATS kann analog ein ganzes Schema schreibgeschützt werden. Über die zugehörigen UNLOCK_*_STATS-Prozeduren wird der Schreibschutz aufgehoben. Die meisten Prozeduren verfügen außerdem über einen Parameter force, der – auf TRUE gesetzt – sich über den Schreibschutz hinwegsetzt.
Abbildung 11.4: Verwaltung von Optimizer-Statistiken via DBMS_STATS
620
Tuning
Speichern von Default-Optionen Für einige Parameter (u.a. cascade, degree, estimate_percent, method_opt) können Default-Werte gesetzt werden. Dies kann beispielsweise einmalig nach dem Setup der Datenbank geschehen, um auf diese Weise »zentrale Richtlinien« für die Statistikerzeugung abzulegen und um diese Werte nicht bei jeder Benutzung wiederholen zu müssen. Das Setzen bzw. Abfragen der Default-Optionen geschieht über die Prozedur SET_PARAM bzw. die Funktion GET_PARAM. SQL> SET SERVEROUTPUT ON SIZE 10000 SQL> execute dbms_output.put_line(dbms_stats.get_param('cascade')); DBMS_STATS.AUTO_CASCADE SQL> execute dbms_stats.set_param('cascade','TRUE');
Spezialfunktionen des ANALYZE-Kommandos Erstellen einer Liste mit verketteten Sätzen SQL> ANALYZE TABLE kunden LIST CHAINED_ROWS INTO CHAINED_ROWS;
Die Tabelle chained_rows kann über ein Skript im Verzeichnis $ORACLE_HOME/rdbms/ admin mit dem Namen utlchain.sql erstellt werden. In der Tabelle chained_rows werden dann die ROWIDs des ursprünglichen Satzes aufgelistet. Diese können anschließend für eine Reparatur zwecks Beseitigung der verketteten Sätze benutzt werden. Validieren von Tabellen, Indizes oder Materialized Views SQL> ANALYZE TABLE kunden VALIDATE STRUCTURE [INTO INVALID_ROWS] CASCADE;
Die Tabelle invalid_rows kann über ein Skript im Verzeichnis $ORACLE_HOME/ rdbms/admin mit dem Namen utlvalid.sql erstellt werden. Bei der Validierung eines Index werden außerdem einige Indexstatistiken geschrieben, die über die Data-Dictionary-Views INDEX_STATS und INDEX_HISTOGRAM verfügbar sind. Diese können Anhaltspunkte für einen Neuaufbau des Index liefern. Validieren von Referenzen in Tabellen SQL> ANALYZE TABLE kunden VALIDATE REF UPDATE;
Mit diesem Befehl können Referenzen in Tabellen validiert werden. Die in den Referenzen vermerkten Teile der ROWID werden mit der tatsächlichen ROWID verglichen und gegebenenfalls korrigiert. SQL> ANALYZE TABLE kunden VALIDATE REF UPDATE SET DANGLING TO NULL;
Sollte in den Referenzen auf nicht existierende oder ungültige Objekte verwiesen werden, so werden diese auf NULL gesetzt.
Der Optimizer
621
11.3.3 Serverparameter mit Relevanz für den Query Optimizer pga_aggregate_target Der Parameter pga_aggregate_target bestimmt die Gesamtspeichermenge des Hauptspeichers, die Serverprozessen zugewiesen wird (die so genannte PGA, Process Global Area). Die Serverprozesse nutzen diesen Speicherbereich u.a. für Sortierungen und für Hash-Algorithmen im Rahmen von Hash-Joins. Je mehr Platz hier zur Verfügung gestellt wird, desto seltener müssen Sortier- und HashZwischenergebnisse in den Temporär-Tablespace ausgelagert werden. Dies führt aber auch dazu, dass der Optimizer tendenziell zu häufig Merge Joins oder Hash Joins verwendet, die für die Ressourcen belastender als Nested Loop Joins sind. Zu beachten ist, dass es bestimmte Obergrenzen für die PGA-Größe geben kann, z.B. werden einem einzelnen Server-Prozess nicht mehr als 5% des gesamten durch pga_aggregate_target definierten Volumens zugeordnet. Prozesse, die mit der Parallel-Query-Funktionalität laufen, können bis zu 30% des Volumens beanspruchen. Die maximale Hauptspeichermenge, die einem einzelnen Serverprozess zugeordnet werden kann, lässt sich durch folgende Abfrage bestimmen: SQL> SELECT value, unit FROM v$pgastat WHERE name = 'global memory bound';
sort_area_size / hash_area_size Als Alternative zur automatischen Verwaltung der PGA-Größen mittels pga_aggregate_target gibt es noch die Möglichkeit, feste Maximalgrößen für verschiedene Arbeitsbereiche festzulegen. Der Parameter sort_area_size bestimmt die maximale Größe des Hauptspeichers, die jeder einzelne Serverprozess für Sortierungen bekommt. Aus diesem Parameter abgeleitet wird die hash_area_size festgelegt, die, wenn nichts anderes spezifiziert wurde, doppelt so groß ist wie die sort_area_size. Dieser Hauptspeicherbereich steht jedem Serverprozess für den Hash-Algorithmus des Hash Join zur Verfügung. Auch hier gilt: Je größer diese Werte sind, desto seltener müssen Zwischenergebnisse in den Temporär-Tablespace ausgelagert werden. Auch hier wird der Optimizer in diesen Fällen zu häufig Merge Joins oder Hash Joins verwenden, die für die Ressourcen belastender als Nested Loop Joins sind. db_file_multiblock_read_count Über diesen Parameter kann eingestellt werden, wie viele Oracle-Blöcke im Rahmen eines Full-Table-Scans jeweils mit einem Betriebssystem-I/O in die SGA geholt werden sollen. Die Standardeinstellung ist 8. Insbesondere bei einem Striping der Platten mit »64-KByte-Chunks« harmoniert dies bei einer Datenbankblockgröße von 8 KByte hervorragend mit der I/O-Größe. Dieser Wert sollte nur dann heraufgesetzt werden, wenn auch Systemstatistiken benutzt werden (siehe Abschnitt Erstellung und Pflege von Statistiken). Der Hintergrund hierfür ist, dass der Optimizer bei höheren Einstellungen Full-Table-Scans stärker favorisiert, da aus seiner Sicht dann eine einzelne I/O-Operation für eine große Menge von Daten ausreicht. Verschärft wird diese Problematik noch dadurch, dass genau genommen maximal acht Blöcke pro I/O-Operation gelesen werden. Befinden sich einzelne Blöcke bereits im Buffer-Cache, wird die I/O-Operation aufgeteilt,
622
Tuning
so dass der bereits im Cache befindliche Block übersprungen wird. Auch über Extent-Grenzen hinweg wird nicht mit einer I/O-Operation gelesen. Werden Tabellen nun vorwiegend unter Verwendung von Indizes gelesen, führt dies häufig zu einer Zersplitterung der I/O-Zugriffe für einen Full-Table-Scan, da viele einzelne Blöcke der Tabelle bereits im Buffer-Cache liegen. Im Rahmen der Systemstatistiken wird daher u.a. ermittelt, wie viele Blöcke im laufenden Betrieb im Durchschnitt tatsächlich gelesen werden. Dieser Wert kann wie folgt abgefragt werden: SQL> SELECT pval1 FROM sys.aux_stats$ WHERE pname = 'MBRC';
Sind Systemstatistiken vorhanden, wird der dort gespeicherte Wert anstelle des über den Parameter db_file_multiblock_read_count gesetzten Wertes für die Kostenschätzungen des Optimizers benutzt. Eine Manipulation dieses Wertes wie in Kapitel Erstellung und Pflege von Statistiken beschrieben ist ebenfalls möglich. In der Praxis tritt häufig das Problem auf, dass eine Anwendung mit Hilfe von ALTER SESSION-Kommandos Optimizer-relevante Serverparameter verändert. Es ist dann nicht so einfach, eine identische Tuning-Umgebung herzustellen, da diese Kommandos u.U. irgendwo in der Anwendung »versteckt« sind. Seit Oracle 10g gibt es für diese Situation eine Lösung: die View V$SES_OPTIMIZER_ ENV, welche die Optimizer-Einstellungen jeder Session zeigt. SQL> SELECT name, value, isdefault FROM v$ses_optimizer_env WHERE sid = <Session-SID>; NAME -----------------------------parallel_execution_enabled optimizer_features_enable cpu_count active_instance_count parallel_threads_per_cpu hash_area_size bitmap_merge_area_size sort_area_size sort_area_retained_size db_file_multiblock_read_count pga_aggregate_target parallel_query_mode parallel_dml_mode parallel_ddl_mode optimizer_mode cursor_sharing star_transformation_enabled optimizer_index_cost_adj optimizer_index_caching
VALUE ---------true 10.1.0.3 1 1 2 2000000 1048576 65536 0 16 51200 KB enabled disabled enabled choose similar false 100 0
ISD --YES YES YES YES YES NO YES YES YES NO YES YES YES YES NO NO YES YES YES
Zugriffsoptimierung query_rewrite_enabled query_rewrite_integrity workarea_size_policy optimizer_dynamic_sampling statistics_level skip_unusable_indexes
623 true trusted auto 2 typical true
YES NO YES YES YES YES
Für besonders harte Fälle kann auch eine vollständige Liste aller (auch undokumentierten) Optimizer-Einstellungen einer Session abgerufen werden: SQL> SELECT pname_qksceserow AS name ,pvalue_qksceserow AS value ,DECODE(BITAND(flags_qksceserow, 2),0,'NO','YES') AS isdefault FROM x$qksceses WHERE sid_qksceserow = <Session-SID>;
11.4
Zugriffsoptimierung
11.4.1 Ausführungspläne Der Ausführungsplan eines Befehls zeigt sowohl die Reihenfolge, in der auf die beteiligten Tabellen zugegriffen wird, als auch die Zugriffmethode, also z.B. indiziertes Lesen, Lesen von Indexbereichen oder Full-Table-Scans. Ausführungspläne (auch Explain Plans) genannt, können auf unterschiedliche Arten erstellt werden. Ermitteln von Ausführungsplänen für aktuelle Befehle über Werkzeuge wie Oracle Enterprise Manager, Quest TOAD und viele weitere grafische Tools. SQL-Tracing von Anwendungen und Erstellung der Ausführungspläne aus der entsprechenden Trace-Datei (z.B. über TKPROF).. Darstellung eines Ausführungsplans für einen konkreten Befehl aus SQL*Plus (AUTOTRACE) nach der Ausführung des Befehls. Alleinige Ermittlung eines Ausführungsplans für ein SQL-Kommando mit dem SQL*Plus-Befehl EXPLAIN PLAN und dem Package DBMS_XPLAN. Alleinige Ermittlung eines Ausführungsplans für ein SQL-Kommando im Cursor-Cache (abfragbar über V$SQL) oder für ein im AWR (Automatic Workload Repository) gespeichertes SQL-Kommando über das Package DBMS_XPLAN. Jede der genannten Arten hat ihre Vor- und Nachteile. Die grafischen Werkzeuge bieten oft die Möglichkeit, neben dem Ausführungsplan auch Informationen über die zugrunde liegenden Tabellen und deren Indizes anzuzeigen. Das Tracing von Anwendungen hat hingegen den Vorteil, dass die gesamte Anwendung bzw. der relevante Teil betrachtet werden kann. Außerdem werden dabei zusätzliche Statistikinformationen wie z.B. der CPU-Bedarf der einzelnen Phasen und die im Kontext der Phasen aufgetretenen Wartezustände ermittelt.
624
Tuning
Die Generierung eines Ausführungsplans aus SQL*Plus ist hingegen dann interessant, wenn keine grafische Oberfläche zur Verfügung steht und die SQL-Befehle mehrfach geändert und dann wieder überprüft werden sollen. Das folgende Beispiel generiert für einen SQL-Befehl den Ausführungsplan aus SQL*Plus heraus. Voraussetzung ist, dass die Rolle PLUSTRACE existiert und dem Benutzer zugewiesen wurde: SQL> connect / as sysdba SQL> @?/sqlplus/admin/plustrce SQL> grant plustrace to demo;
Als Nächstes muss für den entsprechenden Benutzer die Tabelle plan_table angelegt werden: SQL> connect demo/demo SQL> @?/rdbms/admin/utlxplan
Jetzt steht der Benutzung von Autotrace nichts mehr im Wege: SQL> set autotrace on -- Einschalten von Autotrace SQL> set autotrace traceonly -- Nur Tracing-Informationen ausgeben SQL> SELECT k.kd_ort, SUM(p.pos_menge * p.pos_einzelpreis) AS umsatz FROM kunden k, auftraege a, positionen p WHERE k.kd_nr = a.auf_kdnr AND a.auf_nr = p.pos_aufnr AND UPPER(k.kd_nachname) = 'AHRENDS' AND UPPER(k.kd_vorname) = 'GERD' GROUP BY k.kd_ort; Ausführungsplan ---------------------------------------------------------0 SELECT STATEMENT Optimizer=CHOOSE (Cost=582 Card=8 Bytes=432) 1 0 SORT (GROUP BY) (Cost=582 Card=8 Bytes=432) 2 1 TABLE ACCESS (BY INDEX ROWID) OF 'POSITIONEN' (Cost=2 Card=3 Bytes=39) 3 2 NESTED LOOPS (Cost=578 Card=287 Bytes=15498) 4 3 NESTED LOOPS (Cost=348 Card=115 Bytes=4715) 5 4 TABLE ACCESS (FULL) OF 'KUNDEN' (Cost=337 Card=11 Bytes=341) 6 4 INDEX (RANGE SCAN) OF 'AUFTRAEGE_IDX_002' (NON-UNIQUE) (Cost=1 Card=10 Bytes=100) 7 3 INDEX (RANGE SCAN) OF 'POSITIONEN_IDX_003' (NON-UNIQUE) (Cost=1 Card=3) Statistiken ---------------------------------------------------------157 recursive calls 0 db block gets 2282 consistent gets 2210 physical reads 0 redo size 451 bytes sent via SQL*Net to client
Zugriffsoptimierung 503 2 5 0 1
625
bytes received via SQL*Net from client SQL*Net roundtrips to/from client sorts (memory) sorts (disk) rows processed
Listing 11.2: Ausführungsplan mit SQL*Plus
Der Ausführungsplan muss jetzt wie folgt interpretiert werden: Die erste Spalte ist eine Nummerierung aller Befehlsteile. Die zweite Spalte gibt an, auf welche Befehlszeile dieser Befehl aufbaut. Die dritte Spalte gibt dann den Zugriffspfad bzw. den ausgeführten Befehl an. Die Ausführung beginnt mit dem Befehl, der am weitesten eingerückt wurde (in dem Beispiel Zeile 5 und 6). Das gesamte Beispiel liest sich also wie folgt: 1. Zeile 5: TABLE ACCESS (FULL) OF 'KUNDEN': Es wird ein Full-Table-Scan auf die Kundentabelle ausgeführt. 2. Zeile 6: INDEX (RANGE SCAN) OF 'AUFTRAEGE_IDX_002': Es wird auf einen Index über einen Bereich zugegriffen. 3. Zeile 4: NESTED LOOPS: Ein Nested-Loop-Join wird zwischen dem in Zeile 5 ermittelten Indexbereich und dem Full-Table-Scan durchgeführt. 4. Zeile 7: INDEX (RANGE SCAN) OF 'POSITIONEN_IDX_003': Es wird auf einen zweiten Index über einen Bereich zugegriffen. 5. Zeile 3: NESTED LOOPS: Ein Nested-Loop-Join wird zwischen dem in Zeile 7 ermittelten Indexbereich und dem Ergebnis des Nested-Loop-Joins aus Zeile 4 durchgeführt. 6. Zeile 2: TABLE ACCESS (BY INDEX ROWID) OF 'POSITIONEN': Es wird auf die Datensätze der Tabelle positionen über ihre Rowid (aus dem Index Zeile 7 ermittelt) zugegriffen. 7. Zeile 1: SORT (GROUP BY): Das ermittelte Ergebnis wird sortiert. 8. Zeile 0: SELECT STATEMENT: Das Ergebnis wird dargestellt. In dem obigen Beispiel fällt auf, dass auf die Tabelle auftraege gar nicht zugegriffen wird. Dies ist darauf zurückzuführen, dass alle für die Abfrage relevanten Daten aus dem zugehörigen Index (AUFTRAEGE_IDX_002) ermittelt werden können. Statt AUTOTRACE könnte auch ein EXPLAIN PLAN verwendet werden. In diesem Fall wird der Ausführungsplan in der Tabelle plan_table eingetragen, aber nicht ausgeführt. Daher eignet sich dieses Vorgehen vor allen Dingen bei komplexen und lang laufenden SQL-Befehlen bzw. bei Befehlen, bei denen Bindevariablen verwendet werden, die nicht bekannt sind.
626
Tuning
Das obige Beispiel mit Bindevariablen könnte so aussehen: EXPLAIN PLAN SET STATEMENT_ID = 'demo_explain' FOR SELECT k.kd_ort, SUM(p.pos_menge * p.pos_einzelpreis) AS umsatz FROM kunden k, auftraege a, positionen p WHERE k.kd_nr = a.auf_kdnr AND a.auf_nr = p.pos_aufnr AND UPPER(k.kd_nachname) = :nachname AND UPPER(k.kd_vorname) = :vorname GROUP BY k.kd_ort;
Das Anzeigen des Ausführungsplans geschieht über eine Abfrage der Tabellenfunktion DBMS_XPLAN.DISPLAY: SQL> SELECT plan_table_output FROM TABLE( dbms_xplan.display('plan_table','demo_explain','basic' )); PLAN_TABLE_OUTPUT --------------------------------------------------------------Plan hash value: 1679115540 ------------------------------------------------------------| Id | Operation | Name | ------------------------------------------------------------| 0 | SELECT STATEMENT | | | 1 | SORT GROUP BY | | | 2 | TABLE ACCESS BY INDEX ROWID | POSITIONEN | | 3 | NESTED LOOPS | | | 4 | NESTED LOOPS | | | 5 | TABLE FULL SCAN | KUNDEN | | 6 | INDEX RANGE SCAN | AUFTRAEGE_IDX_002 | | 7 | INDEX RANGE SCAN | POSITIONEN_IDX_003 | ------------------------------------------------------------14 Zeilen ausgewählt.
Der dritte Parameter ist optional und kann außer basic noch die Werte typical und all annehmen, die weitere Informationen zum Ausführungsplan ausgeben. Default und für den Normalfall zu empfehlen ist typical, hierbei werden auch Kostenschätzungen mit ausgegeben. Handelt es sich um ein SQL-Kommando, das im Cursor-Cache – also über die View V$SQL – sichtbar ist oder bereits im AWR (Automatic Workload Repository) gespeichert ist, kann es über die Prozeduren DISPLAY_CURSOR und DISPLAY_AWR in demselben
Package angezeigt werden. Die Aufrufe sind analog. Dabei wird auf ein SQL-Kommando im Cursor-Cache durch Angabe der SQL-ID sowie der Child-Number Bezug
Zugriffsoptimierung
627
genommen. Unterschiedliche Child-Nummern zu derselben SQL-ID identifizieren unterschiedliche Ausführungspläne für dasselbe Kommando. Zum Beispiel: SQL> SELECT sql_id, child_number FROM v$sql WHERE ...; SQL_ID CHILD_NUMBER ------------- -----------ffwhd4jkg425q 0 SQL> SELECT plan_table_output FROM TABLE( dbms_xplan.display_cursor('ffwhd4jkg425q','0','all' ));
Der Aufrufende benötigt SELECT-Rechte auf den Views V$SQL, V$SQL_PLAN und V$SQL_PLAN_STATISTICS_ALL, sonst wird eine entsprechende Meldung (keine Fehlermeldung !) ausgegeben. Ein im AWR gespeichertes Kommando wird ebenfalls über seine SQL-ID identifiziert. Diese taucht in jedem AWR- oder ADDM-Report auf oder kann direkt den AWR-Views entnommen werden, zum Beispiel: SQL> SELECT sql_id FROM dba_hist_sqltext
Gibt es unterschiedliche Ausführungsplänen für dasselbe Kommando, werden alle angezeigt. Die Einschränkung auf eine Variante geschieht hier nicht über die Child-Number, sondern über den Plan-Hashwert (Spalte plan_hash_value in V$SQL oder DBA_HIST_SQL_PLAN), der als zweiter Parameter übergeben werden kann. Der dritte Parameter ist die Datenbank-ID. Im Normalfall wird auf das AWR der lokalen Datenbank Bezug genommen, so dass dieser Parameter ebenfalls auf NULL gesetzt werden kann. Der Aufrufende benötigt SELECT-Rechte auf den Views dba_hist_ sql_plan, dba_hist_sqltext und V$DATABASE. Gespeicherte Statistiken Es ist wünschenswert, dass SQL-Befehle auf ihre Performance hin getestet werden, bevor sie in den Produktionsbetrieb gehen. Insbesondere dann, wenn der kostenbasierte Optimizer genutzt wird, stellt sich diese Untersuchung auf dem Entwicklungs- oder Testrechner als sehr problematisch dar, da diese Rechner immer kleiner ausgelegt sind als das Produktionssystem und keinen kompletten Abzug der Produktionsdaten bieten. Ein solcher Aufwand ist meist aus Kostengründen nicht möglich und auch unter Datenschutzgesichtspunkten problematisch. Hier bieten die gespeicherten Statistiken einen Lösungsweg. Über Prozeduren des mitgelieferten Packages DBMS_STATS können Statistiken von Tabellen, Indizes und Feldern aus dem Data Dictionary in eine Statistiktabelle exportiert werden. Diese Statistiktabelle kann auf ein Testsystem übertragen werden, aus dem dann die Statistiken der Produktionsdatenbank in das Data Dictionary der Testdatenbank importiert werden können. Über diesen Weg kann ohne physikalischen Platzbedarf eine große Datenbank für den kostenbasierten Optimizer simuliert werden.
628
Tuning
Eine weitergehende Möglichkeit der Simulation ist auch das manuelle Verändern der Statistiken. So kann der Einfluss einer Veränderung in der Statistik auf Ausführungspläne im Vorfeld bestimmt werden. Für Details wird auf den Abschnitt Erstellung und Pflege von Statistiken verwiesen, wo die notwendigen Schritte und Prozeduren dafür bereits beschrieben wurden. Auch das Aufbewahren historischer Statistiken war und ist ein gutes Mittel, um ggf. alte Statistiken zurückzuholen, wenn aus den neuen Statistiken Ausführungspläne mit schlechterer Performance resultieren. Mit Oracle 10g werden Statistiken – wie bereits berieben wurde – automatisch historisiert, ein manuell erstelltes Skript hierfür ist daher nicht mehr nötig. Plan Stability Trotz gespeicherter Statistiken kann ein Entwickler nicht garantieren, dass ein für ein Produktionssystem ausgelieferter SQL-Befehl den gleichen Ausführungsplan wie auf seinem Testsystem hat. Eine Änderung des Ausführungsplans kann naturgemäß jederzeit durch Aktualisierung der Statistiken stattfinden, aber auch durch Serverparameter, die sich von denen des Testsystems unterscheiden. Besonders geht es hier um Parameter wie pga_aggregate_target, sort_area_size, hash_area_size oder db_file_multiblock_ read_count. Die Lösung dieses Problems heißt Plan Stability. Ein Ausführungsplan für einen SQL-Befehl kann während der Ausführung aufgezeichnet werden. Solchermaßen gespeicherte Ausführungspläne werden auch als Stored Outlines bezeichnet. Sobald ein SQL-Befehl ausgeführt wird, der identisch mit dem gespeicherten ist, wird der gespeicherte Ausführungsplan verwendet. Die Erkennung von identischen Befehlen ist dabei äquivalent zu der im Shared Pool. Das bedeutet, dass die Verwendung von Literalen oder zusätzliche Leerzeichen die Verwendung verhindert. Hier ist aber auch die automatische Ersetzung von Literalen durch Bindevariablen möglich, die über den Serverparameter cursor_sharing = force | similar erreicht werden kann – wie im Folgenden noch ausgeführt werden wird. Die Zugriffspfade werden in den Data-Dictionary-Tabellen OL$, OL$HINTS und OL$NODES abgelegt, deren Eigentümer der automatisch bei der Erstellung der Datenbank angelegte Benutzer OUTLN ist. Stored Outlines können in unterschiedlichen Kategorien abgelegt werden. Es existiert eine feste Kategorie mit dem Namen DEFAULT. Weitere Kategorien werden implizit angelegt, wenn ein Outline in eine neue Kategorie verschoben oder in dieser neu erstellt wird.
Zugriffsoptimierung
629
Voraussetzungen Um mit Stored Outlines wirklich konstante Ausführungspläne zu garantieren, müssen die Serverparameter query_rewrite_enabled, star_transformation_enabled und optimizer_features_enable bei der Erstellung der Stored Outlines und bei deren Benutzung identische Werte haben. Zur Erstellung von Stored Outlines ist außerdem das Systemprivileg CREATE ANY OUTLINE notwendig. Anlegen von Stored Outlines Zum Anlegen von Stored Outlines gibt es drei Möglichkeiten: 1. Aktivierung der Aufzeichnung von Ausführungsplänen auf der Sitzungsebene: SQL> ALTER SESSION SET CREATE_STORED_OUTLINES = TRUE;
Für alle SQL-Befehle, die nach der Aktivierung ausgeführt werden, werden die Zugriffspläne gespeichert, und zwar in der Standardkategorie DEFAULT. Möchten Sie in eine selbst benannte Kategorie, z.B. rule_cat, speichern, so sieht die Aktivierung wie folgt aus: SQL> ALTER SESSION SET CREATE_STORED_OUTLINES = rule_cat;
Möchten Sie die Aufzeichnung von Ausführungsplänen beenden, so geben Sie ein: SQL> ALTER SESSION SET CREATE_STORED_OUTLINES = FALSE;
2. Benutzung des SQL-Kommandos CREATE OUTLINE Sie können auch gezielt für einen SQL-Befehl eine Stored Outline erstellen. Es ist jedoch darauf zu achten, dass bei dieser Art der Erstellung der Serverparameter cursor_sharing nicht berücksichtigt wird, so dass bei Befehlen mit Literalen – wie noch beschrieben wird – keine Übereinstimmung erkannt wird. SQL> CREATE OUTLINE zugriff_1 FOR CATEGORY rule_cat ON SELECT ...;
3. Benutzung der Prozedur DBMS_OUTLN.CREATE_OUTLINE Auch ein SQL-Befehl aus dem Cursor-Cache (View V$SQL) kann direkt zur Angabe der Parameter hash_value und child_number (aus den gleichnamigen Spalten in der View V$SQL) für die Erstellung eines Stored Outlines herangezogen werden. In der Version 10.1.0.3 ist diese Methode aber noch mit derart vielen Bugs behaftet, dass sie praktisch nicht brauchbar ist. Public Outlines und Private Outlines Neben unterschiedlichen Kategorien können Sie auch Private Outlines definieren. Dazu müssen Sie sich zuerst eigene Outline-Tabellen definieren. SQL> execute dbms_outln_edit.create_edit_tables;
Nun kann mit dem Befehl SQL> CREATE PRIVATE OUTLINE priv_outline_1 ON SELECT ...;
630
Tuning
eine neue Private Outline erzeugt werden. Sie können sich aber auch eine Stored (Public) Outline in eine Private Outline kopieren: SQL> CREATE PRIVATE OUTLINE priv_outline_1 FROM outline_1;
Private
Outlines
werden
dann
verwendet,
wenn
über
die
Prozedur
dbms_outln_edit.change_join_pos die Join-Reihenfolge vertauscht werden soll
(Änderung des LEADING-Hints). Damit Fehler, die hier entstehen können, nicht nach außen getragen werden, kann also in einer lokalen Kopie gestestet werden. Wird manuell editiert, so muss anschließend eine Synchronisierung ausgeführt werden. SQL> execute dbms_outln_edit.refresh_private_outline (priv_outline_1);
Nach einem Test kann die Private Outline wieder in die Public Outline überstellt werden. SQL> CREATE OR REPLACE OUTLINE outline_1 FROM PRIVATE priv_outline_1;
Verwendung der Stored Outlines Bisher ist beschrieben worden, wie Stored Outlines erstellt werden. Damit identische SQL-Befehle diese gespeicherten Zugriffspfade auch nutzen, muss entweder auf Sitzungs- oder auf Systemebene der entsprechende Serverparameter aktiviert werden. SQL> ALTER SESSION | SYSTEM SET USE_STORED_OUTLINES = TRUE | category;
Die Nutzung von Private Outlines ist ausschließlich auf Sitzungsebene möglich und kann daher auch nicht generell über einen Serverparameter oder von außen gesetzt werden. SQL> ALTER SESSION SET USE_PRIVATE_OUTLINES = TRUE | category;
Nach Aktivierung eines dieser Parameter wird also die Erkennung identischer Befehle ausgeführt und der entsprechende gespeicherte Ausführungsplan benutzt. Administration von Stored Outlines Die in der Datenbank abgelegten Stored Outlines können nun vom Administrator abgefragt werden, müssen aber auch überwacht und verwaltet werden. Abfragemöglichkeiten Zwei Views, dba_outlines und dba_outline_hints, liefern die Daten aus den Dictionary-Tabellen OL$, OL$HINTS und OL$NODES. In dba_outlines wird die Zuordnung von Stored Outlines mit Namen zu Kategorien und SQL-Befehlen dargestellt. dba_outline_hints zeigt zu den einzelnen Stored Outlines die Zugriffspfade.
Zugriffsoptimierung
631
Verwaltung von Kategorien Einzelne Stored Outlines können von einer Kategorie in eine andere verlegt werden. Das ist z.B. dann sinnvoll, wenn erkannt wird, dass ein gespeicherter Zugriffspfad nicht performant ist. In diesem Fall kann eine Kategorie für Problemfälle definiert werden, in die diese Stored Outlines dann ausgelagert werden. Dort können sie dann weiter untersucht werden, stören aber nicht mehr bei der Benutzung der allgemeinen Kategorie. SQL> ALTER OUTLINE zugriff_1 CHANGE_CATEGORY TO problem_cat;
Weiterhin steht ein Package zur Verfügung, das für die Administration verwendet werden sollte. Die wichtigen Prozeduren aus dem Package dbms_outln sind: drop_by_cat: Löscht alle Stored Outlines einer bestimmten Kategorie. drop_unused: Löscht alle Stored Outlines aller Kategorien, die noch nie verwendet worden sind. Bei Anwendungen, die dynamisches SQL verwenden, können bei der Erstellung der Stored Outlines SQL-Kommandos auftauchen, die später nie wieder vorkommen (»Eintagsfliegen«). Deren Outlines verbrauchen sonst unnötigen Platz. update_by_cat: Ordnet alle Stored Outlines einer Kategorie einer anderen zu. Export und Import von Stored Outlines Mit Hilfe der Stored Outlines ist es nun möglich, feste Zugriffspfade für SQLZugriffe zusammen mit einer Anwendung auszuliefern. Dazu können diese aus den Data-Dictionary-Tabellen exportiert werden. Mit Hilfe des QUERY-Parameters des Exports ist es so auch möglich, nur bestimmte Kategorien zu extrahieren. $ exp system/pwd file=ol.dmp tables=(outln.ol$, outln.ol$hints, outln.ol$nodes) query='WHERE CATEGORY=''DEFAULT'''
In diesem Beispiel wird nur die Kategorie DEFAULT exportiert. Da der QUERY-Parameter nur bei tabellenbezogenem Export möglich ist, müssen hier die drei beteiligten Tabellen explizit aufgeführt werden. Wird die Exportdatei nun in die Zieldatenbank importiert, sind die gespeicherten Ausführungspläne dort vorhanden und können aktiviert werden (für Data Pump sowie konventionellen Export/Import siehe auch Kapitel 10). Zur Laufzeit wird anhand eines Hashwertes, der so genannten Signatur, überprüft, ob für das betreffende SQL-Kommando ein Stored Outline hinterlegt ist. Da der Hash-Algorithmus mit der Oracle-Version variiert, muss im Falle eines Imports aus einer älteren Datenbankversion nach dem Import einmalig die Prozedur DBMS_OUTLN.UPDATE_SIGNATURES aufgerufen werden, damit die Stored Outlines gefunden werden.
632
Tuning
Anwendungsmöglichkeiten Eine Anwendungsmöglichkeit ist natürlich die Auslieferung von stabilen Ausführungsplänen mit einer Software. Stored Outlines sind aber auch sehr hilfreich, wenn Sie z.B. vom regelbasierten Optimizer auf den kostenbasierten Optimizer u