In dieser praktischen Einführung haben sowohl der "Accountant" als auch der "Sales Manager" Aufgaben, welche die Tabellen "SalesOrder" und "SalesOrderItems" betreffen. Der "Accountant" muss die Beträge der Kommissionszahlungen überprüfen, die dem Verkaufspersonal für die im April 2001 durchgeführten Verkäufe zustehen. Der "Sales Manager" bemerkt, dass sich einige Aufträge nicht in der Datenbank befinden, und möchte diese hinzufügen.
Bei diesen Vorgängen wird gezeigt, wie Phantomsperren funktionieren. Eine Phantomsperre ist eine gemeinsame Sperre, die auf eine indizierte Suchposition gesetzt wird, um Phantomzeilen zu verhindern. Wenn eine Transaktion mit Isolationsstufe 3 Zeilen auswählt, die ein angegebenes Kriterium erfüllen, bringt der Datenbankserver Anti-Einfügesperren an, damit andere Transaktionen keine Zeilen einfügen können, die ebenfalls diesem Kriterium entsprechen. Die Anzahl der für Ihre Transaktion gesetzten Sperren hängt sowohl vom Suchkriterium als auch vom Aufbau der Datenbank ab.
Damit diese praktische Einführung funktioniert, darf die Option Datenbanksperren automatisch freigeben in Interactive SQL nicht aktiviert sein. Sie können die Einstellung dieser Option überprüfen, indem Sie auf Extras » Optionen klicken und anschließend im linken Fensterausschnitt auf SQL Anywhere.
Starten Sie zwei Instanzen von Interactive SQL. Siehe Schritte 1 bis 4 der praktischen Einführung in nicht wiederholbare Lesevorgänge. Siehe Praktische Einführung: Einführung in nicht-wiederholbare Lesevorgänge.
Setzen Sie die Isolationsstufe sowohl im Fenster des "Sales Managers" als auch im Fenster des "Accountants" auf 2, indem Sie die folgende Anweisung ausführen.
SET TEMPORARY OPTION isolation_level = 2; |
Die Handelsvertreter erhalten monatlich eine Provision, die als Prozentsatz der Umsätze für den jeweiligen Monat berechnet wird. Der "Accountant" bereitet die Provisionszahlungen für April 2001 vor. Seine erste Aufgabe besteht darin, den Gesamtumsatz jedes Vertreters für diesen Monat zu berechnen.
Führen Sie die folgende Anweisung im Fenster des "Accountants" aus: Die Preise, Bestellinformationen und Daten der Angestellten sind in getrennten Tabellen gespeichert. Verknüpfen Sie diese Tabellen unter Verwendung von Fremdschlüsselbeziehungen, um die notwendigen Teilinformationen zusammenzusetzen.
SELECT EmployeeID, GivenName, Surname, SUM( SalesOrderItems.Quantity * UnitPrice ) AS "April sales" FROM Employees KEY JOIN SalesOrders KEY JOIN SalesOrderItems KEY JOIN Products WHERE '2001-04-01' <= OrderDate AND OrderDate < '2001-05-01' GROUP BY EmployeeID, GivenName, Surname ORDER BY EmployeeID; |
EmployeeID | GivenName | Surname | April sales |
---|---|---|---|
129 | Philip | Chin | 2160.00 |
195 | Marc | Dill | 2568.00 |
299 | Rollin | Overbey | 5760.00 |
467 | James | Klobucher | 3228.00 |
... | ... | ... | ... |
Der "Sales Manager" bemerkt, dass ein großer Auftrag von Philip Chin nicht in die Datenbank eingegeben wurde. Philip will seine Provision immer pünktlich erhalten, also gibt der "Sales Manager" den fehlenden Auftrag ein, der am 25. April gebucht wurde.
Führen Sie im Fenster des "Sales Managers" die folgenden Anweisungen aus. Die Bestellung und die Elemente werden in getrennten Tabellen eingegeben, da eine Bestellung viele Elemente umfassen kann. Sie sollten zuerst den Eintrag für die Bestellung durchführen, bevor Sie Elemente hinzufügen. Um die referenzielle Integrität aufrechtzuerhalten, gestattet der Datenbankserver eine Transaktion, mit der Elemente einer Bestellung hinzufügt werden, nur dann, wenn diese Bestellung bereits vorhanden ist.
INSERT into SalesOrders VALUES ( 2653, 174, '2001-04-22', 'r1', 'Central', 129 ); INSERT into SalesOrderItems VALUES ( 2653, 1, 601, 100, '2001-04-25' ); COMMIT; |
Der "Accountant" kann nicht wissen, dass der "Sales Manager" gerade einen neuen Auftrag hinzugefügt hat. Wäre der neue Auftrag früher eingegeben worden, so wäre er in der Berechnung von Philip Chins Aprilumsätzen berücksichtigt.
Berechnen Sie im Fenster des "Accountants" noch einmal den Gesamtumsatz für den Monat April. Verwenden Sie die gleiche Anweisung. Es wird Ihnen auffallen, dass Philip Chins Aprilumsatz plötzlich $4560,00 beträgt.
EmployeeID | GivenName | Surname | April sales |
---|---|---|---|
129 | Philip | Chin | 4560.00 |
195 | Marc | Dill | 2568.00 |
299 | Rollin | Overbey | 5760.00 |
467 | James | Klobucher | 3228.00 |
... | ... | ... | ... |
Nehmen wir an, dass der "Accountant" alle im April gebuchten Aufträge markiert, um anzuzeigen, dass die Provision bezahlt wurde. Der vom "Sales Manager" gerade eingegebene Auftrag wird in der zweiten Suchabfrage gefunden und als bezahlt markiert, obwohl er nicht in Phillips Gesamtumsatz für den Monat April berücksichtigt wurde.
Bei Isolationsstufe 3 bringt der Datenbankserver Anti-Einfügesperren an, um zu gewährleisten, dass keine anderen Transaktionen eine Zeile hinzufügen können, die den Such- oder Auswahlkriterien entspricht.
Führen Sie im Fenster des "Sales Managers" die folgenden Befehle aus, um den neuen Auftrag zurückzunehmen:
DELETE FROM SalesOrderItems WHERE ID = 2653; DELETE FROM SalesOrders WHERE ID = 2653; COMMIT; |
Führen Sie im Fenster des "Accountants" die folgenden zwei Befehle aus:
ROLLBACK; SET TEMPORARY OPTION isolation_level = 3; |
Führen Sie im Fenster des "Accountants" dieselbe Abfrage wie vorhin aus.
SELECT EmployeeID, GivenName, Surname, SUM( SalesOrderItems.Quantity * UnitPrice ) AS "April sales" FROM Employees KEY JOIN SalesOrders KEY JOIN SalesOrderItems KEY JOIN Products WHERE '2001-04-01' <= OrderDate AND OrderDate < '2001-05-01' GROUP BY EmployeeID, GivenName, Surname; |
Da Sie die Isolationsstufe auf 3 gesetzt haben, bringt der Datenbankserver automatisch Anti-Einfügesperren an, die gewährleisten, dass der "Sales Manager" keine April-Aufträge eingeben kann, solange der "Accountant" seine Transaktion nicht beendet hat.
Kehren Sie zum "Sales Manager"-Fenster zurück. Versuchen Sie, Philip Chins fehlenden Auftrag einzugeben, indem Sie die folgende Anweisung ausführen.
INSERT INTO SalesOrders VALUES ( 2653, 174, '2001-04-22', 'r1','Central', 129 ); |
Das "Sales Manager"-Fenster reagiert nicht mehr und der Vorgang wird nicht abgeschlossen. Klicken Sie in der Symbolleiste auf Stopp (oder klicken Sie auf SQL » Stopp), um diesen Eintrag zu unterbrechen.
Der "Sales Manager" kann den Auftrag zwar nicht im April eingeben, aber der Eintrag im Mai sollte doch möglich sein.
Ändern Sie das Datum in der Anweisung auf den 05. Mai und versuchen Sie es noch einmal.
INSERT INTO SalesOrders VALUES ( 2653, 174, '2001-05-05', 'r1', 'Central', 129 ); |
Das "Sales Manager"-Fenster reagiert nicht mehr. Klicken Sie in der Symbolleiste auf Stopp (oder klicken Sie auf SQL » Stopp), um diesen Eintrag zu unterbrechen. Obwohl der Datenbankserver nicht mehr als die notwendigen Sperren zum Vermeiden von Einfügungen anbringt, haben diese Sperren das Potenzial, sich mit vielen Transaktionen zu überlagern.
Der Datenbankserver bringt Sperren in Tabellenindizes an. Er bringt zum Beispiel eine Phantomsperre in einem Index an, damit keine Zeile direkt davor eingefügt werden kann. Ist aber kein entsprechender Index vorhanden, so muss jede Zeile in der Tabelle gesperrt werden.
Es gibt Situationen, in denen Anti-Einfügesperren einige Einfügungen in einer Tabelle verhindern, andere aber erlauben.
Schließen Sie diese praktische Einführung ab, indem Sie alle Änderungen rückgängig machen, damit die SQL Anywhere-Beispieldatenbank nicht geändert wird. Führen Sie die folgende Anweisung im Fenster des "Sales Managers" aus:
ROLLBACK; |
Führen Sie die folgende Anweisung im Fenster des "Accountants" aus:
ROLLBACK; |
Fahren Sie beide Instanzen von Interactive SQL herunter.
![]() |
Kommentieren Sie diese Seite in DocCommentXchange.
|
Copyright © 2012, iAnywhere Solutions, Inc. - SQL Anywhere 12.0.1 |