MySQL
MySQL SLOTTAFEL
Zoeken…
Syntaxis
LOCK TABLES tabelnaam [READ | SCHRIJVEN]; // Vergrendeltabel
ONTGRENDEL TABELLEN; // Ontgrendel tabellen
Opmerkingen
Vergrendeling wordt gebruikt om gelijktijdigheidsproblemen op te lossen. Vergrendeling is alleen vereist bij het uitvoeren van een transactie, die eerst een waarde uit een database leest en die waarde later in de database schrijft. Vergrendelingen zijn nooit vereist voor zelfstandige invoeg-, update- of verwijderbewerkingen.
Er zijn twee soorten sloten beschikbaar
LEESVERGRENDELING - wanneer een gebruiker alleen van een tafel leest.
SCHRIJFSLOT - wanneer een gebruiker zowel aan een tafel leest als schrijft.
Wanneer een gebruiker een WRITE LOCK
op een tafel heeft, kunnen geen andere gebruikers naar die tafel lezen of schrijven. Wanneer een gebruiker een READ LOCK
op een tafel heeft, kunnen andere gebruikers ook een READ LOCK
lezen of vasthouden, maar geen enkele gebruiker kan een WRITE LOCK
op die tafel schrijven of vasthouden.
Als de standaardopslag-engine InnoDB is, gebruikt MySQL automatisch vergrendeling op rijniveau zodat meerdere transacties dezelfde tabel tegelijkertijd kunnen gebruiken voor lezen en schrijven, zonder elkaar te laten wachten.
Voor alle andere opslagmotoren dan InnoDB gebruikt MySQL tabelvergrendeling.
Voor meer informatie over tafelslot Zie hier
MySQL-sloten
Tafelsloten kunnen een belangrijk hulpmiddel zijn voor ENGINE=MyISAM
, maar zijn zelden handig voor ENGINE=InnoDB
. Als u in de verleiding komt om tafelsloten met InnoDB te gebruiken, moet u heroverwegen hoe u met transacties werkt.
Met MySQL kunnen clientsessies expliciet tafelsloten verkrijgen om samen te werken met andere sessies voor toegang tot tabellen, of om te voorkomen dat andere sessies tabellen wijzigen tijdens perioden waarin een sessie exclusieve toegang tot hen vereist. Een sessie kan vergrendelingen alleen voor zichzelf verkrijgen of vrijgeven. De ene sessie kan geen vergrendelingen voor een andere sessie verwerven of vergrendelingen van een andere sessie vrijgeven.
Vergrendelingen kunnen worden gebruikt om transacties te emuleren of om meer snelheid te krijgen bij het bijwerken van tabellen. Dit wordt later in deze sectie meer gedetailleerd uitgelegd.
Commando: LOCK TABLES table_name READ|WRITE;
u kunt alleen het vergrendelingstype toewijzen aan een enkele tabel;
Voorbeeld (LEES VERGRENDELING):
LOCK TABLES table_name READ;
Voorbeeld (SCHRIJFSLOT):
LOCK TABLES table_name WRITE;
Gebruik de volgende opdracht om te zien of vergrendeling is toegepast of niet
SHOW OPEN TABLES;
Gebruik de volgende opdracht om alle vergrendelingen te spoelen / verwijderen:
UNLOCK TABLES;
VOORBEELD:
LOCK TABLES products WRITE:
INSERT INTO products(id,product_name) SELECT id,old_product_name FROM old_products;
UNLOCK TABLES;
Bovenstaand voorbeeld kan een externe verbinding geen gegevens naar de producttabel schrijven totdat het tafelproduct wordt ontgrendeld
VOORBEELD:
LOCK TABLES products READ:
INSERT INTO products(id,product_name) SELECT id,old_product_name FROM old_products;
UNLOCK TABLES;
Bovenstaand voorbeeld kan een externe verbinding geen gegevens uit de producttabel lezen totdat het tafelproduct wordt ontgrendeld
Rij niveau vergrendeling
Als de tabellen InnoDB gebruiken, gebruikt MySQL automatisch vergrendeling op rijniveau zodat meerdere transacties dezelfde tabel tegelijkertijd kunnen gebruiken voor lezen en schrijven, zonder elkaar te laten wachten.
Als twee transacties proberen dezelfde rij te wijzigen en beide gebruikmaken van vergrendeling op rijniveau, wacht een van de transacties totdat de andere is voltooid.
Vergrendeling op rijniveau kan ook worden verkregen met de instructie SELECT ... FOR UPDATE
voor elke naar verwachting te wijzigen rijen.
Overweeg twee verbindingen om de vergrendeling van het rijniveau in detail uit te leggen
Verbinding 1
START TRANSACTION;
SELECT ledgerAmount FROM accDetails WHERE id = 1 FOR UPDATE;
In verbinding 1, rijniveau lock verkregen door SELECT ... FOR UPDATE
statement.
Verbinding 2
UPDATE accDetails SET ledgerAmount = ledgerAmount + 500 WHERE id=1;
Wanneer iemand probeert dezelfde rij in verbinding 2 bij te werken, wacht dat tot verbinding 1 klaar is om de transactie te voltooien of wordt een foutbericht weergegeven volgens de instelling innodb_lock_wait_timeout
, die standaard 50 seconden is.
Error Code: 1205. Lock wait timeout exceeded; try restarting transaction
Als u details over dit slot wilt bekijken, voert 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:
Verbinding 2
UPDATE accDetails SET ledgerAmount = ledgerAmount + 250 WHERE id=2;
1 row(s) affected
Maar tijdens het bijwerken van een andere rij in verbinding 2 zal zonder enige fout worden uitgevoerd.
Verbinding 1
UPDATE accDetails SET ledgerAmount = ledgerAmount + 750 WHERE id=1;
COMMIT;
1 row(s) affected
Nu wordt rijblokkering vrijgegeven, omdat transactie is vastgelegd in Verbinding 1.
Verbinding 2
UPDATE accDetails SET ledgerAmount = ledgerAmount + 500 WHERE id=1;
1 row(s) affected
De update wordt zonder enige fout in Verbinding 2 uitgevoerd nadat Verbinding 1 rijblokkering heeft vrijgegeven door de transactie te voltooien.