orm@doc-tcpip.org | Erstellt: Juli 2007 - Letzte Modifikation: September 2009 |
Datenbanken setzen traditionell oft sogenannte "Raw Devices" ein; unter AIX wird das als "Raw Logical Volume" realisiert. Das hat Performance-Gründe. Auf ein Raw Device greift die Datenbank direkt zu, unter Umgehung aller Mechnismen auf Ebene des Filesystems.
Nur das ermöglicht es einer Datenbank, an einem Datenbankfile parallel an verschiedenen Stellen zu schreiben - wobei die Software für die Datenintegrität sorgen muß.
File Systeme bringen in der Regel folgende Mechanismen mit:
Ein Locking System für die Inodes, sodaß einzelne Files beim Schreiben gelockt werden können.
Jedes File besitzt eine Datenstruktur, in der die Eigenschaften des Files festgelegt sind (darunter fallen Besitzer, Permissions, Größe sowie die wirkliche, physikalische Lage des Files in den Blöcken der Platte). Diese Struktur ist in der Inode abgelegt und wird beim Schreiben des Files modifiziert.
Es ist also ein Locking Mechanismus nötig, damit immer nur ein Prozess die Inode ändern kann. Das JFS2 benutzt ein Inode-Sperre, die vielen Prozessen das lesen erlaubt, aber bei schreibenden Zugriffen das File exklusiv für einen Prozess sperrt ("read-shared, write-exclusive lock"). Für die Dauer eines schreibenden Zugriffes ist das File daher für alle anderen Prozesse gesperrt. Der schreibende Prozess muß sich zuerst um die exklusive Sperre des Files bemühen, erst dann kann er schreiben.
Dieser Mechanismus wird durch die "Concurrent IO" (cio) mount-Option aufgehoben. Die Applikation (die Datenbank) sorgt hier selbst für die richtige Reihenfolge und achtet darauf, das keine veralteten Daten gelesen bzw. Daten überschrieben werden.
Einen "File Buffer Cache"
Die Daten eines Files werden nicht direkt auf die Platten geschrieben, sondern in einem File Buffer Cache zwischengespeichert. Dieser liegt im (schnellen) Hauptspeicher, und wird bei jedem lesenden Zugriff zuerst überprüft. Wenn die gewünschten Daten schon im Puffer liegen, wird aus diesem ausgelesen, wodurch der Dateizugriff erheblich beschleunigt wird. Das bezeichnet man als einen "cache hit".
Zusätzlich wertet der Algorithmus den Zugriff auf den Plattenspeicher aus und lädt von sich aus anstehende Blocks in den Puffer. Die Anzahl der Blocks, die voraus gelesen werden, hängt von der Anzahl der zusammenhängend bisher gelesenen Blocks ab. So kann zb. ein File aus dem Puffer gelesen werden, ohne das ein Plattenzugriff abgewartet werden muß. Dieser Mechanismus wird als "read ahead" bezeichnet.
Im Fall des JFS2 kann man mit dem ioo-Kommando das Verhalten des read ahead beeinflussen. Dazu gibt es zwei Parameter, die eingestellt werden können:
Auch die schreibenden Zugriffe erfolgen im Hauptspeicher. Betroffene Blocks werden als "dirty" gekennzeichnet. Die angesammelten, modifizierten Blocks werden regelmäßig vom syncd gegen die Platten syncronisiert. Das reduziert einmal die Anzahl der Plattenzugriffe erheblich, zum anderen ist der Zugriff auf ein File aus der Sicht der Applikation asynchron - die Applikation kann also weiterarbeiten, und muß nicht auf den Platten IO warten. Das wird als "write behind" bezeichnet.
Beide Mechanismen werden durch die "Direct IO" (dio) mount-Option aufgehoben. Die Applikation (die Datenbank) sorgt in diesem Fall selbst für einen effizienten Zugriff auf die gespeicherten Files.
Einen Mechanismus, der regelmäßig den Cache mit den Platten synchronisiert (der syncd)
Mit AIX 5.2 wurde versucht, das Enhanced Journaled Filesystem (JFS2) mit speziellen Mount Optionen auszustatten, um die Zuverlässigkeit eines Filesystems mit dem schnellen und direkten Datenzugriff zu kombinieren.
Direct IO kann pro File benutzt werden (dabei muß das File im open() Systemcall mit einem entsprechenden Flag geöffnet werden: O_DIRECT).
In der Regel wird jedoch das ganze Filesystem mit der mount-Option dio (mount -o dio mein_FS) gemountet. Dann wird auf alle Files im Filesystem direkt zugegriffen.
Eine dritte Möglichkeit ist, die Files, auf die direkt zugegriffen
werden soll, in ein eigenes Verzeichnis zu legen (alle_dio_files)
und dieses dann
mit dem Kommando namefs zu mounten:
mount -v namefs -o dio /mein_fs/alle_dio_files/mein_fs
Für den User ist das transparent.
Ist diese Mount-Option gesetzt, so ändert sich die Art, wie der Kernel mit einer Lese- oder Schreib-Anforderung umgeht. Im Normalfall prüft der Kernel zuerst den Puffer, bevor er auf die Platte zugreift. Ist die "dio" mount-Option gesetzt, so löst der Kernel für das betreffende Filesystem sofort Operationen auf der Platte aus. Es wird also kein Puffer aufgebaut, und Daten werden auch nur einmal kopiert (von der Platte in den Speicherbereich des Programmes).
Das ist sehr nachteilhaft bei vielen kleinen Files, aber von großem Vorteil bei großen Datenbankfiles, die Alternativ auf Raw Devices gelegt würden. Hier serialisiert die Datenbank die Lese- und Schreiboperationen, sodaß die Mechanismen des Filesystems für doppelten Aufwand sorgen.
Concurrent IO kann pro File benutzt werden (dabei muß das File im open() Systemcall mit einem entsprechenden Flag geöffnet werden: O_CIO).
In der Regel wird jedoch das ganze Filesystem mit der mount-Option cio (mount -o cio mein_FS) gemountet. Dann wird auf alle Files im Filesystem direkt zugegriffen.
Eine dritte Möglichkeit ist, die Files, auf die direkt zugegriffen
werden soll, in ein eigenes Verzeichnis zu legen (alle_cio_files)
und dieses dann
mit dem Kommando namefs zu mounten:
mount -v namefs -o cio /mein_fs/alle_cio_files/mein_fs
Für den User ist das transparent.
Die Benutzung des Concurrent IO beinhaltet implizit auch Direct IO. So wird zusätzlich zum File Cache Mechanismus auch noch die Sperrung der Inodes der Files im Filesystem eingeschränkt. Dabei wird das Lock sowohl für Lesen wie auch für Schreiben als "read-shared" angelegt - es kann also parallel an einem File geschrieben werden. Die Applikation sorgt dabei für die Konsistenz der Daten.
Ein spezieller Fall sind die Operationen, die das File vergrößern oder verkleinern, also in der Inode die Verteilung des Files auf die Blöcke der Platte modifizieren. Dann kann der zugreifende Prozess das Lock in den "write-exclusive" Modus abheben, andere Prozesse müßen dann warten. Nach erfolgtem Schreibvorgang wird das Lock wieder losgelassen, es ist für keinen Prozess nötig, das File neu zu öffnen.
Setzen tut man diese Parameter per smitty chfs, direkt mit dem chfs-Kommando oder gleich durch editieren der /etc/filesystems. Das ist auch der einzige Ort, wo es definiert wird - in der ODM steht der Parameter nicht. Wichtig ist, dass der Parameter erst nach einem erneuten Mount angezogen wird.
Hier ein kleines Beispiel für den cio Parameter:
/etc/filesystems: /ORACLE/TRGR/ext: account = false dev = /dev/o_rgrext_lv log = INLINE mount = true options = cio,rw type = oracle vfs = jfs2 Ausgabe des mount-Kommandos: 0:root:/ # mount |grep TRGR/ext /dev/o_rgrext_lv /ORACLE/TRGR/ext jfs2 Sep 04 11:43 rw,cio,log=INLINE
Beliebt sind diese Einstellungen für Datenbanken. Jetzt hat man das Problem, dass man in die mit diesen Parametern versehenen Filesystemen ab und an mal ein größeres Datenbank File legen möchte.
Wie oben ausgeführt, schalten diese Parameter alles aus, was ein Filesystem schnell und sicher macht - im Betrieb sorgt Orace dafür. Beim Hochladen eines Files geht das aber normal über das Filesystem, was aber nicht mehr richtig funktioniert.
In so einer Situation sollte man also das Filesystem normal mounten, und nach dem Upload mit den Parametern erneut mounten - sonst wartet man sehr, sehr lange.
[ Allgemein | UNIX | AIX | TCP-IP | TCP | ROUTING | DNS | NTP | NFS | FreeBSD | Linux | RPi | SMTP | Tracing | GPS | LW ]
Copyright 2001-2021 by Orm Hager - Es gilt die GPL