All pages
Powered by GitBook
1 of 5

Loading...

Loading...

Loading...

Loading...

Loading...

Thread Pool

Optimize MariaDB Server with the thread pool. This section explains how to manage connections and improve performance by efficiently handling concurrent client requests, reducing resource overhead.

Thread Pool in MariaDB 5.1 - 5.3

This page describes the old thread pool implementation in MariaDB up to version 5.3.

It's left here because some refer to it.

For the current implementation, refer to the Thread Pool in MariaDB page.

About Pool of Threads

This is an extended version of the pool-of-threads code from MySQL 6.0. This allows you to use a limited set of threads to handle all queries, instead of the old 'one-thread-per-connection' style. In recent times, its also been referred to as "thread pool" or "thread pooling" as this feature (in a different implementation) is available in Enterprise editions of MySQL (not in the Community edition).

This can be a very big win if most of your queries are short running queries and there are few table/row locks in your system.

Instructions

To enable pool-of-threads you must first run configure with the--with-libevent option. (This is automatically done if you use any 'max' scripts in the BUILD directory):

When starting mysqld with the pool of threads code you should use:

Default values are:

One issue with pool-of-threads is that if all worker threads are doing work (like running long queries) or are locked by a row/table lock no new connections can be established and you can't login and find out what's wrong or login and kill queries.

To help this, we have introduced two new options for mysqld; and :

If is <> 0 then you can connect max_connections number of normal threads + 1 extra SUPER user through the 'extra-port' TCP/IP port. These connections use the old one-thread-per-connection method.

To connect with through the extra port, use:

This allows you to freely use, on connection bases, the optimal connection/thread model.

See also

This page is licensed: CC BY-SA / Gnu FDL

Thread Pool in MariaDB

Problems That Thread Pools Solve

The task of scalable server software (and a DBMS like MariaDB is an example of such software) is to maintain top performance with an increasing number of clients. MySQL traditionally assigned a thread for every client connection, and as the number of concurrent users grows this model shows performance drops. Many active threads are a performance killer, because increasing the number of threads leads to extensive context switching, bad locality for CPU caches, and increased contention for hot locks. An ideal solution that would help to reduce context switching is to maintain a lower number of threads than the number of clients. But this number should not be too low either, since we also want to utilize CPUs to their fullest, so ideally, there should be a single active thread for each CPU on the machine.

MariaDB Thread Pool Features

MariaDB has a dynamic and adaptive thread pool, aimed at optimizing resource utilization and preventing deadlocks.

For example, a thread may depend on another thread's completion, and they may block each other via locks and/or I/O. It is hard, and sometimes impossible, to predict how many threads are ideal or even sufficient to prevent deadlocks in every situation. MariaDB implements a dynamic and adaptive pool that takes care of creating new threads in times of high demand, and retiring threads if they have nothing to do. This is a complete reimplementation of the legacy pool-of-threads scheduler, with the following goals:

  • Make the pool dynamic, so that it will grow and shrink whenever required.

  • Minimize the amount of overhead that is required to maintain the thread pool itself.

  • Make the best use of underlying OS capabilities. For example, if a native thread pool implementation is available, it should be used. If not, the best I/O multiplexing method should be used.

  • Limit the resources used by threads.

There are currently two different low-level implementations – depending on OS. One implementation is designed specifically for Windows which utilizes a native CreateThreadpool API. The second implementation is primarily intended to be used in Unix-like systems. Because the implementations are different, some system variables differ between Windows and Unix.

When to Use the Thread Pool

Thread pools are most efficient in situations where queries are relatively short and the load is CPU-bound, such as in OLTP workloads. If the workload is not CPU-bound, then you might still benefit from limiting the number of threads to save memory for the database memory buffers.

When the Thread Pool is Less Efficient

There are special, rare cases where the thread pool is likely to be less efficient.

  • If you have a very bursty workload, then the thread pool may not work well for you. These tend to be workloads in which there are long periods of inactivity followed by short periods of very high activity by many users. These also tend to be workloads in which delays cannot be tolerated, so the throttling of thread creation that the thread pool uses is not ideal. Even in this situation, performance can be improved by tweaking how often threads are retired. For example, with thread_pool_idle_timeout on Unix, or with thread_pool_min_threads on Windows.

  • If you have many concurrent, long, non-yielding queries, then the thread pool may not work well for you. In this context, a "non-yielding" query is one that never waits or which does not indicate waits to the thread pool. These kinds of workloads are mostly used in data warehouse scenarios. Long-running, non-yielding queries will delay execution of other queries. However, the thread pool has stall detection to prevent them from totally monopolizing the thread pool. See Thread Groups in the Unix Implementation of the Thread Pool: Thread Group Stalls for more information. Even when the whole thread pool is blocked by non-yielding queries, you can still connect to the server through the extra-port TCP/IP port.

  • If you rely on the fact that simple queries always finish quickly, no matter how loaded your database server is, then the thread pool may not work well for you. When the thread pool is enabled on a busy server, even simple queries might be queued to be executed later. This means that even if the statement itself doesn't take much time to execute, even a simple SELECT 1, might take a bit longer when the thread pool is enabled than with one-thread-per-connection if it gets queued.

