¿Es posible hacer que MySQL use más de un núcleo?

131

Se me presentaron algunos servidores MySQL dedicados que nunca usan más de un núcleo. Soy más desarrollador que DBA para MySQL, así que necesito ayuda

Preparar

Los servidores son bastante pesados ​​con una carga de tipo OLAP / DataWarehouse (DW):

  • Primario: 96 GB de RAM, 8 núcleos + matriz RAID 10 única
  • Prueba: 32 GB de RAM con 4 núcleos
  • El DB más grande es de 540 GB, el total es de alrededor de 1.1TB y en su mayoría tablas de InnoDB
  • Solaris 10 Intel-64
  • MySQL 5.5.x

Nota: El DB más grande es el replicado del servidor OLTP DR y el DW se carga desde este. No es un DW completo: solo dura entre 6 meses y 6 semanas, por lo que es más pequeño que el DB OLTP.

Observaciones en un servidor de prueba

  • 3 conexiones separadas
  • cada uno tiene un concurrente (y diferente) ALTER TABLE...DROP KEY...ADD INDEX
  • las 3 tablas tienen 2.5, 3.8 y 4.5 millones de filas
  • El uso de la CPU sube al 25% (un núcleo está al máximo) y no más
  • Los 3 ALTERS toman de 12 a 25 minutos (un solo en el más pequeño toma 4.5)

Preguntas

  1. ¿Qué configuración o parche se requiere para permitir que se use más de un núcleo?
    Es decir, ¿por qué MySQL no usa todos los núcleos disponibles? (como otros RDBMS)
  2. ¿Es consecuencia de la replicación?

Otras notas

  • Entiendo la diferencia entre un "hilo" RDBMS y un "hilo" del sistema operativo
  • No estoy preguntando sobre ninguna forma de paralelismo
  • Algunas de las variables del sistema para InnoDB y los subprocesos son subóptimas
    (en busca de una ganancia rápida)
  • A corto plazo, no puedo cambiar el diseño del disco
  • El sistema operativo se puede modificar si es necesario
  • Una sola TABLA DE ALTERACIÓN en la mesa más pequeña toma 4.5 minutos (IMO impactante)

Editar 1

  • innodb_thread_concurrency se establece en 8 en ambos. Sí, está mal, pero no hará que MySQL use múltiples núcleos
  • innodb_buffer_pool_size tiene 80 GB en primaria, 10 GB en una prueba (se cierra otra instancia). Esto está bien por ahora.
  • innodb_file_per_table = ON

Editar 2

Probar

  • innodb_flush_method no se muestra como O_DIRECT cuando debería ser
  • seguirá la configuración de RolandoMySQLDBA

Avísame si me he perdido algo importante

Salud

Actualizar

Cambió innodb_flush_method + 3 x configuraciones de hilo en la respuesta de RolandoMySQLDBA
Resultado:> 1 núcleo utilizado para las pruebas = resultado positivo

gbn
fuente
@Dtest: innodb_file_per_table = ON. MOSTRAR ESTADO INNODB DEL MOTOR \ G es solo la línea de comando?
gbn
@Dtest: no obtuve resultados en SQLyog y tendría que pedirle a alguien que ejecute esto desde la línea de comandos
gbn
1
webyog.com/forums/index.php?showtopic=1290 debería funcionar sin el \G. Además, creo que SHOW INNODB STATUSestá en desuso a favor de SHOW ENGINE INNODB STATUS5.5 ( aparece un error al ejecutar el primero en la línea de comandos.)
Derek Downey
1
Si bien todas las otras respuestas son buenas, dado que usted es un desarrollador, le recomendaría echar un vistazo a Shard Query code.google.com/p/shard-query Puede ayudarlo, especialmente en un entorno de datawarehouse.
Jonathan
Gracias, es una opción que hemos pensado. También estoy asumiendo el rol de DBA también.
gbn

Respuestas:

