Mysql
 sql >> Datenbank >  >> RDS >> Mysql

MySQL:Wie man eine Transaktionssperre auf Zeilenebene anstelle einer Tabellensperre erreicht

Es kann nützlich sein, sich anzusehen, wie diese Abfrage tatsächlich von MySQL ausgeführt wird:

select * from tbl_codes where available = 1 order by rand() limit 1 for update

Dadurch werden alle Zeilen gelesen und sortiert, die mit WHERE übereinstimmen Bedingung, generieren Sie eine Zufallszahl mit rand() in eine virtuelle Spalte für jede Zeile, sortieren Sie alle Zeilen (in einer temporären Tabelle) basierend auf dieser virtuellen Spalte und geben Sie dann Zeilen aus der sortierten Menge bis zum LIMIT an den Client zurück erreicht ist (in diesem Fall nur eine). Der FOR UPDATE wirkt sich auf das Sperren der gesamten Anweisung während der Ausführung aus, und als solche wird die Klausel angewendet, wenn Zeilen innerhalb von InnoDB gelesen werden , nicht wie sie an den Client zurückgegeben werden.

Abgesehen von den offensichtlichen Auswirkungen auf die Leistung (es ist schrecklich), werden Sie niemals ein vernünftiges Sperrverhalten erzielen.

Kurze Antwort:

  1. Wählen Sie die gewünschte Zeile mit RAND() aus oder jede andere Strategie, die Sie mögen, um den PRIMARY KEY zu finden Wert dieser Zeile. Beispiel:SELECT id FROM tbl_codes WHERE available = 1 ORDER BY rand() LIMIT 1
  2. Sperren Sie die gewünschte Zeile mit ihrem PRIMARY KEY nur. Beispiel:SELECT * FROM tbl_codes WHERE id = N

Hoffentlich hilft das.