Ich versuche, die MySQL-Zeilensperre zu verwenden, um einen MuteEx in einer Zeile zu emulieren. Nehmen wir an, dass meine Tabelle zwei Spalten, eine ID und ein Textfeld sowie drei Einträge (1, a) (2, b) und (3, c) enthält. SELECT * FROM Tabelle; würde diese Ergebnisse zurückgeben. Ich kann eine bestimmte Zeile auf die normale Weise sperren.
%Vor%Wenn ich jedoch von einer zweiten Verbindung aus SELECT * aus der Tabelle wählen würde. Es würde alle 3 Ergebnisse zurückgeben. Gibt es eine Möglichkeit zum Sperren auf Zeilenebene, um zu verhindern, dass SELECT eine gesperrte Zeile sieht / verwendet? Im Grunde versuche ich zu verhindern, dass irgendjemand die gerade verwendete / manipulierte Zeile benutzt, oder sogar die Zeile als ihre Daten anzusehen (da sie benutzt / manipuliert wird), kann nicht vertrauenswürdig sein, um zum Zeitpunkt einer AUSWAHL genau zu sein .
Wenn Sie die Transaktionsisolationsstufe auf SERIALIZABLE
, InnoDB
wil implicity, setzen Sie LOCK IN SHARE MODE
auf alle SELECT
-Anweisungen.
Dieser Modus steht im Konflikt mit den Sperren, die von SELECT FOR UPDATE
und von SELECT
s gesetzt wurden.
Beachten Sie jedoch, dass InnoDB
möglicherweise mehr Zeilen sperrt als die Bedingung WHERE
erfüllt. Dies liegt daran, dass alle gescannten Zeilen gesperrt werden, nicht nur die übereinstimmenden .
Angenommen, Sie haben einen Index für col1
und diese Abfrage:
verwendet diesen Index.
Dadurch werden alle Datensätze mit col1 = 1
gesperrt, sogar mit col2 <> 2
Sie benötigen ein LOCK IN SHARE MODE
. Die Verwendung mit SELECT garantiert, dass niemand sonst Zeilen mit FOR UPDATE
schließt.
z.B.
Client A tut SELECT * FROM table WHERE type=2 FOR UPDATE
Client B tut SELECT * FROM table LOCK IN SHARE MODE
und hängt hier
Client A schreibt / INSERTs / UPDATEs etwas und dann ein COMMIT
Client B deaktiviert nun die Verarbeitung und setzt die Verarbeitung fort
Tatsächlich können die Zeilendaten sogar während der Bearbeitung vertrauenswürdig sein.
Wenn Sie eine Transaktion von einer Verbindung aus starten, sehen andere Verbindungen keine Ihrer Änderungen, bis Sie die Transaktion festgeschrieben haben.
Ich weiß nicht, ob es einen nativen, sperrenden Mechanismus dafür gibt, aber mein erster Grund wäre, der Tabelle eine Statusspalte zu geben (zB locked
) und diese auf 1
zu setzen, wenn ich die Sperre sperre Reihe. Ein select
sensitive würde dann immer eine WHERE locked != '1'
Bedingung zu jeder Abfrage hinzufügen.
Nebenbei bemerkt, ich weiß nicht, was Sie tun, aber ist das nicht eine Aufgabe, die ein oder zwei Level über der Datenbank-Engine durchgeführt werden sollte?