Diese Seite wurde maschinell übersetzt. Lesen Sie das englische Original. English

IBSurgeon-Bibliothek

Datenbank-Physische Struktur (InterBase und Firebird)

Alexey Kovyazin, Sergey Vostrikov, letzte Aktualisierung 05-Juni-2004

Physische Struktur der Datenbank

Warum müssen wir die physische Struktur von InterBase-Datenbanken untersuchen?

Wenn wir über die physische Struktur von InterBase-Datenbanken sprechen, meinen wir normalerweise, dass sie Daten aus der Sicht der Datenorganisation auf niedriger Ebene darstellt - bis hin zur Ebene der Bytes. Viele Programmierer, die Anwendungen mit einer Hochsprache entwickeln, vernachlässigen das Studium der Details auf niedriger Ebene. Die Kenntnis der wichtigsten Prinzipien der Datenorganisation innerhalb der Datenbank ist jedoch der Schlüssel zum effektiven Design von Datenbankanwendungen. Deshalb werden wir einen Exkurs in das Innere der InterBase-Datenbankorganisation machen und herausfinden, wie sie aufgebaut ist.

Was ist also der Zweck eines Datenbankmanagementsystems (DBMS)? Offensichtlich zur Speicherung und Kontrolle der Daten. Das klingt banal, aber es lohnt sich, darüber nachzudenken. Ein Benutzer gibt Daten in das DBMS ein, das diese Daten auf irgendeine Weise in für es verständliche interne Formate übersetzt. Man kann sich „0 und 1“ vorstellen, wenn die Worte „internes Datenformat“ Schwierigkeiten bei Assoziationen verursachen. Das DBMS speichert diese Daten und muss sie bei der ersten Anfrage aus seinem Format extrahieren, in eine geeignete Ansicht konvertieren und dem Benutzer zur Verfügung stellen.

Das Thema dieses Kapitels ist, wie das DBMS seine Daten speichert, in welcher Ansicht und wie sie auf der niedrigsten Ebene organisiert sind. Wir werden versuchen, Ihnen zu erklären, wie wir aus Bits und Bytes, die auf der Festplatte liegen, wertvolle Daten erhalten.

InterBase-Datenbankdateien

Wenn wir über eine Datenbank sprechen, meinen wir normalerweise das DBMS selbst und die Benutzerinformationen, und sogar die Programme der Clients, die mit den Daten arbeiten. In diesem Kapitel betrachten wir eine Datenbank als Datenbankdateien.

Eine InterBase-Datenbank stellt eine oder mehrere Dateien dar, die Informationen über alles enthalten, was mit dieser Datenbank zusammenhängt. Eine Ausnahme bilden Informationen über Benutzer, da Benutzer auf der Ebene des gesamten Servers definiert und separat in der Sicherheitsdatenbank admin.ib gespeichert werden (in Versionen vor 7 war es ISC4.GDB).

Hinweis: Schauen Sie sich das Kapitel „Server- und Datenbanksicherheit“ an, um mehr über die Sicherheitsprinzipien von InterBase zu erfahren.

Alle Informationen über die Datenbank werden also in diesen Dateien gespeichert: die Daten selbst, Indizes, Trigger, gespeicherte Prozeduren usw.

Eine InterBase-Datenbank für ein durchschnittliches Projekt stellt eine Datei dar, da moderne InterBase-Versionen 64bitIO verwenden können, um mit der Datendatei zu arbeiten, und dies gibt Ihnen die Möglichkeit, eine Datendatei von bis zu 64 GB zu haben. Frühere InterBase-Versionen hatten die Einschränkung von 4 Gigabyte pro Datenbankdatei (bis zu 64 Tbytes für die gesamte Datenbank). Wie wir annehmen können, sind 64 Gigabyte völlig ausreichend, um Informationen fast jeder Datenbankanwendung zu speichern. Aber wenn es notwendig ist, können wir eine Datenbank in mehrere Dateien aufteilen. Übrigens gibt es InterBase-Datenbanken mit einer Größe von mehreren hundert Gigabyte.

IBSurgeon - ein Führer durch die InterBase-Datenbank

Wir müssen die Struktur der InterBase-Datenbankdateien im Detail kennen. Und deshalb ist es wünschenswert, ein geeignetes Werkzeug zu haben, das direkt mit Datenbankdateien arbeiten kann, nicht über den InterBase-Serverkern. Der einfachste Weg ist, einen gewöhnlichen Hexadezimal-Viewer zu verwenden und zu versuchen, die Struktur der Datenbankdateien anhand ihrer HEX-Darstellung zu verstehen. Das wäre eine ziemlich mühsame Arbeit.

Aber glücklicherweise gibt es ein Werkzeug für die direkte Arbeit mit InterBase-Datenbanken. Es ist der IBSurgeon Editor - ein Werkzeug für die direkte Arbeit auf niedriger Ebene mit InterBase-Datenbanken, das zum Studium der internen Struktur von InterBase-Datenbanken und zur Diagnose beschädigter Datenbanken verwendet werden kann, um sie wiederherzustellen. Weitere Details finden Sie im Anhang „Werkzeuge für Administratoren und InterBase-Entwickler“.

IBSurgeon verwendet seinen eigenen alternativen Mechanismus für den Datenbankzugriff, der es ermöglicht, Datenbanken in jedem Zustand zu öffnen und zu überprüfen, einschließlich stark beschädigter Datenbanken, die vom InterBase/FireBird/Yaffil-Serverkern nicht geöffnet werden können.

Wir werden IBSurgeon verwenden, um die interne Struktur der Datenbank zu veranschaulichen.

