In MySQL Warum wird beim Festlegen einer Variablen aus einer Auswahl eine Sperre angefordert, wenn Lese nicht festgeschrieben verwendet wird?

8

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?

%Vor%

Wenn versucht wird, diese Tabelle von einer anderen Eingabeaufforderung aus zu aktualisieren, tritt ein Zeitüberschreitungsfehler auf:

%Vor%     
Yoseph 31.10.2012, 05:37
quelle

2 Antworten

2

Für das, was es wert ist, ist diese Sperre nicht auf READ-UNCOMMITTED beschränkt:

%Vor%

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 ... oder UPDATE t ... WHERE col IN (SELECT ... FROM s ...) verwendet wird, setzt InnoDB freigegebene Next-Key-Sperren für Zeilen aus der Tabelle s .

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.

    
Bill Karwin 01.05.2014 18:09
quelle
0

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.

    
RandomSeed 31.10.2012 13:46
quelle