2015-04-07 17 views
13

abbiamo visto un sacco di errori di recente:rilascio di MySQL blocco delle transazioni al di fuori (rotaie)

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

non è in grado di capire il ragionamento dietro di esso. Ma ho notato una cosa in nostro codice, che sta cercando di bloccare un record al di fuori di transazione:

acc = Account.lock.find acc_id 

Sopra il codice non è all'interno di qualsiasi transazione ed è usato solo per controllare che l'altra transazione che ottiene anche lo stesso blocco è finito o non. Qualche idea su se questo può essere il colpevole?

risposta

0

Controllare che cosa si sta configurando sul server MySQL per innodb_lock_wait_timeout e lock_wait_timeout. È possibile farlo eseguendo il comando seguente

show global variables like '%lock_wait_timeout';

Quale di questi parametri è in uso dipende dalla versione di MySQL e il motore del tavolo

dalla documentazione:

# select * da account dove id = 1 per l'aggiornamento

Account.lock.find(1)

for update significa - acquisire un blocco per scrivere.

Probabilmente la transazione richiede più tempo rispetto a quella configurata sul DB e la richiesta di controllo che tenta di verificare la transazione originale è stata completata, ottenendo questo errore quando scade il tempo di attesa.

1

InnoDB utilizza il blocco a livello di riga per una maggiore concorrenza in caso di carico di scrittura elevato. Il motore prende alcune precauzioni per eliminare le letture fantasma, una di queste è gap_lock, che potrebbe causare questo problema. Utilizzare

SHOW ENGINE INNODB STATUS 

per analizzare su gap_lock.

Se questo è proble, è possibile provare le seguenti opzioni

  1. cambiare il livello ISOLATION-READ COMMITTED.

  2. set innodb_locks_unsafe_for_binlog = 1. Ciò disabilita i blocchi di separazione, ad eccezione del controllo dei vincoli con chiave esterna o del controllo della chiave duplicata.

  3. Utilizzare di nuovo show innodb status per analizzare cosa sta succedendo.Se necessario ottimizzare il codice per evitare il blocco

  4. Se in precedenza non funziona, cercare di aumentare a livello globale lock_wait_timeout

SET GLOBAL innodb_lock_wait_timeout = 120;

O per una sessione di

SET innodb_lock_wait_timeout = 120; 
  1. Verificare nuovamente la configurazione, se ancora non aggiornato quindi impostare di nuovo le variabili globali

    show variables like '%wait_timeout%'; 
    
    show variables like '%tx_isolation%'; 
    
    SELECT @@GLOBAL.tx_isolation, @@tx_isolation; 
    
Problemi correlati