После обновления mailcow MariaDB сыплет ошибками: reset_password, column_stats и код 1442
Панель mailcow работает, почта ходит, но лог MariaDB после очередного update.sh забит ошибками — то про несуществующую таблицу reset_password, то про несовпадение типов в column_stats, то про код 1442 в триггере mailbox. Показываю три разных реальных сценария из issue-трекера mailcow, чем они отличаются и что с каждым реально делать, на кейсе самиздат-лаборатории на 15 рабочих мест.
Ошибка в логе MariaDB после обновления — это не всегда авария
Первая реакция на новую строку в логах MariaDB после апгрейда почтового сервера — откатить контейнер назад или сразу лезть чинить руками. Я так не делаю, пока не разобрался, к какой из трёх принципиально разных категорий относится ошибка: ломает ли она реальную функциональность прямо сейчас, или база просто «шумит» несоответствием схемы, которое давно никому не мешает. Разница критична, потому что цена ошибочного вмешательства в системные таблицы MariaDB куда выше, чем цена нескольких строк в логе.
На issue-трекере mailcow на GitHub я нашёл ровно три разных, документированных сообщества сценария, которые внешне выглядят похоже — «после обновления MariaDB ругается» — а по сути требуют разных действий. Дальше разбираю каждый: что именно происходит, откуда берётся и чем заканчивается.
Сценарий 1: reset_password не существует в engine, код 1932
В issue #6348 админ поднимал mailcow с версии 2023-12a сразу до 2025-02 — большой скачок через несколько релизов. После обновления интерфейс замедлился, а панель начала выдавать ошибку с кодом 1932: Table 'mailcow.reset_password' doesn't exist in engine, источник — файл /web/inc/init_db.inc.php на строке 1157. В логах при этом стоял MariaDB 10.11.11-MariaDB-ubu2204 — версия подтянулась штатно, проблема не в самой MariaDB, а в конкретной таблице приложения mailcow. Причём таблица в SHOW TABLES была видна — «doesn't exist in engine» означает, что InnoDB не может её открыть, хотя описание таблицы на месте. Автор восстановил бэкап, повторил обновление и получил то же самое, а разработчик в обсуждении предположил, что база повредилась во время обновления или ещё до него: то есть бэкап уже содержал сломанную таблицу.
Автор проблемы пробовал запустить mysql_upgrade -p --force вручную и продолжал получать тот же код 1932 и SQLSTATE[42S02] (таблица не найдена). Это ожидаемо: mysql_upgrade/mariadb-upgrade обновляет системные таблицы в базе mysql — добавляет новые поля туда, где ожидает MariaDB, — и прогоняет проверку пользовательских таблиц (CHECK TABLE … FOR UPGRADE). Но он не создаёт заново прикладную таблицу reset_password, если она физически отсутствует или повреждена: это таблица приложения mailcow, а не системный объект MariaDB, и утилита mariadb-upgrade её попросту не касается.
Из этого следует практический вывод: большой скачок версий (несколько релизов за раз) — сам по себе фактор риска для промежуточных миграций схемы, которые должны были отработать по очереди. Я стараюсь не пропускать релизы mailcow на боевых серверах именно по этой причине — регулярные обновления небольшими шагами снижают шанс попасть в ситуацию, где одна из промежуточных миграций частично не выполнилась.
Сценарий 2: column_stats ругается на hist_type и histogram, но почта работает
В issue #6349, тоже после обновления до mailcow 2025-02, в логах MariaDB появились две конкретные ошибки про системную таблицу mysql.column_stats: несовпадение типа поля hist_type (ожидался enum с тремя значениями, включая JSON_HB, а фактически в базе было только два — без JSON_HB) и несовпадение типа поля histogram (ожидался longblob, а фактически был varbinary(255)). Это прямое следствие перехода MariaDB с 10.5 на 10.11: формат системной таблицы статистики менялся между версиями, и новый сервер ругается на старую структуру, пока системные таблицы не обновлены. В mailcow mariadb-upgrade запускает не сам контейнер mysql-mailcow, а entrypoint php-fpm-mailcow при старте, поэтому в первые секунды после обновления такие строки в логе появляются почти у всех — участники обсуждения видели их один раз, в момент апгрейда, и больше никогда.
Важное отличие от первого сценария: несмотря на ошибки в логе, вся функциональность mailcow у автора issue продолжала работать в штатном режиме — контейнеры поднимались, почта ходила, включая интеграции через Fetchmail. Это классический случай, когда ошибка в логе не равна аварии: mysql.column_stats используется оптимизатором запросов MariaDB для сбора статистики по гистограммам данных, и её частичное несоответствие формату не блокирует базовые операции INSERT/SELECT/UPDATE, которыми живёт mailcow.
Issue в итоге закрыл бот как устаревший (статус not planned) — отдельного патча в mailcow не понадобилось. Разработчики в обсуждении предложили ровно тот инструмент, для которого эта ошибка и существует: source mailcow.conf, затем docker compose exec mysql-mailcow mariadb-upgrade -p$DBROOT -f. У одного из участников после этого и нескольких перезапусков стека ошибки ушли. На практике я сначала подтверждаю, что реальных сбоев нет, смотрю, повторяется ли ошибка после рестарта или была разовой в момент апгрейда, и только если повторяется — делаю бэкап и запускаю mariadb-upgrade. Руками ALTER TABLE по системной таблице mysql.column_stats по советам с форумов я не выполняю.
Сценарий 3: SQLSTATE 1442 при смене пароля — триггер update_sogo_static_view
Третий сценарий совсем другой природы. В issue #6423, после обновления до mailcow 2025.03a, смена пароля ящика через веб-интерфейс стала падать с ошибкой SQLSTATE[HY000]: General error: 1442 Can't update table 'mailbox' in stored function/trigger because it is already used by statement which invoked this stored function/trigger. По стеку видно цепочку: json_api.php вызывает edit_user_account(), та — update_sogo_static_view() в /web/inc/functions.inc.php, и на выполнении запроса внутри неё MariaDB возвращает 1442. Смысл ошибки: сработавший триггер пытается изменить таблицу mailbox, которую уже использует вызвавший его оператор, — MariaDB такое изменение изнутри триггера запрещает.
Здесь причина не в миграции версии MariaDB, а в устаревшем SQL-объекте, оставшемся в базе от старой схемы SOGo: разработчики mailcow сами признали проблему и в релизе 2025-09b (ревизия от 12 сентября 2025 года) выпустили исправление — PR #6727 «Drop deprecated sogo_update_password sql trigger if it still exists». Удаление выполняет скрипт bootstrap-sogo.sh при старте контейнера sogo-mailcow (DROP TRIGGER IF EXISTS sogo_update_password), образ SOGo в том же релизе подняли до 1.135. Это значит: если ошибка 1442 при смене пароля появилась на версии до 2025-09b, обновление до неё и выше само устраняет первопричину, а не просто прячет симптом.
Проверить, остался ли у вас в базе такой устаревший триггер, можно командой SHOW TRIGGERS FROM mailcow — она показывает все определённые в базе триггеры: имя, таблицу, событие (INSERT/UPDATE/DELETE) и момент срабатывания (BEFORE/AFTER). Выполнение требует привилегии TRIGGER, поэтому я запускаю её от root из каталога mailcow: source mailcow.conf, затем docker compose exec mysql-mailcow mysql -uroot -p$DBROOT -e "SHOW TRIGGERS FROM mailcow\G". Делаю это при каждой жалобе на странные ошибки при редактировании ящиков ещё до того, как искать issue на GitHub: лишний триггер с именем из старой схемы виден сразу.
MariaDB 10.5 → 10.11: почему откат версии не выход
Все три сценария выше объединяет один и тот же фон: релиз mailcow 2025-02 (27 февраля 2025 года) перевёл MariaDB с 10.5 на 10.11 — существенный скачок мажорных версий с изменением формата ряда системных таблиц. Разработчики mailcow прямо предупредили в анонсе релиза: откат невозможен — после того как базы мигрированы на 10.11, вернуться на 10.5 нельзя. Отдельно там же есть предостережение не менять версию образа MariaDB вручную в docker-compose.yml: это может привести к повреждению базы, если код приложения не адаптирован под другую версию, потому что весь остальной mailcow уже рассчитан на работу именно с 10.11.
Отсюда практическое правило, которое я соблюдаю на всех боевых серверах: перед любым крупным обновлением mailcow с изменением версии MariaDB — свежий бэкап базы отдельно от штатного backup-скрипта mailcow, и проверка этого бэкапа восстановлением на тестовом окружении, а не просто факт его создания. Если что-то пойдёт не так на масштабе одной из трёх описанных выше проблем, откат средствами Docker-образа не сработает — сработает только восстановление из проверенной резервной копии, сделанной до миграции.
Разница между «база повреждена и функциональность сломана» и «база шумит несоответствием, но работает» определяет, насколько срочно нужно действовать. Первый случай — это авария, второй — задача с низким приоритетом, которую можно спланировать. Смешивать их и одинаково паниковать в обоих случаях — типичная ошибка, из-за которой к разбору привлекают больше ресурсов, чем реально нужно.
Кейс: самиздат-лаборатория «Тираж Один», 15 рабочих мест
У клиента — небольшой самиздат-лаборатории на 15 рабочих мест, которая печатает малотиражные книги и держит переписку с авторами и типографиями на собственном mailcow, — обновление до 2025-03a совпало с жалобой редактора: «не могу сменить пароль почты, выдаёт ошибку». Симптом совпал один в один со сценарием SQLSTATE 1442: при попытке смены пароля через веб-интерфейс операция падала, при этом входящая и исходящая почта продолжала работать без сбоев.
Запустил SHOW TRIGGERS FROM mailcow — в списке действительно нашёлся устаревший триггер, оставшийся от более ранней схемы SOGo. Дальше два варианта: вручную удалить конкретный триггер, разобравшись в его определении, либо обновиться до релиза 2025-09b и позже, где этот объект удаляет сам контейнер sogo-mailcow при старте. Для клиента с небольшой инфраструктурой и без выделенного DBA я выбрал второй путь — плановое обновление до актуальной ветки вместо ручного вмешательства в системные объекты базы, которое я не видел задокументированным официально.
После планового апгрейда до текущей стабильной версии смена пароля заработала штатно, а повторный SHOW TRIGGERS FROM mailcow подтвердил, что устаревший объект исчез вместе с обновлением. Отдельно на этом сервере я заодно сверил, что security-патчи не пропущены: у mailcow были случаи серьёзных уязвимостей в шаблонах, которые я разбирал в статье про доступ ко всей переписке через CVE-2025-53909 — обновляться вовремя нужно не только ради починки триггеров, но и ради безопасности, и откладывать апгрейды из страха перед ошибками в логе MariaDB — не лучшая стратегия.
Что делать по порядку, если MariaDB ругается после обновления
Мой порядок действий один и тот же для любого из трёх сценариев: сначала проверяю, есть ли реальный сбой функциональности — не открывается панель, не меняется пароль, не создаётся ящик, — или это просто новая строка в логе без видимых последствий. Дальше смотрю точный текст ошибки и код: 1932/42S02 про отсутствующую таблицу указывает на прикладную схему mailcow и требует восстановления структуры или бэкапа, несоответствие полей системной таблицы (как column_stats) — на незавершённое обновление системных таблиц MariaDB, в большинстве случаев не критично и лечится mariadb-upgrade, а 1442 в триггере — на конкретный устаревший SQL-объект, который проверяется командой SHOW TRIGGERS.
Дальше — mariadb-upgrade/mysql_upgrade я запускаю только когда ошибка действительно относится к системным таблицам mysql, а не к прикладным таблицам самого mailcow: для системных таблиц эта утилита штатно чинит формат, для прикладных — нет, и ожидать от неё восстановления недостающей таблицы reset_password бессмысленно. Официальная процедура ручного апгрейда MariaDB в mailcow — сначала остановить mysql-mailcow и watchdog-mailcow, затем поднять MariaDB через docker compose run с флагом --skip-grant-tables, выполнить mysql_upgrade внутри и выйти; документация прямо отмечает, что этот шаг обычно не требуется в штатном сценарии. В обсуждении #6349 разработчики предлагали и вариант проще, без остановки: source mailcow.conf; docker compose exec mysql-mailcow mariadb-upgrade -p$DBROOT -f (а сначала — с ключом --check-if-upgrade-is-needed, чтобы понять, нужен ли апгрейд вообще).
Если ни один из трёх сценариев не совпадает, а ошибка новая и код в логе непонятен, я не импровизирую с системными таблицами MariaDB руками — восстанавливаю тестовое окружение из свежего бэкапа, воспроизвожу проблему там и уже на копии ищу первопричину, не рискуя боевой базой. Такой же принцип — сначала проверенная копия, потом эксперименты — я использую при разборе повреждений баз в других почтовых системах, например в статье про восстановление InnoDB в Zimbra после аварии питания: логика диагностики похожая, даже если движок другой.
Частые вопросы
Ошибка про mysql.column_stats в логе MariaDB — это авария?
Не обязательно. Обычно это разовое сообщение в момент первого старта на MariaDB 10.11, пока php-fpm-mailcow не прогнал mariadb-upgrade. Если ошибка повторяется после рестарта — сделайте бэкап и запустите mariadb-upgrade -f в контейнере mysql-mailcow.
Поможет ли mysql_upgrade -p --force, если панель mailcow пишет, что таблица reset_password не существует?
Обычно нет. mysql_upgrade/mariadb-upgrade обновляет системные таблицы базы mysql, а не прикладные таблицы mailcow. Если reset_password физически отсутствует или повреждена, нужно смотреть бэкап схемы или обращаться к структуре инициализации базы mailcow.
Можно ли откатить MariaDB с 10.11 обратно на 10.5, если после обновления начались проблемы?
Нет. Разработчики mailcow прямо указывают: после миграции баз на 10.11 откат на 10.5 невозможен. Единственный надёжный путь назад — восстановление из резервной копии, сделанной до обновления.
Как узнать, остался ли в базе устаревший триггер SOGo, вызывающий ошибку 1442?
Командой SHOW TRIGGERS FROM mailcow от root в контейнере mysql-mailcow (нужна привилегия TRIGGER). Начиная с mailcow 2025-09b устаревший триггер sogo_update_password удаляется автоматически при старте sogo-mailcow.
Что делать, если код ошибки не совпадает ни с одним из трёх известных сценариев?
Не экспериментировать с системными таблицами MariaDB на боевой базе. Восстановить свежий бэкап на тестовом окружении, воспроизвести проблему там и разбираться на копии, а не на проде.
Источники
- GitHub issue #6348 — mailcow-dockerized — Ошибка 1932/SQLSTATE[42S02] «Table mailcow.reset_password doesn't exist in engine» после обновления 2023-12a → 2025-02, MariaDB 10.11.11-MariaDB-ubu2204, mysql_upgrade -p --force не помог. https://github.com/mailcow/mailcow-dockerized/issues/6348
- GitHub issue #6349 — mailcow-dockerized — Ошибки mysql.column_stats (hist_type без JSON_HB, histogram varbinary(255) вместо longblob) после обновления до 2025-02; функциональность не нарушена; mariadb-upgrade в mailcow запускает entrypoint php-fpm, разработчики предложили docker compose exec mysql-mailcow mariadb-upgrade -p$DBROOT -f; закрыт ботом как stale (not planned). https://github.com/mailcow/mailcow-dockerized/issues/6349
- GitHub issue #6423 — mailcow-dockerized — SQLSTATE[HY000] 1442 в update_sogo_static_view() при смене пароля на версии 2025.03a, стек через edit_user_account(). https://github.com/mailcow/mailcow-dockerized/issues/6423
- mailcow blog — Febmooary 2025 (release 2025-02) — Дата 27.02.2025, переход MariaDB 10.5 → 10.11, предупреждение о невозможности отката и риске ручной смены версии образа в docker-compose.yml. https://mailcow.email/posts/2025/release-2025-02/
- mailcow blog — release 2025-09 — Ревизия 2025-09b от 12 сентября 2025: PR #6727 — DROP TRIGGER IF EXISTS sogo_update_password в bootstrap-sogo.sh при старте sogo-mailcow (образ sogo 1.135), устраняет первопричину ошибки 1442 из issue #6423. https://mailcow.email/posts/2025/release-2025-09/
- mailcow documentation — Manual MySQL upgrade — Официальная процедура: остановка mysql-mailcow и watchdog-mailcow, запуск MariaDB с --skip-grant-tables, mysql_upgrade внутри контейнера; шаг обычно не требуется. https://docs.mailcow.email/troubleshooting/debug-mysql_upgrade/



