PostgreSQL зависает на Alpine Linux в VirtualBox: причины и решение
Ситуация, когда веб-сервер на базе Alpine Linux, Nginx, PHP-FPM и PostgreSQL внезапно перестаёт отвечать, знакома многим администраторам. Особенно неприятно, когда база данных входит в ступор, а Load average взлетает до 16 и выше. В этой статье мы разберём типичные причины такого поведения, как диагностировать проблему и что делать, если kill не помогает.
Почему PostgreSQL зависает и не реагирует на сигналы?
Из логов видно, что процесс postgres (PID 9805) работает уже 11 часов 24 минуты, а в dmesg появляется сообщение watchdog: BUG: soft lockup - CPU#0 stuck for 37522s!. Это означает, что ядро Linux обнаружило зависший поток на CPU, который не переключается более 37 тысяч секунд. Причина - часто в бесконечном цикле внутри кода СУБД или драйвера диска, особенно при работе в виртуализированной среде VirtualBox.
Команда kill 9805 не завершает процесс, потому что процесс находится в непрерываемом состоянии (D state) - ожидает завершения операции ввода-вывода, которая никогда не завершится. Это типично для ситуаций, когда дисковая подсистема или файловая система зависает.
Как правильно диагностировать проблему
Прежде чем перезагружать виртуальную машину, выполните следующие шаги:
- Проверьте
dmesg -Tна наличие сообщений soft lockup или rcu stall. - Посмотрите
ps auxна процессы в состоянии D (uninterruptible sleep). - Используйте
strace -p 9805илиgdb, чтобы понять, на каком системном вызове завис процесс. - Проверьте логи PostgreSQL (
postmaster.log) на наличие FATAL: the database system is shutting down - это указывает на некорректное завершение.
Почему не срабатывает стандартный перезапуск?
Команда sudo /etc/init.d/postgresql restart пытается отправить сигнал SIGTERM процессу, но если процесс в состоянии D, сигнал не доставляется. start-stop-daemon сообщает 1 process refused to stop. В таких случаях требуется более агрессивное вмешательство.
Как решить проблему без перезагрузки ВМ
Если процесс не убивается через kill, попробуйте следующие методы:
- Используйте kill -9 - иногда даже
SIGKILLне срабатывает для процессов в D state, но попробовать стоит. - Перезагрузите только службу PostgreSQL через
rc-service postgresql restart(Alpine). - Сбросьте диск через sysrq - если проблема в диске, выполните
echo 1 > /proc/sys/kernel/sysrq, затемecho b > /proc/sysrq-triggerдля принудительной перезагрузки (аварийный вариант). - Используйте magic SysRq для разблокировки -
echo f > /proc/sysrq-triggerвызывает OOM killer, который может завершить зависший процесс.
Однако в большинстве случаев, как и в вашем, единственный надёжный способ - полная перезагрузка виртуальной машины. После перезагрузки обязательно проверьте целостность базы данных.
Как предотвратить повторение
Чтобы избежать таких сбоев в будущем, выполните следующие рекомендации:
- Настройте мониторинг процессов PostgreSQL и Load average (например, через Prometheus + Alertmanager).
- Обновите VirtualBox и гостевые дополнения - ошибка
vmwgfx seems to be running on an unsupported hypervisorуказывает на несовместимость драйверов. - Настройте autovacuum и statement_timeout в PostgreSQL, чтобы предотвратить долгие запросы.
- Увеличьте shared_buffers и work_mem, если база активно используется.
- Рассмотрите миграцию на более стабильную гипервизорную платформу (KVM, VMware) или используйте Docker для изоляции.
Ошибка vmwgfx после перезагрузки
Сообщение [drm] *ERROR* vmwgfx seems to be running on an unsupported hypervisor не связано напрямую с зависанием PostgreSQL, но указывает на проблемы с графическим драйвером VirtualBox. Это может вызывать дополнительные задержки ввода-вывода. Рекомендуется отключить 3D-ускорение в настройках ВМ и обновить гостевые дополнения.
Если проблема повторяется, проверьте версию ядра Alpine (uname -r) и при необходимости обновите систему.