2015-04-07 9 views
13

Zostaliśmy widząc dużo błędów ostatnio:Uwalnianie mysql zablokować transakcję zewnętrzną (szyny)

ActiveRecord::TransactionIsolationConflict: Transaction isolation conflict detected: Lock wait timeout exceeded; try restarting transaction 

nie jest w stanie zorientować się, rozumowanie za nim. Ale zauważyłem jedną rzecz w naszym kodzie, który próbuje zablokować rekord poza transakcji:

acc = Account.lock.find acc_id 

Powyższy kod nie jest wewnątrz każdej transakcji i jest używany tylko w celu sprawdzenia, że ​​druga transakcja, która uzyska również taką samą blokadę zakończeniu lub nie. Jakieś przemyślenia na temat tego, czy to może być winowajcą?

Odpowiedz

0

Proszę sprawdzić, co jest skonfigurowane na serwerze MySQL dla innodb_lock_wait_timeout i lock_wait_timeout. Można to zrobić uruchamiając następującą komendę

show global variables like '%lock_wait_timeout';

Które z tych parametrów jest używany zależy od wersji MySQL oraz silnik stołu

z dokumentacją:

# wybierz * z kont, dla których id = 1 dla aktualizacji

Account.lock.find(1)

oznacza - nabyć zamek do zapisu.

Prawdopodobnie transakcja zajmuje więcej czasu niż skonfigurowano w bazie danych, a żądanie sprawdzania, które próbuje zweryfikować oryginalną transakcję, zostało zakończone - pojawienie się tego błędu, gdy upłynie czas oczekiwania.

1

Blokowanie poziomu wiersza InnoDB zapewnia lepszą współbieżność przy dużym obciążeniu zapisu. Silnik podejmuje pewne środki ostrożności, aby pozbyć się odczytów fantomowych, jednym z nich jest luka_własna, która może być przyczyną tego problemu. Użyj analizatora o luce_lock, aby uzyskać więcej informacji.

Jeśli jest to proble, można spróbować następujących opcji

  1. zmienić poziom do READ COMMITTEDISOLATION.

  2. set innodb_locks_unsafe_for_binlog = 1. Spowoduje to wyłączenie blokad luki za wyjątkiem sprawdzania ograniczeń obcymi kluczami lub sprawdzania kluczy duplikatów.

  3. Ponownie użyj show innodb status, aby przeanalizować, co się dzieje.W razie potrzeby zoptymalizować kod, aby uniknąć blokowania

  4. Jeśli powyżej nie działa, spróbuj zwiększyć lock_wait_timeout globalnie

SET GLOBAL innodb_lock_wait_timeout = 120;

Albo na sesję

SET innodb_lock_wait_timeout = 120; 
  1. sprawdź ponownie swój config, jeśli jeszcze nie uaktualnili następnie ponownie ustawić zmienne globalne

    show variables like '%wait_timeout%'; 
    
    show variables like '%tx_isolation%'; 
    
    SELECT @@GLOBAL.tx_isolation, @@tx_isolation; 
    
Powiązane problemy