Spec-Zone.ru › MySQL 9.2

7.6.3.3 Работа пула потоков

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

Пул потоков предоставляет системные переменные, которые могут быть использованы для настройки его работы:

  • thread_pool_algorithm: Алгоритм конкурентности для планирования.

  • thread_pool_dedicated_listeners: Назначает поток-слушатель в каждой группе потоков для прослушивания входящих заявок от подключений, назначенных этой группе.

  • thread_pool_high_priority_connection: Способ планирования выполнения запросов для сеанса.

  • thread_pool_max_active_query_threads: Количество активных потоков на группу.

  • thread_pool_max_transactions_limit: Максимальное количество транзакций, разрешенных плагином пула потоков.

  • thread_pool_max_unused_threads: Разрешенное количество спящих потоков.

  • thread_pool_prio_kickup_timer: Время, через которое пул потоков перемещает запрос, ожидающий выполнения, из очереди низкого приоритета в очередь высокого приоритета.

  • thread_pool_query_threads_per_group: Количество потоков запросов, разрешенных в группе потоков (по умолчанию один поток запросов). Увеличение этого значения может быть полезно, если наблюдаются задержки в ответах из-за длительных транзакций.

  • thread_pool_size: Количество групп потоков в пуле. Это наиболее важный параметр, влияющий на производительность пула потоков.

  • thread_pool_stall_limit: Время, после которого выполняемый запрос считается заблокированным.

  • thread_pool_transaction_delay: Период ожидания перед запуском новой транзакции.

Для настройки количества групп потоков используйте системную переменную thread_pool_size. По умолчанию количество групп равно 16. Рекомендации по настройке этой переменной см. в Разделе 7.6.3.4, «Настройка пула потоков».

Максимальное количество потоков на группу составляет 4096 (или 4095 на некоторых системах, где один поток используется внутренне).

