Verhindern Datenbank-Transaktionen Race Conditions?
Es ist mir nicht ganz klar, welche Transaktionen in Datenbank-Systemen tun. Ich weiß, Sie können verwendet werden, um ein rollback der Update-Liste komplett (z.B. abziehen von Geld auf ein Konto und fügen Sie es zu einem anderen), aber ist das alles, was Sie tun? Insbesondere können Sie verwendet werden, um zu verhindern, dass race conditions? Zum Beispiel:
// Java/JPA example
em.getTransaction().begin();
User u = em.find(User.class, 123);
u.credits += 10;
em.persist(u); // Note added in 2016: this line is actually not needed
em.getTransaction().commit();
(Ich weiß, das könnte wahrscheinlich so geschrieben werden, als ein einzelnes update-Abfrage, aber das ist nicht immer der Fall ist)
Ist dieser code geschützt gegen race conditions?
Ich bin hauptsächlich daran interessiert, MySQL5 + InnoDB, aber Allgemeine Antworten sind auch willkommen.
InformationsquelleAutor der Frage Bart van Heukelom | 2011-06-25
Du musst angemeldet sein, um einen Kommentar abzugeben.
TL/DR: Transaktionen nicht inhärent verhindern, dass alle racebedingungen. Sie müssen noch sperren -, abort-und-retry-handling, oder andere schützende Maßnahmen in allen real-world-Datenbank-Implementierungen. Transaktionen sind nicht eine geheime Zutat, die Sie hinzufügen können, auf Ihre Anfragen, um Sie sicher von allen parallelitätseffekte.
Isolation
Was Sie bekommen haben, mit Frage ist ich in SÄURE - isolation. Die akademisch Reine Idee ist, dass Transaktionen, die sollte bieten die perfekte isolation, so dass das Ergebnis ist das gleiche, als wenn jede Transaktion, die Seriell ausgeführt. In Wirklichkeit ist das selten der Fall, in realen RDBMS-Implementierungen; Funktionen variieren je nach Umsetzung, und die Regeln kann abgeschwächt werden durch Verwendung eines schwächeren isolation level wie
READ COMMITTED
. In der Praxis Sie können nicht davon ausgehen, dass Transaktionen, die verhindern, dass alle race-Bedingungenauch beiSERIALIZABLE
isolation.Einige RDBMSs haben Sie stärkere Fähigkeiten als andere. Zum Beispiel PostgreSQL 9.2 und neuer haben sehr gute
SERIALIZABLE
isolation, erkennt die meisten (aber nicht alle) möglichen Interaktionen zwischen Transaktionen und bricht alle aber eines der kollidierenden Transaktionen. So kann es laufen Transaktionen parallel Recht sicher.Wenige, wenn überhaupt3Systeme wirklich perfekt
SERIALIZABLE
isolation, die verhindert, dass alle möglichen Rassen und Anomalien, einschließlich Probleme wie bei der Sperre und Sperre Bestellung von deadlocks.Sogar mit starken isolation einige Systeme (wie PostgreSQL) wird abgebrochen, widersprüchliche Transaktionen, anstatt Sie warten, und laufen Sie abwechselnd. Ihre app darf daran erinnern, was es war zu tun und erneut versuchen die Transaktion. So, während die Transaktion verhindert hat, concurrency-related anomalies gespeichert werden, um die DB, es ist getan in einer Weise, die nicht transparent für die Anwendung.
Atomarität
Wohl der primäre Zweck einer Datenbank-Transaktion ist, dass es für Atomare commit -. Die änderungen werden nicht wirksam, bis Sie einen commit für die Transaktion. Wenn Sie verpflichten sich, alle änderungen werden wirksam, in demselben Augenblick so weit wie andere Transaktionen betroffen sind. Keine Transaktion kann immer sehen, nur einige der änderungen, die eine Transaktion macht1,2. Ebenso, wenn Sie
ROLLBACK
dann wird keiner der Transaktion ändert sich jemals, gesehen von einer anderen Transaktion; es ist, als ob Ihre Transaktion nie gegeben.Dass die Eine in SÄURE.
Haltbarkeit
Anderen ist die Haltbarkeit - die D in SÄURE. Es legt fest, dass, wenn Sie ein commit für eine Transaktion muss es wirklich gespeichert werden-Speicher, überleben eine Störung wie Stromausfall oder einem plötzlichen Neustart.
Konsistenz:
Sehen wikipedia
Optimistische concurrency control
Anstatt mit Verriegelung und/oder hohe isolation levels, ist es üblich, für ORMs wie Hibernate, EclipseLink, etc. zu verwenden optimistic concurrency control (oft auch als "optimistic locking") zu überwinden die Grenzen der schwächere isolation levels während der Erhaltung der Leistung.
Ein wesentliches Merkmal dieses Ansatzes ist, dass es lässt Sie die Spannweite der Arbeit über mehrere Transaktionen, das ist ein großes plus bei Systemen mit hohen Benutzerzahlen und können lange Verzögerungen zwischen Interaktionen mit einem Benutzer.
Referenzen
Zusätzlich zu den in-text-links, siehe die PostgreSQL-Dokumentation Kapitel zu sperren, isolation und Parallelität. Auch wenn Sie mit einem anderen RDBMS-du wirst eine Menge lernen von den Konzepten es erklärt.
1ich Ignoriere die selten umgesetzt
READ UNCOMMITTED
Isolationsstufe hier für die Einfachheit; es erlaubt dirty reads.2Als @meriton Punkte heraus, die logische Folge ist nicht unbedingt wahr. Phantom reads treten in alles, was sich darunter
SERIALIZABLE
. Ein Teil eines in-progress-Transaktion nicht sehen, einige änderungen (von einem noch nicht committed-Transaktion), dann wird der nächste Teil des in-progress-Transaktion hat sehen die änderungen, wenn die andere Transaktion ein commit ausgeführt wird.3 Naja, IIRC SQLite2 hat aufgrund von sperren der gesamten Datenbank, wenn ein Schreibzugriff versucht, aber das ist nicht das, was ich nennen würde eine ideale Lösung, um Parallelitätsprobleme.
InformationsquelleAutor der Antwort Craig Ringer
Der Datenbank-Schicht unterstützt die Atomarität von Transaktionen in unterschiedlichem Maße, sogenannte isolation levels. Überprüfen Sie die Dokumentation zu Ihrem Datenbank-management-system für die isolation Ebenen unterstützt, und Ihre trade-offs. Die stärkste Isolationsstufe Serializableerfordert Transaktionen ausführen, als ob Sie ausgeführt wurden. Dies ist in der Regel implementiert, mit exklusiven locks in der Datenbank. Dies kann dazu führen, deadlocks, die das Datenbank-management-system erkennt und behebt, indem ein Rollback einige der beteiligten Transaktionen. Dieser Ansatz wird oft als pessimistische sperren.
Viele Objekt-relationalen Mapper (einschließlich der JPA-Provider) unterstützen auch optimistic lockingwo update-Konflikte sind nicht gehindert, in der Datenbank, aber erkannt in der Anwendung-Schicht, in der dann die Transaktion zurück. Wenn Sie das optimistische sperren aktiviert, ist eine typische Ausführung der Beispiel-code emittieren würde die folgende sql-Abfragen:
Lassen Sie uns sagen, dies gibt (123, 13, 100).
Die Datenbank zeigt uns, wie viele Zeilen, bei denen aktualisiert. Wenn es einer war, gab es keine in Konflikt stehende update. Wenn es null war, einem Konflikt-update aufgetreten ist, und der JPA-provider tun
und eine exception werfen, so dass der code der Anwendung kann mit den fehlgeschlagenen Transaktionen, zum Beispiel durch wiederholen.
Zusammenfassung: Mit Ansatz, deine Aussage kann sicher gemacht werden, der auf Rasse-Bedingungen.
InformationsquelleAutor der Antwort meriton
Es hängt von der Isolationsstufe (serialisierbare Sie verhindert, dass eine race-Bedingung, da in der Regel in der Isolationsstufe serializable Transaktionen werden in der Reihenfolge, nicht in paralell (oder zumindest exklusive sperren verwendet werden, so dass Transaktionen, das ändern die gleichen Zeilen, sind in der entsprechenden Reihenfolge ausgeführt).
Um zu verhindern, dass die race-condition, besser manuell sperren den Datensatz (mysql zum Beispiel unterstützt "select ... for update" - Anweisung, die übernimmt die write-Sperre auf die ausgewählten Datensätze)
InformationsquelleAutor der Antwort Maxim Krizhanovsky
Hängt es vom jeweiligen rdbms. Im Allgemeinen werden Transaktionen sperren wie beschlossen, während der query evaluation plan. Einige können verlangen, table-level locks, die andere Spalte Ebene, andere Datensatz-Ebene, die zweite ist bevorzugt für die Leistung. Die kurze Antwort auf Ihre Frage ist ja.
In anderen Worten, eine Transaktion soll die Gruppe eine Reihe von Abfragen und vertreten Sie als eine Atomare operation. Wenn der Vorgang fehlschlägt, werden die änderungen rolledback. Ich nicht genau weiß, was der adapter, die Sie verwenden, aber wenn es entspricht der definition der Transaktionen, die Sie sollten in Ordnung sein.
Während dies garantiert die Vermeidung von race conditions, es nicht explizit zu verhindern, dass Hunger oder deadlocks. Die Transaktion sperren-manager ist verantwortlich, dass. Tabelle sperren, die irgendwann verwendet, aber Sie kommen mit einer saftigen Preis von Verringerung der Anzahl gleichzeitiger Operationen.
InformationsquelleAutor der Antwort Candide