Click here to view and discuss this page in DocCommentXchange. In the future, you will be sent there automatically.

SQL Anywhere 12.0.1 (Deutsch) » SQL Anywhere Server - SQL-Benutzerhandbuch » Transaktionen und Isolationsstufen » Praktische Einführung in Isolationsstufen

 

Praktische Einführung: Einführung in Dirty Reads

Die folgende praktische Einführung zeigt einen Typ von Inkonsistenz, der auftreten kann, wenn mehrere Transaktionen gleichzeitig ausgeführt werden. Zwei Angestellte einer kleinen Handelsfirma greifen gleichzeitig auf die Datenbank der Firma zu. Bei der ersten Person handelt es sich um den "Sales Manager"(Verkaufsleiter) der Firma. Die zweite Person ist der "Accountant"(Buchhalter).

Der "Sales Manager" möchte den Preis für ein von der Firma verkauftes T-Shirtmodell um $0.95 erhöhen, hat aber Schwierigkeiten mit der Syntax der SQL-Sprache. Was der "Sales Manager" nicht weiß, ist, dass der "Accountant" gleichzeitig versucht, den Einzelhandelswert des gegenwärtigen Inventars für einen Bericht zu berechnen, den er bei der nächsten Besprechung der Geschäftsleitung vorlegen möchte.

Tipp

Vor dem Ändern der Datenbank auf die im Folgenden dargestellte Weise, empfiehlt es sich, die Änderung durch die Verwendung von SELECT anstelle von UPDATE zu testen.

Hinweis

Damit diese praktische Einführung funktioniert, darf die Option Datenbanksperren automatisch freigeben in Interactive SQL (Extras » Optionen » SQL Anywhere) nicht aktiviert sein.