Dateien *.IB/*.FDB von innen

IB ist eine Erweiterung, die für InterBase-Datenbankdateien empfohlen wird, und FDB für Firebird (früher war es GDB). Das erste, was wir über die Struktur der IB-Datei sagen müssen, ist, dass sie eine Menge von Seiten mit streng definierter Größe darstellt. Die Größe der Datenbankdatei ist durch die Seitengröße teilbar, die für alle Dateien dieser Datenbank unverändert ist. Verschiedene InterBase-Versionen unterstützen unterschiedliche Seitengrößen, wie in Tabelle 1 gezeigt. Die Seitengröße wird beim Erstellen einer Datenbank festgelegt und kann während ihres Lebenszyklus nicht geändert werden. Mit anderen Worten, wir können eine Seitengröße nur beim Wiederherstellen einer Datenbank aus einem Backup ändern.

Tabelle 1. Seitengrößen, die von verschiedenen InterBase-Versionen unterstützt werden

InterBase-Version Seitengröße, Bytes
1024 2048 4096 8192 16384
InterBase 4.0 * * * *
InterBase 5.x * * * *
InterBase 6.x-7.x * * * *

Das Lesen und Schreiben von Daten in einer Datenbank wird Seite für Seite ausgeführt, viele wichtige Server- und Datenbankeigenschaften wie die Größe des Datenbankcaches hängen von der Seitengröße ab und werden in „Seiten“ gezählt.

Lassen Sie uns eine beliebige InterBase-Datenbank mit IBSurgeon öffnen. Es genügt, doppelt auf die Datenbankdatei zu klicken. Bild 1 zeigt eine Liste von Seiten, die erscheint, nachdem IBSurgeon die Datenbank geöffnet hat:

![](/images/IB DB structure/InterBase database structure_html_m4f802417.png)

Bild 1. Eine Liste von Datenbankseiten

Seiten können verschiedene Typen haben, von denen jeder einem bestimmten Zweck dient. Die Abhängigkeiten zwischen verschiedenen Typen sind in Bild 2 bedingt dargestellt. Bild 2 zeigt schematisch die Verteilung der Seiten in der Datenbankdatei - von links nach rechts, von oben nach unten, wenn man vom Anfang der Datei zählt. Seiten desselben Typs gehen nicht streng nacheinander - sie können leicht gemischt sein und in einer Datei in der Reihenfolge zugewiesen werden, in der sie vom Server beim Erweitern oder Erstellen von Datenbanken erzeugt wurden.

![](/images/IB DB structure/InterBase database structure_html_4005a6b0.png)

Bild 2. Abhängigkeiten zwischen verschiedenen Seitentypen in einer InterBase-Datenbank

Sie müssen bemerkt haben, dass einige Seitentypen keine Verweise auf andere Seitentypen haben. Es gibt hier jedoch keinen Widerspruch, die Sache ist, dass diese Seitentypen auf einer anderen strukturellen Ebene verknüpft und verwendet werden. Sie können mit der Tabelle RDB$PAGES und anderen Systemtabellen verknüpft sein (diese Tabelle und andere Systemobjekte werden wir unten betrachten - im Kapitel „Logische Struktur der Datenbank“). In Bild 2 sehen wir nur explizite Verweise zwischen den Seiten auf der physischen Ebene.

Betrachten wir im Detail, welche Seitentypen es in einer InterBase-Datenbank gibt. In der Datei ods.h aus dem Satz der InterBase-Primärcodes gibt es Informationen über alle möglichen Seitentypen. Wir werden uns häufig auf diese Datei beziehen, um Daten nicht nur über ODS, sondern auch über viele andere grundlegende Dinge des InterBase-Kerns im Originalquellcode zu erhalten. Insgesamt sind 11 Seitentypen deklariert, aber nur 9 davon sind eine Erklärung wert (das können wir deutlich aus Tabelle 2 sehen). Seitentypen mit den Bezeichnern 0 und 1 sind undefiniert oder werden nicht verwendet.

Tabelle 3. Seitentypen in FB

Die Definition in ods.h Seitentyp-Bezeichner Seitenbeschreibungen
pag_undefined 0 Undefiniert - Wenn eine Seite diesen Seitentyp hat, ist sie wahrscheinlich frei
pag_header 1 Datenbank-Header-Seite
pag_pages 2 Seiteninventarseite (oder Space-Inventarseite - SIP)
pag_transactions 3 Transaktionsinventarseite (TIP)
pag_pointer 4 Zeigerseite
pag_data 5 Datenseite
pag_root 6 Index-Wurzelseite
pag_index 7 Index- (B-Baum-) Seite
pag_blob 8 Blob-Datenseite
pag_ids 9 Gen-IDs
pag_log 10 Write-Ahead-Log-Informationen

Jede Seite hat einen Header, der Informationen über den Seitentyp und die Nummer der nächsten Seite desselben Typs enthält. Wir können die vollständige Liste der Parameter, die jeder Seitenheader enthält, erhalten, wenn wir die pag-Struktur in der Definitionsdatei ods.h betrachten.

/\* Grundlegender Seitenheader */

typedef struct pag {

SCHAR pag_type; /*Seitentyp-Bezeichner*/

SCHAR pag_flags; /*Seitenflags*/

USHORT pag_checksum; /*Seitenprüfsumme: sie entspricht 12345 nach Version 5.0 */

ULONG pag_generation; /*Seitengeneration */

ULONG pag_seqno; /* WAL-Sequenznummer der letzten Aktualisierung - veraltet*/

ULONG pag_offset; /* WAL-Offset der letzten Aktualisierung - veraltet*/

} *PAG;

Seitentypen und ihre Verwendung

Betrachten wir jeden Seitentyp im Detail und erfahren wir etwas über ihre Funktion und die Informationen, die sie enthalten. Wir beginnen Schritt für Schritt - mit der ersten Seite.

Jede Operation mit einer Datenbank beginnt mit dem Lesen der Datenbank-Header-Seite (oder Header-Seite). Die Datenbank-Header-Seite steht in allen Datenbankdateien an erster Stelle. Dementsprechend ist sie in Bild 2 zuerst dargestellt (wenn wir uns vorstellen, dass das Bild eine Erweiterung der Datenbankdatei von links nach rechts, von oben nach unten darstellt).

Eine Header-Seite enthält Informationen über die Datenbank als Ganzes. In Bild 3 ist eine Datenseite so dargestellt, wie IBSurgeon sie uns zeigt:

![](/images/IB DB structure/InterBase database structure_html_m3c792928.png)

Bild 3. Datenbank-Header-Seite.

Sie können eine Vorstellung vom Inhalt der Header-Seite erhalten, indem Sie die Datenbankstatistiken abrufen. Dazu können Sie das Befehlszeilen-Dienstprogramm gstat oder ein anderes bequemeres Werkzeug für die InterBase-Administration aus der Liste in der Anwendung „Werkzeuge für Administratoren und InterBase-Entwickler“ verwenden. Weitere Details zum Prozess der Statistikerfassung und zur Beschreibung der Header-Seitendaten finden Sie im Kapitel „Statistiken“.