Configuring the Thread Pool

The thread_handling system variable is the primary system variable that is used to configure the thread pool.

There are several other system variables as well, which are described in the sections below. Many of the system variables documented below are dynamic, meaning that they can be changed with SET GLOBAL on a running server.

Generally, there is no need to tweak many of these system variables. The goal of the thread pool was to provide good performance out-of-the box. However, the system variable values can be changed, and we intended to expose as many knobs from the underlying implementation as we could. Feel free to tweak them as you see fit.

If you find any issues with any of the default behavior, then we encourage you to .

See Thread Pool System and Status Variables for the full list of the thread pool's system variables.

Configuring the Thread Pool on Unix

On Unix, if you would like to use the thread pool, then you can use the thread pool by setting the thread_handling system variable to pool-of-threads in a server option group in an option file prior to starting up the server. For example:

The following system variables can also be configured on Unix:

  • thread_pool_size – The number of thread groups in the thread pool, which determines how many statements can execute simultaneously. The default value is the number of CPUs on the system. When setting this system variable's value at system startup, the max value is 100000. However, it is not a good idea to set it that high. When setting this system variable's value dynamically, the max value is either 128 or the value that was set at system startup--whichever value is higher. See Thread Groups in the Unix Implementation of the Thread Pool for more information.

  • thread_pool_max_threads – The maximum number of threads in the thread pool. Once this limit is reached, no new threads will be created in most cases. In rare cases, the actual number of threads can slightly exceed this, because each thread group needs at least two threads (i.e. at least one worker thread and at least one listener thread) to prevent deadlocks. The default value is 65536.

  • – The number of milliseconds between each stall check performed by the timer thread. The default value is 500. Stall detection is used to prevent a single client connection from monopolizing a thread group. When the timer thread detects that a thread group is stalled, it wakes up a sleeping worker thread in the thread group, if one is available. If there isn't one, then it creates a new worker thread in the thread group. This temporarily allows several client connections in the thread group to run in parallel. However, note that the timer thread will not create a new worker thread if the number of threads in the thread pool is already greater than or equal to the maximum defined by the variable, unless the thread group does not already have a listener thread. See for more information.

  • – Determines how many worker threads in a thread group can remain active at the same time once a thread group is oversubscribed due to stalls. The default value is 3. Usually, a thread group only has one active worker thread at a time. However, the timer thread can add more active worker threads to a thread group if it detects a stall. There are trade-offs to consider when deciding whether to allow only one thread per CPU to run at a time, or whether to allow more than one thread per CPU to run at a time. Allowing only one thread per CPU means that the thread can have unrestricted access to the CPU while its running, but it also means that there is additional overhead from putting threads to sleep or waking them up more frequently. Allowing more than one thread per CPU means that the threads have to share the CPU, but it also means that there is less overhead from putting threads to sleep or waking them up. This is primarily for internal use, and it is not meant to be changed for most users. See for more information.

  • – The number of seconds before an idle worker thread exits. The default value is 60. If there is currently no work to do, how long should an idle thread wait before exiting?

Configuring the Thread Pool on Windows

The Windows implementation of the thread pool uses a native thread pool created with the CreateThreadpool API.

On Windows, if you would like to use the thread pool, then you do not need to do anything, because the default for the thread_handling system variable is already preset to pool-of-threads.

However, if you would like to use the old one thread per-connection behavior on Windows, then you can use that by setting the thread_handling system variable to one-thread-per-connection in a server option group in an option file prior to starting up the server. For example:

On older versions of Windows, such as XP and 2003, pool-of-threads is not implemented, and the server will silently switch to using the legacyone-thread-per-connection method.

The native CreateThreadpool API allows applications to set the minimum and maximum number of threads in the pool. The following system variables can be used to configure those values on Windows:

  • thread_pool_min_threads – The minimum number of threads in the pool. Default is 1. This applicable in a special case of very “bursty” workloads. Imagine having longer periods of inactivity after periods of high activity. While the thread pool is idle, Windows would decide to retire pool threads (based on experimentation, this seems to happen after thread had been idle for 1 minute). Next time high load comes, it could take some milliseconds or seconds until the thread pool size stabilizes again to optimal value. To avoid thread retirement, one could set the parameter to a higher value.

  • thread_pool_max_threads – The maximum number of threads in the pool. Threads are not created when this value is reached. The default is 1000. This parameter can be used to prevent the creation of new threads if the pool can have short periods where many or all clients are blocked (for example, with FLUSH TABLES WITH READ LOCK, high contention on row locks, or similar). New threads are created if a blocking situation occurs (such as after a throttling interval), but sometimes you want to cap the number of threads, if you’re familiar with the application and need to, for example, save memory. If your application constantly pegs at 500 threads, it might be a strong indicator for high contention in the application, and the thread pool does not help much.

