Ich führe die folgende MySQL- UPDATE
Anweisung aus:
mysql> update customer set account_import_id = 1;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
Ich verwende keine Transaktion. Warum sollte ich diesen Fehler erhalten? Ich habe sogar versucht, meinen MySQL-Server neu zu starten, aber es hat nicht geholfen.
Die Tabelle enthält 406.733 Zeilen.
quelle
process
bis sie inaktiv sind. Wenn ja, könnten Sie diesen Fehler bekommen. Habe ich recht?connection.commit()
, verwenden Sie zum Festschreiben desINSERT
oderUPDATE
Sie haben gerade durchgeschossen.So erzwingen Sie das Entsperren für gesperrte Tabellen in MySQL:
Das Aufbrechen solcher Schlösser kann zu Atomizität führen Aufheben solcher in der Datenbank für die SQL-Anweisungen, die die Sperre verursacht haben, nicht erzwungen wird.
Dies ist hackisch und die richtige Lösung besteht darin, Ihre Anwendung zu reparieren, die die Sperren verursacht hat. Wenn jedoch Dollars auf dem Spiel stehen, bringt ein schneller Tritt die Dinge wieder in Bewegung.
1) Geben Sie MySQL ein
2) Sehen wir uns die Liste der gesperrten Tabellen an
3) Sehen wir uns die Liste der aktuellen Prozesse an. Einer von ihnen sperrt Ihre Tabelle (n).
4) Beenden Sie einen dieser Prozesse
quelle
Lösen Sie nun die Sperre erneut aus. Sie haben 100 Sekunden Zeit, um eine
SHOW ENGINE INNODB STATUS\G
an die Datenbank zu senden und festzustellen, welche andere Transaktion Ihre sperrt.quelle
lock_wait_timeout
Wert überschritten hatÜberprüfen Sie, ob Ihre Datenbank genau abgestimmt ist. Besonders die Transaktionsisolation. Es ist keine gute Idee, die Variable innodb_lock_wait_timeout zu erhöhen.
Überprüfen Sie die Isolationsstufe Ihrer Datenbanktransaktion in der MySQL-CLI:
Sie könnten Verbesserungen erhalten, wenn Sie die Isolationsstufe ändern. Verwenden Sie das Orakel wie READ COMMITTED anstelle von REPEATABLE READ (InnoDB Defaults).
Verwenden Sie SELECT FOR UPDATE auch nur, wenn dies erforderlich ist.
quelle
tx_isolation
Variable in umbenannttransaction_isolation
.Keine der vorgeschlagenen Lösungen hat bei mir funktioniert, aber das hat funktioniert.
Etwas blockiert die Ausführung der Abfrage. Höchstwahrscheinlich wird eine andere Abfrage aktualisiert, eingefügt oder aus einer der Tabellen in Ihrer Abfrage gelöscht. Sie müssen herausfinden, was das ist:
Sobald Sie den Blockierungsprozess gefunden haben, suchen Sie ihn
id
und führen Sie Folgendes aus:Führen Sie Ihre erste Abfrage erneut aus.
quelle
100% mit dem, was MarkR gesagt hat. Autocommit macht jede Anweisung zu einer Transaktion mit einer Anweisung.
SHOW ENGINE INNODB STATUS
sollte Ihnen einige Hinweise auf den Grund des Deadlocks geben. Sehen Sie sich auch Ihr langsames Abfrageprotokoll genau an, um zu sehen, was die Tabelle sonst noch abfragt, und versuchen Sie, alles zu entfernen, was einen vollständigen Tabellenscan ausführt. Das Sperren auf Zeilenebene funktioniert gut, aber nicht, wenn Sie versuchen, alle Zeilen zu sperren!quelle
Können Sie einen anderen Datensatz in dieser Tabelle aktualisieren oder wird diese Tabelle häufig verwendet? Ich denke, während des Versuchs, eine Sperre zu erhalten, die zum Aktualisieren dieses Datensatzes erforderlich ist, ist das festgelegte Zeitlimit abgelaufen. Möglicherweise können Sie die Zeit verlängern, die möglicherweise hilfreich ist.
quelle
innodb_lock_wait_timeout
inmy.cnf
Die Anzahl der Zeilen ist nicht sehr groß ... Erstellen Sie einen Index für account_import_id, wenn dies nicht der Primärschlüssel ist.
quelle
Wenn Sie gerade eine große Abfrage beendet haben, dauert es einige Zeit
rollback
. Wenn Sie eine andere Abfrage ausgeben, bevor das Zurücksetzen der getöteten Abfrage abgeschlossen ist, wird möglicherweise ein Fehler beim Sperren-Timeout angezeigt. Das ist mir passiert. Die Lösung bestand darin, ein bisschen zu warten.Einzelheiten:
Ich hatte eine DELETE-Abfrage ausgegeben, um ungefähr 900.000 aus ungefähr 1 Million Zeilen zu entfernen.
Ich habe dies versehentlich ausgeführt (entfernt nur 10% der Zeilen):
DELETE FROM table WHERE MOD(id,10) = 0
Stattdessen (entfernt 90% der Zeilen):
DELETE FROM table WHERE MOD(id,10) != 0
Ich wollte 90% der Zeilen entfernen, nicht 10%. Also habe ich den Prozess in der MySQL-Befehlszeile abgebrochen, da ich wusste, dass er alle bisher gelöschten Zeilen zurücksetzen würde.
Dann habe ich sofort den richtigen Befehl ausgeführt und
lock timeout exceeded
kurz darauf einen Fehler erhalten. Mir wurde klar, dass die Sperre tatsächlichrollback
die getötete Abfrage sein könnte, die immer noch im Hintergrund stattfindet. Also habe ich ein paar Sekunden gewartet und die Abfrage erneut ausgeführt.quelle
Stellen Sie sicher, dass die Datenbanktabellen die InnoDB-Speicher-Engine und die Transaktionsisolationsstufe READ-COMMITTED verwenden.
Sie können dies überprüfen, indem Sie SELECT @@ GLOBAL.tx_isolation, @@ tx_isolation; auf MySQL-Konsole.
Wenn es nicht auf READ-COMMITTED eingestellt ist, müssen Sie es einstellen. Stellen Sie vor dem Einstellen sicher, dass Sie über SUPER-Berechtigungen in MySQL verfügen.
Sie können Hilfe von nehmen http://dev.mysql.com/doc/refman/5.0/en/set-transaction.html erhalten .
Wenn Sie dies einstellen, wird Ihr Problem wahrscheinlich gelöst.
Möglicherweise möchten Sie auch überprüfen, ob Sie nicht versuchen, dies in zwei Prozessen gleichzeitig zu aktualisieren. Benutzer (@tala) haben in diesem Zusammenhang ähnliche Fehlermeldungen festgestellt. Überprüfen Sie möglicherweise, ob ...
quelle
Ich kam von Google und wollte nur die Lösung hinzufügen, die für mich funktioniert. Mein Problem war, dass ich versuchte, Datensätze einer riesigen Tabelle zu löschen, die viel FK in Kaskade hatte, sodass ich den gleichen Fehler wie beim OP bekam.
Ich habe das deaktiviert
autocommit
und dann hat es einfach funktioniertCOMMIT
am Ende des SQL-Satzes . Soweit ich verstanden habe, gibt dies den Puffer Stück für Stück frei, anstatt am Ende des Befehls zu warten.Um mit dem Beispiel des OP Schritt zu halten, hätte dies funktionieren müssen:
mysql> set autocommit=0;
mysql> update customer set account_import_id = 1; commit;
Vergessen Sie nicht, das
autocommit
erneut zu aktivieren , wenn Sie die MySQL-Konfiguration wie zuvor verlassen möchten.mysql> set autocommit=1;
quelle
Spät zur Party (wie üblich) war mein Problem jedoch die Tatsache, dass ich schlechtes SQL geschrieben habe (als Anfänger) und mehrere Prozesse eine Sperre für die Datensätze hatten <- nicht sicher, welche Sprache richtig ist. Am Ende musste ich nur:
SHOW PROCESSLIST
und dann die IDs mit tötenKILL <id>
quelle
So etwas passierte mir, als ich PHP Language Construct Exit verwendete. mitten in der Transaktion. Dann "hängt" diese Transaktion und Sie müssen den MySQL-Prozess beenden (oben mit Prozessliste beschrieben;)
quelle
In meinem Fall habe ich eine abnormale Abfrage ausgeführt, um Daten zu reparieren. Wenn Sie die Tabellen in Ihrer Abfrage sperren, müssen Sie sich nicht mit dem Sperrzeitlimit befassen:
Dies ist wahrscheinlich keine gute Idee für den normalen Gebrauch.
Weitere Informationen finden Sie unter: MySQL 8.0 Referenzhandbuch
quelle
Ich bin auf diese mit 2 Doctrine DBAL-Verbindungen gestoßen, von denen eine nicht transaktionsbezogen ist (für wichtige Protokolle). Sie sollen parallel laufen, unabhängig voneinander.
Meine Integrationstests wurden nach dem Test in Transaktionen für das Daten-Rollback verpackt.
Meine Lösung bestand darin, die Wrapping-Transaktion in diesen Tests zu deaktivieren und die Datenbankdaten auf andere Weise zurückzusetzen.
quelle
Hatte den gleichen Fehler, obwohl ich nur eine Tabelle mit einem Eintrag aktualisierte, aber nach dem Neustart von MySQL wurde es behoben.
quelle