AK-Automatisierungs und Kommunikationstechnik – TI – Technische Informatik NWT – Netzwerktechnik – www.munz-udo.de Einführung Dieser Artikel behandelt das Sperren von Dateien in PHP, Perl, Python und Java. Das Sperren von Datenbanken folgt danach. Excell‐Sheets kann man im Netzwerk explizit sperren. Es werden hier zum einen die Grundlagen veranschaulicht und zum anderen konkrete Codebeispiele geliefert, mit deren Hilfe es möglich ist, Dateien auf korrekte Weise zu sperren. In Webanwendungen kommt es häufiger vor, dass auf Dateien zugegriffen werden muss ‐ sowohl lesend als auch schreibend. Hierbei treten allerdings Probleme auf: Wenn mehrere Prozesse gleichzeitig auf die Datei zugreifen, kann es zu Konflikten kommen, und in ungünstigen Fällen kann der Inhalt der Datei durcheinandergebracht oder gar komplett gelöscht werden. Natürlich finden Zugriffe auf die gleiche Datei nie exakt gleichzeitig statt (selbst auf Mehrprozessorsystemen nicht), aber wenn bestimmte Aktionen nicht atomar ablaufen, das heißt, wenn sie unterbrochen werden können und zwischenzeitlich eine andere Aktion bevorzugt wird, dann kommt es zu eben diesen Problemen. Folgendes Beispiel soll dies verdeutlichen: Gegeben sei ein einfaches Script, das eine Datei öffnet, eine Zahl, die in dieser Datei gespeichert ist, ausliest, den Dateiinhalt löscht und dann die Zahl um eins erhöht wieder hineinschreibt (also ein einfacher Zähler). Bricht man diese Aktionen in ihre Bestandteile herunter, für die heutige Betriebssysteme garantieren können, dass sie atomar ablaufen, d.h. nicht unterbrochen werden können, dann werden folgende Schritte durchgeführt: 1. 2. 3. 4. 5. Datei zum Lesen‐ und Schreiben öffnen Den Inhalt der Datei auslesen Den Dateiinhalt löschen (truncate) Die Zahl um 1 erhöht in die Datei schreiben (Die Datei schließen) Folgendes Szenario zeigt, wie bereits dieses einfache Script zum Stolpern gebracht werden kann. Vorraussetzung ist, dass zwei Besucher das Script fast zeitgleich aufrufen. Die Aktionen (da sie die gleiche Datei betreffen) werden zwar nie exakt zeitgleich ausgeführt, aber die Reihenfolge ist absolut zufällig. Im folgenden soll gezeigt werden, was im ungünstigsten Fall passieren kann (die beiden Scriptaufrufe sind jeweils andersfarbig hervorgehoben), der Zähler sei am Anfang z.B. 42: 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. Script 1 öffnet die Datei Script 1 liest den Inhalt der Datei aus, weiß, dass der Zähler 42 ist Script 2 öffnet die Datei Script 1 löscht den Inhalt der Datei Script 2 liest den Inhalt der Datei aus ‐ und stellt fest: sie ist leer, nimmt daher 0 an Script 1 schreibt 43 in die Datei Script 1 schließt die Datei Script 2 löscht den Inhalt der Datei Script 2 schreibt 1 in die Datei Script 2 schließt die Datei Wie dieses Beispiel zeigt, kann das fast gleichzeitige Ausführen von Scripten zu Probleme führen, die man auf einem Client‐System in der Regel nicht gewohnt ist. Man nennt diese Probleme auch race conditions. Der Ausweg aus D:\Dokumente und Einstellungen\Munz\Desktop\Technische Informatik\Datenbanken\Zugriff sperren.doc 1 AK-Automatisierungs und Kommunikationstechnik – TI – Technische Informatik NWT – Netzwerktechnik – www.munz-udo.de dieser Situation (im Dateifall) ist das Sperren von Dateien, auf Englisch file locking genannt. Damit kann verhindert werden, dass die Dateien von mehr als einem Programm gleichzeitig verwendet werden. Arten von Dateisperren Es gibt zwei Arten von Dateisperren: Verpflichtende Sperren (Mandatory Locking) Diese Dateisperren sind intuitiv am einfachsten zu begreifen: Sobald ein Programm die Datei sperrt, kann kein anderes Programm Änderungen an der Datei vornehmen, bis die Sperre wieder aufgehoben wurde (was implizit durch das Schließen der Datei oder das Beenden des Programms geschehen kann oder explizit durch das Programm selbst). Freiwillige (kooperative) Sperren (Advisory Locking) Bei freiwilligen Dateisperren werden die normalen Dateizugriffsfunktionen nicht beeinträchtigt, d.h. ein bösartiges Programm könnte problemlos die Datei überschreiben, während sie von einem anderen gesperrt ist. Allerdings soll kooperatives Sperren auch nicht vor derartigen Fällen schützen, sondern gutartigen Programmen helfen, sich nicht gegenseitig in die Quere zu kommen. Zudem sind selbst verpflichtende Sperren prinzipbedingt nicht vollkommen immun gegen bösartige Programme (die könnten das Programm, das die Datei sperrt, zum Beispiel auch gewaltsam beenden). Unterschiedliche Betriebssysteme implementieren Sperren unterschiedlich. Microsoft Windows implementiert ausschließlich verpflichtende Sperren. UNIX‐artige Betriebssysteme wie Linux, FreeBSD oder Mac OS X implementieren hauptsächlich freiwillige Sperren, während verpflichtende Sperren zumindest unter Linux wahlweise unterstützt werden, sofern sie über ein vergleichsweise aufwändiges Verfahren dateisystem‐ und dateiweise aktiviert werden. Im Folgenden wird davon ausgegangen, dass immer nur kooperative Sperren verwendet werden, denn wenn jedes Programm, das auf die Datei zugreifen will, die Dateisperrfunktionalität nutzt, gibt es keine effektiven Unterschiede zwischen kooperativen und verpflichtenden Sperren ‐ bei verpflichtenden Sperren werden zusätzlich jedoch Dateizugriffe von anderen Programmen untersagt, die diese Funktionalität nicht nutzen. Sperrstufen Ferner gibt es zwei verschiedene Stufen, eine Datei zu sperren: Exklusive Sperre (exclusive lock) Solange diese Sperre in Kraft ist, ist es nicht möglich, dass die Datei von einem anderen Programm gesperrt wird (egal in welcher Stufe). Mitbenutzbare Sperre (shared lock) Solange diese Sperre in Kraft ist, ist es nicht möglich, dass die Datei von einem anderen Programm exklusiv gesperrt wird, jedoch dürfen andere Programme die Datei problemlos mit einer weiteren mitbenutzbaren Sperre belegen. D:\Dokumente und Einstellungen\Munz\Desktop\Technische Informatik\Datenbanken\Zugriff sperren.doc 2 AK-Automatisierungs und Kommunikationstechnik – TI – Technische Informatik NWT – Netzwerktechnik – www.munz-udo.de Wenn ein Programm den Inhalt einer Datei lediglich auslesen will, dann ist eine mitbenutzbare Sperre das Mittel der Wahl. Denn für die Dauer des Lesevorgangs dürfen andere Programme die Datei natürlich weiterhin auslesen, der Schreibzugriff (bei dem eine exklusive Sperre verwendet würde) muss jedoch bis zum Ende des Lesevorgangs warten. Wenn ein Programm auf die Datei selbst schreiben will, dann ist eine exklusive Sperre das Mittel der Wahl, denn dann müssen alle anderen Zugriffe bis zum Ende des Schreibvorgangs warten. Allgemeines In diesem Abschnitt werden die Locking‐Mechanismen unter den verschiedenen Betriebssystemen näher erläutert. Dies sind Hintergrundinformationen, die für den praktischen Einsatz nicht unbedingt relevant sind, da viele Sprachen wie Java, PHP oder Perl Abstraktionsschichten anbieten, die es ermöglichen, Dateien zu sperren, ohne sich um die Eigenheiten des Betriebssystems Sorgen zu machen. Daher kann dieser Abschnitt auch gerne übersprungen werden. Dateisperren unter UNIX‐artigen Betriebssystemen Unter UNIX‐artigen Betriebssystemen wie Linux, FreeBSD oder Mac OS X sind Dateisperren im Normalfall immer kooperativ. Zudem gibt es aus historischen Gründen drei verschiedene Mechanismen, mit deren Hilfe eine Datei gesperrt werden kann. Hinzu kommt noch, dass die verschiedenen Spezifikationen nicht fordern, dass diese Mechanismen kompatibel zueinander sind ‐ was auf Grund der Freiwilligkeit dazu führt, dass man als Programmierer Sorge tragen muss, dass alle Programme den gleichen Mechanismus verwenden. Folgende Mechanismen stehen zur Auswahl, sie werden von allen oben genannten UNIX‐artigen Betriebssystemen unterstützt: flock(2) Dies ist der einfachste Sperrmechanismus. Er sperrt immer die vollständige Datei und unterstützt beide Sperrstufen (exklusiv und mitbenutzbar). Die Betriebssystemfunktion besitzt nur zwei Parameter: Den Dateideskriptor der geöffneten Datei, die gesperrt werden soll und die Operation (exklusiv sperren, mitbenutzbar sperren oder entsperren). fcntl(2) Dieser Mechanismus ermöglicht das Sperren von Dateibereichen anstelle von ganzen Dateien. Auch hier werden beide Sperrstufen unterstützt. Allerdings muss hierzu eine Struktur initialisiert werden, die dann die Sperreinstellungen (Sperrstufe sowie Position und Länge des zu sperrenden Bereichs) enthält. Die Funktion fcntl ist ferner eine allgemeine Systemfunktion zur Manipulation von Dateideskriptoren, das Setzen von Sperren ist nur eine Aufgabe, die mit ihrer Hilfe erledigt werden kann. Zudem besitzen Sperren, die durch fcntl(2) angelegt wurden, den Nachteil, dass alle Sperren auf eine Datei, die ein Prozess geöffnet hat, beim Schließen eines Dateideskriptors aufgehoben werden ‐ selbst wenn die Datei anderweitig vom selbstn Prozess noch geöffnet ist. lockf(3) Dies ist auch ein einfacher Sperrmechanismus, der nur exklusive Sperren untersützt, dafür jedoch auch Dateibereiche. Der Dateibereich fängt immer bei der aktuellen Position in der Datei an (an der auch gelesen/geschrieben werden würde), die Länge wird über einen Parameter übergeben. Auf den meisten D:\Dokumente und Einstellungen\Munz\Desktop\Technische Informatik\Datenbanken\Zugriff sperren.doc 3 AK-Automatisierungs und Kommunikationstechnik – TI – Technische Informatik NWT – Netzwerktechnik – www.munz-udo.de Betriebssystemen ruft diese Funktion intern nur fcntl auf, dies ist jedoch nicht im Standard vorgeschrieben, und man sollte sich nicht darauf verlassen, dass diese beiden Locking‐Mechanismen miteinander kompatibel sind. Verpflichtende Dateisperren unter Linux Um sogenanntes mandatory locking unter Linux zu aktivieren, muss man das Dateisystem mit der Option mand mounten (die man zum Beispiel in die /etc/fstab schreiben kann), und bei jeder Datei, die so gesperrt werden soll, muss das Set‐Group‐ID‐Bit in den Dateirechten gesetzt und das Group‐Executable‐Bit gelöscht sein, was man über chmod g‐x+s datei erreichen kann. In dem Fall sind alle Sperren, die über fcntl (nicht jedoch flock!) eingerichtet werden, verpflichtend anstelle von freiwillig. Allerdings schützt dies auf Grund der Dateizugriffssemantiken von Linux nicht vor dem Löschen der Datei selbst (und beispielsweise anschließendem Wiederanlegen). Dateisperren unter Microsoft Windows Dateisperren unter Microsoft Windos sind immer verpflichtend. Sobald eine Datei über die Windows‐API‐Funktion CreateFile geöffnet wurde, kann sie über die API‐Funktion LockFileEx gesperrt werden. Diese unterstützt sowohl exklusive als auch mitbenutzbare Sperren sowie auch Dateibereiche. Kooperative Sperren werden von Windows dagegen nicht unterstützt (auch wenn sie über bestimmte Tricks mit verpflichtenden Sperren simuliert werden können). Zu beachten ist, dass Dateisperren nur unter NT‐basierten Betriebssystemen (wie Windows NT, 2000, XP, 2003 oder Vista) mit NTFS als Dateisystem zuverlässig funktionieren. D:\Dokumente und Einstellungen\Munz\Desktop\Technische Informatik\Datenbanken\Zugriff sperren.doc 4 AK-Automatisierungs und Kommunikationstechnik – TI – Technische Informatik NWT – Netzwerktechnik – www.munz-udo.de Bei Datenbanken z.B. auch Access Ausdrückliche Sperren PostgreSQL bietet verschiedene Sperrmodi, um den gleichzeitigen Zugriff auf Tabellendaten zu kontrollieren. Diese Modi können verwendet werden, um Sperren von der Anwendung aus zu kontrollieren, wenn MVCC nicht das gewünschte Verhalten bietet. Die meisten PostgreSQL‐Befehle setzen auch automatisch die passenden Sperren, um sicherzustellen, dass die verwendeten Tabellen nicht entfernt oder auf nichtverträgliche Art verändert werden, während der Befehl ausgeführt wird. (Zum Beispiel kann ALTER TABLE nicht gleichzeitig mit irgendeiner anderen Operation an der gleichen Tabelle ausgeführt werden.) Tabellensperren Die unten folgende Liste zeigt die vorhandenen Sperrmodi und in welchen Zusammenhängen die Sperren von PostgreSQL automatisch gesetzt werden. Denken Sie daran, dass alle diese Sperren auf Tabellenebene wirken, selbst wenn der Name das Wort „row“ (Zeile) enthält; die Namen der Sperrmodi sind historisch bedingt. In gewisser Weise spiegeln die Namen die typischen Verwendungssituationen eines Sperrmodus wider, aber die Bedeutung ist bei allen Sperren die gleiche. Der einzige wirkliche Unterschied zwischen den Sperrmodi ist, mit welchen anderen Modi sie in Konflikt stehen. Zwei Transaktionen können nicht zur gleichen Zeit für die gleiche Tabelle Sperren innehaben, die in Konflikt zueinander stehen. (Eine Transaktion kann allerdings nie mit sich selbst in Konflikt stehen. Sie kann zum Beispiel eine ACCESS EXCLUSIVE Sperre setzen und später eine ACCESS SHARE Sperre für die selbe Tabelle.) Sperren, die nicht in Konflikt miteinander stehen, können von mehreren Transaktionen gleichzeitig gehalten werden. Beachten Sie auch besonders, dass einige Sperrmodi mit sich selbst in Konflikt stehen (zum Beispiel kann eine ACCESS EXCLUSIVE Sperre nicht von mehreren Transaktionen gleichzeitig gehalten werden), aber einige nicht (zum Beispiel kann eine ACCESS SHARE Sperre von mehreren Transaktionen gehalten werden). Wenn eine Sperre gesetzt wurde, dann bleibt sie bis zum Ende der Transaktion erhalten. Um zu überprüfen, welche Sperren gerade im Datenbankserver gehalten werden, können Sie die Systemsicht pg_locks verwenden. Weitere Informationen, wie Sie das Sperrensystem überwachen können, finden sich in Netz. Tabellensperrmodi ACCESS SHARE Steht nur in Konflikt mit dem Sperrmodus ACCESS EXCLUSIVE. Der Befehl SELECT setzt Sperren dieses Modus für alle verwendeten Tabellen. Generell setzt jede Anfrage, die eine nur Tabelle liest und nicht verändert, diesen Sperrmodus. ROW SHARE Steht in Konflikt mit den Sperrmodi EXCLUSIVE und ACCESS EXCLUSIVE. D:\Dokumente und Einstellungen\Munz\Desktop\Technische Informatik\Datenbanken\Zugriff sperren.doc 5 AK-Automatisierungs und Kommunikationstechnik – TI – Technische Informatik NWT – Netzwerktechnik – www.munz-udo.de Der Befehl SELECT FOR UPDATE setzt Sperren dieses Modus für die Zieltabelle(n) (zusätzlich zu ACCESS SHARE Sperren für alle anderen Tabellen, die verwendet werden, aber nicht in der FOR UPDATE‐Klausel stehen). ROW EXCLUSIVE Steht in Konflikt mit den Sperrmodi SHARE, SHARE ROW EXCLUSIVE, EXCLUSIVE und ACCESS EXCLUSIVE. Der Befehl UPDATE, DELETE und INSERT setzen Sperren dieses Modus für die Zieltabelle (zusätzlich zu ACCESS SHARE Sperren für alle anderen verwendeten Tabellen). Generell setzt jeder Befehl, der die Daten in einer Tabelle verändert, diesen Sperrmodus. SHARE UPDATE EXCLUSIVE Steht in Konflikt mit den Sperrmodi SHARE UPDATE EXCLUSIVE, SHARE, SHARE ROW EXCLUSIVE, EXCLUSIVE und ACCESS EXCLUSIVE. Dieser Modus schützt eine Tabelle gegen gleichzeitige Schemaveränderungen oder VACUUM‐Läufe. Automatisch von VACUUM (ohne FULL) gesetzt. SHARE Steht in Konflikt mit den Sperrmodi ROW EXCLUSIVE, SHARE UPDATE EXCLUSIVE, SHARE ROW EXCLUSIVE, EXCLUSIVE und ACCESS EXCLUSIVE. Dieser Modus schützt eine Tabelle gegen gleichzeitige Datenänderungen. Automatisch von CREATE INDEX gesetzt. SHARE ROW EXCLUSIVE Steht in Konflikt mit den Sperrmodi ROW EXCLUSIVE, SHARE UPDATE EXCLUSIVE, SHARE, SHARE ROW EXCLUSIVE, EXCLUSIVE und ACCESS EXCLUSIVE. Dieser Sperrmodus wird von keinem PostgreSQL‐Befehl automatisch verwendet. EXCLUSIVE Steht in Konflikt mit den Sperrmodi ROW SHARE, ROW EXCLUSIVE, SHARE UPDATE EXCLUSIVE, SHARE, SHARE ROW EXCLUSIVE, EXCLUSIVE und ACCESS EXCLUSIVE. Dieser Modus erlaubt nur eine gleichzeitige ACCESS SHARE Sperre, das heißt, gleichzeitig mit einer Transaktion, die diesen Sperrmodus hält, können nur Lesevorgänge in der Tabelle stattfinden. Dieser Sperrmodus wird von keinem PostgreSQL‐Befehl automatisch verwendet. ACCESS EXCLUSIVE D:\Dokumente und Einstellungen\Munz\Desktop\Technische Informatik\Datenbanken\Zugriff sperren.doc 6 AK-Automatisierungs und Kommunikationstechnik – TI – Technische Informatik NWT – Netzwerktechnik – www.munz-udo.de Steht in Konflikt mit allen Sperrmodi (ACCESS SHARE, ROW SHARE, ROW EXCLUSIVE, SHARE UPDATE EXCLUSIVE, SHARE, SHARE ROW EXCLUSIVE, EXCLUSIVE und ACCESS EXCLUSIVE). Dieser Modus garantiert, dass die Transaktion, die diese Sperre hält, die einzige Transaktion ist, die auf diese Tabelle auf irgendeine Art zugreift. Wird automatisch von den Befehlen ALTER TABLE, DROP TABLE und VACUUM FULL gesetzt. Dieser Modus wird auch vom Befehl LOCK TABLE verwendet, wenn kein anderer Sperrmodus ausdrücklich angegeben wurde. Tipp: Nur eine ACCESS EXCLUSIVE Sperre blockiert einen SELECT‐Befehl (ohne FOR UPDATE). Zeilensperren Neben Tabellensperren gibt es Zeilensperren. Eine Zeilensperre für eine bestimmte Zeile wird automatisch gesetzt, wenn die Zeile aktualisiert (oder gelöscht oder zur Aktualisierung markiert) wird. Der Sperre wird gehalten bis die Transaktion abgeschlossen oder zurückgerollt wird. Zeilensperren haben keine Auswirkungen auf das Anfragen von Daten; sie blockieren nur Schreibvorgänge in der selben Zeile. Um eine Zeilensperre zu setzen, ohne die Zeile wirklich zu verändern, wählen Sie die Zeile mit SELECT FOR UPDATE aus. Wenn eine bestimmte Zeilensperre gesetzt wurde, dann kann eine Transaktion eine Zeile mehrfach aktualisieren, ohne vor Konflikten Angst haben zu müssen. PostgreSQL speichert keine Informationen über veränderte Zeilen im Hauptspeicher und hat daher keine Höchstgrenze, wie viele Zeilen auf einmal gesperrt sein können. Das sperren einer Zeile kann allerdings Schreibvorgänge auf die Festplatte verursachen; ein SELECT FOR UPDATE verändert die ausgewählten Zeilen zum Beispiel, und dadurch muss auf die Festplatte geschrieben werden. Außer Tabellen‐ und Zeilensperren gibt es noch exklusive und nichtexklusive Sperren auf Speicherseitenebene, welche den Lese‐ und Schreibzugriff auf die Tabellenspeicherseiten im gemeinsamen Pufferpool kontrollieren. Diese Sperren werden sofort wieder aufgehoben, sobald eine Zeile gelesen oder aktualisiert wurde. Anwendungsentwickler müssen sich in der Regel nicht mit diesen Sperren befassen, aber wir erwähnen sie hier der Vollständigkeit halber. Verklemmungen (Deadlocks Î s.a. Betriebssystem Problem der speissenden Philosophen) Durch die Verwendung von expliziten Sperren können Verklemmungen (englisch deadlock) auftreten, wenn zwei (oder mehr) Transaktionen jeweils Sperren halten, die die anderen erlangen wollen. Zum Beispiel, wenn Transaktion 1 eine exklusive Sperre für Tabelle 1 setzt und danach versucht, eine exklusive Sperre für Tabelle B zu erlangen, während Transaktion 2 schon eine exklusive Sperre für Tabelle B hält und jetzt eine exklusive Sperre für Tabelle A möchte, dann kann keine der beiden Transaktionen fortfahren. PostgreSQL entdeckt Verklemmungen automatisch und löst sie, indem eine der verwickelten Transaktionen abgebrochen wird, wodurch die andere(n) fortfahren können. (Welche Transaktion genau abgebrochen wird ist schwer vorherzusagen und man sollte sich nicht darauf verlassen.) Die beste Vorsorge gegen Verklemmungen ist im Allgemeinen, dass man sie vermeidet, indem man darauf achtet, dass alle Anwendungen in einer Datenbank Sperren für mehrere Objekte in einer einheitlichen Reihenfolge anfordern. Außerdem sollte man sicherstellen, dass die erste Sperre, die für ein Objekt in einer Transaktion D:\Dokumente und Einstellungen\Munz\Desktop\Technische Informatik\Datenbanken\Zugriff sperren.doc 7 AK-Automatisierungs und Kommunikationstechnik – TI – Technische Informatik NWT – Netzwerktechnik – www.munz-udo.de angefordert wird, den höchsten Modus, den man für das Objekt benötigen wird, hat. Wenn es nicht praktikabel ist, dies vorher zu überprüfen, dann kann man Verklemmungen zur Laufzeit behandeln, indem man Transaktionen, die wegen Verklemmungen abgebrochen wurden, neu startet. Solange keine Verklemmung entdeckt wird, wird eine Transaktion, die eine Tabellen‐ oder Zeilensperre angefordert hat, endlos darauf warten, dass in Konflikt stehende Sperren aufgehoben werden. Das bedeutet, dass es keine gute Idee ist, Transaktionen über längere Zeiträume offen zu lassen (z.B. während man auf eine Eingabe des Anwenders wartet). LOCK Name LOCK ‐‐ sperrt eine Tabelle Synopsis LOCK [ TABLE ] name [, ...] [ IN sperrmodus MODE ] wobei sperrmodus Folgendes sein kann: ACCESS SHARE | ROW SHARE | ROW EXCLUSIVE | SHARE UPDATE EXCLUSIVE | SHARE | SHARE ROW EXCLUSIVE | EXCLUSIVE | ACCESS EXCLUSIVE Beschreibung LOCK TABLE setzt eine Sperre auf Tabellenebene und wartet wenn nötig, bis Sperren, die in Konflikt zu dieser stehen, aufgegeben werden. Wenn eine Sperre gesetzt wurde, dann bleibt sie bis zum Ende der aktuellen Transaktion erhalten. (Es gibt keinen Befehl UNLOCK TABLE; Sperren werden immer am Transaktionsende aufgegeben.) PostgreSQL setzt immer die am wenigsten restriktive Sperre, wenn ein Befehl eine verwendete Tabelle automatisch sperrt. LOCK TABLE ist für Fälle gedacht, in denen Sie restriktivere Sperren benötigen. Nehmen wir an, Sie wollen eine Transaktion im Isolationsgrad Read Committed ausführen und müssen sicherstellen, dass die Daten in einer Tabelle während der Transaktion stabil bleiben. Dazu könnten Sie für die Tabelle eine Sperre im Modus SHARE setzen, bevor Sie die Anfragen starten. Dadurch werden gleichzeitige Datenänderungen verhindert und den folgenden Lesevorgängen eine stabile Sicht auf die geschriebenen Daten ermöglicht, weil die Sperre im Modus SHARE mit der Sperre im Modus ROW EXCLUSIVE, welche von Lesevorgängen angefordert wird, in Konflikt steht und Ihr Befehl LOCK TABLE name IN SHARE MODE wartet, bis alle Halter einer Sperre des Modus ROW EXCLUSIVE abschließen oder zurückrollen. Wenn Sie also die Sperre erst einmal gesetzt haben, dann gibt es keine Transaktionen mehr, die eventuell noch zu schreibende Daten ausstehen haben; des Weiteren müssen neue Schreibvorgänge warten, bis die Sperre aufgegeben wird. Wenn Sie eine ähnliche Wirkung erzielen wollen und die Transaktion im Isolationsgrad Serializable ausführen, dann müssen Sie den Befehl LOCK TABLE vor allen Datenmodifikationsbefehlen ausführen. Die Datensicht einer D:\Dokumente und Einstellungen\Munz\Desktop\Technische Informatik\Datenbanken\Zugriff sperren.doc 8 AK-Automatisierungs und Kommunikationstechnik – TI – Technische Informatik NWT – Netzwerktechnik – www.munz-udo.de serialisierbaren Transaktion wird eingefroren, wenn der erste Datenmodifikationsbefehl ausgeführt wird. Ein später ausgeführtes LOCK TABLE verhindert trotzdem gleichzeitige Schreibvorgänge, aber es kann nicht versichern, dass die Daten, die von der Transaktion gelesen werden, auch die letzten gültigen Daten sind. Wenn eine Transaktion dieser Art die Daten in der Tabelle ändert möchte, dann sollte sie statt dem Modus SHARE den Modus SHARE ROW EXCLUSIVE verwenden. Damit erreicht man, dass nur eine Transaktion dieser Art zur gleichen Zeit laufen kann. Ohne diese Maßnahme ist eine Verklemmung möglich: Zwei Transaktionen könnten beide eine Sperre im Modus SHARE setzen und dann wäre es beiden nicht möglich eine Sperre im Modus ROW EXCLUSIVE zu erlangen, die sie für den Schreibvorgang benötigen. (Beachten Sie, dass die eigenen Sperren einer Transaktion niemals mit sich in Konflikt stehen. Also kann eine Transaktion eine ROW EXCLUSIVE‐Sperre setzen, wenn Sie schon eine SHARE‐Sperre hält ‐‐ aber nicht, wenn eine andere Transaktion eine SHARE‐Sperre hält.) Um Verklemmungen zu vermeiden, sollte Sie dafür sorgen, dass alle Transaktionen, die Sperren für die selben Objekte in der selben Reihenfolge anfordern, und dass, wenn mehrere Sperren für ein Objekt im Spiel sind, Transaktionen immer die Sperre im restriktivsten Modus zuerst setzen. Parameter name Der Name der zu sperrenden Tabelle (möglicherweise mit Schemaqualifikation). Ein Befehl der Form LOCK a, b; hat die gleiche Auswirkung wie LOCK a; LOCK b;. Die Tabellen werden einzeln in der Reihenfolge, wie sie im LOCK‐Befehl angegeben wurden, gesperrt. sperrmodus Der Sperrmodus gibt an, mit welchen Sperren diese Sperre in Konflikt steht. Wenn kein Sperrmodus angegeben ist, dann wird ACCESS EXCLUSIVE, der restriktivste Sperrmodus, verwendet. Meldungen LOCK TABLE Meldung, wenn die Sperre erfolgreich gesetzt wurde. Hinweise Für LOCK ... IN ACCESS SHARE MODE benötigt man das Privileg SELECT für die Zieltabelle. Für alle anderen Formen von LOCK benötigt man das Privileg UPDATE oder DELETE. LOCK ist nur in einem Transaktionsblock (BEGIN/COMMIT‐Paar) sinnvoll, weil die Sperre am Ende einer Transaktion aufgegeben wird. Wenn LOCK außerhalb eines Transaktionsblock aufgerufen wird, dann bildet es selbst eine Transaktion, also würde die Sperre sofort nach Ende des Befehls wieder aufgegeben werden. LOCK TABLE setzt nur Sperren auf Tabellenebene. Die Modusnamen, die ROW (Zeile) enthalten, sind unzutreffend. Diese Modusnamen sollten generell als Hinweis auf die Absicht des Benutzers verstanden werden, in der gesperrten D:\Dokumente und Einstellungen\Munz\Desktop\Technische Informatik\Datenbanken\Zugriff sperren.doc 9 AK-Automatisierungs und Kommunikationstechnik – TI – Technische Informatik NWT – Netzwerktechnik – www.munz-udo.de Tabelle Zeilensperren zu setzen. Außerdem ist der Modus ROW EXCLUSIVE keine exklusive sondern eine geteilte Sperre. Merken Sie sich, dass die Sperrmodi soweit es LOCK TABLE betrifft alle identische Bedeutungen haben und sich nur dadurch unterscheiden, mit welchen Sperrmodi sie in Konflikt stehen. Beispiele Dieses Beispiel verwendet eine Sperre im Modus SHARE für die Primärschlüsseltabelle, um die Fremdschlüsseltabelle sicher aktualisieren zu können: BEGIN WORK; LOCK TABLE filme IN SHARE MODE; SELECT id FROM filme WHERE name = 'Star Wars: Episode I ‐ Die dunkle Bedrohung'; ‐‐ Hier ROLLBACK, wenn kein Datensatz zurückgegeben wurde INSERT INTO filme_benutzerkommentare VALUES (_id_, 'Super! Habe lange genug darauf gewartet!'); COMMIT WORK; Dieses Beispiel setzt eine Sperre im Modus SHARE ROW EXCLUSIVE für die Primärschlüsseltabelle, während eine Löschoperation durchgeführt wird: BEGIN WORK; LOCK TABLE filme IN SHARE ROW EXCLUSIVE MODE; DELETE FROM filme_benutzerkommentare WHERE id IN (SELECT id FROM filme WHERE bewertung < 5); DELETE FROM filme WHERE bewertung < 5; COMMIT WORK; Kompatibilität Im SQL‐Standard gibt es keinen Befehl LOCK TABLE. Der SQL‐Standard bietet nur SET TRANSACTION um die Konsistenz im Mehrbenutzerbetrieb zu kontrollieren. PostgreSQL bietet diese Funktionalität ebenfalls; siehe SET TRANSACTION. Außer den Sperrmodi ACCESS SHARE, ACCESS EXCLUSIVE und SHARE UPDATE EXCLUSIVE sind die PostgreSQL‐ Sperrmodi und die Syntax des Befehls LOCK TABLE mit Oracle kompatibel. D:\Dokumente und Einstellungen\Munz\Desktop\Technische Informatik\Datenbanken\Zugriff sperren.doc 10