SELFHTML

Konkurrierende Dateizugriffe - Locking unter PHP

Diese Seite ist ein Dokument mit Informationstext

nach unten Der Autor

nach unten Erforderliche Grundlagen für diesen Artikel
nach unten Wozu überhaupt Dateien?
nach unten Dateien öffen und schließen
nach unten Dateien gemeinsam benutzen
nach unten Lockmodes
nach unten Mandatory Locking
nach unten Advisory Locking
nach unten Straight Forward Locking - Blocking Locks
nach unten Nonblocking Locks
nach unten Academic File Locking Strategie
nach unten Academic Record Locking Strategie
nach unten Deadlocks
nach unten Locking mit Hilfsdatei
nach unten Locking bei MySQL
nach unten Testprogramme
nach unten Glossar
nach unten Quellennachweis

Seitenende 

Thomas Schmieder

Bild vom Autor geboren im Jahr 1958 als typischer Wassermann: immer "optimistisch kritisch". Und Nomen est Omen trifft es bei ihm wohl auch: Thomas der Ungläubige will es immer genau wissen und fragt nach.

1979 Studium der Elektrotechnik, Fachbereich Nachrichtentechnik. Eines der liebsten Hobbies während der Schulzeit war die Entwicklung und der Bau von Heimtelefonanlagen, natürlich aus Relais. Erste Erfahrungen mit transistorisierten Computern an der "X1" 1974 mit Fortran und Algol 60. Danach kam eine Zeit der Verweigerung gegen alle Computer und erst 1984 kam dann der erste IBM XT mit 640kB RAM und Doppeldiskettenlaufwerk ins Haus. Über dbase kam er schnell zu den Personnel Databases und entwickelte unter dem Namen bitworks Softsystems Programme für die Fuhrparkverwaltung und für Hotelbuchungssysteme.

Als Gründungsmitglied der bitworks Seminargruppe baute er über 60 IT-Seminare auf und führte Tausende von Mitarbeiter von KMU, Forschungsanstalten, Behörden und Banken in Standardsoftware, Programmierung und die Nutzung des Internet ein. In der Ausbildung von Fachinformatikern half er als Trainer dutzenden von Berufspraktikanten zur erfolgreichen IHK-Prüfung zu gelangen

Seit 1999 hat er seine Leidenschaft für PHP entdeckt und entwickelt seitdem Internet-Dialog-Systeme und SAM-Designs für Client-Server-Applikationen.

Im Selfforum steht er gerne für alle Fragen der logistischen Planung von Datenbank-Dialog-Systemen und bei PHP-Fragen zur Verfügung.

E-Mail: E-Mail tom@bitworks.de
Homepage-URL: deutschsprachig http://selfhtml.bitworks.de/

Bei Fragen zu diesem Beitrag bitte den Autor des Beitrags kontaktieren!

nach obennach unten 

Jeder Feature-Artikel erhält sein eigenes Unterverzeichnis. Sie können also problemlos Grafiken und andere Dateien Ihrem Artikel hinzufügen. Wenn Sie CGI-Scripts installieren wollen, setzen Sie sich gegebenenfalls vorher mit der SELFHTML Redaktion in Verbindung.

In diesem Abschnitt gibt es noch ein paar Hinweise zum SELFHTML-gerechten Arbeitsstil in solchen Artikeln wie diesem. Löschen Sie den Inhalt dieses Unterabschnitts und überschreiben Sie ihn mit Ihren eigenen Inhalten.

Absätze werden stets in <p>...</p> eingeschlossen (schließendes </p> ist wichtig!). Quellcode im Fließtext wird in <code>...</code> eingeschlossen, Tastatureingaben in <kbd>...</kbd> und Namen von Dateien und URLs in <var>...</var>. Größere Quelltext-Beispiele kommen in einen eigenen Kasten. Das sieht so aus:

Beispiel:

Popup-Seite Anzeigebeispiel: So sieht's aus

<html>
<!-- irgendwas. Bitte auch hier alle HTML-eigenen Zeichen maskieren -->
</html>

Erläuterung:

Wenn zuvor ein Beispiel-Code in einem gelben Kasten steht, sollte es stets eine Erläuterung dazu geben. Was tut der Code? Auf welche Stellen im Beispiel sollte man besonders achten usw.

Auch Tabellen sollten ein einheitliches Outfit haben:

Beispiel Bedeutung
Code-Fragmente in gelben Zellen Erläuterungen und allgemeine Sachen in blauen Zellen
Code-Fragmente in gelben Zellen Erläuterungen und allgemeine Sachen in blauen Zellen
Code-Fragmente in gelben Zellen Erläuterungen und allgemeine Sachen in blauen Zellen

Natürlich kann die Tabelle auch mehr Spalten haben. Aber benutzen Sie dieses Grundgerüst.

Und zum Schluß noch ein paar Link-Beispiele (die Links funktionieren so nicht - aber bitte notieren Sie sie so, vor allem mit den relativen Pfadangaben zu Links innerhalb des SELF-Raums):

Ordner Link zu einem Kapitel auf SELFHTML aktuell

Seite Link zu einer Seite auf SELFHTML aktuell

Ordner Link zu einem Kapitel von SELFHTML

Seite Link zu einer Seite von SELFHTML

deutschsprachige Seite Link zu einer fremden, deutschsprachigen Seite

englischsprachige Seite Link zu einer fremden, englischsprachigen Seite

Wir würden uns freuen, wenn Sie einen code-basierten HTML-Editor verwenden. Denn SELFHTML ist pingelig, was sauberes Kodieren betrifft, viel pingeliger als die meisten Wysiwyg-Editoren jedenfalls ;-)

nach obennach unten 

Erforderliche Grundlagen für diesen Artikel

Dieser Artikel richtet sich an Fortgeschrittene.
Zum Verständnis der bechriebenen Techniken benötigen Sie einige Grundlagen:

nach obennach unten 

Wozu überhaupt Dateien?

Zum Speichern von Daten werden in der Infornationstechnik verschiedene Techniken verwendet. Die verschiedenen Hardware-Plattformen verwenden hier unterschiedliche Konzepte. Wir wollen uns in diesem Artikel mit der Thematik der Dateien auf DOS auseinandersetzen. "Halt" werden nun vielleicht einige rufen, was interessiert mich diese Museumstechnik, ich habe doch das neueste Linux oder Windows auf meiner Maschine.

