Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Zakleszczenie przy użyciu SELECT ... FOR UPDATE w MySQL

Co działa, a co nie

Sposobem na przeprowadzenie obu transakcji bez zakleszczenia jest zmiana poziom izolacji do CZYTAJ ZAANGAŻOWANYCH (lub PRZECZYTAJ BEZ ZAANGAŻOWANIA ) w obu połączeniach:

SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;

(przed start transaction ).

Prawdopodobnie wystarczyłoby ustawić go w t2 , ale żeby mieć pewność co do przykładu, ustaw go w obu.

Zmiana poziomu izolacji transakcji wprowadza pewne skutki uboczne, o których należy poinformować w instrukcji przed zmianą tego w środowisku produkcyjnym.

Informacje o stanie dotyczące zakleszczenia

------------------------
LATEST DETECTED DEADLOCK
------------------------
140424  8:45:46
*** (1) TRANSACTION:
TRANSACTION B6F18A3, ACTIVE 5 sec starting index read
mysql tables in use 1, locked 1
LOCK WAIT 2 lock struct(s), heap size 376, 1 row lock(s)
MySQL thread id 13885, OS thread handle 0x7f8b1dbd2700, query id 901012
 localhost root statistics
SELECT * FROM t WHERE id = 1 FOR UPDATE
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 0 page no 22921 n bits 72 index `PRIMARY` of table
 `test`.`t` trx id B6F18A3 lock_mode X locks rec but not gap waiting
Record lock, heap no 4 PHYSICAL RECORD: n_fields 4; compact format; info bits 0
 0: len 4; hex 80000001; asc     ;;
 1: len 6; hex 00000b6f1883; asc    o  ;;
 2: len 7; hex 06000059a211ea; asc    Y   ;;
 3: len 5; hex 48656c6c6f; asc Hello;;

*** (2) TRANSACTION:
TRANSACTION B6F18A2, ACTIVE 10 sec starting index read
mysql tables in use 1, locked 1
3 lock struct(s), heap size 376, 2 row lock(s)
MySQL thread id 13888, OS thread handle 0x7f8b1f64d700, query id 901068
 localhost root Updating
UPDATE t SET `descc` = 'Hello from t1'
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 0 page no 22921 n bits 72 index `PRIMARY` of table
 `test`.`t` trx id B6F18A2 lock_mode X locks rec but not gap
Record lock, heap no 4 PHYSICAL RECORD: n_fields 4; compact format; info bits 0
 0: len 4; hex 80000001; asc     ;;
 1: len 6; hex 00000b6f1883; asc    o  ;;
 2: len 7; hex 06000059a211ea; asc    Y   ;;
 3: len 5; hex 48656c6c6f; asc Hello;;

*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 0 page no 22921 n bits 72 index `PRIMARY` of table
 `test`.`t` trx id B6F18A2 lock_mode X waiting
Record lock, heap no 4 PHYSICAL RECORD: n_fields 4; compact format; info bits 0
 0: len 4; hex 80000001; asc     ;;
 1: len 6; hex 00000b6f1883; asc    o  ;;
 2: len 7; hex 06000059a211ea; asc    Y   ;;
 3: len 5; hex 48656c6c6f; asc Hello;;

*** WE ROLL BACK TRANSACTION (1)

Wyjaśnienie

Jak wspomniano o_koniu_bez_nazwy, wygląda to na błąd w MySQL. Transakcja (2) chce uzyskać blokadę luki w tym samym wierszu, w którym ma już blokadę X. Transakcja (1) czeka na blokadę X bez luki w tym wierszu. Nie jest dla mnie jasne, dlaczego te prośby mają kolidować. Ustawienie poziomu izolacji na READ COMMITTED wyłącza blokowanie przerw. Ponieważ przykład działa wtedy, jest to wskazówka, że ​​rzeczywiście problemem jest tutaj blokowanie luk.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. mysqldump version Błąd podczas eksportowania danych z MySQL

  2. Czy indeksowanie pola logicznego zwiększa wydajność?

  3. Jak zaimportować zrzut MySQL z wiersza poleceń Z nadpisaniem?

  4. MySQL:@zmienna a zmienna. Co za różnica?

  5. Dlaczego wartość autoinkrementacji MySQL zwiększa się w przypadku nieudanych operacji wstawiania?