Szukaj…


Składnia

  • LOCK TABLES nazwa_tabeli [CZYTAJ | PISAĆ]; // Blokuj tabelę

  • ODBLOKUJ TABELE; // Odblokuj tabele

Uwagi

Blokowanie służy do rozwiązywania problemów związanych z współbieżnością. Blokowanie jest wymagane tylko podczas przeprowadzania transakcji, która najpierw odczytuje wartość z bazy danych, a następnie zapisuje tę wartość w bazie danych. Blokady nigdy nie są wymagane do samodzielnych operacji wstawiania, aktualizacji lub usuwania.

Dostępne są dwa rodzaje zamków

ODCZYTAJ BLOKADĘ - gdy użytkownik czyta tylko ze stołu.

BLOKADA ZAPISU - gdy użytkownik zarówno czyta, jak i pisze do tabeli.

Gdy użytkownik trzyma WRITE LOCK na stole, żaden inny użytkownik nie może czytać ani zapisywać na tym stole. Gdy użytkownik trzyma READ LOCK na stole, inni użytkownicy mogą również czytać lub blokować READ LOCK , ale żaden użytkownik nie może pisać ani WRITE LOCK na tym stole.

Jeśli domyślnym silnikiem pamięci jest InnoDB, MySQL automatycznie stosuje blokowanie na poziomie wiersza, dzięki czemu wiele transakcji może jednocześnie używać tej samej tabeli do odczytu i zapisu, bez konieczności wzajemnego oczekiwania.

We wszystkich silnikach pamięci innych niż InnoDB, MySQL stosuje blokowanie tabel.

Aby uzyskać więcej informacji na temat blokady stołu Zobacz tutaj

Zamki MySQL

Blokady tabel mogą być ważnym narzędziem dla ENGINE=MyISAM , ale rzadko są przydatne dla ENGINE=InnoDB . Jeśli masz ochotę korzystać z blokad tabel w InnoDB, powinieneś przemyśleć sposób pracy z transakcjami.

MySQL umożliwia sesjom klienckim jawne uzyskiwanie blokad tabel w celu współpracy z innymi sesjami w celu uzyskania dostępu do tabel lub w celu zapobiegania modyfikowaniu tabel przez inne sesje w okresach, gdy sesja wymaga do nich wyłącznego dostępu. Sesja może uzyskać lub zwolnić blokady tylko dla siebie. Jedna sesja nie może uzyskać blokad dla innej sesji ani zwolnić blokad przechowywanych przez inną sesję.

Blokady mogą być używane do emulacji transakcji lub zwiększenia prędkości podczas aktualizowania tabel. Wyjaśniono to bardziej szczegółowo w dalszej części tego rozdziału.

Polecenie: LOCK TABLES table_name READ|WRITE;

możesz przypisać tylko typ blokady do pojedynczej tabeli;

Przykład (READ LOCK):

LOCK TABLES table_name READ;

Przykład (BLOKADA ZAPISU):

LOCK TABLES table_name WRITE;

Aby zobaczyć, czy zastosowano blokadę, użyj następującego polecenia

SHOW OPEN TABLES;

Aby opróżnić / usunąć wszystkie blokady, użyj następującego polecenia:

UNLOCK TABLES;

PRZYKŁAD:

LOCK TABLES products WRITE:  
INSERT INTO products(id,product_name) SELECT id,old_product_name FROM old_products;
UNLOCK TABLES;

W powyższym przykładzie żadne połączenie zewnętrzne nie może zapisać żadnych danych do tabeli produktów, dopóki nie odblokuje produktu tabeli

PRZYKŁAD:

LOCK TABLES products READ:  
INSERT INTO products(id,product_name) SELECT id,old_product_name FROM old_products;
UNLOCK TABLES;

W powyższym przykładzie żadne połączenie zewnętrzne nie może odczytać żadnych danych z tabeli produktów do momentu odblokowania produktu tabeli

Blokowanie na poziomie rzędu

Jeśli tabele używają InnoDB, MySQL automatycznie stosuje blokowanie na poziomie wiersza, dzięki czemu wiele transakcji może jednocześnie używać tej samej tabeli do odczytu i zapisu, bez konieczności wzajemnego oczekiwania.

Jeśli dwie transakcje próbują zmodyfikować ten sam wiersz i obie wykorzystują blokowanie na poziomie wiersza, jedna z transakcji czeka na zakończenie drugiej.

Blokowanie na poziomie wiersza można również uzyskać za pomocą SELECT ... FOR UPDATE dla każdego wiersza, który ma zostać zmodyfikowany.

Rozważ dwa połączenia, aby szczegółowo wyjaśnić blokowanie na poziomie wiersza

Połączenie 1

START TRANSACTION;
SELECT ledgerAmount FROM accDetails WHERE id = 1 FOR UPDATE;

W połączeniu 1 blokada poziomu wiersza uzyskana przez SELECT ... FOR UPDATE .

Połączenie 2

UPDATE accDetails SET ledgerAmount = ledgerAmount + 500 WHERE id=1;

Gdy ktoś spróbuje zaktualizować ten sam wiersz w połączeniu 2, będzie czekać na zakończenie transakcji przez połączenie 1 lub wyświetli się komunikat o błędzie zgodnie z ustawieniem innodb_lock_wait_timeout , który domyślnie innodb_lock_wait_timeout 50 sekund.

Error Code: 1205. Lock wait timeout exceeded; try restarting transaction

Aby wyświetlić szczegółowe informacje na temat tej blokady, uruchom 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:

Połączenie 2

UPDATE accDetails SET ledgerAmount = ledgerAmount + 250 WHERE id=2;
1 row(s) affected

Ale podczas aktualizacji jakiś inny wiersz w połączeniu 2 zostanie wykonany bez żadnego błędu.

Połączenie 1

UPDATE accDetails SET ledgerAmount = ledgerAmount + 750 WHERE id=1;
COMMIT;
1 row(s) affected

Teraz blokada wiersza jest zwolniona, ponieważ transakcja jest zatwierdzana w Połączeniu 1.

Połączenie 2

UPDATE accDetails SET ledgerAmount = ledgerAmount + 500 WHERE id=1;
1 row(s) affected

Aktualizacja jest wykonywana bez żadnego błędu w Połączeniu 2 po zwolnieniu blokady wiersza 1 przez zakończenie transakcji.



Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow