Bienvenidos sean a este post, hoy hablaremos sobre el pool of threads.
Tanto mariadb como mysql cada vez que reciben una conexion la asignan a un thread, a esta forma de trabajar lo llaman «un thread por conexion», si bien es la forma de trabajar en la mayoria de los sistemas con la excepcion mas evidente que es Windows (a partir del Vista), por esta razon se usa mariadb para las cargas de trabajo descriptas en el Procesamiento de Transacciones En Linea (OLTP por sus siglas en ingles), estas cargas de trabajo incluyen websites y aplicaciones y por lo general siempre trabajan de la misma manera, un cliente se conecta, ejecuta unas pocas acciones y cierra la conexion, imaginemos que tenemos muchas conexiones repitiendo este proceso en un tiempo muy corto, esta forma de trabajar con el metodo nos genera un desperdicio de tiempo de CPU y memoria lo cual no justifica el costo.
Desde la version 5.1 de mariadb se agrego el Pool of Threads, esto nos permite manejar multiples conexiones desde un thread, cada thread es parte de un grupo y tenemos una cantidad fija de threads, si bien a partir de la version 5.5 este fue refactoreado y este metodo crea nuevos threads cuando son insuficientes y elimina los innecesarios, tratando de mantener una cantidad razonable, si es demasiado bajo no es beneficioso y si es demasiado alto es un desperdicio de recursos, otra particularidad que posee es que siempre va a priorizar los queries mas importantes a los mas triviales, por ejemplo uno simple como SELECT VERSION() puede demorarse en ejecutar si existen otros mas prioritarios.
Antes mencionamos que Windows trabaja de forma distinta porque utiliza la implementacion de pool de threads nativa en el resto de los casos se utiliza una implementacion propia, esto significa que las variables de configuracion disponibles en Windows no son iguales que las variables en otros sistemas, en versiones anteriores a Vista esta caracteristica no funciona y el metodo un thread por conexion es siempre utilizado.
Para activar el pool of threads debemos agregar la siguiente linea en el archivo de configuracion dentro de la etiqueta [mysqld]:
thread_handling=pool-of-threads
En versiones de Windows anteriores a Vista esta opcion es ignorada, en esta version y mas recierntes esta es la opcion predeterminada, si este es utilizado en un archivo de configuracion global puede ser anulado en una instalacion de mariadb individual agregando la siguiente linea en su archivo de configuracion:
thread_handling=one-thread-per-connection
Para saber cual es el metodo que maneja la conexion se puede ver el valor de la variable thread_handling mediante el siguiente comando:
MariaDB [(none)]> select @@global.thread_handling;
+--------------------------+
| @@global.thread_handling |
+--------------------------+
| pool-of-threads |
+--------------------------+
1 row in set (0.002 sec)
MariaDB [(none)]>
En este caso podemos ver como gracias a la modificacion anterior ahora tenemos implementado el pool, para ver los estados que disponemos lo podemos hacer mediante el siguiente comando:
MariaDB [(none)]> SHOW STATUS LIKE 'threadpool%';
+-------------------------+-------+
| Variable_name | Value |
+-------------------------+-------+
| Threadpool_idle_threads | 0 |
| Threadpool_threads | 0 |
+-------------------------+-------+
2 rows in set (0.003 sec)
MariaDB [(none)]>
Veamos que representa cada estado:
- Threadpool_threads, indica la cantidad de threads activos
- Threadpool_idle_threads, este indica la cantidad de threads inactivos o esperan que libere un bloqueo.
Como mencionamos anteriormente las variables de configuracion de Windows son distintas a la de Unix, en ambos casos podemos ver las variables con el siguiente comando:
MariaDB [(none)]> SHOW VARIABLES LIKE 'thread_pool%';
Veamos las variables de Unix:
- thread_pool_size, esta variable informa la cantidad de grupos que manejan threads
- thread_pool_stall_limit, esta variable informa un timeout expresada en milisegundos despues de que el thread es considerado detenido
- thread_pool_max_threads, esta informa cual es la cantidad maxima de threads
- thread_pool_idle_timeout, este informa un timeout, en milisegundos, despues de que los threads inactivos son terminados
- thread_pool_oversubscribe, esta es una variable de uso interno y no deberia ser modificada por el usuario
- thread_pool_prio_kickup_timer, esta indica en milisegundos el tiempo antes de que saque una ejecucion de la cola de baja prioridad y se mande a la cola de alta prioridad
- thread_pool_priority, informa como debe ser la prioridad de ejecucion, su valor predeterminado es auto y esto prioriza en base si la conexion esta en la transaccion o no.
Las variables de Windows:
- thread_pool_min_threads, informa la cantidad minima de threads que deben existir antes de comenzar a retirar los mismos
- thread_pool_max_threads, idem al de Unix
Con esto ya tenemos establecido el pool y las variables que podemos configurar (en algunos casos) para manejarlo de mejor forma pero vamos a analizar un par de inconvenientes:
- El primer caso seria un thread que nos bloquea multiples tablas para ejecutar una accion, por ejemplo si ejecutamos un FLUSH TABLES WITH READ LOCK para ejecutar un back up fisico sobre tablas no transaccionales y esto hara que todos o muchos threads sean bloqueados, esto hace que el pool genere nuevos threads pero esto no solucionara el problema y comenzara el consumo excesivo de recursos, para solucionarlo si establecemos a thread_pool_max_threads con un valor suficientemente bajo evitara la creacion de tales threads
- El segundo caso es cuando las cargas de trabajo no son distribuidas equitativamente, por ejemplo si en un cierto periodo de tiempo tenemos una gran cantidad de conexiones lo cual nos puede devolver a un estado de muy baja actividad, tales cargas de trabajo no se benefician del metodo de pool de threads durante el periodo de las multiples conexiones son establecidas porque tiene que crear una gran cantidad de threads y llevara un tiempo, para evitar esto en Unix simplemente debemos incrementar a thread_pool_idle_timeout asi el timeout es mas grande que el tiempo que separa el intervalo entre dos periodos de alta actividad, en el caso de Windows simplemente incrementamos a thread_pool_min_threads
- El tercer caso es cuando las cargas de trabajo de un almacen (si bien no se benefician con el metodo del pool inclusive con bases OLTP), pueden generar reportes periodicamente desde una cantidad de datos no trivial, tales queries no bloquean pero pueden bloquear ejecuciones encoladas por una cantidad de tiempo no aceptable, para evitarlo en Unix simplemente bajamos al menor valor posible a la variable thread_pool_stall_limit
Que sucede si el metodo de pool de threads es usado y un cliente obtiene todos los bloqueo en todas las tablas para ejecutar una operacion muy larga? Todos los otros threads seran bloqueados.
Para resolver este inconveniente mariadb creara nuevos threads pero esto no ayudara porque cada nuevo thread debera esperar a que se libere el bloqueo, incluso se puede alcanzar el limite en thread_pool_max_threads y si bien el servidor rechazara nuevas conexiones, el DBA no podra conectarse para investigar que esta sucediendo, una solucion puede ser incrementar dicho limite para permitir mas threads pero puede convertir al metodo de pool en algo inutil, la solucion para esto es reservar un puerto extra para conexiones que usara a «un thread por conexion» dado que una sola conexion es mas que suficiente, las dos variables que controlan a esta caracteristica son:
- extra_port, este almacena el numero del puerto que aceptara conexiones de «un thread por conexion»
- extra_max_connections, informa la cantidad de conexiones simultaneas que aceptara dicho puerto
En resumen, hoy hemos visto pool de threads, que es, como nos beneficia, para que se usa, como se habilita, las variables que lo manejan y algunos inconvenientes que pueden ocurrir, espero les haya sido util sigueme en tumblr, Twitter o Facebook para recibir una notificacion cada vez que subo un nuevo post en este blog, nos vemos en el proximo post.


Donación
Es para mantenimento del sitio, gracias!
$1.50
