MySQL Ошибка 1038 (HY000): Out of sort memory (Увеличение sort_buffer_size)
Алгоритм сортировки строк Filesort в MySQL
Когда SQL-запрос содержит условия сортировки ORDER BY или группировки GROUP BY, а подходящий индекс для извлечения строк в нужном порядке отсутствует, СУБД использует алгоритм Filesort. Для выполнения сортировки в оперативной памяти каждому клиентскому соединению динамически выделяется буфер, размер которого контролируется системной переменной sort_buffer_size. Если объем сортируемых данных превышает размер этого буфера (либо если размер одной строки превышает максимальный лимит сортировки max_sort_length), запрос аварийно прерывается:
«ERROR 1038 (HY000): Out of sort memory, consider increasing server sort buffer size»
Бизнес-риски
Сбой работы каталогов интернет-магазинов при использовании сортировок (по цене, новизне, популярности), невозможность выгрузки отсортированных реестров и отчетов.
Сравнение стратегий Filesort в памяти и на диске
| Метод сортировки | Где выполняется | Индикатор производительности |
|---|---|---|
| Инструментальный по индексу (Index Scan) | Без использования буфера | Идеальная производительность (Filesort отсутствует в EXPLAIN). |
| В оперативной памяти (Sort Buffer) | В пределах sort_buffer_size | Быстрое выполнение, умеренная нагрузка на RAM. |
| Дисковый Merge Sort | Во временных файлах на диске | Высокий I/O оверхед, инкремент счетчика Sort_merge_passes. |
Регламент устранения ошибки Out of sort memory
Сценарий 1: Безопасное увеличение sort_buffer_size в сессии или глобально
По умолчанию sort_buffer_size обычно составляет от 256K до 2M. Увеличьте его до безопасных пределов:
# 1. Проверка текущего значения sort_buffer_size:
SHOW VARIABLES LIKE 'sort_buffer_size';
# 2. Динамическое увеличение для глобальной конфигурации (например, до 4M или 8M):
SET GLOBAL sort_buffer_size = 4 * 1024 * 1024;
# 3. Персистентное сохранение в my.cnf:
sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf
[mysqld]
sort_buffer_size = 4M
# 4. Перезапуск службы (при необходимости):
sudo systemctl reload mysqlСценарий 2: Оптимизация запроса с помощью добавления индекса
Вместо бездумного наращивания буферов памяти устраните причину Filesort добавлением покрывающего индекса:
-- Пример проблемного запроса:
SELECT id, title, price FROM products WHERE category_id = 15 ORDER BY price DESC;
-- Анализ плана выполнения запроса:
EXPLAIN SELECT id, title, price FROM products WHERE category_id = 15 ORDER BY price DESC;
-- Если в поле 'Extra' написано 'Using filesort' -> индекс отсутствует!
-- Создание композитного индекса (фильтрация + сортировка):
ALTER TABLE `products` ADD INDEX `idx_category_price` (`category_id`, `price`);
-- После добавления индекса в EXPLAIN исчезнет 'Using filesort', а ошибка 1038 полностью пропадет!Сценарий 3: Ограничение выборки тяжелых текстовых полей (TEXT/BLOB)
Если в запросе выбираются широкие текстовые поля, алгоритм сортировки резервирует под них максимальный объем памяти:
-- НЕПРАВИЛЬНО (Выбирает длинные описания, забивая sort buffer):
SELECT * FROM blog_posts ORDER BY created_at DESC LIMIT 20;
-- ПРАВИЛЬНО (Выбираем только необходимые легкие поля):
SELECT id, title, created_at FROM blog_posts ORDER BY created_at DESC LIMIT 20;Типовые ошибки администраторов
- Установка sort_buffer_size = 1G в глобальной конфигурации: Память
sort_buffer_sizeвыделяется каждым потоком индивидуально при выполнении сортировки. Если 100 пользователей одновременно запустят поиск, MySQL попытается выделить 100 Гб RAM и будет немедленно уничтожен демономOOM-Killer. - Игнорирование параметра max_sort_length: При сортировке полей типа
TEXTсервер учитывает только первыеmax_sort_lengthбайт (по умолчанию 1024).
Инженеры ITSTM оптимизируют планы выполнения SQL-запросов (EXPLAIN), добавят эффективные композитные индексы и настроят буферы памяти СУБД.
Частые вопросы (FAQ)
Как узнать, сбрасываются ли сортировки на диск?
Выполните команду SHOW STATUS LIKE 'Sort_merge_passes';. Если значение счетчика постоянно растет, это говорит о том, что sort_buffer_size недостаточен для текущих неиндексированных запросов.
Можно ли увеличить sort_buffer_size только для одного тяжелого запроса?
Да, выполните в рамках сессии перед запросом: SET SESSION sort_buffer_size = 64 * 1024 * 1024;.
Влияет ли ORDER BY RAND() на возникновение ошибки 1038?
Да! Конструкция ORDER BY RAND() заставляет MySQL выполнять полный скан таблицы с генерацией случайных чисел и сортировкой всего массива строк в sort buffer.
Что делает параметр sort_buffer_size в MySQL 8.0.20+?
В свежих версиях MySQL память под sort_buffer выделяется инкрементально по мере необходимости, а не сразу полным объемом, что снижает риск OOM.