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 bestimmtes 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 Ihrer Datenbank ab.
Damit diese praktische Einführung funktioniert, darf die Option Datenbanksperren automatisch freigeben in Interactive SQL (Extras » Optionen » SQL Anywhere) nicht aktiviert sein.
Starten Sie zwei Instanzen von Interactive SQL. Siehe die Schritte 1 bis 4 unter Praktische Einführung: Nicht-wiederholbare Lesevorgänge
Stellen Sie die Isolationsstufe sowohl im Fenster des "Sales Managers" als auch in dem des "Accountant" auf 2, indem Sie den folgenden Befehl 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 den folgenden Befehl 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 Befehle 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 den gleichen Befehl. 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 nochmals, die fehlende Bestellung von Phillip Chin einzugeben.
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 SQL-Anweisung unterbrechen (oder wählen Sie 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 Befehlsdatum auf 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 SQL-Anweisung unterbrechen (oder wählen Sie 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 anderen 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.
Der "Sales Manager" möchte der Bestellung 2651 ein zweites Element hinzufügen. Verwenden Sie den folgenden Befehl.
INSERT INTO SalesOrderItems VALUES ( 2651, 2, 302, 4, '2001-05-22' ); |
Das "Sales Manager"-Fenster reagiert nicht mehr. Klicken Sie in der Symbolleiste auf SQL-Anweisung unterbrechen (oder wählen Sie SQL » Stopp), um diesen Eintrag zu unterbrechen.
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 den folgenden Befehl im Fenster des "Sales Managers" aus.
ROLLBACK; |
Geben Sie den gleichen Befehl im Accountant-Fenster ein.
ROLLBACK; |
Schließen Sie beide Fenster.
Kommentieren Sie diese Seite in DocCommentXchange. Senden Sie uns Feedback über diese Seite via E-Mail. |
Copyright © 2009, iAnywhere Solutions, Inc. - SQL Anywhere 11.0.1 |