Почему DROP DATABASE занимает так много времени? (Баз данных)

46

Новая установка CentOS.

Я выполнял импорт большой БД (файл 2 ГБ sql) и у меня возникла проблема. Казалось, что SSH-клиент потерял соединение, а импорт завис. Я использовал другое окно для входа в MySQL, и импорт оказался мертвым, застрявшим в определенной таблице строк 3M.

Так я попробовал

DROP DATABASE huge_db;

15-20 минут спустя ничего. В другом окне я сделал:

/etc/init.d/mysqld restart

В окне DROP DB появилось сообщение: ВЫКЛЮЧЕНИЕ СЕРВЕРА. Затем я фактически перезапустил физический сервер.

Вернулись в MySQL, проверил, и БД все еще там, побежал

DROP DATABASE huge_db;

снова и снова жду уже минут 5.

Еще раз, это свежая установка. Это huge_dbединственный БД (кроме системных БД). Клянусь, я уже давно и быстро сбросил БД, но, возможно, я ошибаюсь.

Я успешно удалил базу данных. Это заняло около 30 минут. Также обратите внимание, что я думаю, что ошибался, когда думал, что импорт mysqldump был мертв. Терминальное соединение было потеряно, но я думаю, что процесс все еще работает. Скорее всего, я убил промежуточную таблицу импорта (таблицу строк 3M) и, вероятно, 3/4 всего БД. Это вводило в заблуждение, что «top» показывал mysql, используя только 3% памяти, когда казалось, что он должен использовать больше.

Удаление БД заняло 30 минут, поэтому, опять же, мне, возможно, не пришлось перезагружать сервер и, возможно, я мог просто дождаться завершения DROP, но я не знаю, как mysql отреагирует на получение запроса DROP для тот же самый БД, который он импортирует через mysqldump.

Тем не менее, остается вопрос: почему для удаления базы данных объемом 2 ГБ требуется более 30 минут, когда все, что от нее требуется, - это удалить все файлы базы данных и удалить все ссылки на базу данных из information_schema? Подумаешь?

Баттл Буткус
источник

Ответы:

73

Вместо того, чтобы убивать процесс, было бы безопаснее, если бы вы сделали это в MySQL:

$ 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 |
+-----+------+-----------+-------------------+---------+------+-------+------------------+

Запрос с идентификатором 174 блокирует удаление базы данных 'example', поэтому, прежде чем завершить какие-либо процессы, сначала позвольте MySQL попытаться завершить запрос:

$ mysqladmin kill 174

Запустите processlistкоманду выше, чтобы подтвердить, что она была убита.

Если это не сработает, то вы можете посмотреть на уничтожение ошибочного процесса, но перед этим вы можете попробовать перезапустить сервер MySQL.

Вы также можете запустить такие команды, как 'SHOW FULL PROCESSLIST' и 'KILL 174' в оболочке MySQL, например, если у вас установлен только клиент MySQL. Суть в том, чтобы избежать уничтожения процесса с помощью команды kill в оболочке, если это не является абсолютно необходимым

Вообще говоря, вы можете использовать либо mysqlили mysqladmin. Вам не нужно часто запускать такие команды; как только вы начнете регулярно убивать запросы, что-то определенно не так, и вам лучше будет решить эту проблему (уничтожение процесса запроса - это просто устранение симптома).

Стефан Магнусон
источник
1
@BugsBuggy Распространенный способ, которым это может произойти, - это если другой процесс (например, веб-сервер или в этом случае процесс импорта) запущен и подключен к базе данных. При вводе DROP DATABASEкоманды сервер не будет работать, пока все соединения не будут закрыты.
Стефан Магнусон
11

Хотя я думал, что процесс импорта умер, он, вероятно, все еще работает.

Команда, DROP DATABASEвероятно, ожидала завершения импорта базы данных, прежде чем она запустилась.

Таким образом, вместо того, чтобы DROP DATABASEзанять много времени, это был, вероятно, только импорт.

Если кто-то прочтет это и попытается отменить импорт базы данных и удалить ее, я рекомендую сначала найти PID (идентификатор процесса) для импорта и запустить его с другого терминала:

$ kill [PID]

... где [PID] будет фактическим PID для процесса.

Вы должны сразу же увидеть остановку импорта, если другой терминал все еще подключен.

Вы также можете запустить SHOW PROCESSLISTна вкладке phpMyAdmin SQL. Получившаяся таблица показывает запущенные процессы, и нажатие «x» рядом со строкой, которую вы хотите уничтожить, должно помочь.

Тогда беги

DROP DATABASE `database_name`;

И все должно быть чисто.


Другой ответ предполагает, что убивать процесс в MySQL лучше, чем делать это извне. Я не проверял этот ответ, но он звучит очень правдоподобно. Поэтому я пометил его как «принятый ответ» вместо этого.

Баттл Буткус
источник
3

Попробуйте обрезать самые большие таблицы в базе данных youra перед тем, как ее отбросить. Я видел очень похожее поведение при работе с MySQL-архивами трафика межсетевого экрана, и это очень помогло.

Тим Бригам
источник
Согласно документации MySQL, «операции усечения удаляют и воссоздают таблицу, что намного быстрее, чем удаление строк по одной», поэтому нет смысла урезать, чтобы отбрасывать - dev.mysql.com/doc/refman/8.0/en/ truncate-table.html
ejoubaud
3

Я столкнулся с той же проблемой. Но на этот раз я проверил список процессов шоу; он сказал, что проверка разрешений на более длительное время. Затем я обнаружил, что mysqld_safe работает от имени пользователя root, тогда как разрешения на уровне папок были только для пользователя mysql. Следовательно, я убил запрос, конечно, это заняло много времени, сказав, что он в состоянии «убит», но я ждал, пока он отреагирует, затем он убил запрос и изменил разрешения уровня папки на root, добавив его в group и chmod к 770. Затем я выполнил та же самая база данных отбрасывания бла; это сработало для меня за 2 секунды для базы данных объемом 20 ГБ.

Mannoj
источник