Es sollte beachtet werden, dass die Header-Seite so wichtige Informationen wie Seitengröße, ODS-Versionsnummer (Informationen dazu finden Sie unten), Daten der Datenbankerstellung, Informationen über Transaktionen und eine Reihe verschiedener Informationen enthält. Zum Beispiel speichert die Implementierungs-ID Informationen darüber, unter welchem Betriebssystem diese Datenbank erstellt wurde.

Beim Verbinden mit einer Datenbank liest der InterBase-Server die ersten 1024 Bytes Informationen vom Anfang der Datei und bestimmt anhand der gelesenen Werte, ob die in der Verbindungszeile angegebene Datei eine InterBase-Datenbank ist oder nicht. Dann liest der Server die ODS-Versionsnummer von einer Header-Seite und die Seitengröße in dieser Datenbank und, wenn die ODS-Version mit der Serverimplementierung kompatibel ist, liest er die gesamte Header-Seite erneut, wobei er die richtige Seitengröße verwendet, die aus den ersten 1024 Bytes erhalten wurde. Danach werden die restlichen wichtigen Datenbankparameter wie Lese-Schreib-Modus, Datenbankdialekt usw. von der Header-Seite gelesen.

Auf der Header-Seite gibt es einen Verweis auf die erste der Zeigerseiten, die Verweise auf Datenseiten speichert, die Metadaten enthalten: die Tabelle RDB$Pages (siehe unten im Kapitel „Logische Struktur der InterBase-Datenbank“). In Bild 2 wird dieser Verweis durch einen Pfeil mit der Aufschrift „Nummer der 1. Zeigerseite in der Datenbank“ veranschaulicht. Der Server liest die Nummer der 1. Zeigerseite von der Header-Seite und fährt damit fort. Eine Zeigerseite besteht aus einem geordneten Array von Datenseitennummern, die eine bestimmte Tabelle bilden (eine Tabelle wird als SQL-Objekt betrachtet, das durch die logische Datenbankstruktur beschrieben wird). Jetzt können Sie sehen, wie IBSurgeon die Zeigerseite interpretiert (sehen Sie sich Bild 4 an):

![](/images/IB DB structure/InterBase database structure_html_3bb85660.png)

Bild 4. Zeigerseite einer InterBase-Datenbank

Die Seite enthält einen Datenseitenvektor; diese Daten bilden eine bestimmte Tabelle in einer Datenbank. Dieser Vektor stellt ein Array von Zeigern dar, die den Nummern der Datenseiten in der Datei entsprechen. Der Server liest eine 4-Byte-Nummer der Datenseite und fährt mit einer notwendigen Datenseite fort. Wenn er zur 1. Datenseite von RDB$Pages übergeht, beginnt der Server mit der Konstruktion der internen Datenbankdarstellung, die später vom Server für alle Operationen mit der Datenbank verwendet wird. RDB$Pages speichert Verweise nicht nur auf Datenseiten, die Informationen über die Datenbank enthalten, sondern auch auf die restlichen Seiten, die eine Rolle bei der Gewährleistung des Datenbankbetriebs spielen.

Wir erwähnen diese Tabelle oft, die streng genommen zur logischen Datenbankstruktur gehört. Dennoch ist alles miteinander verbunden, daher können wir nichts beschreiben, ohne auf etwas anderes zu verweisen.

Eine der wichtigen Seitentypen ist die Transaktionsinventarseite (TIP). Diese Seiten bestehen wie alle Seiten aus einem Kopfbereich und einem Hauptteil, der ein Array von 2-Byte-Sequenzen darstellt. Die Sequenzen beschreiben den Zustand von Transaktionen in einer Datenbank (weitere Details zu Transaktionen finden Sie im Kapitel „Transaktionen“).

Tabelle 4. Mögliche Transaktionszustände in TIP

Wert der Sequenz auf PIP Bedeutung
0 Transaktion wurde nicht gestartet, ist aktiv oder verloren ohne Commit oder Rollback
1 Transaktion hat Commit ausgeführt
2 Transaktion hat Rollback ausgeführt
3 Limbo-Transaktion (für 2PC)

Jede Datensatzversion hat ihre eigene Transaktionskennung, wodurch gleichzeitig ausgeführte Transaktionen den Zustand der jeweils anderen „kennenlernen“ und Konflikte bei der Mehrbenutzerarbeit lösen können (weitere Informationen zu Datensatzversionen und anderem finden Sie im Kapitel „Multi-Generations-Architektur von InterBase“).

Die Datenbank-Kopfseite, Zeigerseiten und die TIP gehören zu den „Housekeeping“-Seitentypen, die nur vom Server verwendet werden. InterBase-Benutzer erhalten die darin enthaltenen Informationen nie explizit. Seiten, die Informationen über die Zuordnung von Seiten speichern (üblicherweise als Page Inventory Pages (PIP) oder Space Inventory Pages (SIP) bezeichnet), gehören ebenfalls zum Housekeeping-Seitentyp. Diese Seiten befinden sich ab der zweiten Seite, d. h. die erste PIP folgt direkt auf die Kopfseite, und sie erscheinen in einer Datenbank in festen Seitenintervallen anderer Typen. Die Größe dieser Intervalle gibt an, nach wie vielen Seiten anderer Typen eine PIP erscheint, und hängt von der für diese Datenbank festgelegten Seitengröße ab. Page Inventory Pages werden nicht auf Zeigerseiten berücksichtigt und nicht in RDB$Pages aufgeführt. Die Integrität dieser Seiten ist für den erfolgreichen Betrieb der gesamten Datenbank von entscheidender Bedeutung, da der PIP-Inhalt den Zustand aller übrigen Seiten in der Datenbank beschreibt. Jede Datenbankseite kann 3 Zustände haben: nicht zugewiesen, zugewiesen mit Speicherplatz, zugewiesen und voll. Wenn zusätzlicher Speicherplatz für neue Daten benötigt wird, prüft der Server die PIP, um nicht zugewiesene Seiten zu finden. Wenn eine solche Seite vorhanden ist, ändert der Server ihren Zustand in „zugewiesen mit Speicherplatz“. Wenn keine nicht zugewiesenen Seiten vorhanden sind, wird die Datenbank erweitert - eine neue Datenseite wird hinzugefügt.

Ein Beispiel für eine Datenseite in IBSurgeon und die darin enthaltenen Daten ist in Bild 5 dargestellt.

![](/images/IB DB structure/InterBase database structure_html_1cb26c4f.png)

Bild 5. Page Inventory Page

