Wir haben eine Tabelle in MySQL, die InnoDB verwendet, und wir verwenden eine Transaktionsisolationsstufe von uncommitted read. Warum erhält @x
, wie gezeigt, eine Sperre?
Wenn versucht wird, diese Tabelle von einer anderen Eingabeaufforderung aus zu aktualisieren, tritt ein Zeitüberschreitungsfehler auf:
%Vor% Für das, was es wert ist, ist diese Sperre nicht auf READ-UNCOMMITTED
beschränkt:
Wie in dem von Ihnen protokollierten Fehler besprochen, Fehler # 67452 Wenn Sie eine Variable aus einer Auswahl auswählen, wird beim Lesen eine Sperre ausgelöst nicht committed , dieses Verhalten ist wahrscheinlich von Entwurf. Es scheint in die gleiche Kategorie zu fallen wie SELECT
-Anweisungen, deren Ergebnisse zum Ändern von Daten verwendet werden, wie in den beschriebenen Fällen:
Wenn ein SELECT in den Konstrukten
REPLACE INTO t SELECT ... FROM s WHERE ...
oderUPDATE t ... WHERE col IN (SELECT ... FROM s ...)
verwendet wird, setzt InnoDB freigegebene Next-Key-Sperren für Zeilen aus der Tabelles
.
Der Grund für Next-Key-Sperren besteht darin, die SELECT
-Ergebnisse stabiler zu machen. Das heißt, wir möchten nicht, dass sich die mit SELECT
übereinstimmenden Zeilen ändern, während sie für eine UPDATE
oder eine andere datenmodifizierende Anweisung verwendet werden.
Auch wenn tx_isolation REPEATABLE-READ
ist, ist dies wichtig, da InnoDB REPEATABLE-READ
für SELECT
-Anweisungen nicht unterstützt, wenn sie als Teil eines beliebigen Typs von UPDATE
ausgeführt werden.
Re deinen Kommentar:
Unabhängig von der Dokumentation geschieht Folgendes:
Wenn Sie die Anweisung SELECT
ausführen, sperrt InnoDB in keiner Transaktionsisolation irgendetwas außer SERIALIZABLE
.
Wenn du SELECT ... LOCK IN SHARE MODE
oder SELECT ... FOR UPDATE
machst, wird es natürlich gesperrt.
Wenn Sie SELECT
jedoch als Teil einer datenmodifizierenden Anweisung wie INSERT INTO...SELECT
oder in einer Unterabfrage von UPDATE
verwenden oder in einem SET @variable := (SELECT...)
gefunden haben, verwendet es eine gemeinsame Sperre, um sicherzustellen, dass Die Daten ändern sich während der Aktualisierung nicht.
Die Dokumentation kann unvollständig sein. Besser zu testen.
Ihre erste Anweisung führt eine SELECT-Anweisung für die Tabelle aus. Daher erhält die Transaktion eine Lesesperre für eine Zeile.
Die zweite Transaktion versucht, eine Schreibsperre für dieselbe Tabelle zu erhalten (in allen Zeilen, da es keine WHERE
-Klausel gibt), kann aber nicht.
Sie müssen nach dem COMMIT
einen Befehl ROLLBACK
(oder SET @x = (...)
) ausgeben, damit er die Lesesperre freigibt.
Das obige ist falsch. Ich behalte diesen Beitrag, nur weil die folgenden Kommentare von Interesse sein könnten.
Tags und Links mysql locking transaction-isolation read-uncommitted