Команда рассчитала новый сервер MySQL просто: выбрала размер buffer pool, добавила небольшой запас и решила, что процесс mysqld в этот бюджет поместится. В обычный день расчёт выглядел убедительно. Затем несколько клиентов одновременно запустили отчёты, выросло число сортировок и внутренних временных таблиц, а память процесса поднялась намного выше ожидаемого. Сам buffer pool при этом не обязательно был настроен неправильно. Ошибка была в модели: крупнейший и самый заметный потребитель приняли за всю память MySQL. Когда запас закончился, операционная система начала вытеснять страницы, хвост задержки вырос, а риск аварийного завершения процесса стал реальным.

Есть и противоположная ошибка: бюджет строят как сумму предельных размеров всех буферов для каждого разрешённого подключения. Получается дорогой запас, которого реальная нагрузка никогда не просит. Обе крайности смешивают настройку, фактическое выделение памяти и одновременную работу.

Крупнейший буфер не равен процессу

InnoDB buffer pool — внутренняя область памяти движка InnoDB. В ней MySQL держит страницы таблиц и индексов, чтобы повторные обращения не требовали чтения с накопителя. Для многих серверов это действительно крупнейшая постоянная часть расхода, поэтому она естественно становится центром обсуждения. Но значение innodb_buffer_pool_size описывает только настроенный размер этой области, а не потолок mysqld. Документация MySQL 8.4 отдельно предупреждает, что фактическое выделение для buffer pool может быть примерно на десять процентов больше заданного значения из-за дополнительных буферов и управляющих структур. Это ориентир для одного компонента конкретной версии, а не универсальный запас для всего сервера.

Buffer pool обычно выделяется при запуске и хорошо виден в конфигурации. Рядом с ним живут другие структуры InnoDB, общие кэши и служебная память. Одни области постоянны, другие появляются или растут под нагрузкой. Поэтому одинаковый buffer pool не гарантирует одинаковый расход процесса.

Память появляется в разное время

У mysqld есть общий слой памяти, которым пользуется весь сервер, и память, связанная с потоками соединений и конкретными операциями. Соединение само по себе требует некоторого состояния, но крупные рабочие буферы нередко выделяются лишь тогда, когда запрос действительно выполняет соответствующую стадию. Некоторые из них могут расти по мере необходимости, а после завершения работы освобождаться или оставаться доступными для повторного использования.

Именно время выделения меняет бюджет. Сотня открытых, но почти бездействующих соединений и сотня одновременно работающих тяжёлых запросов — совершенно разные события. Формальный предел подключений говорит, сколько клиентов сервер способен допустить, но не сообщает, сколько из них одновременно сортируют большие результаты, строят хэш-структуры или создают временные таблицы. Считать только постоянный buffer pool опасно: нагрузочная память появляется поверх него. Складывать все возможные максимумы тоже неверно: буферы создаются не сразу, нужны не каждому запросу и не всегда достигают предела. Пик определяет совпадение памятьёмких стадий и уже выросших общих структур, а не бухгалтерия настроек.

Подключение и тяжёлая операция — не одно и то же

Представим сервис, где пул приложений постоянно держит много соединений с MySQL. Большинство выполняет короткие запросы и почти не создаёт дополнительной рабочей памяти. В конце дня несколько аналитических задач начинают сортировать и объединять большие выборки, а параллельно идёт обычный поток заказов. Число соединений выросло незначительно, но характер одновременной работы изменился резко. Общая память процесса поднимается ступенью, потому что несколько запросов одновременно проходят дорогие стадии. Если сервер был рассчитан только по buffer pool, эта ступень съедает запас; если он был рассчитан по теоретическому максимуму каждого соединения, закупленная DRAM большую часть времени простаивает без экономического смысла.

Поэтому максимум подключений нельзя превращать в прогноз памяти механическим умножением. Он полезен как административный предел, но не заменяет понимание конкуренции. Интерактивные запросы, пакетные отчёты и загрузка данных создают разные формы расхода; одна цифра «соединения» их скрывает.

