Warum dauert DROP DATABASE so lange? (MySQL)

46

Neue CentOS-Installation.

Ich habe einen Import einer großen Datenbank (2 GB SQL-Datei) ausgeführt und hatte ein Problem. Der SSH-Client schien die Verbindung zu verlieren und der Import schien einzufrieren. Ich benutzte ein anderes Fenster, um mich bei MySQL anzumelden, und der Import schien tot zu sein und auf einer bestimmten 3M-Zeilentabelle festzustecken.

Also habe ich es versucht

DROP DATABASE huge_db;

15-20 Minuten später nichts. In einem anderen Fenster tat ich:

/etc/init.d/mysqld restart

Das DROP DB-Fenster meldete: SERVER SHUTDOWN. Dann habe ich tatsächlich den physischen Server neu gestartet.

Zurück in MySQL eingeloggt, überprüft und die Datenbank war noch da, lief

DROP DATABASE huge_db;

wieder und wieder warte ich schon ca 5 minuten.

Es ist wieder eine Neuinstallation. Das huge_dbist die einzige db (außer System dbs). Ich schwöre, ich habe db's so schnell fallen lassen, aber vielleicht irre ich mich.

Ich habe die Datenbank erfolgreich gelöscht. Es dauerte ungefähr 30 Minuten. Beachten Sie auch, dass ich mich geirrt habe, als ich dachte, der mysqldump-Import sei tot. Die Terminalverbindung wurde unterbrochen, aber ich glaube, der Prozess lief noch. Ich habe höchstwahrscheinlich den Import-Mid-Table (die 3M-Zeilentabelle) und wahrscheinlich 3/4 der gesamten Datenbank getötet. Es war irreführend, dass "top" zeigte, dass mysql nur 3% des Arbeitsspeichers beanspruchte, wenn es so aussah, als ob es mehr verwenden sollte.

Das Löschen der Datenbank dauerte letztendlich 30 Minuten, daher musste ich den Server möglicherweise nicht neu starten und hätte möglicherweise nur auf den Abschluss des DROP warten müssen, aber ich weiß nicht, wie mysql auf das Abrufen einer DROP-Abfrage für reagieren würde Dieselbe Datenbank, die über mysqldump importiert wird.

Es bleibt jedoch die Frage, warum das DROP einer 2-GB-Datenbank 30 Minuten + dauert, wenn alles, was zu tun ist, das Löschen aller DB-Dateien und das Entfernen aller Verweise auf die DB aus information_schema ist. Was ist die große Sache?

Buttle Butkus
quelle

Antworten:

73

Anstatt den Prozess zu beenden, wäre es sicherer, wenn Sie dies in MySQL tun würden:

$ mysqladmin processlist -u root -p
Enter password: 
+-----+------+-----------+-------------------+---------+------+-------+------------------+
| Id  | User | Host      | db                | Command | Time | State | Info             |
+-----+------+-----------+-------------------+---------+------+-------+------------------+
| 174 | root | localhost | example           | Sleep   | 297  |       |                  |
| 407 | root | localhost |                   | Query   | 0    |       | show processlist |
+-----+------+-----------+-------------------+---------+------+-------+------------------+

Die Abfrage mit der ID 174 blockiert das Löschen der 'Beispiel'-Datenbank. Bevor Sie also einen Prozess beenden, lassen Sie MySQL versuchen, die Abfrage zu beenden:

$ mysqladmin kill 174

Führen Sie den processlistobigen Befehl erneut aus, um zu bestätigen, dass er beendet wurde.

Wenn dies nicht funktioniert, könnten Sie vielleicht versuchen, den fehlerhaften Prozess zu beenden, aber vorher könnten Sie versuchen, den MySQL-Server neu zu starten.

Sie können auch Befehle wie 'SHOW FULL PROCESSLIST' und 'KILL 174' in der MySQL-Shell ausführen, wenn Sie beispielsweise nur den MySQL-Client installiert haben. Der wichtigste Punkt ist, zu vermeiden, dass der Prozess mit 'kill' in der Shell beendet wird, es sei denn, dies ist absolut notwendig.