Falsch: auch diese Systeme laufen nach dem DOS Konzept. Sie teilen Ihre Speichermedien in die transienten (RAM) und permanenten (hier Disk) Speicher ein, und sind damit klassische Disk Operating Systems. Dies ermöglicht uns eine einheitliche Aussage über die Techniken der Datenspeicherung und die Strategien für die gemeinsame Verwendung.

Alle Daten, die wir für eine Wiederverwendung konservieren wollen, werden aus dem Hauptspeicher unserer Maschine auf eine Festplatte (oder vergleichbare Medien) übertragen. Diese Aufgabe erledigt das Betriebssystem für das Anwendungsprogramm. Direkte Zugriffe eines Anwendungsprogramms auf die Hardware sind zwar möglich, kommen für uns aber nicht in Betracht. Die Betriebssysteme der betrachteten Systeme MAC und PC organisieren die Festplatten mittels eines Filesystems. Die üblichen Filesysteme teilen die Speichermedien dabei in Cluster ein und regeln die Zugriffe darauf. Allerdings gestatten sie dem Anwendungsprogramm nicht, direkt auf einen Cluster zuzugreifen. Sie stellen dafür in einem API unterschiedliche Interrupts zur Verfügung. Die von uns für die Programmerstellung eingesetzten Hochsprachen nutzen diese Systemroutinen (Interrupts) des Application Programmers Interface (API) zum Aufbau eigener Funktionen. Diese Funktionen stellen sie uns als Programmierern dann für die Verwendung zur Verfügung. Allgemein werden die Daten für die Konservierung in Dateien gespeichert. Die hier betrachteten Dateien bestehen aus einem oder mehreren organisierten Clustern. Sie haben einen Dateinamen, einen Anfang und eine unbestimmte Größe. Zur besseren Organisation werden sie in Directories (Verzeichnisse, Ordner) zusammengefasst.

Bei Zugriffen auf unsere gespeicherten Daten müssen wir also nur den Dateinamen und den Verzeichnisnamen wissen. Beide zusammen ergeben den qualifizierten Pfad zur Datei. Dieser wird noch durch den vorangestellten Datenträgernamen oder sein Äquivalent, den Gerätenamen ergänzt. Wir müssen also nicht wissen, wo die Daten genau auf der Festplatte gespeichert sind, oder welche Cluster in welcher Reihenfolge dazugehören. Das regeln die Filesysteme als Subsyteme der Betriebssysteme für uns.

Hauptspeicher und Dateien sollten wir uns wie einen "Bindfaden" vorstellen. Auf diesem Bindfaden sind die Daten nacheinander angeordnet. Jeder Datenplatz hat eine eindeutige Adresse. Es handelt sich also um lineare Speichersysteme

Die Organisation der Daten in Dateien hat den Vorteil, dass wir so sehr leicht zusammengehörige Daten in der richtigen Reihenfolge von einerm Platz zum anderen kopieren können. Das funktioniert dann sogar über das Internet. Das Quellsystem muss dabei nichts über das Betriebssystem oder die Festplatte des Zielsystmes wissen. Beide verwenden ihre eigene Organisation für die Speicherung der Daten.

Das ist einer der Gründe, wenn nicht sogar der wichtigste, für die Verwendung von Dateien.

nach obennach unten 

Dateien öffnen und schließen

Der Zugriff auf Dateien findet über den Namen statt. Für die praktische Umsetzung hat sich das Verfahren mittels File-Handle durchgesetzt. Es gibt auch noch ein älteres Verfahren mittels File Control Block (FCB). Dies wird uns aber nicht weiter interessieren.

Ein Handle ist im Prinzip nur ein Index in eine Tabelle. Diese Tabelle enthält dann die eigentlichen Informationen über die Datei. Warum aber nun nocheinmal am Rad gedreht, und den Namen der Datei gegen ein Handle getauscht? Ganz einfach: Um eine Datei innerhalb eines Programmes mehrfach öffnen zu können, benötigt man ohnehin ein Unterscheidungskriterium. Da bietet es sich an, den Dateinamen durch eine bestimmte Funktion der Hochsprache und des API gleich durch das Handle zu ersetzen. Außerdem ist ein Handle i.d.R. kürzer, als der qualifizierte Bezeichner der Datei, was einen angenehmen Nebeneffekt für den armen Programmierer darstellt.

Auf die Handletabelle haben wir als Hochsprachen-Programmierr keinen Zugriff. Allerdings wissen alle File-Funktionen der Hochsprache, wo diese Tablle zu finden ist und verwenden sie. Wir müssen den Funktionen nur das Handle übergeben, und diese regeln alles für uns. So kann auch kein Schritt vergessen werden und alle Zugriffe, die über das Betriebssystem auf die Dateien stattfinden, sind einheitlich. In Multithreading- und Multiusersystemen stehen die Informationen nicht direkt in der Handletabelle, die den Funktionen der Hochsprache zugänglich ist, sondern in einer zentralen Tabelle des Betriebssystems. Jede Programminstanz hat nun nochmals einen eigenen Auszug daraus. Die Handles der "privaten" Tabelle beginnen bei 1 und gehen heute üblicherweise bis 255. Das Handle 0 dient als Kennung für eine ungültige Ressource. Die "privaten" Handles verweisen auf die gemeinsamen des Betriebssystems. Die API Funktionen können so den Weg bis zu den eigentlichen Dateiinformationen verfolgen und diese auslesen oder setzen. Um ein Handle zu bekommen, benötigen wir also eine Funktion:

Beispiel:

Popup-Seite Anzeigebeispiel: So sieht's aus

<?php   ### get_handle.php ###

  ini_set('track_errors','1');        ## Fehlerbehandlung einschalten
  error_reporting(E_ALL);

  $dateiname = './textdatei.txt';     ## Dateinamen zuweisen
  $fh = fopen($dateiname,'r');        ## Dateihandle besorgen, Öffnungsmode 'lesen'
  echo "Das Dateihandle lautet: $fh"; ## Handle besorgen
  fclose($fh);                        ## Datei schließen, Handle freigeben

?>

Erläuterung:

Das Script hat den Auftrag, eine Datei, deren qualifizierter Bezeichner in $dateiname angegeben wird, zu öffen und zwar im Modus r. Das erhaltene Dateihandle wird dann mit Echo ausgegeben. Wenn die Funktion erfolgreich war, muss das Handle ungleich 0 sein. Anschließend wird versucht, die Datei wieder zu schließen. Sollte das Handle gleich 0 gewesen sein, könnten Fehlermeldungen ausgegeben werden. Für unsere weiteren Versuche wollen wir die Fehlermeldungen immer alle anzeigen lassen, wenn dies nicht ausdrücklich anders erwähnt wird.

Versuch:

