2015-04-07 11 views
13

Wir haben viele Fehler zu sehen, vor kurzem: dahinterRelease von MySQL sperrt außerhalb Transaktion (Schienen)

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

Nicht in der Lage, um herauszufinden, die Argumentation. Aber bemerkte eine Sache in unserem Code, der einen Datensatz außerhalb Transaktion zu sperren versucht:

acc = Account.lock.find acc_id 

Above-Code ist nicht innerhalb einer Transaktion und wird verwendet, nur um zu prüfen, ob die andere Transaktion, die auch die gleiche Sperre erhält beendet ist oder nicht. Irgendwelche Gedanken darüber, ob dies der Schuldige sein kann?

Antwort

0

Überprüfen Sie, was auf Ihrem MySQL-Server für innodb_lock_wait_timeout und lock_wait_timeout konfiguriert ist. Sie können dies tun, indem Sie den folgenden Befehl ausführen

show global variables like '%lock_wait_timeout';

Welche dieser Parameter verwendet wird auf Ihrer Version von MySQL und den Motor des Tisches

aus der Dokumentation ab:

# Wählen Sie * aus Konten mit ID = 1 für das Update

Account.lock.find(1)

for update bedeutet - erwerben Sie eine Sperre für schreiben.

Wahrscheinlich dauert Ihre Transaktion länger als auf Ihrer Datenbank konfiguriert, und die Prüfanforderung, die versucht, die ursprüngliche Transaktion zu überprüfen, wurde beendet - diese Fehlermeldung wird angezeigt, wenn die Wartezeit abgelaufen ist.

1

Die InnoDB verwenden Sperren auf Zeilenebene für bessere Parallelität bei hoher Schreiblast. Engine ergreift einige Vorkehrungen, um Phantom-Lesevorgänge zu entfernen, von denen einer Gap_lock ist, der dieses Problem verursachen kann. Verwenden Sie

SHOW ENGINE INNODB STATUS 

, um über Gap_lock zu analysieren.

Wenn diese Proble ist, können Sie versuchen, folgende Optionen

  1. Ändern der ISOLATION Ebene READ COMMITTED.

  2. set innodb_locks_unsafe_for_binlog = 1. Dadurch werden die Lückensperren deaktiviert, mit Ausnahme der Prüfung auf Fremdschlüsseleinschränkungen oder der Überprüfung von doppelten Schlüsseln.

  3. Verwenden Sie erneut show innodb status, um zu analysieren, was vor sich geht.Bei Bedarf Ihren Code optimieren zu vermeiden

  4. Sperren Wenn oben nicht funktioniert, versuchen lock_wait_timeout global

SET GLOBAL innodb_lock_wait_timeout = 120 zu erhöhen;

Oder für eine Sitzung

SET innodb_lock_wait_timeout = 120; 
  1. wieder Ihre Konfiguration überprüfen, wenn noch nicht aktualisiert, dann globale Variablen setzen wieder

    show variables like '%wait_timeout%'; 
    
    show variables like '%tx_isolation%'; 
    
    SELECT @@GLOBAL.tx_isolation, @@tx_isolation; 
    
Verwandte Themen