Das Problem der verlorenen Aktualisierung tritt auf, wenn zwei oder mehr Transaktionen dieselben Daten lesen und sie dann basierend auf ihren jeweiligen Lesevorgängen aktualisieren. Wenn die Transaktionen nicht ordnungsgemäß synchronisiert sind, können die Aktualisierungen einer Transaktion die Aktualisierungen eines anderen überschreiben, was zu verlorenen Daten führt. Hier sind mehrere Maßnahmen, die getroffen werden können, um dies zu verhindern:
1. Verriegelungsmechanismen:
* exklusive Sperren (Schreiben von Sperren): Wenn eine Transaktion eine Zeile aktualisieren möchte, erhält sie eine exklusive Sperre in dieser Zeile. Keine andere Transaktion kann in dieser Zeile jegliche Art von Sperre erwerben (gelesen oder schreiben), bis das exklusive Schloss veröffentlicht wird. Dies stellt sicher, dass nur eine Transaktion die Zeile zu einem bestimmten Zeitpunkt ändern kann.
* Shared Sperren (Lesesperrungen): Wenn eine Transaktion eine Zeile lesen möchte, erwirbt sie ein gemeinsames Schloss in dieser Zeile. Mehrere Transaktionen können freigegebene Sperren gleichzeitig in derselben Zeile halten. Es kann jedoch keine Transaktion ein exklusives Schloss erwerben, während in dieser Reihe gemeinsame Schlösser stattfinden. Dies hindert Autoren daran, die Leser zu stören.
* Granularität sperren: Die Ebene, auf der Sperren angewendet werden (z. B. Zeilenebene, Seitenebene, Tabellenebene, Datenbankebene), wirkt sich auf die Parallelität und Leistung aus. Feinkörnige Verriegelung (z. B. Zeilenebene) ermöglicht mehr Parallelität, weist jedoch einen höheren Overhead auf, während die Vergrößerung (z. B. Tabellenebene) den Overhead reduziert, aber die Parallelität einschränkt.
2. Parallelitätskontrollprotokolle:
* Zwei-Phasen-Sperrung (2PL): Ein Parallelitätskontrollprotokoll, das die Serialisierbarkeit garantiert (und somit verlorene Aktualisierungen verhindert). Es hat zwei Phasen:
* Wachstumsphase: Eine Transaktion kann Schlösser erwerben, kann sie jedoch nicht freigeben.
* Schrumpfungsphase: Eine Transaktion kann Schlösser veröffentlichen, kann aber keine neuen erwerben.
Strikte zweiphasige Verriegelung (Strict 2PL) hält alle exklusiven Schlösser bis zum Ende der Transaktion (Commit oder Rollback). Dies verhindert die Kaskadierung von Rollbacks (wobei ein Ausfall einer Transaktion den Rollback anderer erzwingen kann).
* Zeitstempelbestellung (bis): Jede Transaktion wird ein einzigartiger Zeitstempel zugewiesen. Das System nutzt diese Zeitstempel, um sicherzustellen, dass widersprüchliche Vorgänge in der Reihenfolge ihrer Zeitstempel ausgeführt werden. Wenn eine Transaktion versucht, einen Wert zu schreiben, der bereits durch eine Transaktion mit einem späteren Zeitstempel überschrieben wurde, wird das Schreiben abgelehnt und die Transaktion zurückgerollt. Dieser Ansatz vermeidet Deadlocks, kann aber zu Hunger führen.
* optimistische Parallelitätskontrolle (OCC): Transaktionen verlaufen ohne Erwerb von Schlösser. Bevor eine Transaktion beginnt, wird überprüft, ob eine andere Transaktion die gelesenen Daten geändert hat. Wenn es Konflikte gibt, wird die Transaktion zurückgerollt. OCC ist für Situationen mit geringer Streit geeignet, da Rollbacks kostspielig sein können. Es hat typischerweise drei Phasen:
* Phase lesen: Die Transaktion liest Daten und speichert sie in einem lokalen Arbeitsbereich.
* Validierungsphase: Das System prüft, ob eine der Daten, die die Transaktion gelesen hat, seit dem Lesen durch eine andere Transaktion geändert wurde.
* Schreibphase: Wenn die Validierung erfolgreich ist, werden die Änderungen auf die Datenbank angewendet. Andernfalls wird die Transaktion zurückgerollt.
3. Verwenden von Transaktionen:
* Säureeigenschaften: Verwenden Sie immer Transaktionen und stellen Sie sicher, dass Ihr Datenbanksystem die Säureeigenschaften (Atomizität, Konsistenz, Isolation, Haltbarkeit) durchsetzt. Die 'Isolation' -Eigenschaft ist entscheidend, um verlorene Aktualisierungen zu verhindern.
* Transaktions -Isolationsniveaus: SQL -Datenbanken bieten unterschiedliche Isolationsniveaus (z. B. Lesen Sie nicht gebrauchswerte, lesende, wiederholbare Lesen, serialisierbar). Höhere Isolationsniveaus (z. B. serialisierbar) bieten stärkere Garantien gegen Parallelitätsprobleme wie verlorene Aktualisierungen, können jedoch Parallelität und Leistung verringern. Wählen Sie sorgfältig die entsprechende Isolationsstufe für die Anforderungen Ihrer Anwendung. `Serialisierbar" ist das restriktivste und am sicherste, aber möglicherweise langsamste. "Read engagiert" ist ein häufiger Verzug und bietet einen angemessenen Schutz.
4. Logik der Anwendungsebene:
* Atomoperationen (Compare-and-Swap): Einige Datenbanksysteme und Programmiersprachen bieten atomare Operationen, mit denen LEAD-Modify-Write-Operationen in einem einzigen, unteilbaren Schritt durchgeführt werden können. Beispielsweise kann die Operation "Compare-and-Swap" (CAS) (CAS-SWAP "(CAS) einen Wert nur dann atomisch aktualisieren, wenn sein aktueller Wert mit einem angegebenen erwarteten Wert übereinstimmt. Dieser Ansatz kann in einigen Fällen die Notwendigkeit von expliziten Schlössern vermeiden.
* Aufzeichnungsversioning/Optimistisches Sperren in der Anwendung: Die Anwendung kann eine Versionsnummer (oder ein Zeitstempel) in die von ihr gelesenen Daten einbeziehen. Bei der Aktualisierung der Daten enthält die Anwendung die Originalversionsnummer. Die Datenbank aktualisiert dann nur die Zeile, wenn die Versionsnummer mit der aktuellen Versionsnummer in der Datenbank übereinstimmt. Wenn die Versionsnummern nicht übereinstimmen, wird das Update abgelehnt und die Anwendung muss das Update wiederholen. Dies ist eine weitere Implementierung der optimistischen Kontrollstrategie.
* Geschäftslogiküberlegungen: Überprüfen Sie die Geschäftslogik, um festzustellen, ob es Möglichkeiten gibt, Modify-Write-Operationen insgesamt zu vermeiden. Können Sie das Datenmodell oder den Prozess neu gestalten, um das Potenzial für verlorene Aktualisierungen zu vermeiden?
5. Datenbankdesign:
* Normalisierung: Eine ordnungsgemäß normalisierte Datenbank hilft bei der Reduzierung der Datenreduktion und der Verbesserung der Datenkonsistenz, die indirekt dazu beitragen kann, dass Probleme mit Parallelität behoben werden.
* Geeignete Datentypen: Die Verwendung geeigneter Datentypen für Ihre Daten kann dazu beitragen, Fehler zu verhindern und die Leistung zu verbessern, was indirekt dazu beitragen kann, dass Probleme mit Parallelität behoben werden.
Beispielszenario und Lösungen:
Stellen Sie sich zwei Benutzer vor, die versuchen, die Menge eines Produkts in einer Inventartabelle zu aktualisieren.
* Benutzer A: Liest die Menge (z. B. 10). Benutzer A möchte 2 verkaufen, berechnet also die neue Menge als 8.
* Benutzer B: Liest die Menge (z. B. 10). Benutzer B möchte 3 verkaufen, berechnet also die neue Menge als 7.
* Benutzer A: Schreibt die neue Menge (8) in die Datenbank.
* Benutzer B: Schreibt die neue Menge (7) in die Datenbank.
Die endgültige Menge in der Datenbank beträgt 7, sollte jedoch 5 (10 - 2 - 3) sein. Das Update von Benutzer A ging verloren.
Hier sind einige Lösungen für dieses Szenario:
* Exklusives Schloss: Wenn der beiden Benutzer die Menge für das Update liest, erwerben Sie eine exklusive Sperre in der Produktzeile. Der andere Benutzer muss warten, bis das Schloss vor dem Lesen und Aktualisieren veröffentlicht wird.
* serialisierbares Isolationsstufe: Setzen Sie die Transaktions -Isolationsstufe auf serialisierbar. Dies stellt sicher, dass die beiden Transaktionen effektiv serialisiert werden, was verhindert, dass sie sich gegenseitig beeinträchtigen.
* Optimistisches Sperren (mit Versionsnummer):
1. Wenn der Benutzer A die Menge (10) liest, lesen sie auch eine Versionsnummer (z. B. 1).
2. Benutzer A berechnet die neue Menge (8) und enthält die Originalversionsnummer (1) in die Aktualisierungsanweisung.
3. Die Datenbank aktualisiert die Menge nur, wenn die aktuelle Versionsnummer noch 1 ist. Die Aktualisierungsanweisung erhöht auch die Versionsnummer (z. B. bis 2).
V.
* Atomerkrement/Dekrementbetrieb: Verwenden Sie, falls verfügbar eine datenbankspezifische Atominkrement/Dekrement-Operation. Zum Beispiel:`Update Inventory Set Quantity =Quantity-2 wobei product_id =x` Dieser Ansatz vermeidet die Read-Modify-Write-Sequenz.
den richtigen Ansatz auswählen:
Der beste Ansatz, um verlorene Aktualisierungen zu verhindern, hängt von mehreren Faktoren ab, darunter:
* Parallelitätsebene: Wie häufig werden Updates an denselben Daten vorgenommen?
* Leistungsanforderungen: Was ist der akzeptable Overhead für die Parallelitätskontrolle?
* Datenbanksystemfunktionen: Welche Kontrollmechanismen der Parallelität werden von der Datenbank unterstützt?
* Anwendungskomplexität: Wie komplex ist die Anwendungslogik und wie einfach kann sie geändert werden?
Eine sorgfältige Berücksichtigung dieser Faktoren hilft Ihnen dabei, die effektivste Lösung für Ihre spezifische Situation zu wählen. Die Verwendung einer Kombination von Techniken ist häufig die effektivste Strategie. Beispielsweise unter Verwendung von Transaktionen mit einem geeigneten Isolationsniveau in Verbindung mit optimistischer Sperrung auf Anwendungsebene.