Datenbanken und andere speicherhungrige Applikationen haben ein Problem mit 32bit Systemen. Mit 32bit lassen sich gerade mal 2^32 Speicherstellen bzw. 4GB adressieren. 4GB Hauptspeicher sind in Servern keine Seltenheit mehr wo selbst die Daddel-PCs der Lebensmitteldiscounter schon mit mindestens 1GB Hauptspeicher für sich werben. Datenbanken lieben Hauptspeicher. Als Faustregel gilt traditionell, daß Zugriffe auf CPU internen Speicher etwa 1.000x schneller sind als Zugriffe auf den Hauptspeicher und der Hauptspeicher wiederum 1.000x schneller Daten liefern und speichern kann als eine Festplatte. Die Faktoren mögen inzwischen anders sein, aber die Größenordnungen geben eine Vorstellung davon, warum eine Datenbank erst dann genug Pufferspeicher (Cache) hat, wenn der gesamte Datenbestand im schnellen und inzwischen bezahlbaren Hauptspeicher zwischengespeichert werden kann.
Heute nun, lief ich über eine MaxDB, die sich weigerte ihren Job zu machen. In der knldiag Protokolldatei aus dem Rundirectory der Datenbankinstanz fanden sich folgende Einträge:
0xD00 ERR 18853 MEMORY Could not allocate 105676800 Bytes (heap) for task stacks, rc=8
0xB4C ERR 18197 DBCRASH RTE Abort exception
0xD00 ERR 18193 MEMORY Could not allocate the tasks stack, rc = 8
0xD00 ERR 18197 DBCRASH RTE Abort exception
Viele Einträge in der knldiag kann man fast so einfach wie eine Zeitung lesen. Was steht hier? Die Datenbank hat versucht etwa 100MB Speicher für einen “task stack” zu beantragen und zu erhalten. Diese Anforderung schlug fehl. Daraufhin gab es eine “RTE Abort exception”. RTE steht für Runtime Environment oder Laufzeitumgebung. Diese Schicht ist in vielen Programmen dafür zuständig betriebssytemspezifische Aufgaben zu abstrahieren. Bei MaxDB ist das nicht anders. Bei der “Abort exception” handelt es sich um einen gewollten “DBCRASH”. Die Fehlerbehandlungsroutinen in der Datenbank haben ein Problem erkannt. Noch während der Startphase der Datenbank wird der Speicher knapp. Beim “task stack” handelt es sich um Speicher bei dem MaxDB nicht mit sich verhandeln läßt. Entweder das Betriebssystem kann den Speicher bereitstellen oder MaxDB kann interne Prozesse nicht starten. Letzteres ist hier der Fall.
Wie kann es sein, daß in diesem Fall MaxDB bei der Anforderung von 100MB Speicher eine Notabschaltung noch während des Starts einleitet? Der Server war mit 4GB ausgestattet. Das knldiag bestätigt dies:
0xFC 19777 INFO Total physical memory: 4094 MB
Die Größe des Pufferspeichers war mit 330.000 Datenbankseiten bzw. ~2.52 GB angegeben. Eine Datenbankseite von MaxDB ist 8kb groß. Der Hauptspeicher für den Datenpuffer konnte ohne Probleme allokiert werden. Und 2.52 GB + 0.1GB sind doch weit weniger als 4GB…
0xFC 19860 MEMORY I/O buffer cache: 330000 Pages allocated
Auf praktisch allen 32bit Systemen sind die 4GB, die theoretisch angesprochen werden können, in zwei Hälften geteilt. 2GB werden einem Programm (Prozess) zur Verfügung gestellt und 2GB sind für das Betriebssystem reserviert. Wenn man nicht gerade ein sehr altes System verwendet, kann die Aufteilung rekonfiguriert werden. Im obigen Fall kam Windows 2003 Server (Standard Edition) zum Einsatz. Windows 2003 Server kann mit einer 3GB/1GB Aufteilung betrieben werden. Dies war auch bereits konfiguriert. Doch warum gab es trotzdem Probleme? 2.52 GB + 0.1 GB sind auch noch weniger als 3GB!
Dies hat zwei Ursachen: MaxDB verwendet weitere Speicherbereiche, deren Größen nicht explizit im knldiag vermerkt werden. Es gibt z.B. noch Stacks für Threads, diverse Listen und es gibt die Converterstruktur. Die Größe dieser Dinge ist von vielen Faktoren abhängig. Einige der Hauptfaktoren sind die Werte für MAXUSERTASKS, _MAXTASK_STACK, die Größe der Datenbank und die Anzahl der verwendeten Daten- und Logvolumes. Aber es ist schwierig genaue Aussagen zu machen, welcher dieser Speicherbereich wie groß werden kann. Mitsamt der Schätzungen für diese Speicherbereiche wurden 2.52 GB + 0.1 GB + 0.2 GB (initial) = 2.82 GB erreicht. Nah an den 3GB, aber da fehlt immer noch ein letztes Stückchen.
Für des Rätsels Lösung brauchte ich die Hilfe eines Kollegen, der früher in der MaxDB Entwicklungsabteilung im Bereich der Laufzeitumgebung gearbeitet hat: die Shared Libraries (dll’s). Speicher den ein Prozess über eingebundene Shared Libraries verbraucht, ist ebenfalls anzurechnen.
Von den 3GB “virtual address space”, die einem Prozess wie MaxDB theoretisch zur Verfügung stehen sollte man maximal 2.6GB einplanen. Bedenkt man, daß MaxDB nicht nur Hauptspeicher für den Pufferspeicher allokiert, sondern auch für andere Aufgaben, dann ergibt sich als Erfahrungs- und Daumenwert eine Grenze von etwas über 2GB, die als Pufferspeicher genutzt werden können. Die leidigen 32bit…
Auswege? 64bit Hardware und Betriebssystem, AWE/PAE (seit SAPDB 7.4 unterstützt).