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) и при необходимости обновите систему.

    Часто задаваемые вопросы