Завис процесс MySQL / PostgreSQL в Linux: как принудительно завершить процесс
Почему зависают процессы СУБД и чем это опасно
Иногда «тяжелый» SQL-запрос (например, формирование сложного отчета за 5 лет или неудачная блокировка таблицы) намертво вешает сервер базы данных. Нагрузка на процессор улетает в 100%, память забивается, а сайты и 1С перестают отвечать. Если попытаться остановить службу через systemctl stop mysql, сервер может бесконечно ждать ответа от зависшего потока.
Симптомы зависшего процесса базы данных
- База данных перестает принимать новые входящие подключения.
- Сайты выдают ошибки
504 Gateway Time-outилиError establishing a database connection. - В выводе монитора процессов утилита
mysqldилиpostgresнепрерывно грузит CPU и не реагирует на стандартные команды перезапуска.
| Способ завершения | Сигнал ядра | Безопасность для данных |
|---|---|---|
KILL QUERY / pg_terminate_backend | Внутри СУБД | Максимально безопасный: штатная отмена запроса движком. |
kill PID (SIGTERM) | 15 | Безопасный: процесс успевает сбросить транзакции на диск. |
kill -9 PID (SIGKILL) | 9 | Экстренный: немедленное уничтожение ядром (может запустить Crash Recovery). |
Пошаговый алгоритм: как найти и убить зависший процесс базы данных
Шаг 1: Попытка отменить зависший запрос внутри самой СУБД
Всегда начинайте с мягкой остановки на уровне самой базы, чтобы не повредить таблицы InnoDB или страницы PostgreSQL.
Для MySQL / MariaDB:
sudo mysql -e "SHOW FULL PROCESSLIST;"Найдите Id зависшего запроса (колонка Id) и завершите только его:
sudo mysql -e "KILL 12345;"Для PostgreSQL:
sudo -u postgres psql -c "SELECT pid, now() - pg_stat_activity.query_start AS duration, query FROM pg_stat_activity WHERE state != 'idle';"Завершите конкретный проблемный процесс по его PID:
sudo -u postgres psql -c "SELECT pg_terminate_backend(12345);"Шаг 2: Поиск системного PID через htop или pgrep
Если СУБД зависла целиком и консоль базы не открывается, найдем системный идентификатор процесса (PID) в Linux:
pgrep -l mysqld
или для Postgres:
pgrep -l postgresШаг 3: Мягкое завершение службы (SIGTERM)
Отправьте мягкий запрос на остановку процесса:
sudo kill 12345Подождите 15-20 секунд, чтобы база данных успела корректно закрыть файлы таблиц.
Шаг 4: Экстренное уничтожение через kill -9 (SIGKILL) или htop
Если процесс висит в мертвом цикле и не реагирует на обычный kill, примените принудительное уничтожение:
sudo kill -9 12345Через интерактивный монитор htop: установите htop (sudo apt install htop), запустите его, найдите процесс стрелками, нажмите клавишу F9, выберите в меню слева сигнал 9 (SIGKILL) и нажмите Enter.
Шаг 5: Перезапуск и проверка службы
sudo systemctl restart mysql
или
sudo systemctl restart postgresqlТиповые ошибки администраторов
- Применение kill -9 без предварительной попытки мягкого завершения: Жесткое уничтожение СУБД приводит к тому, что при следующем запуске базе потребуется длительное восстановление из журналов предзаписи (WAL / Redo Log), что увеличивает время простоя.
- Игнорирование процессов в состоянии D (Uninterruptible Sleep): Если процесс завис в состоянии D (ожидание зависшего жесткого диска или сетевой шары NFS), команда
kill -9не сработает до тех пор, пока не восстановится работа дисковой подсистемы.
Инженеры ITSTM настроят пул соединений PgBouncer / ProxySQL, оптимизируют медленные запросы и обеспечат отказоустойчивую репликацию ваших СУБД.
Частые вопросы (FAQ)
Повредит ли kill -9 базу данных MySQL?
Современные движки (InnoDB) обладают высокой устойчивостью к сбоям (Crash-Safe). При старте служба автоматически накатит незавершенные транзакции из redo-лога, однако сам процесс восстановления может занять от пары минут до нескольких часов.
Почему процесс не завершается даже после команды kill -9?
Процесс находится в режиме непрерываемого сна (статус D в top/htop), ожидая ответа от диска, файловой системы или медленного сетевого хранилища.
Как убить сразу все зависшие сессии конкретного пользователя базы данных?
В PostgreSQL можно выполнить команду: SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE usename = 'bad_user'; В Linux можно воспользоваться утилитой pkill: sudo pkill -u postgres.
В чем разница между командами KILL QUERY и KILL CONNECTION в MySQL?
KILL QUERY останавливает только выполняющийся в данный момент тяжелый SQL-запрос, оставляя само соединение клиента активным. KILL CONNECTION полностью разрывает сетевую сессию пользователя.