Transaktionen und Isolationsstufen verwenden
Praktische Einführung in Isolationsstufen
Das Beispiel in der Praktische Einführung in Dirty Reads hat den ersten Typ von Inkonstistenz vorgeführt, nämlich Dirty Reads. In diesem Beispiel führte ein "Accountant" eine Berechnung aus, während der "Sales Manager" dabei war, einen Preis heraufzusetzen. Die Berechnung des "Accountants" beruhte auf fehlerhaften Daten, die der "Sales Manager" eingegeben hatte und gerade korrigieren wollte.
Das folgende Beispiel zeigt eine andere Art von Inkonsistenz: nicht-wiederholbare Lesevorgänge. In diesem Beispiel werden Sie die Rolle von zwei Personen spielen, die die Demonstrationsdatenbank gleichzeitig verwenden. Der "Sales Manager" möchte für Plastikschirmmützen einen neuen Preis anbieten. Der "Accountant" will die Preise für einige Waren auf einer kürzlich getätigten Bestellung überprüfen.
Dieses Beispiel beginnt mit beiden Verbindungen auf Isolationsstufe 1 und nicht auf Isolationsstufe 0, was die Standardisolation für die vom Adaptive Server Anywhere gelieferte Demonstrationsdatenbank wäre. Indem die Isolationsstufe auf 1 gesetzt wird, vermeiden Sie die Art von Inkonsistenz, die in der vorherigen praktischen Einführung aufgezeigt wurde, nämlich Dirty Reads.
Starten Sie Interactive SQL.
Verbinden Sie sich als "Sales Manager" mit der Beispieldatenbank.
Wählen Sie im Dialogfeld "Verbinden" die ODBC-Datenquelle ASA 9.0 Sample.
Geben Sie auf der Registerkarte "Erweitert" folgende Zeichenfolge ein, um die Identifikation des Fensters zu erleichtern:
ConnectionName=Sales Manager
Klicken Sie auf OK, um eine Verbindung herzustellen.
Starten Sie eine zweite Instanz von Interactive SQL.
Verbinden Sie sich als "Accountant" mit der Beispieldatenbank.
Wählen Sie im Dialogfeld "Verbinden" die ODBC-Datenquelle ASA 9.0 Sample.
Geben Sie auf der Registerkarte "Erweitert" folgende Zeichenfolge ein, um die Identifikation des Fensters zu erleichtern:
ConnectionName=Accountant
Klicken Sie auf OK, um eine Verbindung herzustellen.
Setzen Sie die Isolationsstufe für die Verbindung des "Accountants" auf 1, indem Sie den folgenden Befehl ausführen.
SET TEMPORARY OPTION ISOLATION_LEVEL = 1
Setzen Sie die Isolationsstufe im Fenster des "Sales Managers" auf 1, indem Sie den folgenden Befehl ausführen:
SET TEMPORARY OPTION ISOLATION_LEVEL = 1
Der "Accountant" beschließt, die Preise für die Schirmmützen aufzulisten. Führen Sie als "Accountant" folgenden Befehl aus:
SELECT id, name, unit_price FROM product
| id | name | unit_price |
|---|---|---|
| 300 | Tee Shirt | 9.00 |
| 301 | Tee Shirt | 14.00 |
| 302 | Tee Shirt | 14.00 |
| 400 | Baseball Cap | 9.00 |
| ... | ... | ... |
Der "Sales Manager" beschließt, für die Schirmmützen einen neuen Verkaufspreis festzusetzen. Führen Sie als "Sales Manager" folgenden Befehl aus:
SELECT id, name, unit_price FROM product WHERE name = 'Visor'; UPDATE product SET unit_price = 5.95 WHERE id = 501; COMMIT;
| id | name | unit_price |
|---|---|---|
| 500 | Visor | 7.00 |
| 501 | Visor | 5.95 |
Vergleichen Sie den Preis für die Schirmmützen (Visor) im Fenster des "Sales Managers" mit dem Preis für die gleichen Schirmmützen im Fenster des "Accountants". Im Fenster des "Accountants" erscheint noch immer der alte Preis, obwohl der "Sales Manager" den neuen Preis eingegeben und die Änderung festgeschrieben hat.
Diese Inkonsistenz wird nicht-wiederholbarer Lesevorgang genannt, da der "Accountant" bei einem zweiten Lesevorgang in der gleichen Transaktion nicht mehr dasselbe Ergebnis erhalten würde. Probieren Sie es. Führen Sie als "Accountant" erneut den SELECT-Befehl aus. Sie werden feststellen, dass der Verkaufspreis des "Sales Managers" jetzt wie folgt lautet:
SELECT id, name, price FROM product
| id | name | unit_price |
|---|---|---|
| 300 | Tee Shirt | 9.00 |
| 301 | Tee Shirt | 14.00 |
| 302 | Tee Shirt | 14.00 |
| 400 | Baseball Cap | 9.00 |
| ... | ... | ... |
Hätte der "Accountant" seine Transaktion mit einem COMMIT- oder ROLLBACK-Befehl beendet, bevor er wiederum den SELECT-Befehl angewendet hätte, wäre die ganze Sache anders verlaufen. Die Datenbank steht für die gleichzeitige Verwendung mehrerer Benutzer zur Verfügung, und es ist absolut zulässig, dass jemand die Werte vor oder nach der Transaktion des "Accountants" verändert. Die geänderten Ergebnisse sind nur deshalb inkonsistent, da die Änderungen während der Transaktion geschahen. Ein solches Ereignis macht das Schema unserialisierbar.
Der "Accountant" bemerkt dieses Verhalten und beschließt, dass er in Zukunft nicht mehr will, dass sich die Preise ändern, während er sie sich ansieht. Wiederholbare Lesevorgänge werden auf Isolationsstufe 2 eliminiert.Spielen Sie den "Accountant":
SET TEMPORARY OPTION ISOLATION_LEVEL = 2; SELECT id, name, unit_price FROM product
Der "Sales Manager" entscheidet, dass es besser ist, mit dem Abverkauf der Schirmmützen bis zur nächsten Woche zu warten, damit er den niedrigeren Preis nicht für eine große Bestellung, die er für den nächsten Tag erwartet, hergeben muss. Versuchen Sie, in seinem Fenster die folgenden Anweisungen auszuführen. Die Ausführung des Befehls beginnt, und plötzlich scheint sein Fenster einzufrieren.
UPDATE product SET unit_price = 7.00 WHERE id = 501
Der Datenbankserver muss wiederholbare Lesevorgänge bei Isolationsstufe 2 garantieren. Damit dies möglich ist, wird eine Lesesperre in jeder Zeile der Produkttabelle angebracht, die der "Accountant" liest. Wenn der "Sales Manager" versucht, den Preis zurückzuändern, muss seine Transaktion eine Schreibsperre für die Zeile mit den Schirmmützen in der Produkttabelle erwerben. Da Schreibsperren Exklusivsperren sind, muss seine Transaktion warten, bis die Transaktion des "Accountants" die Lesesperre freigibt.
Der "Accountant" ist mit der Durchsicht der Preise fertig. Er möchte nicht riskieren, die Datenbank zufällig zu ändern, also beendet er seine Transaktion mit einem ROLLBACK-Befehl.
ROLLBACK
Sie können feststellen, dass die Transaktion des "Sales Managers"abgeschlossen wird, sobald der Datenbankserver diesen Befehl ausgeführt hat.
| id | name | unit_price |
|---|---|---|
| 500 | Visor | 7.00 |
| 501 | Visor | 7.00 |
Der "Sales Manager" kann nun seine Transaktion abschließen. Der "Sales Manager" will seine Änderung festschreiben und den ursprünglichen Preis wiederherstellen.
COMMIT
Als Sie die Isolation des "Accountants" von Stufe 1 auf Stufe 2 erhöhten, verwendete der Datenbankserver Lesesperren, wo es vorher keine gab. Allgemein gilt, dass jede Isolationsstufe durch die benötigten Sperrentypen charakterisiert wird und wie Sperren behandelt werden, die von anderen Transaktionen kommen.
Bei Isolationsstufe 0 benötigt der Datenbankserver nur Schreibsperren. Er verwendet diese Sperren, um zu gewährleisten, dass nicht zwei Transaktionen einander widersprechende Änderungen durchführen. So erwirbt zum Beispiel eine Stufe-0-Transaktion eine Schreibsperre für eine Zeile, bevor sie sie aktualisiert oder löscht, und jede neue Zeile wird bereits mit einer angebrachten Schreibsperre eingefügt.
Stufe 0-Transaktionen führen keine Überprüfung der Zeilen durch, die sie lesen. Wenn zum Beispiel eine Stufe 0-Transaktion eine Zeile liest, überprüft sie nicht, welche Sperren von anderen Transaktionen für diese Zeile erworben wurden. Da keine Überprüfungen notwendig sind, sind Stufe 0-Transaktionen besonders schnell. Diese Geschwindigkeit geht auf Kosten der Konsistenz. Jedes Mal, wenn eine Zeile gelesen wird, für die es eine Schreibsperre durch eine andere Transaktion gibt, laufen Sie Gefahr, nicht festgeschriebene Daten zu erhalten.
Bei Stufe 1 überprüfen Transaktionen, ob Schreibsperren vorliegen, bevor sie eine Zeile lesen. Obwohl hierfür ein Arbeitsgang mehr notwendig ist, ist bei diesen Transaktionen sichergestellt, dass sie nur festgeschriebene Daten lesen. Wiederholen Sie die erste praktische Einführung, und zwar mit der Isolationsstufe 1, und nicht mit 0. Sie werden feststellen, dass der "Accountant" mit seiner Berechnung während der unvollständigen Transaktion des "Sales Managers", der die Preise der T-Shirts aktualisiert, nicht fortfahren kann.
Als der "Accountant" seine Isolation auf Stufe 2 erhöhte, begann der Datenbankserver, Lesesperren zu verwenden. Ab da erwarb er eine Lesesperre für seine Transaktion, und zwar für jede Zeile, die der "Accountant" auswählte.
In der obigen praktischen Einführung fror das Fenster des "Sales Managers" während der Ausführung des UPDATE-Befehls ein. Der Datenbankserver begann den Befehl auszuführen, als er feststellte, dass die Transaktion des "Accountants" eine Lesesperre für die Zeile erworben hat, die der "Sales Manager" ändern musste. An diesem Punkt setzte der Datenbankserver einfach mit der Ausführung der Aktualisierung aus. Sobald der "Accountant" seine Transaktion mit dem ROLLBACK-Befehl abgeschlossen hatte, gab der Datenbankserver seine Sperren automatisch frei. Da es keine weiteren Hindernisse mehr gab, schloss er die Ausführung des UPDATE-Befehls des "Sales Managers" ab.
Im Allgemeinen tritt ein Sperrenkonflikt auf, wenn eine Transaktion versucht, eine Exklusivsperre für eine Zeile zu erwerben, an der eine andere Transaktion eine Sperre hält, oder versucht, eine gemeinsame Sperre für eine Zeile zu erwerben, in der eine andere Transaktion eine Exklusivsperre hält. Eine Transaktion muss warten, bis eine andere Transaktion abgeschlossen ist. Die Transaktion, die warten muss, wird als blockierte Transaktion bezeichnet.
Wenn der Datenbankserver einen Sperrenkonflikt erkennt, der verhindert, dass eine Transaktion sofort abläuft, kann er entweder die Ausführung der Transaktion aussetzen, oder die Transaktion beenden, Änderungen zurücksetzen und einen Fehler zurückgeben. Sie kontrollieren die Route, indem Sie die BLOCKING-Option einstellen. Ist die BLOCKING-Option eingeschaltet, so wartet die zweite Transaktion wie in dem oben angeführten Beispiel.
Weitere Hinweise zu den Blockierungsoptionen finden Sie unter Die BLOCKING-Option.
SQL Anywhere Studio 9.0.1
Copyright © 1989–2004 Sybase Inc. Teil-Copyright © 2001–2004 iAnywhere Solutions Inc. Alle Rechte vorbehalten.