5.5.3.3 Работа пула потоков
Пул потоков состоит из ряда групп потоков, каждая из которых управляет набором клиентских соединений. По мере установления соединений пул потоков распределяет их по группам потоков по круговому циклу.
Пул потоков предоставляет системные переменные, которые могут использоваться для настройки его работы:
thread_pool_algorithm: Алгоритм конкурентности для планирования.thread_pool_high_priority_connection: Способ планирования выполнения запросов для сеанса.thread_pool_max_unused_threads: Количество спящих потоков, разрешенных к работе.thread_pool_prio_kickup_timer: Время, через которое пул потоков перемещает запрос, ожидающий выполнения, из очереди низкого приоритета в очередь высокого приоритета.thread_pool_size: Количество групп потоков в пуле потоков. Это наиболее важный параметр, контролирующий производительность пула потоков.thread_pool_stall_limit: Время, по истечении которого выполняемый запрос считается заблокированным.
Для настройки количества групп потоков используйте системную переменную thread_pool_size. По умолчанию количество групп равно 16. Рекомендации по настройке этой переменной см. в разделе 5.5.3.4 «Настройка пула потоков».
Максимальное количество потоков на группу равно 4096 (или 4095 на некоторых системах, где один поток используется внутренне).
Пул потоков отделяет соединения и потоки, поэтому нет фиксированной связи между соединениями и потоками, которые выполняют запросы, полученные от этих соединений. Это отличается от модели обработки потоков по умолчанию, где одному потоку сопоставляется одно соединение, так что данный поток выполняет все запросы из своего соединения.
Пул потоков старается обеспечить максимум одного выполняющегося потока в каждой группе в любое время, но иногда разрешает больше потоков временно для лучшей производительности:
-
Каждая группа потоков имеет поток-слушатель, который прослушивает входящие запросы от соединений, назначенных этой группе. Когда запрос приходит, группа потоков либо начинает его немедленное выполнение, либо помещает его в очередь на последующее выполнение:
Немедленное выполнение происходит, если запрос является единственным полученным и нет запросов в очереди или в текущем исполнении.
Помещение в очередь происходит, если запрос не может быть выполнен немедленно.
-
Если выполнение происходит немедленно, поток-слушатель выполняет его. (Это означает, что временно ни один поток в группе не прослушивает). Если запрос выполняется быстро, выполняющий поток возвращается к прослушиванию запросов. В противном случае пул потоков считает запрос заблокированным и запускает другой поток в качестве потока-слушателя (создав его при необходимости). Чтобы гарантировать, что ни одна группа потоков не заблокируется из-за заблокированных запросов, пул потоков имеет фоновый поток, который регулярно отслеживает состояние групп потоков.
Используя поток-слушатель для выполнения запроса, который может быть начат немедленно, нет необходимости создавать дополнительный поток, если запрос выполняется быстро. Это обеспечивает наиболее эффективное выполнение в случае небольшого количества одновременных потоков.
При запуске плагина пула потоков создаётся по одному потоку на группу (поток-слушатель) плюс фоновый поток. Дополнительные потоки создаются по мере необходимости для выполнения запросов.
Значение системной переменной
thread_pool_stall_limitопределяет значение “выполняется быстро” в предыдущем пункте. По умолчанию время ожидания перед тем, как потоки считаются заблокированными, составляет 60 мс, но может быть установлено максимум до 6 секунд. Этот параметр настраивается для обеспечения баланса, соответствующего нагрузке сервера. Короткие значения ожидания позволяют потокам начинать быстрее. Короткие значения также лучше для предотвращения тупиковых ситуаций. Длинные значения ожидания полезны для рабочих нагрузок, включающих длительные запросы, чтобы избежать запуска слишком большого количества новых запросов, пока текущие выполняются.Пул потоков фокусируется на ограничении количества одновременных запросов с коротким временем выполнения. Перед тем, как выполняемый запрос достигнет времени блокировки, он предотвращает начало выполнения других запросов. Если запрос выполняется дольше времени блокировки, ему разрешается продолжить выполнение, но он больше не предотвращает начало выполнения других запросов. Таким образом, пул потоков пытается гарантировать, что в каждой группе потоков никогда не будет более одного запроса с коротким временем выполнения, хотя могут быть несколько запросов с длительным временем выполнения. Нежелательно допускать, чтобы запросы с длительным временем выполнения предотвращали выполнение других запросов, поскольку нет предела времени ожидания.
Запрос блокируется, если он сталкивается с операцией ввода-вывода на диск или блокировкой на уровне пользователя (строчная блокировка или табличная блокировка). Блокировка приведет к тому, что группа потоков станет неиспользуемой, поэтому существуют обратные вызовы в пул потоков, чтобы гарантировать, что пул потоков может немедленно запустить новый поток в этой группе для выполнения другого запроса. Когда заблокированный поток возвращается, пул потоков позволяет ему немедленно перезапуститься.
-
Существуют две очереди: очередь высокого приоритета и очередь низкого приоритета. Первый запрос в транзакции попадает в очередь низкого приоритета. Все последующие запросы для транзакции попадают в очередь высокого приоритета, если транзакция продолжается (запросы для неё начаты), или в очередь низкого приоритета в противном случае. Назначение очереди может быть изменено с помощью включения системной переменной
thread_pool_high_priority_connection, которая заставляет все запросы в очереди для сеанса попадать в очередь высокого приоритета.Запросы для нетранзакционного движка хранения данных или транзакционного движка, если включен
autocommit, обрабатываются как запросы низкого приоритета, поскольку в этом случае каждый запрос является транзакцией. Таким образом, учитывая смесь запросов для таблицInnoDBиMyISAM, пул потоков отдает приоритет запросам дляInnoDBнад запросами дляMyISAM, если не включенautocommit. При включенномautocommitвсе запросы имеют низкий приоритет. Когда группа потоков выбирает запрос из очереди для выполнения, она сначала проверяет очередь высокого приоритета, затем очередь низкого приоритета. Если запрос найден, он удаляется из очереди и начинает выполняться.
Если запрос остается в очереди низкого приоритета слишком долго, пул потоков переводит его в очередь высокого приоритета. Значение системной переменной
thread_pool_prio_kickup_timerуправляет временем перемещения. Для каждой группы потоков максимум один запрос перемещается из очереди низкого приоритета в очередь высокого приоритета каждые 10 мс (100 за секунду).Пул потоков повторно использует наиболее активные потоки для достижения лучшего использования кэшей процессора. Это небольшая настройка, которая оказывает большое влияние на производительность.
Пока поток выполняет запрос от пользовательского соединения, инструменты Performance Schema учитывают активность потока для пользовательского соединения. В противном случае Performance Schema учитывает активность для пула потоков.
Вот примеры условий, при которых группа потоков может иметь несколько запущенных потоков для выполнения запросов:
Один поток начинает выполнять запрос, но выполняется достаточно долго, чтобы быть признанным заблокированным. Группа потоков позволяет другому потоку начать выполнение другого запроса, даже если первый поток всё еще выполняется.
Один поток начинает выполнять запрос, затем блокируется и сообщает об этом в пул потоков. Группа потоков позволяет другому потоку начать выполнение другого запроса.
Один поток начинает выполнять запрос, блокируется, но не сообщает о блокировке, так как блокировка не происходит в коде, оснащенном обратными вызовами пула потоков. В этом случае группа потоков воспринимает этот поток как работающий. Если блокировка длится достаточно долго, чтобы запрос считался заблокированным, группа разрешает другому потоку начать выполнение другого запроса.
Пул потоков разработан для масштабирования при увеличении количества соединений. Он также разработан для предотвращения тупиковых ситуаций, которые могут возникнуть из-за ограничения количества активно выполняемых запросов. Важно, чтобы потоки, которые не сообщают в пул потоков, не мешали выполнению других запросов, и таким образом не приводили к тупиковой ситуации в пуле потоков. Примеры таких запросов приведены ниже:
Запросы с длительным временем выполнения. Это привело бы к тому, что все ресурсы будут использоваться только несколькими запросами, и они могли бы помешать всем остальным получить доступ к серверу.
Потоки дублирования бинарного лога, которые читают бинарный лог и отправляют его репликам. Это своего рода запрос с длительным временем выполнения, который работает очень долго и не должен предотвращать выполнение других запросов.
Запросы, заблокированные на строчной блокировке, табличной блокировке, ожидании или любой другой блокирующей деятельности, о которой MySQL Server или движок хранения данных не сообщили пулу потоков.
В каждом случае, чтобы предотвратить тупиковую ситуацию, запрос переводится в категорию заблокированных, когда он не завершается быстро, чтобы группа потоков могла разрешить начало выполнения другого запроса. При такой разработке, когда поток выполняется или блокируется на длительное время, пул потоков переводит поток в категорию заблокированных, и в течение остального времени выполнения запроса он не препятствует выполнению других запросов.
END_OF_DOCUMENT_MARKER Максимальное количество потоков, которое может произойти, равно сумме max_connections и thread_pool_size. Это может произойти в ситуации, когда все подключения находятся в режиме выполнения, и для каждой группы создается дополнительный поток для прослушивания дополнительных заявок. Это не обязательно состояние, которое часто происходит, но теоретически это возможно.
© 2025 Oracle
Licensed under the GPLv2 License.