Zeigen Sie offene Transaktionen in MySQL an

95

Ich habe einige Abfragen ohne Commit durchgeführt. Dann wurde die Anwendung gestoppt.

Wie kann ich diese offenen Transaktionen anzeigen und festschreiben oder abbrechen?

Alex
quelle
Ich denke, alle Ihre Transaktionen werden beim Trennen abgebrochen, aber nicht 100% sicher.
Johan
Welche Art von Tabellen verwenden Sie? MyISAM, InnoDB usw.?
Cdeszaq
@cdeszaq, offensichtlich nicht MyISAM, es hat keine Transaktionen, außerdem hat die Frage wirklich nichts mit Tabellen zu tun.
Johan
2
@Johan - Ich habe MyISAM nur als Beispiel für den Tabellentyp angegeben. Und es ist sehr viel tut Angelegenheit, weil nicht alle Tabellen , dass die Unterstützung Transaktionen die gleiche Art und Weise in Bezug auf Transaktionen auf Verbindungsverlust verhalten.
Cdeszaq
@cdeszaq, Die MySQL-Dokumente geben etwas ganz anderes an.
Johan

Antworten:

60

Wie kann ich diese offenen Transaktionen anzeigen und festschreiben oder abbrechen?

Es gibt keine offene Transaktion. MySQL setzt die Transaktion beim Trennen der Verbindung zurück.
Sie können die Transaktion (IFAIK) nicht festschreiben.

Sie zeigen Threads mit an

SHOW FULL PROCESSLIST  

Siehe: http://dev.mysql.com/doc/refman/5.1/en/thread-information.html

Dies hilft Ihnen nicht, da Sie keine Transaktion über eine unterbrochene Verbindung festschreiben können.

Was passiert, wenn eine Verbindung unterbrochen wird?
Aus den MySQL-Dokumenten: http://dev.mysql.com/doc/refman/5.0/en/mysql-tips.html

4.5.1.6.3. Deaktivieren von MySQL Auto-Reconnect

Wenn der MySQL-Client beim Senden einer Anweisung seine Verbindung zum Server verliert, versucht er sofort und automatisch, erneut eine Verbindung zum Server herzustellen und die Anweisung erneut zu senden. Allerdings , auch wenn mysql in der Wiederverbindung mit dem ersten Verbindung erfolgreich beendet ist und alle Ihre vorherige Sitzung Objekte und Einstellungen verloren gehen : temporäre Tabellen, die Autocommitmodus und benutzerdefiniert und Session - Variablen. Außerdem wird jede aktuelle Transaktion zurückgesetzt .

Dieses Verhalten kann für Sie gefährlich sein, wie im folgenden Beispiel, in dem der Server zwischen der ersten und der zweiten Anweisung heruntergefahren und neu gestartet wurde, ohne dass Sie es wissen:

Siehe auch: http://dev.mysql.com/doc/refman/5.0/en/auto-reconnect.html

So diagnostizieren und beheben Sie dies
So überprüfen Sie die automatische Wiederverbindung:

Wenn eine automatische Wiederverbindung auftritt (z. B. durch Aufrufen von mysql_ping ()), gibt es keinen expliziten Hinweis darauf. Um nach einer erneuten Verbindung zu suchen, rufen Sie mysql_thread_id()an, um die ursprüngliche Verbindungskennung zu erhalten, bevor Sie anrufen mysql_ping(), und rufen Sie dann mysql_thread_id()erneut an, um festzustellen, ob sich die Kennung geändert hat.

Stellen Sie sicher, dass Sie Ihre letzte Abfrage (Transaktion) im Client behalten, damit Sie sie bei Bedarf erneut senden können.
Deaktivieren Sie den automatischen Wiederverbindungsmodus, da dies gefährlich ist. Implementieren Sie stattdessen Ihre eigene Wiederverbindung, damit Sie wissen, wann ein Verbindungsabbruch auftritt, und diese Abfrage erneut senden können.