Das Script hat nun einige Fehlermeldungen erzeugt. Die Meldung in der ersten Zeile ist die wichtigste: eine Warnung, dass die zu öffnende Datei nicht vorhanden ist. Da es sich nur um eine Warnung handelt, wird das Script nicht abgebrochen, sondern weiter ausgeführt. Die zweite Warnung ist daher eine Folge des ersten Fehlers. Das Script konnte die Datei zum Handle 0 nicht schließen, da das Handle ungültig ist. Bei gemeinsam genutzen Dateien dürfen solche Fehler aber nicht geduldet werden, da bei hunderten von Zugriffen auf eine Webseite sonst sehr schnell ein Datenchaos entsteht. Wir wollen uns daher in Zukunft auch immer um eine geigente Fehlerbehandlung bemühen.

Stellen wir also als erstes die Ursache für den Fehler ab.
Bitte legen Sie eine leere Datei mit dem Namen 'textdatei.txt' an und kopieren diese in das Scriptverzeichnis. Der Webserver benötigt auf dieses Verzeichnis Leserechte und damit unsere folgenden Versuche ebenfalls funktionieren erteilen Sie dem Webserver bitte auch Schreib- und Pfad-Rechte auf das Scriptverzeichnis sowie Schreibrechte auf die gemeinsam genutzten Dateien (hier: 'textdatei.txt')
Dann wiederholen Sie den ersten Versuch.

Popup-Seite Anzeigebeispiel: So sieht's aus

Erläuterung:

Diesmal hat das Script Erfolg gehabt. Die Datei konnte zum lesen geöffnete werden und das beschaffte Handle kann angezeigt werden. Durch die automatische Typerkennung ergänzt PHP den numerischen Wert des gültigen Handles automatisch um den Text 'Ressource id #'. Im ersten Versuchsschritt war der Wert false und wurde daher von echo $fh nicht angezeigt.

Modi für die Dateiöffnung:

Um später Fehler zu vermeiden, werden hier nochmals die Öffnungsmodi für Dateien beschrieben. Bitte Testen sie das Verhalten der anschließend aufgeführten Funktionen in Kombination mit den den Öffnungsmodi selbstständig durch.

Öffnungsmode Bedeutung erweiterter
Öffnungsmode
Bedeutung
a Anfügemodus. Eine vorhandene Datei wird zum Anfügen (Schreiben) von Daten geöffnet. Der Dateizeiger wird hinter dem Ende der Datei positioniert. Vorhandene Daten bleiben erhalten. Eine nicht vorhandene Datei wird mit dem gewünschten Namen angelegt. Dieser Modus war ursprünglich ausschließlich Textdateien vorbehalten. Unter C (und PHP) ist diese Restriction aber obsolet geworden. Allerdings sollte auf Windows das b-flag zusätzlich gesetzt werden. a+ Anfügemodus wie a. Zusätzlich: aus der Datei darf auch gelesen werden.
Warnung:
Bei Windows-Sytemen kann nur hinter dem Ende der Datei geschrieben werden, egal, welche Position der Dateizeiger zur Zeit inne hat.
r Lesemodus. Die Datei wird zum Lesen geöffnet. Der Dateizeiger wird auf das erste Byte der Datei positioniert. Die Zählung beginnt bei 0. Vorhandene Daten bleiben erhalten. Ist die Datei nicht vorhanden. wird ein Fehler ausgelöst. r+ Lese-/Schreibmodus wie r. Zusätzlich darf die Datei auch beschrieben werden. Je nach Position des Dateizeigers werden vorhandene Daten überschrieben. Stellt man den Dateizeiger hinter das Ende der Datei, kann man Datan anfügen.
w Schreibmodus. Eine vorhandene Datei wird gelöscht und neu angelegt. Da dies das vorgesehene Verhalten der Funktion ist, wird hierfür keine Fehlermeldung ausgelöst. Eine nicht vorhandene Datei wird mit dem gewünschten Namen angelegt. Der Dateizeiger wird auf den Anfang der Datei (Pos == 0) gestellt. Die Datei ist beschreibbar, aber nicht lesbar. w+ Schreib-/Lesemodus. wie w. Jedoch darf die Datei auch gelesen werden.
x
(ab PHP 4.3.2)
Anlege-Schreibmodus. Eine nicht vorhandene Datei wird mit dem gewünschten Namen neu angelegt. Eine vorhandene Datei wird nicht überschrieben. Ist die Datei schon vorhanden, wird mit dem Fehler file exists abgebrochen. Der Dateizeiger wird auf den Anfang der Datei (Pos == 0) gestellt. Die Datei ist beschreibbar, aber nicht lesbar. x+
(ab PHP 4.3.2)
Anlege-/Schreib-/Lesemodus. wie x. Jedoch darf die Datei auch gelesen werden.

Außerdem kann man alle Modi noch mit b kombinieren (Beispiel: wb+) für eine binäre Öffnung der Dateien. Dies dient der Kompatibilität der Systeme Es wird empfohlen, dieses Flag bei Windows immer zu verwenden.
PHP File-Funktionen Mehr Info zu den Öffnungsmodi

Die Öffnungsmodi haben nichts mit den Prozessrechten/Userrechten auf die Dateien zu tun. Die Datei- und Verzeichnisrechte aus dem Betriebssystem haben Vorrang. Bitte testen Sie einmal selbst, was passiert, wenn für eine Datei mittels chmod() die Rechte r--r--r-- eingestellt werden, und diese dann mit dem Mode w+ geöffnet wird.


Wichtige Dateifunktionen

Funktion Bedeutung
$fh = fopen($dateiname, $mode) Ein Handle für eine Datei beschaffen
$stream = fread($fh, $byteanzahl) Von der aktuellen Satzzeigerpostion aus $byteanzahl Bytes auslesen un in $streamübertragen. Gelesen wird die angeforderte Anzahl Bytes, aber maximal bis zum Dateiende.
$write_ok = fwrite($fh, $buffer, $byteanzahl) Die Anzahl $byteanzahl Bytes vom Beginn des $buffer in die Datei übertragen. Der Schreibvorgang beginnt an der aktuellen Position des Dateizeigers und endet, wenn die gewünschte Anzahl Daten übertragen wurde, oder ggf. vorher das Ende des Buffers erreicht wurde.
$close_ok = fclose($fh) Die angegebene Datei schliessen.
$seek_ok = fseek($sh, $pos, SEEKMODE) Den Dateizeiger auf die gewünschte Postion stellen
SEEKMODE muss durch SEEK_SET, SEEK_CUR oder SEEK_END ersetzt werden.
$pos = ftell($fh) Die Postition des Dateizeigers in der Datei erfragen
$eof = feof($fh) Feststellen, ob der Dateizeiger das Ende der Datei überschritten hat.
$trunc_ok = ftruncate($fh, $position) Datei an der angegebenen Position abschneiden oder sie mittels Hinzufügen von chr(0);nbsp;Zeichen auf die geforderte Länge ergänzen.

