Spec-Zone.ru › MySQL 8.4

7.6.3.4 Настройка пула потоков

В данном разделе приведены рекомендации по определению наилучшей конфигурации пула потоков, измеряемой, например, количеством транзакций в секунду.

Наиболее важным параметром является количество групп потоков в пуле потоков, которое может быть установлено при запуске сервера с помощью опции --thread-pool-size; изменить его во время выполнения невозможно. Рекомендуемые значения для этой опции зависят от того, является ли основной движок хранения данных InnoDB или MyISAM:

  • Если основной движок хранения данных — это InnoDB, рекомендуемое значение размера пула потоков — количество физических ядер, доступных на хост-машине, но не более 512.

  • Если основной движок хранения данных — это MyISAM, размер пула потоков должен быть относительно низким. Оптимальная производительность часто наблюдается при значениях от 4 до 8. Более высокие значения оказывают слабое негативное, но не существенное влияние на производительность.

Верхний предел количества одновременных транзакций, которые может обрабатывать плагин пула потоков, определяется значением thread_pool_max_transactions_limit. Рекомендуемое начальное значение этой системной переменной равно количеству физических ядер умноженному на 32. Возможно, потребуется скорректировать значение от этой точки отсчёта в соответствии с заданной рабочей нагрузкой; разумной верхней границей для этого значения является максимальное ожидаемое количество одновременных подключений; значение статусной переменной Max_used_connections может служить руководством для определения этого значения. Хороший способ действий — начать с значения thread_pool_max_transactions_limit, равного этому значению, а затем уменьшать его, наблюдая за влиянием на пропускную способность.

Максимальное количество потоков запросов, разрешённых в группе потоков, определяется значением thread_pool_query_threads_per_group, которое можно изменить во время выполнения. Произведение этого значения и размера пула потоков примерно равно общему количеству потоков, доступных для обработки запросов. Для достижения наилучшей производительности обычно необходимо добиться надлежащего баланса между thread_pool_query_threads_per_group и размером пула потоков в вашем приложении. Более высокие значения thread_pool_query_threads_per_group уменьшают вероятность одновременного выполнения всех потоков в группе потоков длительных запросов и блокировки коротких, когда рабочая нагрузка включает как длинные, так и короткие запросы. Следует помнить, что накладные расходы операции опроса подключения для каждой группы потоков увеличиваются при использовании меньших значений размера пула потоков с большими значениями thread_pool_query_threads_per_group. По этой причине мы рекомендуем начальное значение 2 для thread_pool_query_threads_per_group; установка этой переменной на меньшее значение обычно не приносит никакой выгоды в плане производительности.

Для наилучшей производительности в стандартных условиях также рекомендуется установить thread_pool_algorithm в 1 для высокой конкуретности.

Кроме того, значение системной переменной thread_pool_stall_limit определяет обработку заблокированных и длительных операторов. Если все вызовы, блокирующие MySQL-сервер, были переданы в пул потоков, он всегда знал бы, когда потоки выполнения заблокированы, но это может не всегда быть правдой. Например, блокировки могут происходить в коде, который не был снабжён обратными вызовами пула потоков. В таких случаях пул потоков должен уметь определять потоки, которые, по-видимому, заблокированы. Это делается с помощью таймаута, определяемого значением thread_pool_stall_limit, что гарантирует, что сервер не заблокируется полностью. Значение thread_pool_stall_limit представляет собой количество 10-миллисекундных интервалов, так что 600 (максимальное значение) представляет 6 секунд.

thread_pool_stall_limit также позволяет пулу потоков обрабатывать длительные операторы. Если длительный оператор разрешено блокировать группу потоков, все остальные подключения, назначенные группе, будут заблокированы и не смогут начать выполнение, пока длительный оператор не завершится. В худшем случае это может занять часы или даже дни.

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

Предположим, сервер выполняет рабочую нагрузку, где 99,9% операторов завершаются в течение 100 мс, даже когда сервер загружен, а оставшиеся операторы занимают от 100 мс до 2 часов, примерно равномерно распределённые. В этом случае имеет смысл установить thread_pool_stall_limit на 10 (10 × 10 мс = 100 мс). Значение по умолчанию 6 (60 мс) подходит для серверов, которые в основном выполняют очень простые операторы.

Параметр thread_pool_stall_limit можно изменить во время выполнения, чтобы можно было найти баланс, подходящий для рабочей нагрузки сервера. Предполагая, что таблица tp_thread_group_stats включена, вы можете использовать следующий запрос для определения доли выполненных операторов, которые были заблокированы:

SELECT SUM(STALLED_QUERIES_EXECUTED) / SUM(QUERIES_EXECUTED)
FROM performance_schema.tp_thread_group_stats;

Это число должно быть как можно ниже. Чтобы уменьшить вероятность блокировки операторов, увеличьте значение thread_pool_stall_limit.

Когда поступает оператор, каково максимальное время задержки перед его фактическим началом выполнения? Предположим, что применяются следующие условия:

  • В очереди низкого приоритета находится 200 операторов.

  • В очереди высокого приоритета находится 10 операторов.

  • thread_pool_prio_kickup_timer установлено на 10000 (10 секунд).

  • thread_pool_stall_limit установлено на 100 (1 секунда).

В худшем случае 10 операторов высокого приоритета представляют 10 транзакций, которые продолжают выполняться долгое время. Таким образом, в худшем случае новые операторы не могут быть перемещены в очередь высокого приоритета, потому что она всегда уже содержит операторы, ожидающие выполнения. Через 10 секунд новый оператор может быть перемещен в очередь высокого приоритета. Однако перед этим все операторы перед ним должны быть перемещены также. Это может занять ещё 2 секунды, так как максимум 100 операторов в секунду перемещаются в очередь высокого приоритета. Теперь, когда оператор попадает в очередь высокого приоритета, перед ним может потенциально находиться множество длительных операторов. В худшем случае каждый из них блокируется, и для каждого оператора требуется 1 секунда, прежде чем следующий оператор извлекается из очереди высокого приоритета. Таким образом, в этом сценарии требуется 222 секунды, прежде чем новый оператор начнёт выполняться.

Этот пример демонстрирует наихудший случай для приложения. Как с ним справиться, зависит от приложения. Если у приложения высокие требования к времени отклика, оно, скорее всего, само будет ограничивать пользователей на более высоком уровне. В противном случае оно может использовать параметры конфигурации пула потоков для установки определённого максимального времени ожидания.

© 2025 Oracle
Licensed under the GPLv2 License.
https://docs.oracle.com/cd/E17952_01/mysql-8.4-en/thread-pool-tuning.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API