Почему бинарные логи MySQL 8 занимают 19 ГБ при базе 2.5 ГБ

    Бинарные логи (binlog) в MySQL 8 - это журналы, которые записывают все изменения данных: INSERT, UPDATE, DELETE, а также изменения структуры таблиц. Они необходимы для репликации и восстановления после сбоев. Однако на сервере Debian с MODX и базой 2.5 ГБ они могут неожиданно разрастись до 19 ГБ. Разберёмся, почему это происходит и как решить проблему.

    Основные причины огромного размера binlog

    Binlog растут из-за частых операций записи. Даже если база небольшая, активные CMS (например, MODX) могут генерировать тысячи запросов в день: логирование, сессии, кеширование. Каждая такая операция фиксируется в бинарном логе. Дополнительные факторы:

    • Формат логирования ROW - в MySQL 8 по умолчанию используется row-based replication, где записывается полная копия каждой изменённой строки, а не только SQL-запрос. Это увеличивает размер лога в 5-10 раз по сравнению со statement-based.
    • Долгое время хранения - если в конфиге не задано expire_logs_days или binlog_expire_logs_seconds, логи хранятся бесконечно и накапливаются.
    • Транзакции большого объёма - массовые обновления (например, импорт данных или массовая публикация ресурсов в MODX) фиксируются одной транзакцией, что создаёт гигантский файл.
    • Отсутствие автоматической очистки - если не настроена ротация, старые логи не удаляются, и суммарный вес растёт.

    Как проверить текущее состояние binlog

    Выполните в MySQL следующие запросы:

    SHOW BINARY LOGS;

    Эта команда покажет список всех файлов и их размер. Чтобы узнать текущий формат логирования:

    SHOW VARIABLES LIKE 'binlog_format';

    Если значение ROW, это одна из причин большого объёма. Также проверьте настройки хранения:

    SHOW VARIABLES LIKE 'binlog_expire_logs_seconds';

    Как уменьшить размер binlog и настроить очистку

    Для решения проблемы настройте следующие параметры в файле /etc/mysql/my.cnf или /etc/my.cnf:

    [mysqld]
    binlog_expire_logs_seconds = 86400
    max_binlog_size = 200M
    • binlog_expire_logs_seconds = 86400 - логи будут храниться ровно 1 день (24 часа). Для тестового сервера этого достаточно. Для продакшена можно поставить 2592000 (30 дней), но тогда контролируйте объём.
    • max_binlog_size = 200M - каждый файл лога не превысит 200 МБ. MySQL автоматически создаст новый файл при достижении лимита.

    После изменения конфига перезапустите MySQL:

    systemctl restart mysql

    Для немедленной очистки старых логов выполните:

    PURGE BINARY LOGS BEFORE NOW();

    Или удалите логи до определённой даты:

    PURGE BINARY LOGS BEFORE '2025-01-01 00:00:00';

    Дополнительные рекомендации

    Если проблема повторяется, рассмотрите:

    • Смена формата на MIXED - для баз, где репликация не критична, можно установить binlog_format = MIXED. Это уменьшит размер, но может нарушить репликацию.
    • Отключение binlog - если репликация не используется, можно закомментировать log-bin в конфиге. Однако это лишит вас возможности восстановления на момент времени.
    • Оптимизация запросов MODX - проверьте, не генерирует ли сайт избыточные записи (например, логи ошибок или сессии в БД). Используйте кеширование.

    Вывод

    Binlog размером 19 ГБ при базе 2.5 ГБ - нормальное явление для MySQL 8 с форматом ROW и отсутствием ротации. Настройте binlog_expire_logs_seconds и max_binlog_size, чтобы автоматически очищать логи. После этого проблема с местом на сервере Debian будет решена.

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