Auch unter den freien Datenbanken belebt Konkurrenz das Geschäft: Seit mehr als einem Jahr ist die ehemalige SAP DB als freie Max DB aus dem Hause MySQL zu haben, im August letzten Jahres stellten fast gleichzeitig IBM und Computer Associates ihre Produkte Cloudscape und Ingres unter eine Open-Source-Lizenz. Gegen diese ehemals kommerzielle Konkurrenz müssen sich die alteingesessenen Open-Source-Datenbanken behaupten.
Wie das gelingt, demonstriert PostgreSQL mit der eben erschienenen Release 8. Zwei der zahlreichen Neuerungen fallen dem erfahrenen Datenbank-Administrator sofort auf, bescheren sie PostgreSQL doch Features, die sie bisher vor allem von Highend-Produkten kannten: Tablespaces für das Positionieren von Datenbankobjekten und ein lückenloses Recovery-Konzept.
Datenbanken halten Festplatten auf Trab. Deshalb ist es ein bewährter Kniff, die häufigen Schreib- und Lese-Zugriffe konkurrierender Operationen auf möglichst viele Platten zu verteilen. Zusätzliche Disks helfen außerdem dabei, Platzmangel auszugleichen.
Divide et impera
Beides war mit PostgreSQL nicht leicht zu bewerkstelligen, denn es gab nur ein zentrales Verzeichnis für Daten. Anderswo verfügbare Speicherkapazität war nicht nutzbar. In der neuen Version kann der Administrator nun auf Table- spaces zurückgreifen. Sie fungieren als Container für Datenbankobjekte, die sich in beliebiger Anzahl an beliebigen Speicherorten verankern lassen. Der Admin kann damit sowohl die I/O-Last verteilen als auch den verfügbaren Platz besser ausnutzen.
Neben kompletten Datenbanken lassen sich bei Bedarf auch nur Schemata, Tabellen oder einzelne Indizes platzieren. Besonders Performance-fördernd wirkt die Verteilung von Tabelle und zughörigem Index auf verschiedene Festplatten. Dadurch müssen die Schreib-Lese-Köpfe weniger springen und bewegen sich stattdessen zeitsparend von Sektor zu Sektor. Wenn man Tabellen, die oft mit Joins verknüpft sind, auf verschiedene Platten legt, ist ein ähnlicher Effekt zu erzielen.
Das funktioniert besonders gut, wenn eine große Anzahl von Zeilen zurückgeliefert wird. In diesem Fall erkennt der Planer in PostgreSQL, dass ein Indexscan langsamer als das sequenzielle Lesen wäre. (»EXPLAIN« oder »EXPLAIN ANALYZE« offenbaren die Kostenrechnung des Planers). Sind die Speicherorte der logisch verbundenen Tabellen physisch getrennt, behindern sich die parallelen Leseoperationen nicht gegenseitig und können dadurch den maximalen Durchsatz liefern.
Wer Tablespaces von anderen Datenbanken (wie etwa Oracle) kennt, dem wird auffallen, dass es in PostgreSQL keinen Parameter gibt, der ihre Größe festlegt. Die Datenbank weist ihnen stattdessen lediglich einen Pfad zu. So belegen sie nur den Speicherplatz, der tatsächlich auch verwendet wird.
Einen neuen Tablespace kreiert der Administrator mit dem SQL-Befehl:
CREATE TABLESPACE Tablespacename [ OWNER Username ] LOCATION Directory
Eine neue Datenbank, ein Schema, eine Tabelle oder einen Index kann er anschließend in dem so erzeugten Container platzieren. Zum Beispiel:
CREATE TABLE test (a INT, b INT) TABLESPACE hd_master;
Wie jede Bank sichern auch Datenbanken ihre Einlagen möglichst wirkungsvoll gegen Verlust. Die meisten verwenden eine mehrstufige Strategie: Regelmäßige Backups retten den kompletten Datenbestand auf sichere Medien. Von dort kann er - etwa nach einen Systemausfall - komplett wiederhergestellt werden. So genannte Transaktionslogfiles (siehe Kasten "Transaktionslogfiles") verzeichnen zusätzlich alle Änderungen an den Datendateien. Dadurch lassen sich unvollendet abgebrochene oder fehlerhafte Operationen wieder rückgängig machen (Rollback) .
|
Das Transaktionslogfile einer Datenbank funktioniert ähnlich dem Journal eines Journaling-Dateisystems. In dem Log werden alle geplanten Änderungen an Daten (Tabellen, Indizes und so weiter) vermerkt. In kurzen Abständen werden sie dann von dort aus auf den Datenbestand übertragen. Stürzt der Rechner während eines solchen Schreibprozesses ab, lässt sich anhand des Transaktionslogfile festgestellen, welche Änderungen bereits vollzogen wurden und welche noch ausstehen. Diese Information ermöglicht es, die Transaktion entweder zu komplettieren oder zurückzunehmen. In jedem Fall bleibt die Konsistenz der Daten gewahrt.
Als weiterer Vorteil ergibt sich eine Steigerung der Geschwindigkeit, denn es ist einfacher, sequenziell Daten an das Transaktionslogfile anzuhängen als den Festplattenkopf ständig auf die richtigen Stellen in den Datendateien zu positionieren. Außerdem können diese Files auch auf einer zweiten Festplatte liegen. Vor PostgreSQL 8.0 wurden die Transaktionslogfiles nach einiger Zeit wieder überschrieben. Nun kann man sie archivieren und auf diese Weise nicht nur ein paar Transaktionen daraus komplettieren, sondern auch all jene noch einmal durchführen, die bis zu einem gewünschten Zeitpunkt stattgefunden haben (Point-in-Time-Recovery).
|
Einlagensicherung
Ohne besondere Vorkehrungen würden die Transaktionslogs unaufhörlich wachsen, wodurch irgendwann das Filesystem überliefe. Dem beugen Datenbanken in der Regel mit einem Rotationsverfahren vor: Neue Einträge überschreiben früher oder später ältere. Das begrenzt den benötigten Platz, aber auch die in den Logs dokumentierte Änderungs-Historie. Reicht sie nicht mehr bis zum letzten Backup zurück, entsteht eine Lücke im Sicherheitskonzept: Alle Daten, die zwischen der letzten Komplettsicherung und den ältesten erhaltenen Einträgen in den Logs geändert wurden, ließen sich nach einem totalen Datenverlust nicht mehr rekonstruieren.
PostgreSQL 8.0 begegnet dem durch ein Verfahren namens Point-in-Time-Recovery. Es sichert alle Logs, bevor sie überschrieben werden, und gewährleistet so, dass sich jeder Zustand der Datenbank seit dem Ende des letzten Backups wiederherstellen lässt. Auch Benutzerfehler sind damit mitversichert: Wer hat beim »DELETE« nicht schon mal das »WHERE« vergessen?
Das Recovery wird trotz des neuen Feature nicht komplizierter. Der Administrator spielt zuerst das letzte Voll-Backup des »data/«-Verzeichnisses sowie alle benutzten Tablespaces ein. Danach legt er im »data/«-Verzeichnis die Datei »recovery.conf« an, in der er angibt, wo sich die Transaktionslogfiles befinden und bis zu welchem Zeitpunkt die Wiederherstellung reichen soll. Ein Beispiel kann so aussehen:
restore_command ='cp /var/lib/pgsql/archive/%f %p'
recovery_target_time ='2004-11-24 15:15:00.0000'
Als Ziel-Zeitpunkt für das Wiedereinspielen (Rollforward) kann er sowohl eine Transaktions-ID als auch - wie in dem Beispiel - einen bestimmten Zeitpunkt festlegen. Startet PostgreSQL und findet die beschriebene Datei, wechselt es in den Recovery-Modus, stellt die Datenbank wieder her und benennt die Steuerdatei von »recovery.conf« in »recovery.done« um. Einen Auszug der Meldungen eines solchen Recovery-Vorgangs zeigt Listing 1.
01 LOG: starte Wiederherstellung aus Archiv
02 LOG: restore_command = »cp /var/lib/pgsql/archive/%f %p«
03 LOG: recovery_target_time = 2004-11-24 15:15:00+01
04 LOG: Logdatei »000000010000000000000007.00EB5DD4.backup« aus Archiv
05 wiederhergestellt
06 LOG: Logdatei »000000010000000000000007« aus Archiv wiederhergestellt
07 LOG: Checkpoint-Eintrag ist bei 0/7EB5DD4
08 LOG: Redo-Eintrag ist bei 0/7EB5DD4; Undo-Eintrag ist bei 0/0; Shutdown FALSE
09 LOG: nächste Transaktions-ID: 1827; nächste OID: 131918
10 LOG: automatische Wiederherstellung läuft
11 LOG: Redo beginnt bei 0/7EB5E10
12 LOG: Logdatei »000000010000000000000008« aus Archiv wiederhergestellt
13 LOG: Logdatei »000000010000000000000009« aus Archiv wiederhergestellt
14 LOG: Wiederherstellung beendet vor Commit der Transaktion 1921, Zeit 2004-11-24 15:15:08 CET
15 LOG: Redo fertig bei 0/9D980F4
16 LOG: gewählte neue Timeline-ID: 2
17 LOG: Wiederherstellung aus Archiv abgeschlossen
18 LOG: Datenbanksystem ist bereit
|
Eine interessante neue Möglichkeit in PostgreSQL 8 betrifft ein Problem, das es bei einer Datenbank im Produktivbetrieb eigentlich gar nicht geben dürfte - wenn doch, ist es meist ein Indiz für Mängel beim Datenbank-Entwurf oder -Test: die nachträgliche Änderung von Spaltentypen in einer Tabelle.