Sobald die Seite zugewiesen ist, schreibt InterBase ihren Zustand auf die SIP und schreibt dann die Seite selbst. Danach müssen wir diese neu gebildete Seite zu einer großen Anzahl von Seiten hinzufügen, z. B. zu Datenseiten für eine Tabelle. Dazu müssen wir den Verweis auf diese neue Seite auf der letzten Seite dieser großen Anzahl von Seiten schreiben - z. B. auf der letzten Datenseite einer Tabelle. Wenn der Server seine Arbeit direkt nach dem Schreiben auf die SIP unterbricht, aber nicht den Verweis auf Seiten schreibt, die auf die gerade zugewiesene Seite verweisen, wird diese Seite zu einer verwaisten Seite. Eine verwaiste Seite ist physisch erstellt und auf der SIP reserviert, aber es gibt keine Verweise auf sie von anderen Seiten, d. h. der Server wird sie nicht finden und keine Daten auf die Festplatte schreiben können. Die verwaiste Seite ist in Bild 2 mit einem roten Quadrat markiert. Verwaiste Seiten entstehen meist durch einen unerwarteten Stromausfall des Servers und werden mit dem speziellen Werkzeug zur Datenbankreparatur gfix (oder mit FirstAID) (oder mit IBSurFirstAID) „geheilt“.

Bevor wir Datenseiten betrachten, sollten wir wichtige Seitentypen erwähnen: Generator- und Indexseiten. Generatorseiten stellen ein Array von 4-Byte-Zahlen dar, die die Zustände der Generatoren anzeigen. Tatsächlich ist der Generator ein gewöhnlicher Zähler.

In Bild 6 sehen Sie eine Generatorseite. Beachten Sie, dass IBSurgeon zwar die Generatornamen anzeigt, diese Namen jedoch nicht auf Generatorseiten gespeichert werden. Dies dient der Bequemlichkeit des Benutzers, der die Datenbank untersucht. In Wirklichkeit werden die Generatornamen in der Systemtabelle RDB$Generators gespeichert.

![](/images/IB DB structure/InterBase database structure_html_7728f31.png)

Bild 6. Generatorseite (g en-ids )

Wie Sie in diesem Beispiel sehen, enthält die Datenbank Systemgeneratoren, die mit dem Präfix RDB$ beginnen, sowie benutzerdefinierte Generatoren. Wenn Sie mehr über Funktion und Verwendung von Generatoren bei der Entwicklung von InterBase-Datenbankanwendungen erfahren möchten, siehe Kapitel „Tabellen. Primärschlüssel und Generatoren“. Generatorseiten werden zusammen mit anderen Seiten in der Tabelle RDB$Pages berücksichtigt.

Jede Tabelle hat mindestens eine Index-Wurzelseite, unabhängig davon, ob sie Indizes hat oder nicht. Diese Seite enthält Zeiger auf Indexseiten für eine bestimmte Tabelle. Man kann sagen, dass die Index-Wurzelseite für Indexseiten dieselbe Bedeutung hat wie die Zeigerseite für Datenseiten. Daher stellt IBSurgeon sie auf ähnliche Weise dar. Ein Beispiel für eine Index-Wurzelseite ist in Bild 7 dargestellt.

![](/images/IB DB structure/InterBase database structure_html_1c46b1cd.png)

Bild 7. Index-Wurzelseite

Die Index-Wurzelseite enthält eine Liste von Seiten, auf denen Indexwerte gespeichert sind, sowie Indexinformationen - die Selektivität des Index und verschiedene Flags. Weitere Details zu Indizes, ihrer Rolle und Verwendung in InterBase-Datenbanken finden Sie im Kapitel „Indizes“.

Indexseiten enthalten direkt die Werte der Indizes oder, wenn die Indexebene > 0 ist, Verweise auf die darunterliegenden Indexseiten. Hier ist ein Beispiel für eine Indexseite (Bild 8).

![](/images/IB DB structure/InterBase database structure_html_m35b3f5ff.png)

Bild 8. Index- (B-Baum-) Seite

Die Indexseite speichert gepackte Werte der indizierten Daten. Es wird ein ziemlich komplexer Indexierungsmechanismus verwendet, insbesondere bei zusammengesetzten Indizes (die mehrere Felder umfassen).

Im Allgemeinen speichern Datenseiten und Seiten mit BLOB-Werten Benutzerinformationen. Datenseiten enthalten Datensätze in Benutzertabellen der Datenbank, Fragmente von Datensätzen, alte Versionen, Unterschiede zwischen Versionen, BLOB-Felder usw. Was BLOB-Felder betrifft, so sind sie mit Datensätzen auf Datenseiten verbunden und enthalten Daten großer Größe, die nicht auf der Datenseite platziert werden können. Die referenzielle Art der Speicherung von BLOB-Werten ermöglicht die Speicherung großer Datenmengen.

Ein Beispiel für die Darstellung einer Datenseite in IBSurgeon ist in Bild 9 dargestellt:

![](/images/IB DB structure/InterBase database structure_html_235e0c51.png)

Bild 9. Datenseite

Der Datenseitenkopf enthält den Seitentyp und die Kennung der Besitzertabelle (relationID). Datensätze werden auf Datenseiten vom Ende der Seite aus gespeichert und beim Auffüllen näher zum Anfang der Seite hin zugewiesen.

Wir können uns davon überzeugen, wenn wir uns die Zeilenindizes ansehen, die 2 Werte enthalten - den Offset auf der Seite und ihre Länge. Wie Sie am Anfang der Zeile sehen, befinden sich Datensätze, die am Ende der Seite zugewiesen sind - z. B. hat der erste Datensatz einen Offset von 8156 Bytes und eine Länge von 34 Bytes - er endet also bei 8156+34=8192 Bytes - ganz am Rand der Seite (in unserem Fall beträgt die Seitengröße 8192 Bytes). Wenn die Seite gefüllt ist (mit Daten von oben und Zeilenindizes von unten), beginnt der Server, neue Datensätze und Versionen alter Datensätze auf neuen Seiten zu schreiben. Aus dem oben beschriebenen Mechanismus der Seitenfüllung können wir leicht erkennen, warum InterBase-Spezialisten nachdrücklich empfehlen, Datenseiten großer Größe zu verwenden (mindestens 4096 Bytes, besser 8192). Wenn wir eine Tabelle erstellen, bei der ein Datensatz ziemlich groß sein wird (z. B. 10 Felder vom Typ VARCHAR (255)), belegen diese mehr als 2550 Bytes. Das bedeutet, dass ein solcher Datensatz für eine Seite kleiner Größe (1024 oder 2048) zu groß wäre. Es ist offensichtlich, dass die Notwendigkeit, mehrere Seiten von der Festplatte zu laden, um einen einzigen Datensatz zu lesen, die Arbeit mit Ihrer Datenbank nicht beschleunigen wird. Daher wird empfohlen, die Größe der Datenseite beim Erstellen oder Wiederherstellen einer Datenbank neu zu definieren, da standardmäßig die Größe von 1024 Bytes eingestellt ist. Wir haben soeben kurz die wichtigsten Typen von InterBase-Datendateiseiten und ihre Funktion betrachtet. Jetzt können wir zu einer höheren Strukturebene übergehen.

