База MySQL занимает слишком много места: где искать причину
Если база MySQL быстро растёт, сайт может начать тормозить, бэкапы становятся тяжелее, импорт занимает больше времени, а на сервере заканчивается место. При этом причина роста не всегда в основных бизнес-данных. Часто место занимают логи, очереди, временные таблицы, история импорта, старые сессии или бинарные логи MySQL.
Начинать нужно с измерения. Пока неизвестно, какие таблицы самые большие, чистка будет случайной.
Размер таблиц
Получить список самых больших таблиц можно через information_schema.
SELECT
table_name,
ROUND((data_length + index_length) / 1024 / 1024, 2) AS size_mb
FROM information_schema.tables
WHERE table_schema = DATABASE()
ORDER BY size_mb DESC
LIMIT 20;
Этот запрос быстро показывает, что реально занимает место: заказы, логи, история изменений, временные данные или системные таблицы приложения.
Логи приложения в базе
Некоторые проекты пишут логи в таблицы: события, ошибки, запросы API, действия пользователей. Это удобно для просмотра в админке, но без очистки такие таблицы растут бесконечно.
SELECT COUNT(*) FROM app_logs;
SELECT MIN(created_at), MAX(created_at) FROM app_logs;
Для логов нужен срок хранения. Например, подробные технические логи хранить 14-30 дней, а бизнес-аудит — дольше, если это действительно нужно.
Очереди
Таблицы очередей могут хранить выполненные, неудачные или зависшие задачи. Если их не чистить, база растёт даже без увеличения заказов.
SELECT status, COUNT(*)
FROM queue
GROUP BY status;
Перед очисткой failed jobs нужно понять, нет ли там полезной диагностики. Удалять всё подряд — плохая практика.
История импорта
Импорты товаров, цен и остатков часто сохраняют историю. Это полезно для аудита, но хранить каждую строку каждого прайса годами обычно не нужно.
- сырые загруженные файлы;
- строки импорта;
- протоколы ошибок;
- старые версии цен;
- история остатков;
- временные таблицы сопоставления.
Для таких данных лучше задать политику хранения: например, последние 30-90 дней или только последние N импортов.
Сессии и кэш в базе
Если сессии или кэш хранятся в MySQL, нужно проверять очистку устаревших записей. Иначе таблицы могут расти без прямой связи с контентом сайта.
SELECT COUNT(*) FROM session;
SELECT COUNT(*) FROM cache;
Для сессий должен быть механизм удаления истёкших записей. Для кэша — TTL и регулярная очистка.
MySQL binary logs
Если место заканчивается на сервере, причина может быть не в размере таблиц, а в binlog-файлах MySQL. Они нужны для репликации и восстановления, но без политики хранения занимают много места.
SHOW BINARY LOGS;
Удалять binlog вручную через rm нельзя. Используют штатные команды и настройки expire_logs_days или binlog_expire_logs_seconds, учитывая репликацию и бэкапы.
PURGE BINARY LOGS BEFORE '2026-06-01 00:00:00';
Перед очисткой нужно убедиться, что эти логи не нужны реплике или восстановлению.
OPTIMIZE TABLE
После большого удаления место внутри таблицы может не сразу вернуться операционной системе. Иногда используют OPTIMIZE TABLE, но на больших таблицах это может быть тяжёлой операцией.
OPTIMIZE TABLE app_logs;
На production сначала нужно оценить размер таблицы, тип движка и окно обслуживания.
Архивирование
Если данные нужны редко, их можно не удалять, а архивировать: перенести в отдельную таблицу, отдельную базу или внешнее хранилище. Главное — чтобы рабочие запросы не сканировали исторический мусор.
Чек-лист
- Найти самые большие таблицы через information_schema.
- Проверить таблицы логов приложения.
- Проверить таблицы очередей.
- Проверить историю импортов.
- Проверить сессии и кэш в базе.
- Проверить MySQL binary logs на диске.
- Задать сроки хранения для временных данных.
- Использовать OPTIMIZE TABLE только осознанно.
- Настроить регулярную очистку или архивирование.
Рост базы нужно лечить не разовой чисткой, а политикой хранения. Если понятно, какие данные временные, сколько они живут и кто их очищает, база перестаёт расти бесконтрольно.
Комментарии (0)
Пока нет комментариев. Будьте первым!