Ich bitte um Verständnis, dass ich hier nur die für den Artikel relavanten Funktionen kurz in Erinnerung rufe und nicht näher darauf eingehe. Die vollständige Dokumentation finden Sie unter PHP File-Funktionen PHP-Manual: Filefunktionen

nach obennach unten 

Dateien gemeinsam benutzen

Um Dateien gemeinsam benutzen zu können, müssen Programme bestimmte Regeln einhalten. Ohne diese Regeln

Wir müssen hier allerdings unterscheiden zwischen der Applikationsschicht, in der diese Aussagen zutreffen und der Filesystem-Schicht des Betriebssystems, in der bereits Regeln vereinbart sind und diese Aussagen deshalb so nicht zutreffen.

Erinnern wir uns aber nochmal an den Abschnitt "Warum Dateien?" und verdeutlichen uns einmal die Vorgänge in vereinfachter Form:

Dateien bestehen aus Clustern. Wenn auf Betriebssystemebene eine Leseanforderung an eine Datei kommt, wird von der Festplatte immer mindestens ein Cluster gelesen, auch wenn nur ein einziges Byte dieses Clusters benötigt wird. Der Cluster wird in einem Buffer zwischengespeichert. Aus dem Cluster werden die angeforderten Bytes an den Lesebuffer der Applikation übertragen. Wenn diese nun auch nur ein Byte verändern will, wird dieses mit der passenden Positionsangabe von der Applikation an das Betriebssystem übergeben. Das Filesystem liest den dazugehörigen Cluster wieder vollständig ein, tausch das Byte an der passenden Stelle aus und schreibt ihn komplett zurück auf die Festplatte. Durch Caching-Mechanismen in allen Schichten inclusive der Hardware wird dieser Vorgang noch um ein Mehrfaches komplexer. Eine genauere Betrachtung wollen wir uns hier ersparen, da wir ja Internet-Dialog-Applikationen erstellen wollen und keine Hard-Disk-Driver.

Was aber durch dieses Beispiel bereits deutlich wird ist, dass zwischen dem Holen der Daten und dem Wegschreiben der veränderten Daten Zeit vergeht. Innerhalb dieser Zeit könnte eine andere Applikation mit der Datei andere Dinge tun.

Die einzelnen Schreib- und Leseanforderungen in der Hardwareschicht sind gegeeinander abgegrenzt, sweit es sich um ein einzelnes Statement handelt. Das bedeuet, dass jeweils der gesamte Buffer der Applikationsschicht ungestört gefüllt oder weggeschrieben werden kann. Während dieser Zeit kann keine andere Applikation eine Anforderung an die Datei absetzen. Allerdings reicht ein Bufferinhalt oft nicht aus, und so muss man die Anforderungen zwangsweise in einer Schleife mehrmals ausführen. Während der Zeit vom Schliefenfuß zum Schleifenkopf vergeht aber schon wieder Zeit. Außerdem muss der Buffer erneut gefüllt oder ausgelesen werden. Auch dabei vergeht Zeit. Zwischen zwei Schreib- oder leseanforderungen en eine Datei uf der untersten Ebene vergeht also genug Zeit, dass eine ander Applikation zwischenschlüpfen kann.

Wir erkennen also, dass beim gemeinsamen Arbeiten mit Dateien viel Unerwünschtes passieren kann. Während der Eine noch seine 17 Cluster lesen lässt, beginnt der Andere bereits an einer anderen Stelle der Datei, 3 Cluster zu schreiben. Da Datensätze aber i.d.R. nicht vor Clustergrenzen halt machen, sondern meistens "irgenwie" über die Platte verteilt liegen, gibt es keine einzige Möglichkeit zu einem geordenten Miteinander. Man hat daher das Filesharing erfunden. Hierbei handelt es sich um einen Regelsatz, der sich entweder in die Betriebssystemfunktionen für die Dateizugriffe eingliedert (Mandatory Locking) oder parallel zu diesen Funktionen geführt wird (Advisory Locking).


nach obennach unten 

Lockmodi

Man unterscheidet bei den Lockingmethoden zwischen:

Die tatsächliche Umsetzung unterscheidet

Außerdem gibt es verschiedene logische Strategien:

Diese werden mit unterschiedlichen Lock Modi (Stufen) erreicht:

Außerdem gibt es für die Locking-Funktionen noch eine Unterscheidung im dynamischen (zeitlichen) Verhalten:

Blocking Modi

In verbindungsorientierten Programmen, also z.B. einer mehrnutzerfähigen Warenwirtschaft auf File-Server-Basis, ist es möglich, einen Datensatz für einen Benutzer (A) solange zu sperren, wie er daran arbeitet. Das nennt man dann pessimistic Locking. Niemand anders (B), als der Prozess dieses Users (A) darf dann Veränderungen an diesem Datensatz durchführen.

Sorgt man dafür, dass auch niemand anders (B) diesen Datensatz während der Bearbeitung durch den Prozess (A) lesen darf, spricht man von einem exclusive Lock.

Erlaubt man während der eigenen Bearbeitung eines Satzes anderen Benutzern zumindest das Lesen, spricht man auch von einem shared Lock oder auch Read Lock.

Da selbst Entwickler von Datenbanken, APIs oder Interpretersprachen die Trennung zwischen Hardwareschicht und Softwareschicht nicht realisieren, oder allergisch auf alle Techniken reagieren, die nicht Unix-Standard von 1970 sind, kommen dann auch mal solche Sätze wie:
flock() wird antiquierten Dateisystemen wie FAT und dessen Derivate nicht unterstützt, und gibt deshalb in solchen Umgebungen immer FALSE zurück (Dies ist speziell bei Windows 98 Benutzern der Fall).
zustande. Würden sich die Entwickler mit einer Portierung des Mandatory Locking in die Strategie des Advisory Locking intensiv beschäftigt haben, hätten sie eine Lösung gefunden. (Inzwischen haben sie, der Satz stand aber immer noch im Manual) Noch besser wäre es, wenn sie zusätzlich zur Methode des "antiquierten" und "hineingebastelten" Mandatory Lockings auch das Advisory Locking anbieten würden. In NOVELL sowie den neueren Unix-Derivaten, speziell in LINUX wird die Methode genauso wie in allen WinDOS Derivaten unterstützt. In PHP hat diese Methode unter der Funktionsgruppe dio_* Einzug gefunden ab Version 4.2.0.