In diesem Beispiel spielen Sie die Rolle von zwei Mitarbeitern, die die SQL Anywhere-Beispieldatenbank gleichzeitig benutzen.

 Erstellen eines Dirty Read
  1. Starten Sie Interactive SQL.

  2. Im Fenster Verbinden stellen Sie als "Sales Manager" eine Verbindung mit der SQL Anywhere-Beispieldatenbank her.

    • Wählen Sie in der Dropdown-Liste Aktion die Option Mit ODBC-Datenquelle verbinden.

    • Klicken Sie auf ODBC-Datenquellenname und geben Sie im Feld darunter SQL Anywhere 12 Demo ein.

    • Klicken Sie auf Erweitert, um die Registerkarte Erweiterte Optionen einzublenden.

    • Klicken Sie auf die Registerkarte Erweiterte Optionen und geben Sie Sales Manager in das Feld ConnectionName ein.

    • Klicken Sie auf Verbinden.

  3. Starten Sie eine zweite Instanz von Interactive SQL.

  4. Im Fenster Verbinden stellen Sie als "Accountant" eine Verbindung mit der SQL Anywhere-Beispieldatenbank her.

    • Wählen Sie in der Dropdown-Liste Aktion die Option Mit ODBC-Datenquelle verbinden.

    • Klicken Sie auf ODBC-Datenquellenname und geben Sie im Feld darunter SQL Anywhere 12 Demo ein.

    • Klicken Sie, falls erforderlich, auf Erweitert, um die Registerkarte Erweiterte Optionen einzublenden.

    • Klicken Sie auf die Registerkarte Erweitert und geben Sie Accountant in das Feld ConnectionName ein.

    • Klicken Sie auf Verbinden.

  5. Erhöhen Sie als "Sales Manager" die Preise aller T-Shirts um $0.95:

    • Im Fenster Sales Manager führen Sie die folgenden Anweisungen aus:

      UPDATE Products
         SET UnitPrice = UnitPrice + 95
         WHERE Name = 'Tee Shirt';
      SELECT ID, Name, UnitPrice
         FROM Products;

    Das Ergebnis sieht folgendermaßen aus:

    ID Name UnitPrice
    300 Tee Shirt 104.00
    301 Tee Shirt 109.00
    302 Tee Shirt 109.00
    400 Baseball Cap 9.00
    ... ... ...

    Sie stellen sofort fest, dass Sie 0.95 statt 95 hätten eingeben sollen, aber bevor Sie Ihren Fehler korrigieren können, greift der "Accountant" von einem anderen Büro aus auf die Datenbank zu.

  6. Der "Accountant" der Firma ist besorgt, dass zuviel Geld im Lager steckt. Führen Sie als "Accountant" die folgende Anweisung aus, um den Gesamt-Einzelhandelswert des Lagerbestandes zu berechnen:

    SELECT SUM( Quantity * UnitPrice )
     AS Inventory
       FROM Products;

    Das Ergebnis sieht folgendermaßen aus:

    Inventory
    21453.00

    Leider ist diese Berechnung falsch. Der "Sales Manager" hat irrtümlich den Preis für die T-Shirts um $ 95 erhöht und das Ergebnis spiegelt diesen fehlerhaften Preis wider. Dieser Fehler zeigt eine typische Art von Inkonsistenz auf, die als Dirty Read bekannt ist. Sie haben als "Accountant" auf Daten zugegriffen, die der "Sales Manager" eingegeben, aber noch nicht festgeschrieben hat.

  7. Korrigieren Sie als "Sales Manager" Ihren Fehler, indem Sie die ersten Änderungen zurücksetzen und die richtige UPDATE-Anweisung eingeben. Überprüfen Sie, ob die neuen Werte auch richtig sind.

    ROLLBACK;
    UPDATE Products
    SET UnitPrice = UnitPrice + 0.95
    WHERE NAME = 'Tee Shirt';
         
    ID Name UnitPrice
    300 Tee Shirt 9.95
    301 Tee Shirt 14.95
    302 Tee Shirt 14.95
    400 Baseball Cap 9.00
    ... ... ...
  8. Der "Accountant" weiß nicht, dass der von ihm berechnete Betrag nicht stimmt. Sie können den richtigen Wert sehen, wenn Sie die SELECT-Anweisung im Fenster des Accountants nochmals ausführen.

    SELECT SUM( Quantity * UnitPrice )
     AS Inventory
       FROM Products;
    Inventory
    6687.15
  9. Beenden Sie die Transaktion im Sales Manager-Fenster. Der "Sales Manager" würde eine COMMIT-Anweisung eingeben, um die Änderungen festzuschreiben, aber Sie sollten stattdessen eine ROLLBACK-Anweisung ausführen, um zu vermeiden, dass die lokale Kopie der SQL Anywhere-Beispieldatenbank geändert wird.

    ROLLBACK;

    Der "Accountant" erhält unwissentlich fehlerhafte Informationen von der Datenbank, da der Datenbankserver sowohl die Arbeit des "Sales Managers", als auch die des "Accountants" gleichzeitig bearbeitet.

  10. (Optional) Stellen Sie den Originalzustand der Beispieldatenbank (demo.db) mit den Schritten unter Neuerstellung der Beispieldatenbank (demo.db) wieder her.

 Snapshot-Isolation zur Vermeidung von Dirty Reads verwenden