Пул потоков отделяет подключения и потоки, поэтому нет фиксированной связи между подключениями и потоками, которые выполняют запросы, полученные от этих подключений. Это отличается от модели обработки потоков по умолчанию, где одному подключению соответствует один поток, и данный поток выполняет все запросы от этого подключения.

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

  • Каждая группа потоков имеет поток-слушатель, который прослушивает входящие запросы от подключений, назначенных группе. Когда запрос поступает, группа потоков либо начинает его немедленное выполнение, либо помещает его в очередь для последующего выполнения:

    • Немедленное выполнение происходит, если запрос является единственным полученным и нет запросов в очереди или выполняемых в данный момент.

      Немедленное выполнение может быть отложено путем настройки thread_pool_transaction_delay, что оказывает сдерживающее влияние на транзакции. Для получения дополнительной информации см. описание этой переменной в последующем обсуждении.

    • Помещение в очередь происходит, если запрос не может начать немедленное выполнение из-за одновременных запросов в очереди или выполняемых запросов.

  • Переменная thread_pool_transaction_delay определяет задержку транзакции в миллисекундах. Рабочие потоки спят в течение указанного периода времени перед выполнением новой транзакции.

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

    Настройка thread_pool_transaction_delay не влияет на запросы, отправленные с привилегированного подключения (подключение, назначенное группе потоков Admin). Эти запросы не подпадают под действие заданной задержки транзакции.

  • Если происходит немедленное выполнение, поток-слушатель выполняет его. (Это означает, что временно ни один поток в группе не прослушивает запросы.) Если запрос завершается быстро, выполняющий поток возвращается к прослушиванию запросов. В противном случае пул потоков рассматривает запрос как заблокированный и запускает другой поток в качестве потока-слушателя (создает его при необходимости). Чтобы гарантировать, что ни одна группа потоков не заблокируется из-за заблокированных запросов, в пуле потоков есть фоновый поток, который регулярно отслеживает состояние групп потоков.

    Использование потока-слушателя для выполнения запроса, который может начать выполнение немедленно, не требует создания дополнительного потока, если запрос завершается быстро. Это гарантирует максимально эффективное выполнение в случае небольшого количества одновременных потоков.

    При запуске плагина пула потоков он создаёт один поток на группу (поток-слушатель) плюс фоновый поток. Дополнительные потоки создаются по мере необходимости для выполнения запросов.

  • Значение системной переменной thread_pool_stall_limit определяет смысл фразы «завершается быстро» в предыдущем пункте. По умолчанию время, по истечении которого потоки считаются заблокированными, составляет 60 мс, но может быть установлено до 6 с. Этот параметр настраивается, чтобы вы могли найти баланс, соответствующий нагрузке сервера. Короткие значения ожидания позволяют потокам запускаться быстрее. Короткие значения также лучше для предотвращения тупиковых ситуаций. Длинные значения ожидания полезны для рабочих нагрузок, включающих длительные запросы, чтобы избежать запуска слишком большого количества новых запросов во время выполнения текущих.

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

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

  • Запрос блокируется, если он сталкивается с операцией ввода-вывода на диск или блокировкой на уровне пользователя (строка или таблица). Блокировка приведет к тому, что группа потоков станет неиспользуемой, поэтому существуют обратные вызовы в пул потоков, чтобы гарантировать, что пул потоков может немедленно запустить новый поток в этой группе для выполнения другого запроса. Когда заблокированный поток возвращается, пул потоков разрешает ему немедленно перезапуститься.

  • Существуют две очереди: очередь с высоким приоритетом и очередь с низким приоритетом. Первый запрос в транзакции попадает в очередь с низким приоритетом. Любые последующие запросы для транзакции попадают в очередь с высоким приоритетом, если транзакция активна (запросы для неё уже начали выполняться), или в очередь с низким приоритетом в противном случае. Назначение очереди может быть изменено включением системной переменной thread_pool_high_priority_connection, которая вызывает попадание всех запросов в очередь с высоким приоритетом.

    Запросы для нетранзакционного хранилища или транзакционного хранилища, если включен autocommit, обрабатываются как запросы с низким приоритетом, потому что в этом случае каждый запрос является транзакцией. Таким образом, при сочетании запросов для таблиц InnoDB и MyISAM пул потоков отдаёт приоритет запросам для InnoDB над запросами для MyISAM, если не включен autocommit. При включенном autocommit все запросы имеют низкий приоритет.

  • Когда группа потоков выбирает запрос из очереди для выполнения, она сначала проверяет очередь с высоким приоритетом, а затем очередь с низким приоритетом. Если запрос найден, он удаляется из своей очереди и начинает выполняться.

  • Если запрос слишком долго находится в очереди с низким приоритетом, пул потоков перемещает его в очередь с высоким приоритетом. Значение системной переменной thread_pool_prio_kickup_timer управляет временем до перемещения. Для каждой группы потоков максимум один запрос перемещается из очереди с низким приоритетом в очередь с высоким приоритетом каждые 10 мс (100 за секунду).

  • Пул потоков повторно использует наиболее активные потоки, чтобы значительно улучшить использование кэшей процессора. Это небольшое изменение, которое оказывает большое влияние на производительность.

  • Пока поток выполняет запрос от пользовательского подключения, инструменты Performance Schema учитывают активность потока по пользовательскому подключению. В противном случае Performance Schema учитывает активность потока по пулу потоков.

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

  • Один поток начинает выполнение запроса, но выполняется достаточно долго, чтобы быть признанным заблокированным. Группа потоков разрешает другому потоку начать выполнение другого запроса, даже если первый поток всё ещё выполняется.

  • Один поток начинает выполнение запроса, затем блокируется и сообщает об этом в пул потоков. Группа потоков разрешает другому потоку начать выполнение другого запроса.

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

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

  • Запросы с длительным временем выполнения. Они приведут к использованию всех ресурсов только несколькими запросами, и они могут помешать всем остальным получить доступ к серверу.

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

  • Запросы, заблокированные на строковой или табличной блокировке, ожидании или любой другой блокирующей активности, которая не была сообщена обратно в пул потоков сервером MySQL или хранилищем.

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

Максимальное количество потоков, которое может возникнуть, равно сумме max_connections и thread_pool_size. Это может произойти в ситуации, когда все подключения находятся в режиме выполнения и для каждой группы создаётся дополнительный поток для прослушивания новых запросов. Такое состояние не обязательно происходит часто, но теоретически возможно.

Привилегированные подключения

Если предел, определенный в thread_pool_max_transactions_limit, достигнут, и новые подключения или новые транзакции с использованием существующих подключений зависают, пока одна или несколько существующих транзакций не завершатся, несмотря на любые внесенные изменения в thread_pool_longrun_trx_limit, так что все существующие подключения заблокированы или имеют длительное выполнение, единственный способ получить доступ к серверу — использовать привилегированное подключение.

Для создания привилегированного подключения пользователь, инициирующий подключение, должен обладать привилегией TP_CONNECTION_ADMIN. Привилегированное подключение игнорирует предел, определенный в thread_pool_max_transactions_limit, и позволяет подключиться к серверу для увеличения предела, удаления предела или завершения выполняемых транзакций. Привилегия TP_CONNECTION_ADMIN должна быть явно предоставлена. Она не предоставляется ни одному пользователю по умолчанию.

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

При запросе таблицы performance_schema.tp_thread_group_stats, которая сообщает статистику по группам потоков, Admin статистика группы потоков отображается в последней строке набора результатов. Например, если SELECT * FROM performance_schema.tp_thread_group_stats возвращает 17 строк (по одной строке на каждую группу потоков), статистика группы потоков Admin отображается в 17-й строке.

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

Spec-Zone.ru

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