Zumindest führt dieses häufig auf Unwissenheit oder Arroganz beruhende Verhalten von Entwicklern zu einer erheblichen Begriffsverwirrung. Hinzu kommt der Fakt, dass die Begriffe häufig von einer Schicht in die andere 1:1 durchgeschleppt werden, was eigentlich nicht zulässig ist.

Funktionsweise der Lock Modi

Modus Funktionsweise
  LOCK_SH
oder
  F_RDLCK
Lock_SH wird nur erteilt, wenn kein anderer Prozess ein Lock_EX auf das Handle besitzt
Lock_SH wird auch erteilt, wenn ein anderer Prozess ein Lock_SH auf das Handle besitzt
Lock_SH wird erteit, unabhängig von Locks des eigenen Prozesses auf das Handle
Der aktuelle Prozess hält anschließend das geteilte Recht auf dauerhaften Lesezugriff und die Unterbindung jeglicher höherer Lockingstufe eines anderen Prozesses
  LOCK_EX
oder
  F_WRLCK
Lock_EX wird nur erteilt, wenn kein anderer Prozess ein Lock_EX oder ein Lock_SH auf das Handle besitzt
Lock_EX wird erteit, unabhängig von Locks des eigenen Prozesses auf das Handle
Der aktuelle Prozess hält anschließend das ausschließliche Recht auf dauerhaften Lese- und Schreibzugriff und die Unterbindung jeglicher Lockingversuche eines anderen Prozesses
  LOCK_UN
oder
  F_UNLCK
Lock_UN wird grundsätzlich erteilt.
vohandene Lockingstufen des eigenen Prozesses werden aus der Lockingtabelle gelöscht.
+ LOCK_NB Lock_NB kann als Zusatzoption nur zusammen mit einem Lock_SH oder einem Lock_EX vergeben werden.
Die Locking-Funktion wird damit angewiesen, nur einen einzigen Lock-Versuch vorzunehmen und nicht zu warten, bis ein Locking erfolgreich war. Auf Betriebssystemschicht wird ein solcher Lockingversuch trotzdem typisch fünf Schleifendurchgänge des eigentlichen Lockvorgangs verursachen, um geringfügige Zeitüberschneidungen unterschiedlicher Prozesse abzufangen.

Alle Funktionen, die direkt über Namen arbeiten, und kein Handle zurückliefern, sind ohne weitere Maßnahmen nicht alleine für den konkurrierenden Betrieb geeignet. Hierzu gehören u.a.:

Für diese und für viele andere Funktionen muss eine besondere Strategie benutzt werden. Man sperrt entweder kurzzeitig das gesamte Verzeichnis, in dem man die Funktionen anwenden will, oder 'klammert' die Operation mit einem speziellen Lockfile (Dummy).


nach obennach unten 

Mandatory Locking

Mandatory Locking ist eine Methode der Zugriffskontrolle, die derartig im Kernel des Betriebssystems verankert ist, dass kein Prozess bei einem Open, Read oder Write auf die durch ein Handle definierte Datei vorbeikommt. Sie wird bereits gleichberechtigt mit einem Open initialisiert und kann dann parallel dazu zwischen verschiedenen Zuständen wechseln. Alle Zugriffe bestehender (älterer) Programme, die bisher keine Rücksicht auf die Methoden des Locking genommen haben, werden automatisch mit dem vom Betriebssystem vorbestimmten Lock Modus behandelt. Dieser ist bei DOS, NOVELL, und Windows bis 98SE "Exclusive" für den jeweils früheren Prozess, bei Windows NT, 2000 und folgenden "None". Bei Unix und Linux sind mir die Verhaltensweisen noch nicht als einheitlich bekannt. Bei Windows NT und folgenden sind bei Workstationversionen und parallelen Prozessen auf diesen zudem "Merkwürdigkeiten" zu beachten, die im lokalen Chaching begründet sind.

Hierbei muss man streng unterscheiden zwischen den allgemeinen im Filesystem oder Netzwerkbetriebssystem festgelegten Dateirechten, den eigenen beantragten und erteilten Rechten auf die Datei und den bei der Beantragung eines Handles oder später mittels diess Handles anderen Prozessen zugestandenen Rechten.

Funktion bei Linux aktivieren:

# /etc/fstab: static file system information.
#
# <file system> <mount point>   <type>  <options>               <dump>  <pass>
/dev/hda1       /               ext2    errors=remount-ro,mand  0       1
/dev/hda2       none            swap    sw                      0       0
proc            /proc           proc    defaults                0       0
/dev/fd0        /floppy         auto    user,noauto             0       0
/dev/cdrom      /cdrom          iso9660 ro,user,noauto          0       0    
      

Erläuterung:

Um bei Linux-System das Mandatory Locking nutzen zu können, muss das Dateisystem mit der Option -o mand mounted werden. Da man ein aktives Filesystem aber nicht einfach herunterfahren kann, bietet es sich an, die Option gleich in den Files System Table fstab einzufügen. Beim nächsten Reboot sollten die Funktionen dann zur Verfügung stehen.

Mandatory File Locking in PHP aktvieren

Die Mandatory File Funktionen stehen in PHP ab der Version 4.2.0 zur Verfügung PHP: direkte Ein-/Ausgabe  (PHP: dio_*)
PHP muss mit der Option --enable-dio compiliert worden sein.

Mandatory File Locking

Beim Mandatory File Locking werden bereits alle erforderlichen Einstellungen mit der Öffnungsanforderung der Datei aktiviert. Die Maßnahmen sind vom Betriebssystem derartig gekapselt, dass kein andere IO-Prozess 'dazwischenfunken' kann. Im PHP-Manual findet man die Besschreibung unter PHP: direkte Ein-/Ausgabe - FileOpen()  (PHP: dio_open)

Mandatory Record Locking

Auf Hardwareebene wird dieser Lock so realisiert, dass das Betriebssystem einen Lese- oder Schreibzugriff von Byteposition[Satzbeginn] bis Byteposition[Satzende] ablehnt und mit einem Fehler quittiert. Diese Sperrart ist also nur für Random Access Files sinnvoll, in denen die Daten(-sätze) immer mit festen Positionen korrelieren. Die Sprerren werden nach dem Öffnen der Datei mit dio_fopen durch die Funktion PHP: direkte Ein-/Ausgabe - FileControl()  (PHP: dio_fctl)