Временная таблица меняет память на ввод-вывод

Для промежуточных результатов MySQL может создавать внутренние временные таблицы. Пока они укладываются в условия и пределы выбранного механизма, часть работы выполняется в памяти. Когда эти условия перестают выполняться или общий предел достигнут, обработка может перейти на дисковую внутреннюю таблицу. Это не означает, что проблема памяти исчезла. Переход меняет профиль ресурса: уменьшается давление одной области памяти, но появляются чтения, записи и очередь накопителя. Запрос может завершиться без прежнего пика RAM, зато его задержка и влияние на соседние запросы возрастут.

Фраза «временные таблицы всё равно уйдут на диск» не даёт безопасного бюджета. Не вся память запроса относится к ним, а общие структуры остаются. Несколько одновременных переходов могут нагрузить накопитель и увеличить p99 — границу, в которую укладывается большинство ответов и которая лучше среднего показывает редкие медленные случаи.

Performance Schema видит не весь mysqld

Performance Schema — встроенный механизм наблюдаемости MySQL. Его таблицы сводки памяти помогают понять, какие инструментированные компоненты выделяют память и как их расход меняется. Но это представление не является полным физическим счётом процесса. Сама Performance Schema тоже использует память. По документации MySQL она выделяет её постепенно под фактическую нагрузку и обычно не возвращает операционной системе до перезапуска, хотя может повторно использовать уже выделенные области. Поэтому после периода высокой активности её собственный след способен остаться выше, чем был сразу после старта.

Ключевое ограничение — слово «инструментированные». Сводки показывают только выделения, для которых есть включённый инструмент. Они не равны RSS — объёму физических страниц процесса в RAM — и не описывают точно кэш файлов ОС или память соседних служб. Внутренние сводки объясняют части расхода, а общий риск виден на уровне процесса, контейнера и хоста.

Бюджет задаёт реальная конкуренция

Разумный бюджет MySQL начинается с постоянной основы: buffer pool и других общих структур. Затем к ней добавляют не все воображаемые максимумы, а воспроизводимый пик нужной бизнес-нагрузки: обычный поток вместе с теми отчётами, загрузками и служебными фазами, которые действительно должны работать одновременно. Отдельный запас остаётся операционной системе, файловому кэшу и соседним процессам. Если пик создаёт один неудачный запрос или необязательное совпадение отчётов, дешевле изменить запрос, индекс или расписание. Если нужная конкуренция устойчиво требует больше памяти и её нельзя убрать без потери сроков или качества, дополнительная DRAM становится обоснованной покупкой.

Прозрачный страничный уровень класса gigaRAM относится к физическому размещению страниц: активные остаются в DRAM, а подходящие менее активные могут обслуживаться через NVMe. Он не меняет innodb_buffer_pool_size, не заменяет управление памятью InnoDB и не убирает пики конкретных запросов. Применимость зависит от подтверждённого профиля памяти и среды эксплуатации. Главный вывод прост: innodb_buffer_pool_size отвечает на вопрос о крупном внутреннем кэше, а не о максимальной памяти mysqld или всего узла. Хороший бюджет связывает постоянные области, фактическую одновременность операций, переход временной работы на диск и качество сервиса. Тогда сервер не покупают ни по одной красивой настройке, ни по сумме максимумов, которые никогда не встречаются вместе.

Источники. MySQL 8.4 — How MySQL Uses Memory описывает общую и потоковую память, динамическое выделение буферов, временные таблицы и модель Performance Schema.

MySQL 8.4 — innodb_buffer_pool_size подтверждает назначение buffer pool и ориентир по его дополнительным структурам.

Internal Temporary Table Use задаёт границу между памятью и диском для внутренних временных таблиц.

Performance Schema Memory-Allocation Model объясняет постепенное выделение и повторное использование памяти, а Monitoring MySQL Memory Usage и Summary Tables — границы инструментированного учёта.

Meta Engineering — TMO используется только для общей механики страничного переноса, а продуктовая страница — только для позиционирования класса решения.