MySQL
MySQL-Sperrtabelle
Suche…
Syntax
LOCK TABLES Tabellenname [READ | SCHREIBEN]; // Tabelle sperren
ENTSPERREN SIE TABELLEN; // Tabellen entsperren
Bemerkungen
Sperren wird verwendet, um Parallelitätsprobleme zu lösen. Das Sperren ist nur erforderlich, wenn eine Transaktion ausgeführt wird, die zuerst einen Wert aus einer Datenbank liest und diesen Wert später in die Datenbank schreibt. Sperren sind niemals für in sich geschlossene Einfügungs-, Aktualisierungs- oder Löschvorgänge erforderlich.
Es gibt zwei Arten von Schlössern
READ LOCK - wenn ein Benutzer nur aus einer Tabelle liest.
WRITE LOCK - wenn ein Benutzer eine Tabelle liest und schreibt.
Wenn ein Benutzer eine WRITE LOCK
für eine Tabelle hält, kann kein anderer Benutzer diese Tabelle lesen oder schreiben. Wenn ein Benutzer eine READ LOCK
für eine Tabelle hält, können andere Benutzer auch eine READ LOCK
lesen oder halten, aber kein Benutzer kann eine WRITE LOCK
für diese Tabelle schreiben oder halten.
Wenn die Standard-Speicher-Engine InnoDB ist, verwendet MySQL automatisch das Sperren auf Zeilenebene, sodass mehrere Transaktionen dieselbe Tabelle gleichzeitig für Lesen und Schreiben verwenden können, ohne sich gegenseitig warten zu müssen.
Für alle Speicher-Engines außer InnoDB verwendet MySQL die Tabellensperre.
Weitere Informationen zur Tabellensperre finden Sie hier
Mysql Locks
Tabellensperren können ein wichtiges Werkzeug für ENGINE=MyISAM
, sind jedoch für ENGINE=InnoDB
selten nützlich. Wenn Sie versucht sind, Tabellensperren mit InnoDB zu verwenden, sollten Sie überdenken, wie Sie mit Transaktionen arbeiten.
MySQL ermöglicht Client-Sitzungen das explizite Anfordern von Tabellensperren, um mit anderen Sitzungen für den Zugriff auf Tabellen zusammenzuarbeiten, oder um zu verhindern, dass andere Sitzungen Tabellen in Zeiten ändern, in denen eine Sitzung exklusiven Zugriff auf sie erfordert. Eine Sitzung kann Sperren nur für sich selbst erwerben oder freigeben. Eine Sitzung kann keine Sperren für eine andere Sitzung abrufen oder Sperren aufheben, die von einer anderen Sitzung gehalten werden.
Sperren können verwendet werden, um Transaktionen zu emulieren oder die Aktualisierung von Tabellen zu beschleunigen. Dies wird später in diesem Abschnitt näher erläutert.
Befehl: LOCK TABLES table_name READ|WRITE;
Sie können einer einzelnen Tabelle nur den Sperrtyp zuweisen.
Beispiel (Lesesperre):
LOCK TABLES table_name READ;
Beispiel (WRITE LOCK):
LOCK TABLES table_name WRITE;
Um zu sehen, ob die Sperre angewendet wird oder nicht, verwenden Sie den folgenden Befehl
SHOW OPEN TABLES;
Verwenden Sie den folgenden Befehl, um alle Sperren zu löschen oder zu entfernen:
UNLOCK TABLES;
BEISPIEL:
LOCK TABLES products WRITE:
INSERT INTO products(id,product_name) SELECT id,old_product_name FROM old_products;
UNLOCK TABLES;
Im obigen Beispiel kann eine externe Verbindung keine Daten in die Produkttabelle schreiben, bis das Tabellenprodukt entsperrt wird
BEISPIEL:
LOCK TABLES products READ:
INSERT INTO products(id,product_name) SELECT id,old_product_name FROM old_products;
UNLOCK TABLES;
Im obigen Beispiel kann eine externe Verbindung keine Daten aus der Produkttabelle lesen, bis das Tabellenprodukt entsperrt wird
Zeilenebenensperre
Wenn die Tabellen InnoDB verwenden, verwendet MySQL automatisch das Sperren auf Zeilenebene, so dass mehrere Transaktionen dieselbe Tabelle gleichzeitig für Lesen und Schreiben verwenden können, ohne sich gegenseitig warten zu müssen.
Wenn zwei Transaktionen, die versuchen, dieselbe Zeile zu ändern, und beide eine Sperrung auf Zeilenebene verwenden, wartet eine der Transaktionen, bis die andere Transaktion abgeschlossen ist.
Das Sperren auf Zeilenebene kann auch mit der Anweisung SELECT ... FOR UPDATE
für jede zu SELECT ... FOR UPDATE
Zeile erhalten werden.
Betrachten Sie zwei Verbindungen, um das Sperren auf Zeilenebene im Detail zu erklären
Verbindung 1
START TRANSACTION;
SELECT ledgerAmount FROM accDetails WHERE id = 1 FOR UPDATE;
In Verbindung 1 wird die SELECT ... FOR UPDATE
Anweisung SELECT ... FOR UPDATE
.
Verbindung 2
UPDATE accDetails SET ledgerAmount = ledgerAmount + 500 WHERE id=1;
Wenn innodb_lock_wait_timeout
versucht, dieselbe Zeile in Verbindung 2 zu aktualisieren, wird darauf gewartet, dass Verbindung 1 die Transaktion beendet oder eine Fehlermeldung wird gemäß der Einstellung innodb_lock_wait_timeout
(50 Sekunden) angezeigt.
Error Code: 1205. Lock wait timeout exceeded; try restarting transaction
Um Details zu dieser Sperre SHOW ENGINE INNODB STATUS
, führen Sie SHOW ENGINE INNODB STATUS
---TRANSACTION 1973004, ACTIVE 7 sec updating
mysql tables in use 1, locked 1
LOCK WAIT 2 lock struct(s), heap size 360, 1 row lock(s)
MySQL thread id 4, OS thread handle 0x7f996beac700, query id 30 localhost root update
UPDATE accDetails SET ledgerAmount = ledgerAmount + 500 WHERE id=1
------- TRX HAS BEEN WAITING 7 SEC FOR THIS LOCK TO BE GRANTED:
Verbindung 2
UPDATE accDetails SET ledgerAmount = ledgerAmount + 250 WHERE id=2;
1 row(s) affected
Während der Aktualisierung wird jedoch eine andere Zeile in Verbindung 2 fehlerfrei ausgeführt.
Verbindung 1
UPDATE accDetails SET ledgerAmount = ledgerAmount + 750 WHERE id=1;
COMMIT;
1 row(s) affected
Jetzt wird die Zeilensperre freigegeben, da die Transaktion in Verbindung 1 festgeschrieben wird.
Verbindung 2
UPDATE accDetails SET ledgerAmount = ledgerAmount + 500 WHERE id=1;
1 row(s) affected
Das Update wird ohne Fehler in Verbindung 2 ausgeführt, nachdem die Zeilensperre von Verbindung 1 durch Beenden der Transaktion freigegeben wurde.