ODS

ODS ist die Abkürzung für On-Disk Structure, also die Datenstruktur der InterBase-Datenbank auf der Festplatte. ODS definiert, wie die Daten in den Datenbankdateien organisiert sind. Die Definition der wichtigsten Konstanten und Datenstrukturen zur Implementierung der On-Disk-Struktur befindet sich in der Datei ods.h aus dem Satz der InterBase-Quellcodes. ODS wurde während der Entwicklung von InterBase geändert, und bei der Arbeit mit einer konkreten Datenbank ermittelt der Server die Nummer der ODS-Version, um zu wissen, womit er es zu tun hat. Die Datei ods.h stellt uns die folgenden Versionen der On-Disk-Struktur dar:

  • ODS 5 wurde von InterBase 3.3 verwendet und wird von höheren Versionen nicht unterstützt

  • ODS 6 und ODS 7 wurden nie veröffentlicht

  • ODS 8 wird von InterBase 4.0 verwendet

  • ODS 9 wird von InterBase 4.5 und höher verwendet

  • ODS 10 kam mit InterBase 6 heraus

  • ODS 11 kam mit InterBase 7.0 heraus

Neben den Haupt-ODS-Versionen gibt es Nebenversionen, die von der konkreten Version des Datenbankservers abhängen, der sie erstellt hat. Die Hauptnummern der Version werden im ganzzahligen Teil der Zahl geschrieben, der die Version angibt, die Nebenversionen im Bruchteil. Beispielsweise erstellt Serverversion 4.0 Datenbanken mit ODS 8.0 und InterBase 4.2 - 8.2. Der Übergang zwischen Nebenversionen von unten nach oben wird automatisch ausgeführt. Beispielsweise reicht es aus, eine Datenbank mit ODS 8.0, die von Server 4.0 erstellt wurde, mit InterBase 5.6 zu öffnen, und die ODS dieser Datenbank hat dann die Version 8.2. Der Übergang zwischen Haupt-Datenbankversionen wird nur über eine Datenbanksicherung mit einer alten Version und eine Wiederherstellung mit einer neuen Serverversion ausgeführt. Der Prozess des Übergangs zwischen Versionen wird in Kapitel 1.4 „Migration“ ausführlich beschrieben.

Der wichtige Punkt bei der Implementierung der ODS-Unterstützung für InterBase-Versionen 4.x und 5.x ist die Abwärtskompatibilität der InterBase-Server 4.x und 5.x mit einer Version, die eine Einheit niedriger ist als die Implementierung eines konkreten Servers. InterBase unterstützt mehrere mögliche ODS und wählt je nach ODS-Version beim Verbinden mit einer konkreten Datenbank die Unterstützung der erforderlichen ODS-Implementierung. Der Mechanismus zur Entscheidung, welche Implementierung der ODS-Unterstützung in einem konkreten Fall zu wählen ist, wird Y-Valve ((c) von Steve Trenton) genannt.

Einfacher gesagt: Eine Datenbank mit ODS 8.x, die InterBase 4.0 entspricht, kann in InterBase 5.x geöffnet werden.

Die vollständige ODS-Kompatibilitätstabelle ist unten dargestellt:

InterBase-Version Haupt-ODS Neben-ODS
4.0/4.1 8.0
4.2 8.2 8.2
5.0/5.1 9.0 8.2
5.5 9.1 8.2
5.6 9.1 8.2
6.0 10.0 9.0/9.1
7.0 11.0 10.0
7.1 11.1 10.0

ODS ist abwärtskompatibel. Mit anderen Worten: Ein Server mit höherer Version und alle seine Werkzeuge können mit einer Datenbank arbeiten, die von früheren Serverversionen erstellt wurde, aber nicht umgekehrt. Wenn Sie versuchen, eine Datenbank zu öffnen, die in der InterBase-Version 6 erstellt wurde, mit InterBase 5.x, erhalten Sie eine Fehlermeldung „Unsupported On-disk structure: Found ODS 10, supported ODS 9“.

Eine Beschreibung des Übergangs zwischen Versionen von unten nach oben und umgekehrt finden Sie im Kapitel „Migration“.

ODS ist sehr wichtig für Fragen der Sicherung und Datenextraktion sowie für die Wiederherstellung beschädigter Datenbanken. Die Werkzeuge zur Sicherung gbak und Wiederherstellung gfix überwachen die ODS-Version und funktionieren einfach nicht, wenn die ODS-Version der Datenbank, der sie dienen sollen, größer ist als die in ihnen implementierte Version. Das bedeutet, dass gbak aus 4.x keine Datenbanksicherung erstellen kann, wenn die Datenbank von Server 5.x erstellt wurde, aber leicht umgekehrt.

Eine Brücke zwischen physischer und logischer Datenbankstruktur