Im Allgemeinen können Sie entweder mysqloder verwenden mysqladmin. Sie sollten jedoch nicht so oft solche Befehle ausführen müssen. Sobald Sie regelmäßig Abfragen beenden, stimmt auf jeden Fall etwas nicht, und Sie sollten dieses Problem besser beheben (das Beenden des Abfrageprozesses behandelt nur das Symptom).

Stefan Magnuson
quelle
1
@BugsBuggy Dies kann häufig auftreten, wenn ein anderer Prozess (z. B. ein Webserver oder in diesem Fall ein Importprozess) ausgeführt wird und mit der Datenbank verbunden ist. Wenn Sie den DROP DATABASEBefehl absetzen, fährt der Server erst fort, nachdem alle Verbindungen geschlossen wurden.
Stefan Magnuson
11

Obwohl ich dachte, der Importprozess sei gestorben, lief er wahrscheinlich noch.

Der DROP DATABASEBefehl hat wahrscheinlich darauf gewartet, dass die Datenbank den Import beendet, bevor sie ausgeführt wurde.

Also, anstatt DROP DATABASElange zu dauern, war es wahrscheinlich nur der Import.

Wenn jemand dies liest und versucht, einen Datenbankimport abzubrechen und die Datenbank zu löschen, empfehle ich, zuerst die PID (Prozess-ID) für den Import zu ermitteln und diese von einem anderen Terminal aus auszuführen:

$ kill [PID]

... wobei [PID] die tatsächliche PID für den Prozess wäre.

Der Import sollte sofort angehalten werden, wenn das andere Terminal noch verbunden ist.

Sie können auch SHOW PROCESSLISTdie Registerkarte phpMyAdmin SQL aufrufen. Die sich daraus ergebende Tabelle zeigt die laufenden Prozesse, und ein Klick auf das 'x' neben der Zeile, die Sie beenden möchten, sollte den Trick ausführen.

Dann renne

DROP DATABASE `database_name`;

Und alles sollte sauber sein.


Eine andere Antwort schlug vor, dass es besser ist, den Prozess in MySQL zu beenden, als ihn von außen zu tun. Ich habe diese Antwort nicht getestet, aber es klingt sehr plausibel. Also habe ich es als die "akzeptierte Antwort" anstatt dieser markiert.

Buttle Butkus
quelle
3

Versuchen Sie, die größten Tabellen in Ihrer Datenbank zu kürzen, bevor Sie sie löschen. Bei der Arbeit mit MySQL-Archiven mit Firewall-Verkehr habe ich ein sehr ähnliches Verhalten festgestellt, das mir sehr geholfen hat.

Tim Brigham
quelle
Laut MySQL - Dokumentation „Leerungsoperationen löschen und neu erstellen die Tabelle, die viel schneller als Löschen von Zeilen einer nach der anderen ist“, so keine Stelle in Kürzen fallen - dev.mysql.com/doc/refman/8.0/en/ truncate-table.html
Ejoubaud
3

Ich hatte das gleiche Problem. Aber diesmal habe ich die Show Processlist überprüft. Es hieß, dass für längere Zeit nach Berechtigungen gesucht wird. Dann stellte ich fest, dass mysqld_safe als root ausgeführt wurde, wohingegen Berechtigungen auf Ordnerebene nur für mysql-Benutzer galten. Daher habe ich die Abfrage abgebrochen. Natürlich hat es lange gedauert, bis der Status "Abgebrochen" angezeigt wurde, aber ich habe darauf gewartet, dass sie reagiert. Dann hat sie die Abfrage abgebrochen und die Berechtigungen auf Ordnerebene auf "root" geändert, indem sie auch zu "group" und "chmod" zu "770" hinzugefügt wurde. Dann habe ich ausgeführt die gleiche Drop-Datenbank blah; es hat für mich in 2 Sekunden für 20 GB Datenbank funktioniert.

Mannoj
quelle