123

De hecho, discutí innodb_thread_concurrency con un experto de MySQL en la conferencia Percona Live NYC en mayo de 2011 .

Aprendí algo sorprendente: a pesar de la documentación, es mejor dejarlo innodb_thread_concurrencyen 0 (concurrencia infinita). De esa manera, InnoDB decide el mejor número de innodb_concurrency_ticketsabrir para una configuración de instancia de MySQL dada.

Una vez que establece innodb_thread_concurrencyen 0, puede establecer innodb_read_io_threadsy innodb_write_io_threads(ambos desde MySQL 5.1.38) al valor máximo de 64. Esto debería involucrar más núcleos.

RolandoMySQLDBA
fuente
Intentare esto. Iba a establecer innodb_thread_concurrency a 0 todos modos basado en cosas que he leído demasiado
GBN
99
+1 para innodb_thread_concurrency = 0
randomx
3
@gbn - Viniendo del tipo # 1 en DBA.SE, un agradecimiento es un refuerzo de confianza y muy apreciado. Gracias y de nada !!!
RolandoMySQLDBA
set global innodb_read_io_threads = 8 Código de error: 1238. La variable 'innodb_read_io_threads' es una variable de solo lectura
wgq3g23g
2
@ wgq3g23g Si está haciendo RDS, cámbielo en el grupo de parámetros de base de datos y reinicie la instancia. Si está haciendo EC2 o bare metal, agregue esa opción my.cnfy reinicie mysqld. Por favor.
RolandoMySQLDBA
29

MySQL usará automáticamente múltiples núcleos, por lo que su carga del 25% es coincidencia 1 o una posible configuración incorrecta en Solaris. No voy a pretender saber cómo sintonizar solaris, pero aquí hay un artículo que trata sobre información de ajuste específica de solaris .

Las páginas de ajuste de InnoDB han sido revisadas en MySQL 5.5, por lo que también hay buena información. Desde el disco InnoDB consejos de E / S :

Si la herramienta superior de Unix o el Administrador de tareas de Windows muestran que el porcentaje de uso de CPU con su carga de trabajo es inferior al 70%, su carga de trabajo probablemente esté vinculada al disco. Tal vez está realizando demasiadas confirmaciones de transacciones, o el grupo de búferes es demasiado pequeño. Ampliar el grupo de búferes puede ayudar, pero no lo establezca en más del 80% de la memoria física.

Algunas otras cosas para verificar:

  • Vale la pena probar cambiar el innodb_flush_method a O_DIRECT. Si esto ayuda, es posible que deba montar el sistema de archivos con la forcedirectioopción

  • Cambie innodb_flush_log_at_trx_commit de 1 a 0 (si no le importa perder el último segundo en el bloqueo de mysql) o 2 (si no le importa perder el último segundo en el bloqueo del sistema operativo).

  • Verifique el valor de innodb_use_sys_malloc . Este artículo tiene más información sobre la variable.

    En ese momento, no había bibliotecas de asignación de memoria ajustadas para CPU de varios núcleos. Por lo tanto, InnoDB implementó su propio asignador de memoria en el subsistema mem. Este asignador está protegido por un único mutex, que puede convertirse en un cuello de botella.

    Pero hay algunas advertencias al final de la sección sobre lo que significa activar la variable (está activada por defecto en 5.5).

    Tenga en cuenta que cuando el asignador de memoria InnoDB está deshabilitado, InnoDB ignorará el valor del parámetro innodb_additional_mem_pool_size.

  • Es posible que la replicación esté causando parte del problema. Me doy cuenta de que no estás interesado en el paralelismo, pero de la descripción de este registro de trabajo :

    Actualmente, la replicación no escala bien en máquinas de múltiples núcleos. El subproceso esclavo único ejecuta eventos de replicación uno por uno y puede no hacer frente a una carga producida por conexiones simultáneas de múltiples clientes servidas por la CPU del servidor maestro separado.