Wenn Sie die Snapshot-Isolation verwenden, erkennen andere Datenbankverbindungen in der Antwort auf ihre Abfragen nur festgeschriebene Daten. Durch Einstellen der Isolationsstufe auf statement-snapshot oder snapshot wird verhindert, dass Dirty Reads auftreten. Der "Accountant" kann die Snapshot-Isolation verwenden, um sicherzustellen, dass bei der Ausführung seiner Abfragen nur festgeschriebene Daten berücksichtigt werden.

  1. Starten Sie Interactive SQL.

  2. Im Fenster Verbinden stellen Sie als "Sales Manager" eine Verbindung mit der SQL Anywhere-Beispieldatenbank her.

    • Wählen Sie in der Dropdown-Liste Aktion die Option Mit ODBC-Datenquelle verbinden.

    • Klicken Sie auf ODBC-Datenquellenname und geben Sie im Feld darunter SQL Anywhere 12 Demo ein.

    • Klicken Sie, falls erforderlich, auf Erweitert, um die Registerkarte Erweiterte Optionen einzublenden.

    • Klicken Sie auf die Registerkarte Erweitert und geben Sie Sales Manager in das Feld ConnectionName ein.

    • Klicken Sie auf Verbinden.

  3. Führen Sie die folgende Anweisung aus, um die Snapshot-Isolation für die Datenbank zu aktivieren:

    SET OPTION PUBLIC.allow_snapshot_isolation = 'ON';
  4. Starten Sie eine zweite Instanz von Interactive SQL.

  5. Im Fenster Verbinden stellen Sie als "Accountant" eine Verbindung mit der SQL Anywhere-Beispieldatenbank her.

    • Wählen Sie in der Dropdown-Liste Aktion die Option Mit ODBC-Datenquelle verbinden.

    • Klicken Sie auf ODBC-Datenquellenname und geben Sie im Feld darunter SQL Anywhere 12 Demo ein.

    • Klicken Sie, falls erforderlich, auf Erweitert, um die Registerkarte Erweiterte Optionen einzublenden.

    • Klicken Sie auf die Registerkarte Erweitert und geben Sie Accountant in das Feld ConnectionName ein.

    • Klicken Sie auf Verbinden.

  6. Erhöhen Sie als "Sales Manager" die Preise aller T-Shirts um $0.95:

    • Führen Sie im Fenster des "Sales Managers" die folgende Anweisung aus:

      UPDATE Products
      SET UnitPrice = UnitPrice + 0.95
      WHERE Name = 'Tee Shirt';
    • Berechnen Sie den gesamten Einzelhandelswert des Lagerbestandes, indem Sie den neuen T-Shirt-Preis für den "Sales Manager" verwenden:

      SELECT SUM( Quantity * UnitPrice )
       AS Inventory
         FROM Products;

      Das Ergebnis sieht folgendermaßen aus:

      Inventory
      6687.15
  7. Führen Sie als "Accountant" die folgenden Anweisungen aus, um den gesamten Einzelhandelswert des Lagerbestandes zu berechnen: Da diese Transaktion die Snapshot-Isolationsstufe verwendet, wird das Ergebnis nur für die Daten berechnet, die in der Datenbank festgeschrieben wurden.

    SET OPTION isolation_level = 'Snapshot';
    SELECT SUM( Quantity * UnitPrice )
     AS Inventory
       FROM Products;

    Das Ergebnis sieht folgendermaßen aus:

    Inventory
    6538.00
  8. Schreiben Sie als "Sales Manager" Ihre Änderungen der Datenbank fest, indem Sie die folgende Anweisung ausführen:

    COMMIT;
  9. Führen Sie als "Accountant" die folgenden Anweisungen aus, um den aktualisierten Einzelhandelswert des aktuellen Lagerbestandes anzuzeigen:

    COMMIT;
    SELECT SUM( Quantity * UnitPrice )
     AS Inventory
       FROM Products;

    Das Ergebnis sieht folgendermaßen aus:

    Inventory
    6687.15

    Da der Snapshot für die Transaktion des "Accountant" mit dem ersten Lesevorgang begann, müssen Sie eine COMMIT-Anweisung ausführen, um die Transaktion zu beenden und es dem "Accountant" zu ermöglichen, die Änderungen zu sehen, die nach dem Beginn der Snapshot-Transaktion für die Daten durchgeführt wurden.

  10. Führen Sie als "Sales Manager" die folgende Anweisung aus, um die Änderungen des T-Shirt-Preises rückgängig zu machen und die SQL Anywhere-Beispieldatenbank wieder in ihren Originalzustand zu versetzen:

    UPDATE Products
    SET UnitPrice = UnitPrice - 0.95
    WHERE Name = 'Tee Shirt';
    COMMIT;
  11. (Optional) Stellen Sie den Originalzustand der Beispieldatenbank (demo.db) mit den Schritten unter Neuerstellung der Beispieldatenbank (demo.db) wieder her.

 Siehe auch