Speicherbelegung in Firebird 2.1 und höher
Vlad Khorsun, 20-OCT-2010
Seit Anbeginn hatte Firebird keine Regeln, wie Speicherplatz für Datenbankdatei(en) zugewiesen werden sollte. Es schreibt einfach neu zugewiesene Seiten in unbestimmter Reihenfolge (wegen Abhängigkeiten zwischen Seiten, um die Strategie des „vorsichtigen Schreibens“ zu bedienen).
Dieser Ansatz ist sehr einfach, hat aber einige Nachteile:
• Wegen der unbestimmten Reihenfolge der Schreibvorgänge kann es vorkommen, dass der Seiten-Cache viele „dirty pages“ enthält, wenn eine neu zugewiesene Seite geschrieben werden muss, dies aber wegen fehlendem Speicherplatz nicht kann. In solchen Fällen gehen oft alle anderen „dirty pages“ verloren, weil Administratoren es vorziehen, die Datenbank herunterzufahren, bevor sie Speicherplatz verfügbar machen. Dies führt zu schwerwiegenden Korruptionen.
• Die Zuweisung von Speicherplatz in relativ kleinen Blöcken kann zu erheblicher Dateifragmentierung auf Dateisystemebene führen und die Leistung großer Scans (z. B. während eines Backups) verringern.
Mit dem neuen ODS 11.1 ändert Firebird seinen Algorithmus zur Speicherplatzzuweisung, um Korruptionen bei fehlendem Speicherplatz zu vermeiden und dem Dateisystem eine Chance zu geben, Fragmentierung zu vermeiden. Diese Änderungen werden unten beschrieben.
a) Jede neu zugewiesene Seite wird sofort auf die Festplatte geschrieben, bevor sie an die Engine zurückgegeben wird. Wenn eine Seite nicht geschrieben werden kann, findet keine Zuweisung statt, das PIP-Bit wird nicht gelöscht und ein entsprechender E/A-Fehler wird ausgelöst. Dieser Fehler kann nicht zu Korruptionen führen, da wir die Garantie haben, dass alle „dirty pages“ im Cache über zugewiesenen Speicherplatz verfügen und sicher geschrieben werden können.
Diese Änderung verursacht einen zusätzlichen Schreibvorgang für jede neu zugewiesene Seite im Vergleich zum alten Verhalten. Daher ist während des Wachstums der Datenbankdatei ein Leistungsabfall zu erwarten. Um diesen Nachteil zu verringern, gruppiert Firebird Schreibvorgänge neu zugewiesener Seiten in Blöcken von bis zu 128 KB und verfolgt die Anzahl der „initialisierten“ Seiten im PIP-Header.
Hinweis: Eine neu zugewiesene Seite wird nur dann zweimal auf die Festplatte geschrieben, wenn sie zum ersten Mal zugewiesen wird. D. h., wenn eine Seite zugewiesen, freigegeben und erneut zugewiesen wird, wird sie bei der zweiten Zuweisung nicht zweimal geschrieben.
b) Um Dateifragmentierung zu vermeiden, nutzt Firebird die entsprechende API des Dateisystems, um Speicherplatz in relativ großen Blöcken vorab zuzuweisen. Derzeit existiert eine solche API nur unter Windows, wurde aber kürzlich zur Linux-API hinzugefügt und könnte in Zukunft in so beliebten Dateisystemen wie ext2 usw. implementiert werden. Daher ist diese Funktion derzeit nur in Windows-Builds von Firebird implementiert und könnte in Zukunft in Linux-Builds implementiert werden.
Für eine bessere Kontrolle der Speicherplatzvorabzuweisung wurde eine neue Einstellung in Firebird.conf eingeführt: DatabaseGrowthIncrement. Dies ist die Obergrenze der Vorabzuweisungsblockgröße in Bytes. Der Standardwert ist 128 MB. Wenn die Engine mehr Speicherplatz benötigt, weist sie 1/16 des bereits zugewiesenen Speicherplatzes zu, jedoch nicht weniger als 128 KB und nicht mehr als den Wert von DatabaseGrowthIncrement. Wenn DatabaseGrowthIncrement auf null gesetzt ist, ist die Vorabzuweisung deaktiviert. Speicherplatz für Datenbank-Schatten-Dateien wird nicht vorab zugewiesen.
Außerdem ist die Vorabzuweisung deaktiviert, wenn die Option „No reserve“ für die Datenbank gesetzt ist.
Hinweis: Die Vorabzuweisung hilft auch, Korruptionen bei fehlendem Speicherplatz zu vermeiden - in einem solchen Fall besteht eine gute Chance, dass die Datenbank genügend vorab zugewiesenen Speicherplatz hat, um zu arbeiten, bis der Administrator Speicherplatz verfügbar macht.
Autor: Vlad Khorsun,