Johan
quelle
Das hat nichts mit der Frage zu tun. Dies wirkt sich nur auf den MySQL-Client aus, und das OP spricht von einer generischen Anwendung, was wahrscheinlich seine Anwendung bedeutet . Wie kann die aufrufende Anwendung die Transaktion im Speicher behalten, da sie gestoppt wurde?
Cdeszaq
@cdeszaq, es hat alles mit der Frage zu tun. Eine Anwendung verwendet normalerweise mysqld.dllAKA, den Client. Und Sie behalten die SQL-Anweisung , die die vollständige Transaktion enthält, im Speicher, damit Sie sie wiedergeben können, wenn die Verbindung unterbrochen wird. Oder Sie speichern es lokal auf der Festplatte, damit Sie es beim Neustart erneut senden können.
Johan
In der SHOW FULL PROCESSLIST wird nur mein Prozesslistenbefehl angezeigt. Ich denke, es gibt einfach keine offenen Transaktionen. Der lustige Teil ist, dass die autoincrement_ids verloren zu sein scheinen.
Alex
@alex die offiziellen Dokumente geben das an, so dass das Verhalten dokumentiert ist. Siehe die Links.
Johan
Schön, Johan. Beantwortete die Frage und zeigte einige Konsequenzen und die Lösungen für diese Konsequenzen, alle innerhalb weniger Absätze.
Gerard ONeill
52

Obwohl in diesem Fall keine Transaktion übrig bleibt, wie @Johan sagte, können Sie die aktuelle Transaktionsliste in InnoDB mit der folgenden Abfrage anzeigen, wenn Sie möchten.

SELECT * FROM information_schema.innodb_trx\G

Aus dem Dokument :

Die Tabelle INNODB_TRX enthält Informationen zu jeder Transaktion (ausgenommen schreibgeschützte Transaktionen), die derzeit in InnoDB ausgeführt wird, einschließlich der Frage, ob die Transaktion beim Start der Transaktion auf eine Sperre wartet, und der SQL-Anweisung, die die Transaktion ausführt, falls vorhanden.

Sanghyun Lee
quelle
Nehmen Sie nicht an, dass Sie feststellen können, ob die Transaktionen in dieser Tabelle zu Ihrer spezifischen Anforderung / Sitzung gehören.
Captain Hypertext
1
Bitte beachten Sie, dass der \GModifikator am Ende nur nützlich ist, wenn Sie die Abfrageausgabe im MySQL-CLI-Tool formatieren möchten. Wenn Sie ein GUI-Tool wie MySQL Workbench verwenden, benötigen Sie es nicht.
Barell
29

Sie können show innodb status(oder show engine innodb statusfür neuere Versionen von MySQL) verwenden, um eine Liste aller derzeit in der InnoDB-Engine anstehenden Aktionen abzurufen. In der Wand der Ausgabe sind die Transaktionen und die interne Prozess-ID vergraben, unter der sie ausgeführt werden.

Sie können ein Commit oder Rollback dieser Transaktionen nicht erzwingen, aber Sie KÖNNEN den MySQL-Prozess beenden, der sie ausführt, was im Wesentlichen auf ein Rollback hinausläuft. Es unterbricht die Verbindung der Prozesse und bewirkt, dass MySQL das verbleibende Chaos beseitigt.

Folgendes möchten Sie suchen:

------------
TRANSACTIONS
------------
Trx id counter 0 140151
Purge done for trx's n:o < 0 134992 undo n:o < 0 0
History list length 10
LIST OF TRANSACTIONS FOR EACH SESSION:
---TRANSACTION 0 0, not started, process no 17004, OS thread id 140621902116624
MySQL thread id 10594, query id 10269885 localhost marc
show innodb status

In diesem Fall besteht derzeit nur eine Verbindung zur InnoDB-Engine (mein Login, Ausführen der showAbfrage). Wenn diese Zeile eine tatsächliche Verbindung / feststeckende Transaktion wäre, die Sie beenden möchten, würden Sie eine kill 10594.

Marc B.
quelle
Es ist wirklich nicht erforderlich, eine Verbindung nach einer Zeitüberschreitung aktiv zu beenden. Die Verbindung wird ohnehin beendet, und ausstehende Transaktionen von einer unterbrochenen Verbindung können nicht festgeschrieben werden, sodass sie ohne Angst vor Duplikaten erneut gesendet werden können.
Johan
3
Es ist besser, die festgefahrenen Transaktionen zu beenden, ohne auf eine Zeitüberschreitung beim Aufräumen zu warten. Andernfalls riskieren Sie Deadlocks.
Marc B
Ah ja, +1 für diesen Kommentar. Ich habe diese Deadlocks für eine Minute vergessen.
Johan
@MarcB, warum haben sie es geändert show engine innodb status?
Pacerier
1

Mit dieser Abfrage können Sie alle offenen Transaktionen anzeigen.

Alles auflisten:

SHOW FULL PROCESSLIST  

Wenn Sie eine Hang-Transaktion beenden möchten, kopieren Sie die Transaktions-ID und beenden Sie die Transaktion mit diesem Befehl:

KILL <id>    // e.g KILL 16543
M. Hamza Rajput
quelle