nach obennach unten 

Advisory Locking

Advisory Locking ist eine Methode, die im Betriebssystem für alle Prozesse gleichermaßen zugänglich der Methode des File Open untergeordnet ist. Sie steht aber eigenständig neben den vorhandenen Zugriffsmethoden auf Dateien und sollte von jedem Prozess freiwillig beachtet werden. Kein Prozess wird allerdings zur Beachtung gezwungen.

Laut PHP Manual wird das Advisory Locking auf Windows-Systemen nicht unterstützt, was an der fehlenden Portierung des vorhandenen Mandatory Locking auf diesen Systemen zum Mandatory Locking liegen dürfte. Die von mehreren Forumsmitgliedern durchgeführten eigenen Versuche mit dem Musterscript haben aber das Gegenteil ergeben. Nur mit dem gezielten Buffer-Flush gab es bei Windows Probleme.

Auch bei dieser Methode muss man streng unterscheiden zwischen den allgemeinen im Filesystem oder Netzwerkbetriebssystem festgelegten Dateirechten, den eigenen beantragten und erteilten Rechten auf die Datei und den bei der Beantragung eines Locks mittels vorhandenem Handle oder später mittels dieses Handles anderen Prozessen zugestandenen Rechten.


nach obennach unten 

Straight Forward Locking - Blocking Locks

PHP bietet mit der Funktion deutschsprachige Seite flock() einen einfachen Weg, Dateien für die Dauer der Veränderung zu sperren. Es wird das advisory Locking verwendet. Das bedeutet, dass alle zugriffsberchtigten Prozesse freiwillig dieselben Lockingmechanismen beachten müssen. Das Verfahren ist im Prinzip folgendes:

  1. Handle auf Datei besorgen
  2. Dateisperre beantragen und warten bis sie erfolgreich ist
  3. Daten aus Datei holen
  4. Daten verändern
  5. Daten in Datei wegschreiben
  6. Datei schließen und Sperre aufheben

Gehen wir als erstes Szenario einmal davon aus, dass die Datei, die unsere Daten enthält, bereits existiert. In der Datei soll ein Array gespeichert werden, dass für jeden Aufrufer die IP und die Häufigkeit seines Aufrufes enthält.

Besucherzähler

<?php   ### count_visitors.php ###

ini_set('track_errors','1');        ## verdeckte Fehlermeldung aktivieren
                                    ## $php_errormsg wird nun gepflegt
$dateiname = 'visitors.dat';

$fh = fopen($dateiname,'r+');       ## Datei zum Lesen und Schreiben öffnen
if(!$fh)
{
  ## Fehlerbehandlung, wenn Dateiöffnung fehlgeschlagen ist.
  die('Es ist der Fehler 002 aufgetreten. Bitte informieren Sie den Operator'. 
      '<a href="mailto:webmaster@example.com?subject=Fehler 002 '.
      'beim Counter&amp;body='.php_errormsg.'">per eMail</a>');
}     

$lock_ok  = flock($fh,LOCK_EX);             ## Dateisperre beantragen.
$file_len = filesize($dateiname);           ## Dateigröße erfragen

if($file_len > 0)
{
  $datastream = fread($fh,$file_len);       ## vorhandene Daten lesen
  $_visitors  = unserialize($datastream);   ## Array wiederherstellen
  if ($_visitors === false)                 ## Fehler beim Umwandeln 
  {
    mail('webmaster@example.com','Fehler 105 beim Visitor-Zähler',date('Y-m-d H:i:s'));
    $_visitors = array();                   ## Array neu anlegen
  }
}
else ## es waren keine Daten da 
{
  $_visitors = array();                     ## Array neu anlegen
}

$_visitors[$_SERVER['REMOTE_ADRESS']]++;    ## Besucher zählen
$datastream = serialize($_visitors);        ## Array serialisieren 

$seek_ok  = fseek($fh,0,SEEK_SET);          ## Dateizeiger auf Anfang zurückstellen
                                            ## 0 = kein Fehler, (-1) = Fehler
$write_ok = fwrite($fh,$datastream);        ## Daten zurückschreiben
$trunc_ok = ftruncate($fh,strlen($datastream)); ## Datei trimmen auf neue Datenlänge
fclose($fk);                                ## Datei schließen und freigeben 

echo "<p>Sie wurden gezählt</p>;
?>

Erläuterung:

Um Fehlermeldungen auch still abfragen zu können, wird die Fehlerverfolgung eingeschaltet. Es wird die Zählerdatei zerstörungsfrei zum Lesen und anschließenden Schreiben geöffnet. Die Datei muss vorhanden sein, sonst wird ein Fehler ausgelöst. Ebenso, wenn die Datei für den Webserver nicht les- oder beschreibbar ist. Der Fehler wird hier dem User beispielhaft angezeigt sowie der eMailclient des Users aufgerufen.
Konnte die Datei zum Lesen und Schreiben geöffnet werden, wird sie exclusiv gesperrt . Ein exclusive Lock ist immer dann zwingend nötig, wenn vorhandene Daten verändert werden sollen und das Locking so einfach wie möglich bleiben soll. Dabei muss unbedingt der gesamte Lese- und Schreibvorgang durch die exclusive Sperre geschützt werden. Verwendet man nur ein shared Lock, könnte es passieren, dass mehrere Benutzer gleichzeitig Daten auslesen, um diese dann später in veränderter Form zurückzuschreiben. Das würde an einer Stelle Parallelität erzeugen, an der strengste Serialisierung der Prozesse notwendig ist. Die Voreinstellung für flock() ist die blockierende Sperranforderung. Das bedeutet, dass die Ausführung des Scriptes an dieser Stelle so lange 'angehalten' wird, bis die Sperranforderung erfolgreich war, oder aber die max_execution_time erreicht ist. Im Erfolgsfall wird das Script fortgeführt, im Misserfolgsfall abgebrochen und der exit_handler des Scriptes aufgerufen. Alle anderen Statements würden dann ignoriert werden.