En última instancia, InnoDB podría no ser el mejor motor para el almacenamiento de datos debido a las operaciones basadas en disco que ocurren. Podría considerar alterar las tablas de datawarehouse para que sean MyISAM comprimido .

1 Por coincidencia, quiero decir que hay un cuello de botella que impide que su carga aumente por encima del 25%, pero no es necesariamente un problema forzado de un solo núcleo.

Derek Downey
fuente
Gracias. Sección de configuración agregada a la pregunta. El problema son varias consultas intensivas que usan un solo núcleo: aún no la configuración de memoria o subproceso. Más hilos todavía se ejecutan en el mismo núcleo
gbn
@gbn gracias por la actualización, sigue buscando. Estaba pensando que era una 'coincidencia'. Me pregunto si es un problema solo de Solaris ( developers.sun.com/solaris/articles/mysql_perf_tune.html ), pero no sé mucho sobre ese sistema.
Derek Downey
1
@Dtest: también enviaré ese artículo al administrador de Solaris. Algunas cosas buenas allí
gbn
1
Ahora, la replicación es (opcionalmente) multiproceso en el esclavo. InnoDB ha mejorado desde que se escribió esta respuesta. No recomendaría usar MyISAM, especialmente si está comprimido.
Rick James
15

Una sola conexión solo usará un solo núcleo. (OK, InnoDB usa otros hilos, por lo tanto, núcleos, para algunos procesos de E / S, pero eso no es significativo).

Tenías 3 ALTERS, por lo que no estabas usando mucho más de 3 núcleos.

Por desgracia, ni siquiera PARTITION usa múltiples núcleos.

Hasta hace poco, las conexiones múltiples alcanzarían su máximo después de 4-8 núcleos. El Xtradb de Percona (incluido en MariaDB) hace un mejor uso de múltiples núcleos, pero aún así solo uno por hilo. Llegan al máximo a unos 32 núcleos.

Rick James
fuente
(Actualización en 2015 :) Múltiples conexiones con 5.6 máximos en aproximadamente 48 núcleos. 5.7 promete ser aún mejor. (Eso dice los puntos de referencia de Oracle). Pero aún no se utilizan múltiples núcleos para una sola conexión.
Rick James
Actualización (después de ir a OpenWorld de Oracle): la nueva versión 8.x no tendrá ningún paralelismo.
Rick James
9

En mi humilde opinión y en el caso de uso descrito, nunca utilizará más de un núcleo. La razón es que su carga de trabajo está vinculada a IO, no a la CPU. Como sus 3 conexiones están creando un nuevo índice, cada una de ellas necesita leer la tabla completa del disco: esto es lo que lleva tiempo, no calcular los índices.

jfg956
fuente
8

Tenga en cuenta que su cuello de botella podría ser el rendimiento IO de su sistema de archivos.

Además de la configuración sugerida por @RolandoMySQLDBA , también configuré la noatimeconfiguración de montaje /etc/fstabpara la partición que contiene mi directorio de datos mysql ( /data01/mysqlen mi caso, con /dev/sdb1montado en /data01).

De forma predeterminada, Linux registra el tiempo de acceso para CADA lectura o escritura de discos que afecta negativamente el rendimiento de IO, especialmente para aplicaciones de IO altas como bases de datos. Esto significa que incluso leer datos de un archivo desencadena una escritura en el disco ... ¡WAT!

Para deshabilitar esto, agregue la noatimeopción de montaje /etc/fstabpara el punto de montaje deseado de la siguiente manera (ejemplo en mi caso):

/dev/sdb1  /data01  ext4  defaults,noatime  0  2

Luego vuelva a montar la partición:

mount -o,remount /data01

Esto debería aumentar el rendimiento de lectura / escritura de las aplicaciones que usan esa partición. PERO ... nada mejor que mantener todos sus datos en la memoria.

OkezieE
fuente