Wir haben die physische Struktur von Datenbankdateien allgemein betrachtet. Jetzt müssen wir zur logischen Datenbankstruktur übergehen. Lassen Sie uns eine Brücke zwischen der physischen und der logischen Ebene der Informationsdarstellung in einer Datenbank schlagen, damit es keine Abgrenzung bei den Begriffen und keine Lücken im Material gibt. Alles, was auf verschiedenen Datenbankseiten gespeichert ist, muss irgendwie im Computerspeicher organisiert werden; Daten aus der Datenbankdatei müssen in einen Satz von Intra-Server-Objekten und Variablen umgewandelt werden. Dieser Satz wird nach der Terminologie von Ann Harrison [1.. als internes Datenbankabbild bezeichnet. Wir werden also versuchen, den Prozess der Erstellung des internen Datenbankabbilds zu betrachten.

  • Der Server liest 1024 Bytes vom Anfang der Datei und wenn es sich tatsächlich um eine InterBase-Datenbankdatei handelt, ermittelt er die Seitengröße dieser Datenbank und liest die gesamte Kopfseite erneut.

  • Aus der Kopfseite extrahiert der Server die Nummer der Zeigerseite, die Referenzen auf Datenseiten speichert und die Tabelle RDB$Pages definiert.

  • Der Server geht zu dieser Zeigerseite und beginnt, Informationen von den referenzierten Datenseiten zu lesen. Er füllt die erste RDB$Pages-Tabelle mit Daten. Diese Tabelle ist eine Art Brücke zwischen physischen Objekten - Seiten der Datenbankdateien - und logischen - Tabellen. Die Struktur von RDB$Pages ist wie die anderer Systemtabellen in InterBase streng festgelegt.

  • Nachdem der Server Daten über die Seitenzuordnung zu Relationen erhalten hat (Relationen - tatsächlich dasselbe wie gewöhnliche Tabellen, und wir können diese Begriffe zur Vereinfachung gedanklich austauschen), beginnt InterBase, Datenstrukturen zu bilden: zuerst Systemtabellen, Constraints und Indizes, dann Benutzerobjekte.

  • Nach der Initialisierung von System- und Benutzermetadaten (Tabellen, Constraints, Indizes und andere Datenbankobjekte) gibt InterBase das Handle dieser Datenbank an den Benutzer zurück, der die Datenbank öffnen wollte. Im Wesentlichen ist das Handle ein Bezeichner, der InterBase zeigt, mit welcher Datenbank gearbeitet werden soll, da mehrere Benutzer gleichzeitig arbeiten können, was bedeutet, dass mehrere Datenbanken geöffnet sein können.

  • Nach diesen Operationen gilt die Datenbank als geöffnet und der Server ist bereit, Benutzerabfragen darauf auszuführen. Nun, da eine gewisse Brücke geschlagen ist, die die physische und logische Struktur der Datenbank verbindet, können wir beginnen, die Besonderheiten der logischen Struktur zu untersuchen.

Logische Struktur der InterBase-Datenbank

Die logische Struktur ist ein eher vager Begriff, daher werden wir versuchen, die wichtigsten Ideen schrittweise zu erfassen, in der Hoffnung, dass sie später intuitiv klar werden. Das erste, was wir in Bezug auf die logische Struktur der Datenbank betrachten, sind Systemtabellen und ihre Inhalte. Systemtabellen beschreiben das System sowie Benutzermetadaten. Allgemein gesprochen bedeutet der Begriff „Metadaten“ „Daten, die eine Menge von Daten beschreiben“. Das Präfix „Meta“ bedeutet: „beschreibt eine Menge“. Zum Beispiel ist Metasprache eine Sprache, die eine Menge von Sprachen beschreibt. Metadaten beschreiben Benutzerdaten, also Tabellen, Trigger, Views, gespeicherte Prozeduren und so weiter - alles, was die Regeln zum Speichern und Verarbeiten von Informationen implementiert, wegen denen diese konkrete Datenbank erstellt wurde.

Es ist beim ersten Mal ziemlich amüsant zu erfahren, dass alle Metadaten - Benutzertabellen, Trigger, Views sowie alle Systemobjekte - in denselben Tabellen gespeichert sind, aus denen Sie Daten mit gewöhnlichen SQL-Abfragen lesen und schreiben können. Diese Tabellen unterscheiden sich „visuell“ nur dadurch, dass ihre Namen mit RDB$ beginnen. Diese 4 Symbole sind für die Namen von Systemobjekten reserviert. Keine einzige Benutzertabelle, Spalte oder anderes Objekt hat das Recht, Namen zu haben, die mit diesen Symbolen beginnen. Formal können Sie eine Tabelle erstellen, deren Name mit den reservierten Symbolen beginnt, aber die InterBase-Dokumentation empfiehlt dies nicht.

Es stellt sich die Frage: Wenn die Daten über die Datenbankstruktur in denselben Tabellen gespeichert sind wie die Benutzerdaten, wo werden dann die Informationen über die Tabellen gespeichert, die Tabellen beschreiben? Ein klassisches Beispiel für das Problem von „Henne und Ei“ - wie könnte eines früher erscheinen als das andere, wenn sie voneinander abhängig sind? Die Antwort ist, dass Systemtabellen in ihrem primitiven Zustand in den ursprünglichen InterBase-Codes festgelegt sind und beim Erstellen einer Datenbank automatisch in einer bestimmten Reihenfolge geöffnet werden. Wir haben bereits über die Tabelle RDB$Pages gesprochen, die physische Seiten in Datenbankdateien mit bestimmten Objekten dieser Datenbank vergleicht. Die Struktur dieser Tabelle ist unten angegeben:

Tabelle 5. Systemtabelle RDB$Pages

Spaltenname Datentyp Beschreibung
RDB$PAGE_NUMBER INTEGER Nummer der physischen Seite
RDB$RELATION_ID SMALLINT Bezeichner der Tabelle, für die die Seite zugewiesen ist
RDB$PAGE_SEQUENCE INTEGER Nummer dieser Seite
RDB$PAGE_TYPE SMALLINT Seitentyp - siehe Tabelle 3

Jede Datenseite ist einer bestimmten Tabelle zugeordnet. Diese Zuordnung wird durch das Feld RDB$RELATION_ID unterstützt, in dem ein Verweis auf die Tabelle gespeichert ist. Wie oben beschrieben, erstellt der Server beim Aufbau des internen Datenbankabbilds diese Tabelle und füllt sie nach einem festgelegten Algorithmus mit Daten. Um genau zu sein, ist RDB$Pages zum Zeitpunkt der Erstellung des internen Datenbankabbilds keine Tabelle, sondern nur eine Datendatei eines bestimmten Formats, das InterBase bekannt ist. Nach einem festgelegten Algorithmus liest der Server Daten aus dieser Datei und erstellt eine Tabelle - RDB$Relations - die für die gesamte Datenbank wichtig ist. Diese Tabelle beschreibt alle Datenbanktabellen. Wenn wir eine SQL-Abfrage ausführen:

SELECT * from RDB$Relations

um herauszufinden, auf welche Tabellen RDB$Relations verweist, sehen wir, dass sie RDB$Pages und sich selbst enthält. Es ist offensichtlich, dass der Server in diesem Fall ein wenig trickst, indem er diese und andere Systemtabellen in RDB$Relations rückwirkend einträgt und sie auf diese Weise legalisiert. Der Server protokolliert sie als „normale“ Tabellen, in denen er Datensätze hinzufügen oder löschen kann. Mit anderen Worten: Er stellt eine standardmäßige SQL-Schnittstelle für die Arbeit mit Metadaten bereit.

Und eine ziemlich vernünftige Frage könnte aufkommen - warum sollten InterBase-Entwickler ihre Systemdaten an die Benutzerschnittstelle anpassen? Schließlich wären interne Zugriffs- und Leseoperationen schneller. Natürlich ergibt es großen Sinn, einen universellen Mechanismus für die Arbeit mit Tabellen bereitzustellen, die Metadaten beschreiben.

Die Sache ist die, dass die logische Datenbankstruktur nicht nur aus Tabellen, sondern auch aus anderen Objekten besteht. In InterBase gibt es folgende Objekte:

  • Tabelle

  • View

  • Trigger

  • Computed_field

  • Validation

  • Prozedur

  • Expression_index

  • Exception

  • Benutzer

  • Feld

  • Index

  • Benutzerdefinierte Funktion (UDF)

Wir kennen die Funktion einiger Objekte noch nicht genau, aber wir wissen sicher, dass alle in einer Ansicht beschrieben und gespeichert werden müssen, die für den Benutzer und für den Zugriff aus dem InterBase-Kernel bequem ist. Am besten wäre es, diese Objekte in Systemtabellen zu speichern. Ihre Hinzufügung und Änderung erfolgt durch SQL-Abfragen. Eine kluge Lösung, nicht wahr? Die Serverimplementierung ist vollständig von einer konkreten Datenbank getrennt - alle Verbindungen werden durch SQL und seine Erweiterungen - die Sprache der gespeicherten Prozeduren und Trigger - beschrieben.

Alle Serverobjekte werden also in Tabellen gespeichert. Jeder Objekttyp hat eine Tabelle, die alle in der Datenbank beschriebenen Instanzen beschreibt. Zum Beispiel gibt es für Trigger eine Tabelle RDB$Triggers, für gespeicherte Prozeduren RDB$Procedures, Views werden in der Tabelle RDB$Relations beschrieben.

Betrachten wir im Detail die Struktur der letzten Tabelle, die alle Tabellen und Views in einer Datenbank beschreibt. Die Struktur der Tabelle RDB$RELATIONS ist aus dem Language Reference für InterBase 6 entnommen und unten in Tabelle 6 angegeben.

Tabelle 6. Systemtabelle RDB$Relations

Spaltenname Datentyp Länge Beschreibung
RDB$VIEW_BLR BLOB 80 BLR: für Views, enthält BLR (Binary Language Representation) der Abfrage, die InterBase jedes Mal ausführt, wenn auf die View zugegriffen wird.
RDB$VIEW_SOURCE BLOB 80 Text: für Views, enthält den Code der SQL-Abfrage, die diese View implementiert.
RDB$_DESCRIPTION BLOB 80 Benutzerbeschreibung der Tabelle oder View
RDB$RELATION_ID SMALLINT Enthält die interne Kennung der Tabelle/View
RDB$SYSTEM_FLAG SMALLINT Definiert den Typ der Tabelle: Benutzerdaten - 0; Systeminformationen > 0.
RDB$DBKEY_LENGTH SMALLINT Länge von db$key
RDB$FORMAT SMALLINT Für die interne Verwendung durch InterBase reserviert. Enthält den Änderungszähler der Metadaten für die angegebene Tabelle.
RDB$FIELD_ID SMALLINT Die Anzahl der Felder in der Tabelle.
RDB$RELATION_NAME CHAR 31 Eindeutiger Tabellenname.

In der Beschreibung dieser Systemtabelle sehen wir eine Abkürzung BLR. Um zu verstehen, was das ist, machen wir einen Exkurs in SQL. Wie bekannt, sind Views, Trigger und gespeicherte Prozeduren ein Code, der in einer Erweiterung der SQL-Sprache geschrieben ist (für jeden DBMS-Server gibt es eigene Erweiterungen). Sie ist der menschlichen Sprache nahe, was das Erstellen von Abfragen darin erleichtert. Aber InterBase übersetzt sie offensichtlich in etwas „Maschinelleres“ - nämlich in BLR (Binary Language Representation). Jede Abfrage, View, Trigger, gespeicherte Prozedur wird immer in BLR übersetzt und dann zur Ausführung an den InterBase-Kernel übertragen.

BLR

BLR ist eine spezielle Sprache, die als Zwischenglied zwischen dem SQL-Code, den ein Programmierer schreibt, und dem Maschinencode, den der Server akzeptiert, verwendet wird. Niemand schreibt direkt in BLR - das wäre ziemlich schwierig, da für die höchstmögliche Ausführungsgeschwindigkeit in dieser Sprache die sogenannte umgekehrte polnische Notation verwendet wird. Hier ist ein kleines Beispiel:

blr_begin,

     blr\_assignment,

        blr\_field, 0, 7, 'D','A','T','E','I','Z','M',

        blr\_variable, 1,0,

     blr\_assignment,

        blr\_field, 0, 4, 'R','A','T','E',

        blr\_variable, 0,0,

     blr\_block,

BLR für Ihre Abfragen, Prozeduren, Trigger und andere Trigger wird von einem speziellen Präprozessor gebildet, der Teil des Serverkerns ist. Wie in Tabelle 7 gezeigt, wird für Views sowohl ihr Text (ursprüngliche) View als auch die kompilierte View, also BLR, gespeichert. Wenn auf ein Objekt mit BLR verwiesen wird, führt der Server den Binärcode des Objekts aus und interpretiert nicht jedes Mal den ursprünglichen Text dieser Objekte, was die Ausführung komplexer Abfragen beschleunigt.

Hierarchie der Objekte in InterBase

Um eine klare Vorstellung davon zu bekommen, was Datenbankobjekte darstellen, werden wir versuchen, eine Hierarchie der Datenbankobjekte nach dem Prinzip „wer enthält was“ zu erstellen. Physische Seiten der Datenbankdateien sind das erste, was in unsere Hierarchie als unterste Ebene der Datenorganisation aufgenommen werden muss. Dann folgen Tabellen als grundlegende Objekte, die alle anderen Objekttypen beschreiben. Tabellen beschreiben gespeicherte Prozeduren, Trigger, berechnete Felder, Validierungen, Ausdrucksindizes, Exceptions und so weiter. Beachten Sie - nur beschreiben! Tabellen enthalten nur Deklarationen und Definitionen dieser Objekte, und Objekte werden durch BLR implementiert. Daher können wir Tabellen in Form eines Rahmens darstellen, der alle anderen Datenbankobjekte unterstützt. BLR wird am unteren Ende des Rahmens als Implementierungsebene stehen, dann Trigger, gespeicherte Prozeduren, Ausdrucksindizes und Views.

Um die Spezialisten für die interne InterBase-Struktur zu beruhigen, die einwenden könnten, dass BLR vieler Objekte (wie Views) in Systemtabellen gespeichert sind, kommentieren wir, dass diese Beziehung auf einem Bild schwer darzustellen ist und wir sie zur Vereinfachung weglassen. Das Schema hat nicht das Ziel, die Abhängigkeiten der Datenbankobjekte absolut genau nachzubilden; es veranschaulicht nur ihre enge Verbindung.

Die Tatsache, dass diese Objekttypen direkt mit BLR verbunden sind, das sie ohne Zwischenlogik implementiert, vereint sie. Exceptions sollten separat zugeordnet werden - sie stellen spezielle Arten von Fehlern dar, die vom Benutzer definiert werden. Exceptions werden auf der Ebene des InterBase-Kernels verarbeitet und haben daher kein BLR. Solche Arten von Constraints wie Checks sind über Triggern zugeordnet, da Trigger tatsächlich die Logik von Constraints und Checks implementieren.

Eine Hierarchie der Objekte der logischen und physischen Datenbankstruktur ist in Bild 2 dargestellt.

Bild 10. Objekte der logischen Struktur der InterBase-Datenbank

Natürlich beschreibt dieses Schema die logische Struktur und die Verbindungen der Objekte in der Datenbank nur annähernd und vermittelt eine allgemeine Vorstellung davon. Jeder, der die Struktur der InterBase-Datenbankmetadaten studieren möchte, kann ein Reengineering der Datenbanksystemtabellen durchführen und alle Verbindungen zwischen ihren Objekten betrachten sowie auf Dokumentation und InterBase-Primärcodes zurückgreifen. Diese Tabelle zeigt nur die wichtigsten Datenbankobjekte. Lassen Sie uns kurz die Hauptfunktionen beschreiben, die diese Objekte in der Datenbank ausführen.

Tabellen - das Hauptobjekt, das Benutzer- und Systemdaten enthält. Eine Tabelle hat einen eindeutigen Namen und enthält eine Reihe benannter Felder. Ein Benutzer kann Daten in Tabellen ablegen, extrahieren und ändern. Man kann sagen, dass eine Tabelle ähnlich wie eine gewöhnliche, von Hand gezeichnete Papiertabelle ist.

Trigger - ausführbare Codeteile, die verwendet werden, um zusätzliche Aktionen zum Zeitpunkt von Datenoperationen zu implementieren. Trigger werden vor oder nach Einfüge-, Änderungs- oder Löschoperationen ausgeführt und ermöglichen das Einsetzen von Werten in neu erstellte Datensätze sowie viele andere Dinge.

Eine gespeicherte Prozedur ist ein leistungsfähiges Werkzeug zur Implementierung von Geschäftslogik auf Datenbankebene. Da sie auf Serverebene ausgeführt wird, arbeitet sie sehr schnell und ermöglicht die Ausführung einer Reihe von Operationen auf Datenmengen. Gespeicherte Prozeduren von InterBase geben standardmäßige SQL-Datenmengen zurück, auf denen alle SQL-Operationen, einschließlich der Vereinigung mit anderen Tabellen, ausgeführt werden können.

Views sind kompilierte SQL-Abfragen, die auf dem Server ausgeführt werden. Views ermöglichen die Organisation von Datenmengen und die Übertragung eines Teils der Geschäftslogik auf den Server.

Validierungen sind Einschränkungen, die auf Feldwerte in der Tabelle gesetzt werden. Zum Beispiel können wir festlegen, dass das jeweilige Feld nur positive Werte akzeptiert. Einschränkungen auf Feldwerte werden durch Trigger implementiert und ermöglichen eine effektive Kontrolle der referenziellen Integrität auf Datenbankebene. Üblicherweise werden Einschränkungen verwendet, um zu verhindern, dass falsche Werte in eine Tabelle eingefügt werden.

Benutzer - InterBase ermöglicht es uns, mehrere Benutzer für die Arbeit mit der Datenbank zu haben und die Zugriffsrechte auf verschiedene Datenbankobjekte unter ihnen zu verteilen. So können wir Berechtigungen für bestimmte Datenbankoperationen steuern.

Benutzerdefinierte Funktionen (UDF) - Funktionen, die vom Benutzer definiert werden. Dies ist eine der leistungsfähigsten InterBase-Fähigkeiten, die es uns ermöglicht, die standardmäßige SQL-Schnittstelle durch eigene Funktionen zu erweitern. Zum Beispiel sind Funktionen zur Arbeit mit Zeichenketten wie UPPER (setzt alle Zeichen in Großbuchstaben) in der standardmäßigen UDF-Bibliothek implementiert, die im InterBase-Paket enthalten ist. Dank der Möglichkeit, eigene UDFs zu erstellen, können Entwickler die InterBase-Funktionalität praktisch um beliebige Funktionen erweitern. Wir können jede Programmierumgebung verwenden, die das Erstellen dynamischer Bibliotheken ermöglicht (Visual C++, C++ Builder, Delphi usw.), um UDFs zu erstellen.

Fazit

In diesem Kapitel haben wir uns zum ersten Mal mit Fragen der Implementierung von Speicherung und Verarbeitung von Daten in einer InterBase-Datenbank beschäftigt. Leider können wir dieses Thema nicht kurz behandeln, ohne auf eine große Anzahl von Begriffen und ungenaue Analogien zurückzugreifen. Wenn wir die physische und logische Struktur der Datenbank detaillierter beschreiben würden, müssten wir uns ohnehin auf die primären InterBase-Codes beziehen, aber das wäre ein anderes Buch.

Dennoch denken wir, dass es für jeden Programmierer nützlich wäre, sich mit dem Inhalt des Produkts vertraut zu machen, das er täglich verwendet.

Literaturverzeichnis

  1. «The On-Disk Structure of InterBase» von Ann.W.Harrison

  2. «Space Management in InterBase» von Ann W.Harrison

  3. «Structure of a Data Page» von Paul Beach (Mit Dank an Dave Schnepper und Deej Bredenberg)