War die Dateisperre erfolgreich, wird die Länge der Datei festgestellt. Die Funktion filesize() darf nur innerhalb des Schutzbereiches durch flock() benutzt werden, da anderenfalls noch eine Änderung der Dateigröße durch fremde Prozesse nach dem Abfragezeitpunkt möglich wäre. Ist die Datei leer, wird der Inhalt neu erstellt. Dies kommt im Prinzip nur ein einziges Mal direkt nach der Installation des Zählers und dem Anlegen der Datei vor. Entählt die Datei Daten, werden diese komplett ausgelesen und anschließend in ein Array decodiert. Wenn die Dekodierung scheitert, erhält der Webmaster still eine Warn-Email und das Datenarray wird neu erzeugt. Im Array wird dann unter dem Index der IP des Besuchers die Zählung vorgenommen. Das Array wird wieder in einen Stream umgewandelt (serialisiert). Der Dateizeiger steht vom Holen der Daten noch am Ende der Datei. Deshalb wird er nun auf den Dateianfang zurückgesetzt. Anschließend werden die geänderten Daten weggeschrieben. Da zu einer sauberen Programmierung auch gehört, dass man vorhersehbare Fehler vermeidet, wird die Datei noch auf die neue zulässige Länge gekürzt bevor sie dann geschlossen wird. Die Funktion ftruncate() stellt hier diese Kürzung sicher. Der Dateizeiger muss dafür innerhalb des Dateibereiches, also maximal hinter dem letzten Byte der Datei stehen. Das ist durch den vorangegangenen Schreibprozess vom Dateianfang ausgehend auf jeden Fall gewährleistet. Wenn sichergestellt ist, dass die Länge der Datei immer nur wachsen kann, kann man auf das ftruncate() auch verzichten. Durch das fclose() wird die Datei geschlossen und auch die Dateisperre automatisch wieder freigegeben.

Der Nachteil dieses Lockingverfahrens liegt darin, dass der Webserver für die Dauer des Lockversuches das Script 'anhält' und der User solange warten muss. Bei größeren Datenmengen und/oder Bearbeitungszeiten führt das zu unerwünschten Wartezeiten am Client. Die Wartezeit stellt allerdings für den Prozessor nahezu keine Last dar, da die interne Idle-Funktion die Wartezeit den übrigen Prozessen zur Verfügung stellt. In ungünstigen Fällen kann das aber für den einzelnen Benutzer schon mal 30 Sekunden Wartezeit bis zur Fehlermeldung bedeuten.


nach obennach unten 

Nonblocking Locks

Einen nicht wartenden Lock oder auch non blocking Lock schauen wir uns beispielhaft für das Holen und Anzeigen der aktuellen Zugriffsdaten an. Hier sollen ausschließlich Daten angezeigt und nicht verändert werden. Daher ist ein shared lock ausreichend.
Das Verfahren ist im Prinzip folgendes:

  1. Handle auf Datei besorgen
  2. Dateisperre beantragen und prüfen, ob sie erfolgreich war
  3. Bei Erfolg:
    1. Daten aus Datei holen
    2. Datei schließen und entsperren
  4. Bei Misserfolg
    1. Datei schließen
    2. Mitteilung für den Benutzer bereitstellen
    3. Erneuten Versuch anbieten
<?php   ### show_visitors.php ###

error_reporting(E_ALL ^ E_NOTICE);   ## alle Fehler außer Systemwarnungen anzeigen 
#error_reporting(E_ALL);              ## alle Fehler anzeigen, nur zur Entwicklung
                                      ## passendes Statement aktivieren 
ini_set('track_errors','1');         ## verdeckte Fehlermeldung aktivieren
                                     ## $php_errormsg wird nun gepflegt
$dateiname = 'visitors.dat';         ## Dateiname der Log-Datei

$error_no = 0;                       ## Merker für die Fehlerbearbeitung 
#---- Error Codes ----------------
#  0: kein Fehler aufgetreten
#---- Low Level Errors -----------
#  1:
#  2: File not Found
#  3: File already exists
#  4: Could not read file, no data
#  5: Could file not open
#  6: Could file not lock file
#  7:
#---- Data Errors ----------------
# 11: No valid data format

#------------------------------------------------------------------------------
# Datei im shared-Lock Modus zum Lesen öffnen

function readlock($lockfile_name,&$error_no)
{ 
  if ($error_no > 0) return false;
  
  for ($x=0; $x < 5; $x++)                       ## 5 Öffnungsversuche
  {
    if($lh = @fopen($lockfile_name,"rb")) break; ## oder bei Erfolg abbrechen
    usleep(8000);                                ## 8ms warten bis zum nächsten 
  }                                              ## Öffnungsversuch 

  if (!$lh)
  {
    $error_no = 5;                               ## konnte Datei nicht öffnen            
    return false;                                ## bei Misserfolg Funktionsende
  }
  
  # Lockversuch
  for ($x=0; $x<5; $x++)                         ## 5 Lockversuche
  {
    if (@flock($lh,LOCK_SH + LOCK_NB)) return $lh;
    usleep(8000);                                ## 8ms warten 
  }
  
  $error_no = 6;                                 ## konnte Datei nicht sperren
  @fclose($lh);
  return false;
}
#------------------------------------------------------------------------------
# Daten aus der Datei holen

function get_data($lockfile_name,&$error_no)
{
  if ($error_no > 0) return false;
  
  $fh = readlock($lockfile_name,$error_no);
  if ($error_no > 0) return false;
      
  $filedata = fread($fh,filesize($lockfile_name));
  if (!$filedata)
  {
    $error_no = 4;                        ## File enthält keine Daten    
    return false;
  }
  
  $_data = unserialize($filedata);
  if (!is_array($_data))
  {
    $error_no = 11;                       ## Dateiformat passt nicht
    return false;
  }
    
  fclose($fh);                            ## Datei schließen
  
  return $_data;                          ## Daten zurückliefern
}
#------------------------------------------------------------------------------
function make_out_table($_data)
{
  $out_table ="<table>\n";
  $out_table .= "  <tr bgcolor=\"#CCCCDD\">\n";
  $out_table .= "    <th align=\"right\">lfd. Nr</th>\n";  
  $out_table .= "    <th align=\"left\">IP-Nummer</th>\n";      
  $out_table .= "    <th align=\"right\">Besuche</th>\n";  
  $out_table .= "  </tr>\n";

  $_data=array_flip($_data);  ## Schlüssel und Wert vertauschen
  natsort($_data);            ## IPs sortieren lassen 
  $_data=array_flip($_data);  ## Schlüssel und Wert zurücktauschen, 
                              ## was bei zwei Spalten eigentlich überflüssig ist

  $_color = array('#AAFFEE','#AAEEFF');

  $count = 0;
  if(is_array($_data))
  {
    foreach ($_data as $ip => $visits)
    {
      $count++;
      $out_table .= "  <tr bgcolor=\"".$_color[$count%2]."\">\n";
      $out_table .= "    <td align=\"right\">$count</td>\n";
      $out_table .= "    <td>$ip</td>\n";
      $out_table .= "    <td align=\"right\">$visits</td>\n";
      $out_table .= "  </tr>\n";
    }
  }
  else
  {
    $out_table .= "  <tr bgcolor=\"".$_color[$count%2]."\">\n";
    $out_table .= "    <td align=\"right\"> </td>\n";
    $out_table .= "    <td>keine (weiteren) Daten</td>\n";
    $out_table .= "    <td align=\"right\"> </td>\n";
    $out_table .= "  </tr>\n";
  }
  $out_table .="</table>\n";

  return $out_table;
}