Configuring Priority Scheduling

It is possible to configure connection prioritization. The priority behavior is configured by the thread_pool_priority system variable.

By default, if thread_pool_priority is set to auto, then queries would be given a higher priority, in case the current connection is inside a transaction. This allows the running transaction to finish faster, and has the effect of lowering the number of transactions running in parallel. The default setting will generally improve throughput for transactional workloads. But it is also possible to explicitly set the priority for the current connection to either 'high' or 'low'.

There is also a mechanism in place to ensure that higher priority connections are not monopolizing the worker threads in the pool (which would cause indefinite delays for low priority connections). On Unix, low priority connections are put into the high priority queue after the timeout specified by the thread_pool_prio_kickup_timer system variable.

Configuring the Extra Port

MariaDB allows you to configure an extra port for administrative connections. This is primarily intended to be used in situations where all threads in the thread pool are blocked, and you still need a way to access the server. However, it can also be used to ensure that monitoring systems (including MaxScale's monitors) always have access to the system, even when all connections on the main port are used. This extra port uses the old one-thread-per-connection thread handling.

You can enable this and configure a specific port by setting the extra_port system variable.

You can configure a specific number of connections for this port by setting the extra_max_connections system variable.

These system variables can be set in a server option group in an option file prior to starting up the server. For example:

Once you have the extra port configured, you can use the mariadb client with the -P option to connect to the port.

Monitoring Thread Pool Activity

Currently there are two status variables exposed to monitor pool activity.

Variable
Description

Number of threads in the thread pool. In rare cases, this can be slightly higher than , because each thread group needs at least two threads (i.e. at least one worker thread and at least one listener thread) to prevent deadlocks.

Number of inactive threads in the thread pool. Threads become inactive for various reasons, such as by waiting for new work. However, an inactive thread is not necessarily one that has not been assigned work. Threads are also considered inactive if they are being blocked while waiting on disk I/O, or while waiting on a lock, etc. This status variable is only meaningful on Unix.

Thread Groups in the Unix Implementation of the Thread Pool

On Unix, the thread pool implementation uses objects called thread groups to divide up client connections into many independent sets of threads. See Thread Groups in the Unix Implementation of the Thread Pool for more information.

Fixing a Blocked Thread Pool

When using global locks, even with a high value on the thread_pool_max_threads system variable, it is still possible to block the entire pool.

Imagine the case where a client performs FLUSH TABLES WITH READ LOCK then pauses. If then the number of other clients connecting to the server to start write operations exceeds the maximum number of threads allowed in the pool, it can block the Server. This makes it impossible to issue the UNLOCK TABLES statement. It can also block MaxScale from monitoring the Server.

To mitigate the issue, MariaDB allows you to configure an extra port for administrative connections. See Configuring the Extra Port for information on how to configure this.

Once you have the extra port configured, you can use the mariadb client with the -P option to connect to the port.

This ensures that your administrators can access the server in cases where the number of threads is already equal to the configured value of the thread_pool_max_threads system variable, and all threads are blocked. It also ensures that MaxScale can still access the server in such situations for monitoring information.

Once you are connected to the extra port, you can solve the issue by increasing the value on the thread_pool_max_threads system variable, or by killing the offending connection, (that is, the connection that holds the global lock, which would be in the sleep state).

Information Schema

The following Information Schema tables relate to the thread pool:

  • Information Schema THREAD_POOL_GROUPS Table

  • Information Schema THREAD_POOL_QUEUES Table

  • Information Schema THREAD_POOL_STATS Table

  • Information Schema THREAD_POOL_WAITS Table

MariaDB Thread Pool vs Oracle MySQL Enterprise Thread Pool

Commercial editions of MySQL since 5.5 include an Oracle MySQL Enterprise thread pool implemented as a plugin, which delivers similar functionality. A detailed discussion about the design of the feature is at Mikael Ronstrom's blog. Here is the summary of similarities and differences, based on the above materials.

Similarities

  • On Unix, both MariaDB and Oracle MySQL Enterprise Thread Pool will partition client connections into groups. The thread_pool_size parameter thus has the same meaning for both MySQL and MariaDB.

  • Both implementations use similar schema checking for thread stalls, and both have the same parameter name for thread_pool_stall_limit (though in MariaDB it is measured using millisecond units, not 10ms units like in Oracle MySQL).

Differences

  • The Windows implementation is completely different – MariaDB's uses native Windows thread pooling, while Oracle's implementation includes a convenience function WSAPoll() (provided for convenience to port Unix applications). As a consequence of relying on WSAPoll(), Oracle's implementation does not work with named pipes and shared memory connections.

  • MariaDB uses the most efficient I/O multiplexing facilities for each operating system: Windows (the I/O completion port is used internally by the native thread pool), Linux (epoll), Solaris (event ports), FreeBSD and OSX (kevent). Oracle uses optimized I/O multiplexing only on Linux, with epoll, and uses poll() otherwise.

  • Unlike Oracle MySQL Enterprise Thread Pool, MariaDB's one is built in, not a plugin.

MariaDB Thread Pool vs Percona Thread Pool

Percona's implementation is a port of the MariaDB's thread pool with some added features. In particular, Percona added priority scheduling to its 5.5-5.7 releases. MariaDB and Percona priority scheduling works in a similar fashion, but there are some differences in details.

  • MariaDB's thread_pool_priority=auto,high, low correspond to Percona's thread_pool_high_prio_mode=transactions,statements,none.

  • Percona has a thread_pool_high_prio_tickets connection variable to allow every nth low priority query to be put into the high priority queue. MariaDB does not have a corresponding setting.

  • MariaDB has a thread_pool_prio_kickup_timer setting, which Percona does not have.

Running Benchmarks

When running sysbench and maybe other benchmarks, that create many threads on the same machine as the server, it is advisable to run benchmark driver and server on different CPUs to get the realistic results. Running lots of driver threads and only several server threads on the same CPUs will have the effect that OS scheduler will schedule benchmark driver threads to run with much higher probability than the server threads, that is driver will pre-empt the server. Use "taskset –c" on Linuxes, and "set /affinity" on Windows to separate benchmark driver and server CPUs, as the preferred method to fix this situation.

A possible alternative on Unix (if taskset or a separate machine running the benchmark is not desired for some reason) would be to increase thread_pool_size to make the server threads more "competitive" against the client threads.

When running sysbench, a good rule of thumb could be to give 1/4 of all CPUs to the sysbench, and 3/4 of CPUs to mariadbd. It is also good idea to run sysbench and mariadbd on different NUMA nodes, if possible.

Notes

The thread_cache_size system variable is not used when the thread pool is used and the Threads_cached status variable will have a value of 0.

See Also

  • Thread Pool System and Status Variables

This page is licensed: CC BY-SA / Gnu FDL

extra_port
extra_max_connections
extra-port
Thread-handling and thread-pool-size variables
How MySQL Uses Threads for Client Connections

Thread Groups in the Unix Implementation of the Thread Pool

This article does not apply to the thread pool implementation on Windows. On Windows, MariaDB uses a native thread pool created with the CreateThreadpool APl, which has its own methods to distribute threads between CPUs.

On Unix, the thread pool implementation uses objects called thread groups to divide up client connections into many independent sets of threads. The thread_pool_size system variable defines the number of thread groups on a system. Generally speaking, the goal of the thread group implementation is to have one running thread on each CPU on the system at a time. Therefore, the default value of the thread_pool_size system variable is auto-sized to the number of CPUs on the system.

When setting the thread_pool_size system variable's value at system startup, the max value is 100000. However, it is not a good idea to set it that high. When setting its value dynamically, the max value is either 128 or the value that was set at system startup--whichever value is higher. It can be changed dynamically with SET GLOBAL. For example:

It can also be set in a server option group in an option file prior to starting up the server. For example:

If you do not want MariaDB to use all CPUs on the system for some reason, then you can set it to a lower value than the number of CPUs. For example, this would make sense if the MariaDB Server process is limited to certain CPUs with the utility on Linux.

If you set the value to the number of CPUs and if you find that the CPUs are still underutilized, then try increasing the value.

The system variable tends to have the most visible performance effect. It is roughly equivalent to the number of threads that can run at the same time. In this case, run means use CPU, rather than sleep or wait. If a client connection needs to sleep or wait for some reason, then it wakes up another client connection in the thread group before it does so.

One reason that CPU underutilization may occur in rare cases is that the thread pool is not always informed when a thread is going to wait. For example, some waits, such as a page fault or a miss in the OS buffer cache, cannot be detected by MariaDB.

Distributing Client Connections Between Thread Groups

When a new client connection is created, its thread group is determined using the following calculation:

The connection_id value in the above calculation is the same monotonically increasing number that you can use to identify connections in output or the table.

This calculation should assign client connections to each thread group in a round-robin manner. In general, this should result in an even distribution of client connections among thread groups.

Types of Threads

Thread Group Threads

Thread groups have two different kinds of threads: a listener thread and worker threads.

  • A thread group's worker threads actually perform work on behalf of client connections. A thread group can have many worker threads, but usually, only one will be actively running at a time. This is not always the case. For example, the thread group can become oversubscribed if the thread pool's timer thread detects that the thread group is stalled. This is explained more in the sections below.

  • A thread group's listener thread listens for I/O events and distributes work to the worker threads. If it detects that there is a request that needs to be worked on, then it can wake up a sleeping worker thread in the thread group, if any exist. If the listener thread is the only thread in the thread group, then it can also create a new worker thread. If there is only one request to handle, and if the system variable is not enabled, then the listener thread can also become a worker thread and handle the request itself. This helps decrease the overhead that may be introduced by excessively waking up sleeping worker threads and excessively creating new worker threads.

Global Threads

The thread pool has one global thread: a timer thread. The timer thread performs tasks, such as:

  • Checks each thread group for stalls.

  • Ensures that each thread group has a listener thread.

Thread Creation

A new thread is created in a thread group in the scenarios listed below.

In all of the scenarios below, the thread pool implementation prefers to wake up a sleeping worker thread that already exists in the thread group, rather than to create a new thread.

Worker Thread Creation by Listener Thread

A thread group's listener thread can create a new worker thread when it has more client connection requests to distribute, but no pre-existing worker threads are available to work on the requests. This can help to ensure that the thread group always has enough threads to keep one worker thread active at a time.

A thread group's listener thread creates a new worker thread if all of the following conditions are met:

  • The listener thread receives a client connection request that needs to be worked on.

  • There are more client connection requests in the thread group's work queue that the listener thread still needs to distribute to worker threads, so the listener thread should not become a worker thread.

  • There are no active worker threads in the thread group.

  • There are no sleeping worker threads in the thread group that the listener thread can wake up.

Thread Creation by Worker Threads During Waits

A thread group's worker thread can create a new worker thread when the thread has to wait on something, and the thread group has more client connection requests queued, but no pre-existing worker threads are available to work on them. This can help to ensure that the thread group always has enough threads to keep one worker thread active at a time. For most workloads, this tends to be the primary mechanism that creates new worker threads.

A thread group's worker thread creates a new thread if all of the following conditions are met:

  • The worker thread has to wait on some request. For example, it might be waiting on disk I/O, or it might be waiting on a lock, or it might just be waiting for a query that called the function to finish.

  • There are no active worker threads in the thread group.

  • There are no sleeping worker threads in the thread group that the worker thread can wake up.

  • And one of the following conditions is also met:

Listener Thread Creation by Timer Thread

The thread pool's timer thread can create a new listener thread for a thread group when the thread group has more client connection requests that need to be distributed, but the thread group does not currently have a listener thread to distribute them. This can help to ensure that the thread group does not miss client connection requests because it has no listener thread.

The thread pool's timer thread creates a new listener thread for a thread group if all of the following conditions are met:

  • The thread group has not handled any I/O events since the last check by the timer thread.

  • There is currently no listener thread in the thread group. For example, if the system variable is not enabled, then the thread group's listener thread can became a worker thread, so that it could handle some client connection request. In this case, the new thread can become the thread group's listener thread.

  • There are no sleeping worker threads in the thread group that the timer thread can wake up.

  • And one of the following conditions is also met:

Worker Thread Creation by Timer Thread during Stalls

The thread pool's timer thread can create a new worker thread for a thread group when the thread group is stalled. This can help to ensure that a long query can't monopole its thread group.

The thread pool's timer thread creates a new worker thread for a thread group if all of the following conditions are met:

  • The timer thread thinks that the thread group is stalled. This means that the following conditions have been met:

    • There are more client connection requests in the thread group's work queue that the listener thread still needs to distribute to worker threads.

    • No client connection requests have been allowed to be dequeued to run since the last stall check by the timer thread.

  • There are no sleeping worker threads in the thread group that the timer thread can wake up.

Thread Creation Throttling

In some of the scenarios listed above, a thread is only created within a thread group if no new threads have been created for the thread group within the throttling interval. The throttling interval depends on the number of threads that are already in the thread group.

In and later, thread creation is not throttled until a thread group has more than 1 + threads:

Number of Threads in Thread Group
Throttling Interval (milliseconds)

The throttling factor is calculated like this (see for more information):

Thread Group Stalls

The thread pool has a feature that allows it to detect if a client connection is executing a long-running query that may be monopolizing its thread group. If a client connection were to monopolize its thread group, then that could prevent other client connections in the thread group from running their queries. In other words, the thread group would appear to be stalled.

This stall detection feature is implemented by creating a timer thread that periodically checks if any of the thread groups are stalled. There is only a single timer thread for the entire thread pool. The system variable defines the number of milliseconds between each stall check performed by the timer thread. The default value is 500. It can be changed dynamically with . For example:

It can also be set in a server in an prior to starting up the server. For example:

The timer thread considers a thread group to be stalled if the following is true:

  • There are more client connection requests in the thread group's work queue that the listener thread still needs to distribute to worker threads.

  • No client connection requests have been allowed to be dequeued to run since the last stall check by the timer thread.

This indicates that the one or more client connections currently using the active worker threads may be monopolizing the thread group, and preventing the queued client connections from performing work. When the timer thread detects that a thread group is stalled, it wakes up a sleeping worker thread in the thread group, if one is available. If there isn't one, then it creates a new worker thread in the thread group. This temporarily allows several client connections in the thread group to run in parallel.

The system variable essentially defines the limit for what a "fast query" is. If a query takes longer than , then the thread pool is likely to think that it is too slow, and it will either wake up a sleeping worker thread or create a new worker thread to let another client connection in the thread group run a query in parallel.

In general, changing the value of the system variable has the following effect:

  • Setting it to higher values can help avoid starting too many parallel threads if you expect a lot of client connections to execute long-running queries.

  • Setting it to lower values can help prevent deadlocks.

Thread Group Oversubscription

If the timer thread were to detect a stall in a thread group, then it would either wake up a sleeping worker thread or create a new worker thread in that thread group. At that point, the thread group would have multiple active worker threads. In other words, the thread group would be oversubscribed.

You might expect that the thread pool would shutdown one of the worker threads when the stalled client connection finished what it was doing, so that the thread group would only have one active worker thread again. However, this does not always happen. Once a thread group is oversubscribed, the system variable defines the upper limit for when worker threads start shutting down after they finish work for client connections. The default value is 3. It can be changed dynamically with . For example:

It can also be set in a server in an prior to starting up the server. For example:

To clarify, the system variable does not play any part in the creation of new worker threads. The system variable is only used to determine how many worker threads should remain active in a thread group, once a thread group is already oversubscribed due to stalls.

In general, the default value of 3 should be adequate for most users. Most users should not need to change the value of the system variable.

This page is licensed: CC BY-SA / Gnu FDL

[mariadb]
...
thread_handling=pool-of-threads
[mariadb]
...
thread_handling=one-thread-per-connection
[mariadb]
...
extra_port = 8385
extra_max_connections = 10
$ mariadb -u root -P 8385 -p
$ mariadb -u root -P 8385 -p
./configure --with-libevent
mysqld --thread-handling=pool-of-threads --thread-pool-size=20
thread-handling=  one-thread-per-connection
thread-pool-size= 20
--extra-port=#             (Default 0)
--extra-max-connections=#  (Default 1)
mysql --port='number-of-extra-port' --protocol=tcp
SET GLOBAL thread_pool_size=32;
[mariadb]
..
thread_handling=pool-of-threads
thread_pool_size=32

And one of the following conditions is also met:

  • The entire thread pool has fewer than thread_pool_max_threads.

  • There are fewer than two threads in the thread group. This is to guarantee that each thread group can have at least two threads, even if thread_pool_max_threads has already been reached or exceeded.

  • The entire thread pool has fewer than thread_pool_max_threads.

  • There are fewer than two threads in the thread group. This is to guarantee that each thread group can have at least two threads, even if thread_pool_max_threads has already been reached or exceeded.

  • And one of the following conditions is also met:

    • There are more client connection requests in the thread group's work queue that the listener thread still needs to distribute to worker threads. In this case, the new thread is intended to be a worker thread.

    • There is currently no listener thread in the thread group. For example, if the thread_pool_dedicated_listener system variable is not enabled, then the thread group's listener thread can became a worker thread, so that it could handle some client connection request. In this case, the new thread can become the thread group's listener thread.

  • The entire thread pool has fewer than thread_pool_max_threads.

  • There are fewer than two threads in the thread group. This is to guarantee that each thread group can have at least two threads, even if thread_pool_max_threads has already been reached or exceeded.

  • If the thread group already has active worker threads, then the following condition also needs to be met:

    • A worker thread has not been created for the thread group within the throttling interval.

  • And one of the following conditions is also met:

    • The entire thread pool has fewer than thread_pool_max_threads.

    • There are fewer than two threads in the thread group. This is to guarantee that each thread group can have at least two threads, even if thread_pool_max_threads has already been reached or exceeded.

  • A worker thread has not been created for the thread group within the throttling interval.

  • 0-(1 + thread_pool_oversubscribe)

    0

    4-7

    50 * THROTTLING_FACTOR

    8-15

    100 * THROTTLING_FACTOR

    16-65536

    20 * THROTTLING_FACTOR

    taskset
    thread_pool_size
    SHOW PROCESSLIST
    information_schema.PROCESSLIST
    thread_pool_dedicated_listener
    SLEEP()
    thread_pool_dedicated_listener
    thread_pool_oversubscribe
    thread_pool_stall_limit
    thread_pool_stall_limit
    SET GLOBAL
    option group
    option file
    thread_pool_stall_limit
    thread_pool_stall_limit
    thread_pool_stall_limit
    thread_pool_oversubscribe
    SET GLOBAL
    option group
    option file
    thread_pool_oversubscribe
    thread_pool_oversubscribe
    thread_pool_oversubscribe
    thread_pool_stall_limit
    thread_pool_max_threads
    Thread Groups in the Unix Implementation of the Thread Pool: Thread Group Stalls
    thread_pool_oversubscribe
    Thread Groups in the Unix Implementation of the Thread Pool: Thread Group Oversubscription
    thread_pool_idle_timeout
    Threadpool_threads
    thread_pool_max_threads
    Threadpool_idle_threads
    thread_group_id = connection_id % thread_pool_size
    THROTTLING_FACTOR = thread_pool_stall_limit / MAX (500,thread_pool_stall_limit)
    SET GLOBAL thread_pool_stall_limit=300;
    [mariadb]
    ..
    thread_handling=pool-of-threads
    thread_pool_size=32
    thread_pool_stall_limit=300
    SET GLOBAL thread_pool_oversubscribe=10;
    [mariadb]
    ..
    thread_handling=pool-of-threads
    thread_pool_size=32
    thread_pool_stall_limit=300
    thread_pool_oversubscribe=10

    Thread Pool System and Status Variables

    This article describes the system and status variables used by the MariaDB thread pool. For a full description, see Thread Pool in MariaDB.

    System variables

    extra_max_connections

    • Description: The number of connections on the .

      • See for more information.

    • Command line: --extra-max-connections=#

    • Scope: Global

    extra_port

    • Description: Extra port number to use for TCP connections in a one-thread-per-connection manner. If set to 0, then no extra port is used.

      • See for more information.

    • Command line: --extra-port=#

    thread_handling

    • Description: Determines how the server handles threads for client connections. In addition to threads for client connections, this also applies to certain internal server threads, such as . On Windows, if you would like to use the thread pool, then you do not need to do anything, because the default for the thread_handling system variable is already preset to pool-of-threads.

      • When the default one-thread-per-connection mode is enabled, the server uses one thread to handle each client connection.

      • When the pool-of-threads

    thread_pool_dedicated_listener

    • Description: If set to 1, then each group will have its own dedicated listener, and the listener thread will not pick up work items. As a result, the queueing time in the and the actual queue size in the table will be more exact, since IO requests are immediately dequeued from poll, without delay.

      • This system variable is only meaningful on Unix.

    • Command line: thread-pool-dedicated-listener={0|1}

    thread_pool_exact_stats

    • Description: If set to 1, provides better queueing time statistics by using a high precision timestamp, at a small performance cost, for the time when the connection was added to the queue. This timestamp helps calculate the queuing time shown in the table.

      • This system variable is only meaningful on Unix.

    • Command line: thread-pool-exact-stats={0|1}

    thread_pool_idle_timeout

    • Description: The number of seconds before an idle worker thread exits. The default value is 60. If there is currently no work to do, how long should an idle thread wait before exiting?

      • This system variable is only meaningful on Unix.

      • The system variable is comparable for Windows.

    thread_pool_max_threads

    • Description: The maximum number of threads in the . Once this limit is reached, no new threads will be created in most cases.

      • On Unix, in rare cases, the actual number of threads can slightly exceed this, because each needs at least two threads (i.e. at least one worker thread and at least one listener thread) to prevent deadlocks.

    • Scope:

    • Command line:

    thread_pool_min_threads

    • Description: Minimum number of threads in the . In bursty environments, after a period of inactivity, threads would normally be retired. When the next burst arrives, it would take time to reach the optimal level. Setting this value higher than the default would prevent thread retirement even if inactive.

      • This system variable is only meaningful on Windows.

      • The system variable is comparable for Unix.

    thread_pool_oversubscribe

    • Description: Determines how many worker threads in a thread group can remain active at the same time once a thread group is oversubscribed due to stalls. The default value is 3. Usually, a thread group only has one active worker thread at a time. However, the timer thread can add more active worker threads to a thread group if it detects a stall. There are trade-offs to consider when deciding whether to allow only one thread per CPU to run at a time, or whether to allow more than one thread per CPU to run at a time. Allowing only one thread per CPU means that the thread can have unrestricted access to the CPU while its running, but it also means that there is additional overhead from putting threads to sleep or waking them up more frequently. Allowing more than one thread per CPU means that the threads have to share the CPU, but it also means that there is less overhead from putting threads to sleep or waking them up.

      • See for more information.

    thread_pool_prio_kickup_timer

    • Description: Time in milliseconds before a dequeued low-priority statement is moved to the high-priority queue.

      • This system variable is only meaningful on Unix.

    • Command line: thread-pool-kickup-timer=#

    • Scope: Global

    thread_pool_priority

    • Description: priority. High-priority connections usually start executing earlier than low-priority. If set to 'auto' (the default), the actual priority (low or high) is determined by whether or not the connection is inside a transaction.

    • Command line: --thread-pool-priority=#

    • Scope: Global,Connection

    • Data Type: enum

    thread_pool_size

    • Description: The number of in the , which determines how many statements can execute simultaneously. The default value is the number of CPUs on the system. When setting this system variable's value at system startup, the max value is 100000. However, it is not a good idea to set it that high. When setting this system variable's value dynamically, the max value is either 128 or the value that was set at system startup--whichever value is higher.

      • See for more information.

      • This system variable is only meaningful on Unix.

    thread_pool_stall_limit

    • Description: The number of milliseconds between each stall check performed by the timer thread. The default value is 500. Stall detection is used to prevent a single client connection from monopolizing a thread group. When the timer thread detects that a thread group is stalled, it wakes up a sleeping worker thread in the thread group, if one is available. If there isn't one, then it creates a new worker thread in the thread group. This temporarily allows several client connections in the thread group to run in parallel. However, note that the timer thread will not create a new worker thread if the number of threads in the thread pool is already greater than or equal to the maximum defined by the variable, unless the thread group does not already have a listener thread.

      • See for more information.

    Status variables

    Threadpool_idle_threads

    • Description: Number of inactive threads in the . Threads become inactive for various reasons, such as by waiting for new work. However, an inactive thread is not necessarily one that has not been assigned work. Threads are also considered inactive if they are being blocked while waiting on disk I/O, or while waiting on a lock, etc.

      • This status variable is only meaningful on Unix.

    • Scope: Global, Session

    • Data Type:

    Threadpool_threads

    • Description: Number of threads in the . In rare cases, this can be slightly higher than , because each thread group needs at least two threads (i.e. at least one worker thread and at least one listener thread) to prevent deadlocks.

    • Scope: Global, Session

    • Data Type: numeric

    See Also

    This page is licensed: CC BY-SA / Gnu FDL

    Dynamic: Yes

  • Data Type: numeric

  • Default Value: 1

  • Range: 1 to 100000

  • Scope: Global

  • Dynamic: No

  • Data Type: numeric

  • Default Value: 0

  • mode is enabled, the server uses the
    for client connections.
  • When the no-threads mode is enabled, the server uses a single thread for all client connections, which is really only usable for debugging.

  • Command line: --thread-handling=name

  • Scope: Global

  • Dynamic: No

  • Data Type: enumeration

  • Default Value: one-thread-per-connection (non-Windows), pool-of-threads (Windows)

  • Valid Values: no-threads, one-thread-per-connection, pool-of-threads.

  • Documentation: Using the thread pool.

  • Notes: In MySQL, the thread pool is only available in MySQL Enterprise. In MariaDB it's available in all versions.

  • Scope:

  • Dynamic:

  • Data Type: boolean

  • Default Value: 0

  • Introduced: MariaDB 10.5.0

  • Scope:
  • Dynamic:

  • Data Type: boolean

  • Default Value: 0

  • Introduced: MariaDB 10.5.0

  • Command line: thread-pool-idle-timeout=#
  • Scope: Global

  • Dynamic: Yes

  • Data Type: numeric

  • Default Value: 60

  • Documentation: Using the thread pool.

  • thread-pool-max-threads=#
  • Scope: Global

  • Dynamic: Yes

  • Data Type: numeric

  • Default Value: 65536

  • Range: 1 to 65536

  • Documentation: Using the thread pool.

  • Command line: thread-pool-min-threads=#
  • Data Type: numeric

  • Default Value: 1

  • Documentation: Using the thread pool.

  • This is primarily for internal use, and it is not meant to be changed for most users.
  • This system variable is only meaningful on Unix.

  • Scope: Global

  • Dynamic: Yes

  • Data Type: numeric

  • Default Value: 3

  • Range: 1 to 65536

  • Documentation: Using the thread pool.

  • Dynamic: Yes

  • Data Type: numeric

  • Default Value: 1000

  • Range: 0 to 4294967295

  • Introduced: MariaDB 10.2.2

  • Documentation: Using the thread pool.

  • Default Value: auto

  • Valid Values: high, low, auto.

  • Introduced: MariaDB 10.2.2

  • Documentation: Using the thread pool.

  • Command line: --thread-pool-size=#
  • Scope: Global

  • Dynamic: Yes

  • Data Type: numeric

  • Default Value: Based on the number of processors (but see MDEV-7806).

  • Range: 1 to 128

  • Documentation: Using the thread pool.

  • This system variable is only meaningful on Unix.
  • Note that if you are migrating from the MySQL Enterprise thread pool plugin, then the unit used in their implementation is 10ms, not 1ms.

  • Command line: --thread-pool-stall-limit=#

  • Scope: Global

  • Dynamic: Yes

  • Data Type: numeric

  • Default Value: 500

  • Range: 1 to 4294967295

  • Documentation: Using the thread pool.

  • numeric
    extra_port
    Thread Pool in MariaDB: Configuring the Extra Port
    Thread Pool in MariaDB: Configuring the Extra Port
    Information Schema Threadpool_Queues
    Information Schema Threadpool_Groups
    Information Schema Threadpool_Queues
    thread_pool_min_threads
    thread pool
    thread group
    thread pool
    thread_pool_idle_timeout
    Thread Groups in the Unix Implementation of the Thread Pool: Thread Group Oversubscription
    Thread pool
    thread groups
    thread pool
    Thread Groups in the Unix Implementation of the Thread Pool
    thread_pool_max_threads
    Thread Groups in the Unix Implementation of the Thread Pool: Thread Group Stalls
    thread pool
    thread pool
    thread_pool_max_threads
    Thread Pool in MariaDB
    thread pool
    submit a bug report
    Threadpool Benchmarks
    Galera slave threads
    compatibility pages in the release notes
    MariaDB 10.5