#------------------------------------------------------------------------------
# main - Berechnung der Ausgaben
#------------------------------------------------------------------------------

$_data = get_data($dateiname,$error_no);

switch ($error_no)
{
  case 0:  $out = make_out_table($_data);
           break;
  
  default: $out = "Es ist Fehler $error_no aufgetreten"; 
}

###############################################################################
# HTML output
###############################################################################
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<HTML>
<HEAD>
  <TITLE>Besucheranzeige</TITLE>
  <META NAME="Author" CONTENT="Thomas Schmieder">
  <META NAME="Keywords" CONTENT="Besucheranzeige">
</HEAD>

<BODY>
  <h3>Besucheranzeige</h3>
  <?php echo $out;?>

</BODY>
</HTML>

Erläuterung:

Scriptaufbau

Das Script gliedert sich in folgende Bereiche:

  1. allgemeine Variablendeklarationen
  2. Funktionsdefinitionen und -implementierungen
  3. Hauptprogramm (Verarbeitung)
  4. HTML-Ausgabe

Sperrfunktion

Es wird eine eigene Funktion readlock() für den lesenden Zugriff auf die Daten bereitgestellt. Die Funktion übernimmt den Pfad und Dateinamen der Datendatei sowie eine Fehlernummer. Durch die Voranstellung eines & vor der Variablen im Funktionskopf erhält die Funktion Zugriff auf die externe Variable $error_no, sodass sich eine Änderung dieser Variablen innerhalb der Funktion auch außerhalb auswirkt. Diese Aufrufart nennt man auch Call by Reference. das ermöglicht uns, mehr als einen 'Rückgabewert' zu produzieren.
Wenn noch kein Fehler aufgetreten ist, enthält diese Fehlernummer den Wert 0.
. Trat bereits vor dem Funktionsaufruf ein Fehler auf ($error_no > 0), bricht die Funktion sofort ab und gibt false zurück. Anderenfalls wird versucht, die angegebene Datei zu öffnen. Dieser Versuch wird bis zu fünf Mal in einer Schleife wiederholt. Ist der Öffnungsversuch bereits vor dem fünten Mal erfolgreich, wird die Schleife mit break; abgebrochen und mit dem nächsten Funktionsblock fortgefahren. Konnte die Datei nicht geöffnet werden, wird die error_no auf einen passenden Fehlerwert gesetzt und die Funktion mit dem Rückgabewert false verlassen.

Bei erfolgreicher Dateiöffnung wird versucht, die Datei zu sperren. Die Codes für den Lockmode und das Sperrverhalten müssen mit OR verknüpft werden. Da es sich um Bitflags handelt, die keine gemeinsamen Bits haben, hat eine Addition hier dasselbe Ergebnis.
War der Lockversuch innerhalb fünf Versuchen erfolgreich, wird die Funktion mit dem Rückgabewert des gültigen File Handles verlassen. Der Fehlercode verbliebt bei 0.
Konnte keine Sperre durchgeführt werden, wird die Fehlernummer auf einen passenden Wert gesetzt, die Datei geschlossen und die Funktion mit dem Rückgabewert false verlassen.

Holfunktion

Die Funktion get_data() öffnet mittels readlock() eine Datendatei, holt aus der Datei alle Daten und wandelt sie in ein Array um. Auch diese Funktion beachtet und pflegt den als Referenz übergebenen Fehlerwert error_nr.

Ausgabefunktion

make_out_table() erzeugt aus dem übergebenen Datenarray einen HTML-String, der eine vollständige Tabelle enthält und gibt diesen String zurück.

Hauptprogramm (Steuerfluss)

Die Sektion 'Hauptprogramm' enthält den Steuerfluss des Scriptes. Mit der Funktion get_data() werden die Daten ausgelesen. Nach Auswertung des Fehlerwertes eroor_no wird die Ausgabe berechnet.

HTML-Ausgabe

In der HTML-Ausgabe finden keinerlei Berechnungen oder Entscheidungen mehr statt. Alle Ausgaben sind bereits berechnet. Es wird immer eine valide HTML-Seite nach deutschsprachige Seite W3C ausgegeben.


nach obennach unten 

Academic File Locking Strategie

Änderungen am Datenbestand, die auf dem Server automatisch vorgenommen werden, können i.d.R. so schnell abgewickelt werden, dass der Lese- und Schreibvorgang innerhalb eines Requests in einem exclusive lock zusammengefasst werden können. Wenn aber ein Benutzer Daten verändern will, geht das nicht mehr. Der Vorgang sieht dann vereinfacht folgendermaßen aus:

  1. Request:
  2. Response:
  3. Request:
  4. Response:

nach obennach unten 

Academic Record Locking Strategie

In vielbesuchten Seiten ist es meistens lästig, immer die ganze Datei zu sperren, da dies zu unerwünschten Verzögerungen führt. Ohnehin sind die meisten Zugriffe nur lesender Art. Da wird es reichen,

  1. Request:
  2. Response:
  3. Request:
  4. Response:
  5. Request:
  6. Response:

nach obennach unten 

Deadlocks

 


nach obennach unten 

Locking mit Hilfsdatei

 


nach obennach unten 

Locking bei MySQL

 


nach obennach unten 

Testprogramme

 


nach obennach unten 

Glossar

 


nach obennach unten 

Quellennachweis

SelfHTML 8.0
PHP Online-Manual
PHP Sources
PC intern 3.0/4.0, Tischer
Hardware Interrupts, Brown & Kyle
Netware Interrupts, Brown & Kyle
Linux Unix Systemprogrammierung, Helmut Herold

Besonderer Dank gilt vielen Mitgliedern des Selfhtml-Forums, die mich bereitwillig und qualifiziert unterstützt haben.
Es waren diverse Versuche auf verschiedenen Client- und Server-Systemen notwendig, um verbindliche Aussagen treffen zu können. Die Hinweise auf Abweichungen vom "Normalen" verdanke ich diesen vielfältigen Versuchen.


nach oben

© 2004 E-Mail stefan.muenz@selfhtml.org