Capítulo 4. Optimización del sistema operativo y del hardware

Este trabajo se ha traducido utilizando IA. Agradecemos tus opiniones y comentarios: translation-feedback@oreilly.com

Tu servidor MySQL sólo puede funcionar tan bien como su eslabón más débil, y el sistema operativo y el hardware en el que se ejecuta suelen ser factores limitantes. El tamaño del disco, la memoria disponible y los recursos de la CPU, la red y los componentes que los conectan limitan la capacidad final del sistema. Por tanto, tienes que elegir el hardware con cuidado y configurar el hardware y el sistema operativo adecuadamente. Por ejemplo, si tu carga de trabajo está ligada a la E/S, un enfoque es diseñar tu aplicación para minimizar la carga de trabajo de E/S de MySQL. Sin embargo, a menudo es más inteligente actualizar el subsistema de E/S, instalar más memoria o reconfigurar los discos existentes. Si estás ejecutando en un entorno alojado en la nube, la información de este capítulo puede seguir siendo muy útil, especialmente para comprender las limitaciones del sistema de archivos y los programadores de E/S de Linux.

¿Qué limita el rendimiento de MySQL?

Muchos diferentes componentes de hardware pueden afectar al rendimiento de MySQL, pero el cuello de botella más frecuente que vemos es el agotamiento de la CPU. La saturación de la CPU puede ocurrir cuando MySQL intenta ejecutar demasiadas consultas en paralelo o cuando un número menor de consultas se ejecuta durante demasiado tiempo en la CPU.

La saturación de E/S puede seguir ocurriendo, pero con mucha menos frecuencia que el agotamiento de la CPU. Esto se debe en gran parte a la transición al uso de unidades de estado sólido (SSD). Históricamente, la penalización de rendimiento por dejar de trabajar en memoria y pasar a la unidad de disco duro (HDD) era extrema. Las SSD suelen ser entre 10 y 20 veces más rápidas que las SSH. Hoy en día, si las consultas tienen que ir al disco, seguirás obteniendo un rendimiento decente de ellas.

El agotamiento de la memoria aún puede ocurrir, pero normalmente sólo cuando intentas asignar demasiada memoria a MySQL. Hablamos de los ajustes de configuración óptimos para evitarlo en "Configuración del uso de la memoria" en el Capítulo 5.

Cómo seleccionar CPUs para MySQL

En debes considerar si tu carga de trabajo está ligada a la CPU cuando actualices el hardware actual o compres otro nuevo. Puedes identificar una carga de trabajo ligada a la CPU comprobando la utilización de la CPU, pero en lugar de fijarte sólo en lo cargadas que están tus CPUs en general, fíjate en el equilibrio entre el uso de la CPU y las E/S de tus consultas más importantes, y observa si las CPUs están cargadas uniformemente.

A grandes rasgos, tienes dos objetivos para tu servidor:

Baja latencia (tiempo de respuesta rápido)
Para conseguirlo, necesitas CPU rápidas, porque cada consulta utilizará una sola CPU.
Alto rendimiento
Si puedes ejecutar muchas consultas al mismo tiempo, podrías beneficiarte de varias CPU para atender las consultas.

Si tu carga de trabajo no utiliza todas las CPUs, MySQL puede seguir utilizando las CPUs adicionales para tareas en segundo plano, como purgar los búferes de InnoDB, operaciones de red, etc. Sin embargo, estas tareas suelen ser menores en comparación con la ejecución de consultas.

Equilibrar los recursos de memoria y disco

La razón principal para tener mucha memoria no es que puedas guardar muchos datos en ella: es, en última instancia, para que puedas evitar la E/S en disco, que es órdenes de magnitud más lenta que acceder a los datos en memoria. El truco está en equilibrar el tamaño de la memoria y del disco, la velocidad, el coste y otras cualidades, de modo que obtengas un buen rendimiento para tu carga de trabajo.

Almacenamiento en caché, lecturas y escrituras

Si tienes suficiente memoria, puedes aislar completamente el disco de las peticiones de lectura. Si todos tus datos caben en la memoria, cada lectura será un golpe de caché una vez que las cachés del servidor se hayan calentado. Seguirá habiendo lecturas lógicas desde la memoria, pero no lecturas físicas desde el disco. Sin embargo, las escrituras son harina de otro costal. Una escritura puede realizarse en memoria igual que una lectura, pero tarde o temprano tiene que escribirse en el disco para que sea permanente. En otras palabras, una caché puede retrasar las escrituras, pero la caché no puede eliminar las escrituras como puede hacerlo con las lecturas.

De hecho, además de permitir retrasar las escrituras, el almacenamiento en caché puede permitir agruparlas de dos formas importantes:

Muchas escrituras, una descarga
Un mismo dato puede modificarse muchas veces en memoria sin que todos los nuevos valores se escriban en el disco. Cuando los datos se vuelcan finalmente en el disco, todas las modificaciones ocurridas desde la última escritura física son permanentes. Por ejemplo, muchas sentencias podrían actualizar un contador en memoria. Si el contador se incrementa cien veces y luego se escribe en el disco, se habrán agrupado cien modificaciones en una sola escritura.
Fusión de E/S
Muchos datos diferentes pueden modificarse en memoria, y las modificaciones pueden reunirse, de modo que las escrituras físicas pueden realizarse como una única operación de disco.

Por eso muchos sistemas transaccionales utilizan una estrategia de registro de escritura anticipada. El registro de escritura anticipada les permite realizar cambios en las páginas en memoria sin enviar los cambios al disco, lo que normalmente implica E/S aleatorias y es muy lento. En su lugar, escriben un registro de los cambios en un archivo de registro secuencial, que es mucho más rápido. Un subproceso en segundo plano puede enviar las páginas modificadas al disco más tarde; cuando lo haga, puede optimizar las escrituras.

Las escrituras se benefician mucho del almacenamiento en búfer porque convierte la E/S aleatoria en una E/S más secuencial. Las escrituras asíncronas (con búfer) suelen ser gestionadas por el sistema operativo y se agrupan por lotes para que puedan ser volcadas al disco de forma más óptima. Las escrituras síncronas (sin búfer) tienen que escribirse en el disco antes de terminar. Por eso se benefician del almacenamiento en búfer en la caché de escritura de un controlador RAID (Redundant Array of Inexpensive Disks) (hablaremos de RAID un poco más adelante).

¿Cuál es tu conjunto de trabajo?

Todas las aplicaciones de tienen un "conjunto de trabajo" de datos, es decir, los datos que realmente necesitan para hacer su trabajo. Muchas bases de datos también tienen muchos datos que no están en el conjunto de trabajo. Puedes imaginar la base de datos como un escritorio con cajones de archivo. El conjunto de trabajo está formado por los papeles que necesitas tener en el escritorio para realizar tu trabajo. El escritorio representa la memoria principal en esta analogía, mientras que los cajones de archivo son los discos duros. Del mismo modo que no necesitas tener todos los papeles en el escritorio para hacer tu trabajo, no necesitas que toda la base de datos quepa en la memoria para un rendimiento óptimo: sólo el conjunto de trabajo.

Cuando se trataba de discos duros, era una buena práctica intentar encontrar una relación memoria-disco efectiva. Esto se debía en gran parte a la latencia más lenta y a las bajas operaciones de entrada/salida por segundo (IOPS) de los HDD. Con las SSD, la relación memoria-disco es mucho menos importante.

Almacenamiento en estado sólido

Almacenamiento de estado sólido (flash) es el estándar para la mayoría de los sistemas de bases de datos, especialmente los de procesamiento de transacciones en línea (OLTP). Sólo en almacenes de datos muy grandes o en sistemas heredados se suelen encontrar discos duros. Este cambio se produjo cuando el precio de las SSD bajó significativamente alrededor de 2015.

Los dispositivos de almacenamiento de estado sólido utilizan chips de memoria flash no volátil compuestos de celdas en lugar de platos magnéticos. También se llaman memoria de acceso aleatorio no volátil (NVRAM). No tienen piezas móviles, lo que hace que se comporten de forma muy diferente a los discos duros.

Aquí tienes un rápido resumen del rendimiento del flash. Los dispositivos flash de alta calidad tienen:

Rendimiento de lectura y escritura aleatoria muy superior al de los discos duros
Los dispositivos flash suelen ser ligeramente mejores en lectura que en escritura.
Mejor rendimiento de lectura y escritura secuencial que los discos duros
Sin embargo, no es una mejora tan espectacular como la de la E/S aleatoria, porque los discos duros son mucho más lentos en la E/S aleatoria que en la secuencial.
Mucho mejor soporte para la concurrencia que los discos duros
Los dispositivos flash pueden soportar muchas más operaciones concurrentes y, de hecho, no alcanzan realmente su máximo rendimiento hasta que tienes mucha concurrencia.

Lo más importante son las mejoras en la E/S aleatoria y la concurrencia. La memoria flash te ofrece un rendimiento de E/S aleatoria muy bueno con alta concurrencia.

Visión general de la memoria flash

Los discos duros con platos giratorios y cabezales oscilantes tenían limitaciones y características inherentes que son consecuencia de la física implicada. Lo mismo ocurre con el almacenamiento de estado sólido, que se basa en la memoria flash. No te hagas a la idea de que el almacenamiento de estado sólido es sencillo. En realidad es más complejo que un disco duro en algunos aspectos. Las limitaciones de la memoria flash son bastante severas y difíciles de superar, por lo que el dispositivo de estado sólido típico tiene una arquitectura intrincada con muchas abstracciones, almacenamiento en caché y "magia" patentada.

La característica más importante de la memoria flash es que puede leerse muchas veces rápidamente y en unidades pequeñas, pero las escrituras son mucho más difíciles. Una celda no puede reescribirse sin una operación especial de borrado y sólo puede borrarse en bloques grandes, por ejemplo, de 512 KB. El ciclo de borrado es lento y acaba desgastando el bloque. El número de ciclos de borrado que puede tolerar un bloque depende de la tecnología subyacente que utilice.

Las limitaciones en las escrituras son la razón de la complejidad del almacenamiento de estado sólido. Por eso algunos dispositivos ofrecen un rendimiento estable y constante y otros no. La magia está en el firmware propietario, los controladores y otras piezas que hacen funcionar un dispositivo de estado sólido. Para que las operaciones de escritura funcionen bien y evitar el desgaste prematuro de los bloques de memoria flash, el dispositivo debe ser capaz de reubicar las páginas y realizar la recogida de basura y la llamada nivelación de desgaste. El término amplificación de escritura se utiliza para describir las escrituras adicionales causadas por el desplazamiento de datos de un lugar a otro, escribiendo datos y metadatos varias veces debido a escrituras parciales de bloque.

Recogida de Basura

La recogida de basura es importante de entender. Para mantener algunos bloques frescos y listos para nuevas escrituras, el dispositivo recupera bloques. Esto requiere algo de espacio libre en el dispositivo. O bien el dispositivo tendrá espacio reservado internamente que no puedes ver, o bien tendrás que reservarlo tú mismo no llenándolo del todo; esto varía de un dispositivo a otro. En cualquier caso, a medida que el dispositivo se llena, el recolector de basura tiene que trabajar más para mantener limpios algunos bloques, por lo que aumenta el factor de amplificación de escritura.

Como resultado, muchos dispositivos se vuelven más lentos a medida que se llenan. Cuánto más lentos es diferente para cada proveedor y modelo, y depende de la arquitectura del dispositivo. Algunos dispositivos están diseñados para ofrecer un alto rendimiento incluso cuando están bastante llenos, pero en general, un archivo de 100 GB tendrá un rendimiento diferente en un SSD de 160 GB que en uno de 320 GB. La ralentización se debe a tener que esperar a que se completen los borrados cuando no hay bloques libres. Una escritura en un bloque libre tarda un par de cientos de microsegundos, pero un borrado es mucho más lento, normalmente unos pocos milisegundos.

Optimización del rendimiento RAID

Los motores de almacenamiento suelen guardar sus datos y/o índices en archivos únicos de gran tamaño, lo que significa que RAID suele ser la opción más viable para almacenar muchos datos. RAID puede ayudar con la redundancia, el tamaño del almacenamiento, el almacenamiento en caché y la velocidad. Pero al igual que con las otras optimizaciones que hemos estado viendo, hay muchas variaciones en las configuraciones RAID, y es importante elegir una que sea apropiada para tus necesidades.

En no cubriremos aquí todos los niveles RAID, ni entraremos en los detalles de cómo almacenan los datos exactamente los distintos niveles RAID. En su lugar, nos centraremos en cómo las configuraciones RAID satisfacen las necesidades de un servidor de bases de datos. Estos son los niveles RAID más importantes:

RAID 0

El RAID 0 es la configuración RAID más barata y de mayor rendimiento, al menos cuando mides el coste y el rendimiento de forma simplista (si incluyes la recuperación de datos, por ejemplo, empieza a parecer más caro). Como no ofrece redundancia, no creemos que el RAID 0 sea nunca apropiado en una base de datos de producción, pero si realmente buscas ahorrar costes, puede ser una opción en entornos de desarrollo en los que un fallo completo del servidor no se convierta en un incidente.

De nuevo, ten en cuenta que el RAID 0 no proporciona ninguna redundancia, aunque "redundante" sea la R del acrónimo RAID. De hecho, la probabilidad de que falle una matriz RAID 0 es mayor que la probabilidad de que falle un solo disco, ¡no menor!

RAID 1

El RAID 1 ofrece un buen rendimiento de lectura en muchos casos, y duplica los datos en los discos, por lo que hay una buena redundancia. El RAID 1 es un poco más rápido que el RAID 0 para las lecturas. Es bueno para servidores que manejan registros y cargas de trabajo similares, porque las escrituras secuenciales rara vez necesitan muchos discos subyacentes para rendir bien (a diferencia de las escrituras aleatorias, que pueden beneficiarse de la paralelización). También es una opción típica para servidores de gama baja que necesitan redundancia pero sólo tienen dos discos duros.

Los RAID 0 y RAID 1 son muy sencillos, y a menudo pueden implementarse bien por software. La mayoría de los sistemas operativos te permitirán crear volúmenes RAID 0 y RAID 1 por software fácilmente.

RAID 5

El RAID 5 solía asustar bastante a los sistemas de bases de datos, en gran parte debido a sus implicaciones en el rendimiento. Con la generalización de los SSD, ahora es una opción viable. Reparte los datos entre muchos discos con bloques de paridad distribuidos, de modo que si falla un disco, los datos pueden reconstruirse a partir de los bloques de paridad. Si fallan dos discos, todo el volumen fallará irrecuperablemente. En términos de coste por unidad de almacenamiento, es la configuración redundante más económica, porque sólo pierdes el espacio de almacenamiento de un disco en toda la matriz.

El mayor "problema" del RAID 5 es cómo funciona el conjunto si falla un disco. Esto se debe a que los datos tienen que reconstruirse leyendo todos los demás discos. Esto afectaba gravemente al rendimiento de los discos duros en, por lo que generalmente se desaconsejaba. Era aún peor si tenías muchos discos. Si intentas mantener el servidor en línea durante la reconstrucción, no esperes que ni la reconstrucción ni el rendimiento de la matriz sean buenos. Otros costes de rendimiento fueron la escalabilidad limitada debido a los bloques de paridad -el RAID 5 no escala bien más allá de 10 discos o así- y los problemas de almacenamiento en caché. Un buen rendimiento del RAID 5 depende en gran medida de la caché de la controladora RAID, que puede entrar en conflicto con las necesidades del servidor de base de datos. Como hemos mencionado antes, los discos SSD ofrecen un rendimiento sustancialmente mejorado en términos de IOPS y rendimiento, y también han desaparecido los problemas del bajo rendimiento de lectura/escritura aleatoria.

Uno de los factores atenuantes del RAID 5 es que es muy popular. Como resultado, las controladoras RAID suelen estar muy optimizadas para RAID 5 y, a pesar de los límites teóricos, las controladoras inteligentes que utilizan bien las cachés a veces pueden rendir casi tan bien como las controladoras RAID 10 para algunas cargas de trabajo. En realidad, esto podría reflejar que las controladoras RAID 10 están menos optimizadas, pero independientemente del motivo, esto es lo que hemos visto.

RAID 6
El mayor problema del RAID 5 era que la pérdida de dos discos era catastrófica. Cuantos más discos tengas en tu matriz, mayor será la probabilidad de fallo de disco. El RAID 6 ayuda a frenar la posibilidad de fallo añadiendo un segundo disco de paridad. Esto te permite soportar dos fallos de disco y aun así reconstruir la matriz. El inconveniente es que el cálculo de la paridad adicional hará que las escrituras sean más lentas que en RAID 5.
RAID 10

El RAID 10 es una muy buena opción para el almacenamiento de datos. Está formado por pares en espejo que se dividen en franjas, por lo que se adapta bien tanto a las lecturas como a las escrituras. Es rápido y fácil de reconstruir, en comparación con el RAID 5. También se puede implementar bastante bien por software.

La pérdida de rendimiento cuando se avería un disco duro puede seguir siendo significativa, porque esa franja puede convertirse en un cuello de botella. El rendimiento puede degradarse hasta un 50%, dependiendo de la carga de trabajo. Algo que hay que tener en cuenta son las controladoras RAID que utilizan una implementación de "espejo concatenado" para RAID 10. Esto es subóptimo debido a la ausencia de striping: tus datos de acceso más frecuente pueden colocarse en un solo par de discos en lugar de repartirse entre muchos, por lo que obtendrás un rendimiento deficiente.

RAID 50
El RAID 50 consiste en matrices RAID 5 divididas en bandas, y puede ser un buen compromiso entre la economía del RAID 5 y el rendimiento del RAID 10 si tienes muchos discos. Es útil sobre todo para conjuntos de datos muy grandes, como almacenes de datos o sistemas OLTP extremadamente grandes.

La Tabla 4-1 resume las distintas configuraciones RAID.

Tabla 4-1. Comparación de los niveles RAID
Nivel Sinopsis Redundancia Discos necesarios Lecturas más rápidas Escribe más rápido
RAID 0 Barato, rápido, peligroso No N
RAID 1 Lectura rápida, sencilla y segura 2 (normalmente) No
RAID 5 Barato y rápido con los SSD N + 1 Depende
RAID 6 Como RAID 5 pero más resistente N + 2 Depende
RAID 10 Caro, rápido, seguro 2N
RAID 50 Para almacenes de datos muy grandes 2(N + 1)

Fallo, recuperación y monitoreo de RAID

Las configuraciones RAID (a excepción del RAID 0) ofrecen redundancia. Esto es importante, pero es fácil subestimar la probabilidad de fallos concurrentes en los discos. No debes pensar en el RAID como una garantía sólida de seguridad de los datos.

RAID no elimina -ni siquiera reduce- la necesidad de hacer copias de seguridad. Cuando haya un problema, el tiempo de recuperación dependerá de tu controlador, del nivel RAID, del tamaño de la matriz, de la velocidad del disco y de si necesitas mantener el servidor en línea mientras reconstruyes la matriz.

Existe la posibilidad de que los discos fallen exactamente al mismo tiempo. Por ejemplo, un pico de tensión o un sobrecalentamiento pueden acabar fácilmente con dos o más discos. Sin embargo, lo más habitual es que dos fallos de disco se produzcan muy juntos. Muchos de estos problemas pueden pasar desapercibidos. Una causa común es la corrupción de los soportes físicos que contienen datos a los que se accede con poca frecuencia. Esto puede pasar desapercibido durante meses, hasta que intentes leer los datos o falle otra unidad y el controlador RAID intente utilizar los datos dañados para reconstruir la matriz. Cuanto mayor sea el disco duro, más probable es que esto ocurra.

Por eso es importante monitorizar tus matrices RAID. La mayoría de las controladoras ofrecen algún tipo de software para informar sobre el estado de la matriz, y debes estar al tanto de ello porque, de lo contrario, podrías ignorar por completo el fallo de una unidad. Podrías perder la oportunidad de recuperar los datos y descubrir el problema sólo cuando falle una segunda unidad, y entonces ya es demasiado tarde. Debes configurar un sistema de monitoreo para que te avise cuando una unidad o volumen cambie a un estado degradado o de fallo.

Puedes mitigar el riesgo de corrupción latente comprobando activamente la coherencia de tus matrices a intervalos regulares. La Lectura de Patrulla en segundo plano, una función de algunas controladoras que comprueba si hay soportes dañados y los repara mientras todas las unidades están en línea, también puede ayudar a evitar esos problemas. Al igual que con la recuperación, las matrices extremadamente grandes pueden tardar en comprobarse, así que asegúrate de planificarlo adecuadamente cuando crees matrices grandes.

También puedes añadir una unidad de repuesto en caliente, que no se utilice y esté configurada como reserva para que el controlador la utilice automáticamente para la recuperación. Es una buena idea si dependes de cada servidor. Es caro con servidores que sólo tienen unos pocos discos duros, porque el coste de tener un disco inactivo es proporcionalmente mayor, pero si tienes muchos discos, es casi una tontería no tener un disco de repuesto en caliente. Recuerda que la probabilidad de que falle un disco aumenta rápidamente cuantos más discos tengas.

Además de monitorizar los fallos de las unidades, debes monitorizar la unidad de reserva de la batería de la controladora RAID y la política de escritura en caché. Si falla la batería, por defecto la mayoría de las controladoras desactivarán la caché de escritura cambiando la política de caché a escritura directa en lugar de escritura inversa. Esto puede provocar una grave disminución del rendimiento. Muchas controladoras también realizarán periódicamente un ciclo de aprendizaje de la batería, durante el cual también se desactiva la caché. La utilidad de gestión de tu controladora RAID debería permitirte ver y configurar cuándo está programado el ciclo de aprendizaje, para que no te pille desprevenido. Las controladoras RAID más recientes evitan esto utilizando una caché respaldada por flash que utiliza NVRAM para almacenar las escrituras no comprometidas, en lugar de una caché respaldada por batería. Esto evita todo el dolor del ciclo de aprendizaje.

También puedes comparar tu sistema con la política de caché configurada en escritura continua, para saber qué esperar. Lo mejor es programar los ciclos de aprendizaje de la batería en periodos de poco tráfico, normalmente por la noche o durante el fin de semana. Si el rendimiento se resiente lo suficiente con el write-through en cualquier momento, también puedes conmutar por error a otro servidor antes de que empiece el ciclo de aprendizaje. Como último recurso, podrías reconfigurar tus servidores cambiando las variables innodb_flush_log_at_trx_commit y sync_binlog a valores de durabilidad más bajos. Esto reducirá la utilización del disco durante la escritura y puede ofrecer un rendimiento aceptable; sin embargo, esto debe hacerse realmente como último recurso. Reducir la durabilidad tiene un gran impacto en la cantidad de datos que puedes perder durante un fallo de la base de datos y en tu capacidad para recuperarlos.

Configuración RAID y Caché

En normalmente puedes configurar la propia controladora RAID entrando en su utilidad de configuración durante la secuencia de arranque de la máquina o ejecutándola desde el símbolo del sistema. Aunque la mayoría de las controladoras ofrecen muchas opciones, las dos en las que nos centraremos son el tamaño de los trozos para las matrices en franjas y la caché de la controladora (también conocida como caché RAID; utilizamos los términos indistintamente).

El tamaño de trozo de la franja RAID

El tamaño óptimo del trozo de banda es específico de la carga de trabajo y del hardware. En teoría, es bueno tener un tamaño de trozo grande para la E/S aleatoria, porque eso significa que se pueden satisfacer más lecturas desde una sola unidad.

Para ver por qué es así, considera el tamaño de una operación de E/S aleatoria típica de tu carga de trabajo. Si el tamaño del trozo es al menos así de grande y los datos no abarcan la frontera entre trozos, sólo es necesario que participe en la lectura una única unidad. Pero si el tamaño del trozo es menor que la cantidad de datos que hay que leer, no hay forma de evitar que participe más de una unidad en la lectura.

Hasta aquí la teoría. En la práctica, muchos controladores RAID no funcionan bien con trozos grandes. Por ejemplo, el controlador podría utilizar el tamaño del trozo como unidad de caché en su caché, lo que podría ser un despilfarro. El controlador también podría hacer coincidir el tamaño del trozo, el tamaño de la caché y el tamaño de la unidad de lectura (la cantidad de datos que lee en una sola operación). Si la unidad de lectura es demasiado grande, su caché podría ser menos eficaz, y podría acabar leyendo muchos más datos de los que realmente necesita, incluso para peticiones minúsculas.

También es difícil saber si un trozo de datos abarcará varias unidades. Aunque el tamaño del trozo sea de 16 KB, que coincide con el tamaño de página de InnoDB, no puedes estar seguro de que todas las lecturas se alinearán en los límites de 16 KB. El sistema de archivos puede fragmentar el archivo, y normalmente alineará los fragmentos en el tamaño de bloque del sistema de archivos, que suele ser de 4 KB. Algunos sistemas de archivos pueden ser más inteligentes, pero no debes contar con ello.

La caché RAID

La caché RAID es una cantidad (relativamente) pequeña de memoria que se instala físicamente en una controladora RAID de hardware. Se puede utilizar para almacenar datos en búfer mientras viajan entre los discos y el sistema anfitrión. Estas son algunas de las razones por las que una tarjeta RAID puede utilizar la caché:

Caché de lecturas

Después de que el controlador lea algunos datos de los discos y los envíe al sistema anfitrión, puede almacenarlos; esto le permitirá satisfacer futuras peticiones de los mismos datos sin tener que acudir de nuevo al disco.

Esto suele ser un uso muy pobre de la caché RAID. ¿Por qué? Porque el sistema operativo y el servidor de bases de datos tienen sus propias cachés, mucho más grandes. Si se produce un fallo en una de estas cachés, no se utilizarán los datos de la caché RAID. Por el contrario, si se produce un fallo en una de las cachés de nivel superior, la probabilidad de que se produzca un acierto en la caché RAID es muy pequeña. Como la caché RAID es mucho más pequeña, es casi seguro que también se habrá vaciado y llenado con otros datos. Lo mires como lo mires, es un desperdicio de memoria almacenar las lecturas en la caché RAID.

Almacenamiento en caché de datos de lectura anticipada
Si el controlador RAID detecta solicitudes secuenciales de datos, puede decidir realizar una lectura anticipada, es decir, buscar previamente los datos que prevé que se necesitarán pronto. Sin embargo, tiene que tener un lugar donde colocar los datos hasta que se soliciten. Para ello puede utilizar la caché RAID. El impacto de esto en el rendimiento puede variar mucho, y debes comprobar que realmente ayuda. Las operaciones de lectura anticipada pueden no ser útiles si el servidor de la base de datos realiza su propia lectura anticipada inteligente (como hace InnoDB), y pueden interferir con el almacenamiento en búfer de las escrituras síncronas, que es muy importante.
Escrituras en caché
La controladora RAID puede almacenar las escrituras en su caché y programarlas para más adelante. La ventaja de hacer esto es doble: en primer lugar, puede devolver el "éxito" al sistema anfitrión mucho más rápidamente de lo que lo haría si tuviera que realizar realmente las escrituras en los discos físicos, y en segundo lugar, puede acumular escrituras y realizarlas de forma más eficiente.
Operaciones internas
Algunas operaciones RAID son muy complejas, especialmente las escrituras RAID 5, que tienen que calcular bits de paridad que pueden utilizarse para reconstruir los datos en caso de fallo. El controlador necesita utilizar algo de memoria para este tipo de operaciones internas. Ésta es una de las razones por las que el RAID 5 puede funcionar mal en algunas controladoras: necesita leer muchos datos en la caché para obtener un buen rendimiento. Algunas controladoras no pueden equilibrar el almacenamiento en caché de las escrituras con el almacenamiento en caché de las operaciones de paridad del RAID 5.

En general, la memoria de la controladora RAID es un recurso escaso que debes intentar utilizar sabiamente. Utilizarla para lecturas suele ser un desperdicio, pero utilizarla para escrituras es una forma importante de acelerar tu rendimiento de E/S. Muchos controladores te permiten elegir cómo asignar la memoria. Por ejemplo, puedes elegir cuánta de ella utilizar para almacenar en caché las escrituras y cuánta para las lecturas. Para RAID 0, RAID 1 y RAID 10, probablemente deberías asignar el 100% de la memoria de la controladora a las escrituras en caché. Para RAID 5, debes reservar parte de la memoria de la controladora para sus operaciones internas. En general, éste es un buen consejo, pero no siempre es aplicable: las distintas tarjetas RAID requieren configuraciones diferentes.

Cuando utilizas la caché RAID para almacenar escrituras, muchas controladoras te permiten configurar cuánto tiempo es aceptable retrasar las escrituras (un segundo, cinco segundos, etc.). Un retraso mayor permite agrupar más escrituras y enviarlas a los discos de forma óptima. El inconveniente es que tus escrituras serán más "a ráfagas". Eso no es malo, a menos que tu aplicación haga un montón de peticiones de escritura justo cuando la caché del controlador se llena, cuando está a punto de ser volcada al disco. Si no hay espacio suficiente para las peticiones de escritura de tu aplicación, tendrá que esperar. Mantener el retardo más corto significa que tendrás más operaciones de escritura y serán menos eficientes, pero suaviza los picos y ayuda a mantener más parte de la caché libre para gestionar las ráfagas de la aplicación. (Estamos simplificando: los controladores suelen tener complejos algoritmos de equilibrado específicos de cada proveedor, así que sólo intentamos cubrir los principios básicos).

La caché de escritura es muy útil para escrituras síncronas, como la emisión de llamadas a fsync() en los registros de transacciones y la creación de registros binarios con sync_binlog activado, pero no deberías activarla a menos que tu controlador tenga una unidad de batería de reserva (BBU) u otro almacenamiento no volátil. Almacenar en caché las escrituras sin una BBU es probable que corrompa tu base de datos, e incluso tu sistema de archivos transaccional, en caso de pérdida de alimentación. Sin embargo, si tienes una BBU, activar la caché de escritura puede aumentar el rendimiento en un factor de 20 o más para cargas de trabajo que realizan muchas descargas de registro, como la descarga del registro de transacciones cuando una transacción se confirma.

Una última consideración es que muchos discos duros tienen cachés de escritura propias, que pueden "falsear" las operaciones de fsync() mintiendo a la controladora de que los datos se han escrito en un soporte físico. Los discos duros que están conectados directamente (en lugar de estar conectados a un controlador RAID) a veces pueden dejar que sus cachés sean gestionadas por el sistema operativo, pero esto tampoco funciona siempre. Normalmente, estas cachés se vacían para un fsync() y se omiten para la E/S síncrona, pero de nuevo, el disco duro puede mentir. Deberías asegurarte de que estas cachés se vacían en fsync() o desactivarlas porque no están respaldadas por batería. Los discos duros que no son gestionados adecuadamente por el sistema operativo o el firmware RAID han causado muchos casos de pérdida de datos.

Por ésta y otras razones, siempre es una buena idea hacer auténticas pruebas de choque (desconectando literalmente el enchufe de la pared) cuando instales nuevo hardware. A menudo es la única forma de encontrar sutiles errores de configuración o comportamientos furtivos del disco duro. Puedes encontrar en Internet un práctico script para ello.

Para comprobar si realmente puedes confiar en la BBU de tu controlador RAID, asegúrate de dejar el cable de alimentación desenchufado durante un tiempo realista. Algunas unidades no duran sin alimentación tanto como se supone. También en este caso, un eslabón defectuoso puede inutilizar toda tu cadena de componentes de almacenamiento.

Configuración de red

Al igual que la latencia y el rendimiento son factores limitantes para un disco duro, la latencia y el ancho de banda son factores limitantes para una conexión de red. El mayor problema para la mayoría de las aplicaciones es la latencia; una aplicación típica realiza muchas pequeñas transferencias de red, y el ligero retraso de cada transferencia se va acumulando.

Una red que no funciona correctamente también es un importante cuello de botella para el rendimiento. La pérdida de paquetes es un problema común. Incluso un 1% de pérdida es suficiente para causar una degradación significativa del rendimiento, porque varias capas de la pila de protocolos intentarán solucionar los problemas con estrategias como esperar un rato y volver a enviar paquetes, lo que añade tiempo extra. Otro problema habitual es la resolución DNS defectuosa o lenta.1

DNS es un talón de Aquiles suficiente como para que habilitar skip_name_resolve sea una buena idea para los servidores de producción. Una resolución de DNS rota o lenta es un problema para muchas aplicaciones, pero es particularmente grave para MySQL. Cuando MySQL recibe una solicitud de conexión, realiza una búsqueda DNS directa e inversa. Hay muchas razones por las que esto puede salir mal. Cuando lo hace, provocará que se denieguen las conexiones, ralentizará el proceso de conexión al servidor y, en general, causará estragos, hasta ataques de denegación de servicio. Si activas la opción skip_name_resolve, MySQL no realizará ninguna búsqueda de DNS. Sin embargo, esto también significa que tus cuentas de usuario deben tener sólo direcciones IP, "localhost" o comodines de dirección IP en la columna host. Cualquier cuenta de usuario que tenga un nombre de host en la columna host no podrá iniciar sesión.

Sin embargo, suele ser más importante ajustar la configuración para gestionar eficazmente muchas conexiones y pequeñas consultas. Uno de los ajustes más comunes es cambiar tu rango de puertos locales. Los sistemas Linux tienen un rango de puertos locales que se pueden utilizar. Cuando se establece la conexión con una persona que llama, ésta utiliza un puerto local. Si tienes muchas conexiones simultáneas, puedes quedarte sin puertos locales.

Aquí tienes un sistema configurado con los valores por defecto:

$ cat /proc/sys/net/ipv4/ip_local_port_range
32768 61000

A veces puede que necesites cambiar estos valores a un rango mayor. Por ejemplo:

$ echo 1024 65535 > /proc/sys/net/ipv4/ip_local_port_range

El protocolo TCP permite a un sistema poner en cola las conexiones entrantes, como si fuera un cubo. Si el cubo se llena, los clientes no podrán conectarse. Puedes permitir que se pongan en cola más conexiones de la siguiente forma:

$ echo 4096 > /proc/sys/net/ipv4/tcp_max_syn_backlog

Para los servidores de bases de datos que se utilizan sólo localmente, puedes acortar el tiempo de espera que se produce después de cerrar un socket en caso de que el peer esté roto y no cierre su parte de la conexión. El valor por defecto es de un minuto en la mayoría de los sistemas, lo que es bastante largo:

$ echo <value> > /proc/sys/net/ipv4/tcp_fin_timeout

La mayoría de las veces, estos ajustes pueden dejarse en sus valores predeterminados. Normalmente, sólo tendrás que cambiarlos cuando ocurra algo inusual, como un rendimiento de la red extremadamente bajo o un número muy elevado de conexiones. Si buscas en Internet "Variables TCP" encontrarás mucha información útil sobre éstas y muchas otras variables.

Elegir un sistema de archivos

Tus opciones del sistema de archivos dependen bastante de tu sistema operativo. En muchos sistemas, como Windows, realmente sólo tienes una o dos opciones, y sólo una (NTFS) es realmente viable. GNU/Linux, en cambio, admite muchos sistemas de archivos.

Mucha gente quiere saber qué sistemas de archivos darán el mejor rendimiento para MySQL en GNU/Linux o, más concretamente, cuál de las opciones es mejor para InnoDB. En realidad, los puntos de referencia muestran que la mayoría de ellos están muy cerca en la mayoría de los aspectos, pero fijarse en el rendimiento del sistema de archivos es realmente una distracción. El rendimiento del sistema de archivos es muy específico de la carga de trabajo, y ningún sistema de archivos es una bala mágica. La mayoría de las veces, un sistema de archivos determinado no funcionará significativamente mejor o peor que cualquier otro sistema de archivos. La excepción es si te encuentras con algún límite del sistema de archivos, como la forma en que gestiona la concurrencia, el trabajo con muchos archivos, la fragmentación, etc.

En general, es mejor que utilices un sistema de archivos con registro diario, como ext4, XFS o ZFS. Si no lo haces, una comprobación del sistema de archivos tras un fallo puede tardar mucho tiempo.

Si utilizas ext3 o su sucesor, ext4, tienes tres opciones sobre cómo se registran los datos en el diario, que puedes colocar en las opciones de montaje de /etc/fstab:

data=writeback

Esta opción significa que sólo se registran en el diario las escrituras de metadatos. Las escrituras en los metadatos no se sincronizan con las escrituras en los datos. Ésta es la configuración más rápida, y suele ser segura de utilizar con InnoDB porque tiene su propio registro de transacciones. La excepción es que un fallo en el momento justo podría causar la corrupción de un archivo .frm en una versión pre-8.0 de MySQL.

He aquí un ejemplo de cómo esta configuración podría causar problemas. Supongamos que un programa decide ampliar un archivo para hacerlo más grande. Los metadatos (el tamaño del archivo) se registrarán y escribirán antes de que los datos se escriban realmente en el archivo (ahora más grande). El resultado es que la cola del archivo -la zona recién ampliada- contiene basura.

data=ordered
Esta opción también registra sólo los metadatos, pero proporciona cierta coherencia al escribir los datos antes que los metadatos, de modo que se mantiene la coherencia. Sólo es ligeramente más lenta que la opción writeback, y es mucho más segura cuando se produce un fallo. En esta configuración, si volvemos a suponer que un programa quiere ampliar un archivo, los metadatos del archivo no reflejarán el nuevo tamaño del archivo hasta que se hayan escrito los datos que residen en la zona recién ampliada.
data=journal
Esta opción proporciona un comportamiento atómico en el diario, escribiendo los datos en el diario antes de escribirlos en la ubicación final. Suele ser innecesaria y tiene una sobrecarga mucho mayor que las otras dos opciones. Sin embargo, en algunos casos puede mejorar el rendimiento porque el registro en el diario permite al sistema de archivos retrasar las escrituras en la ubicación final de los datos.

Independientemente del sistema de archivos, hay algunas opciones específicas que es mejor desactivar porque no aportan ninguna ventaja y pueden añadir bastante sobrecarga. La más famosa es el registro del tiempo de acceso, que requiere una escritura incluso cuando estás leyendo un archivo o directorio. Para desactivar esta opción, añade las opciones de montaje noatime,nodiratime a tu /etc/fstab; esto a veces puede aumentar el rendimiento hasta un 5%-10%, dependiendo de la carga de trabajo y del sistema de archivos (aunque puede que no suponga mucha diferencia en otros casos). Aquí tienes un ejemplo de línea /etc/fstab para las opciones ext3 que hemos mencionado:

/dev/sda2 /usr/lib/mysql ext3 noatime,nodiratime,data=writeback 0 1

En también puedes ajustar el comportamiento de lectura anticipada del sistema de archivos, porque puede ser redundante. Por ejemplo, InnoDB realiza su propia predicción de lectura anticipada. Desactivar o limitar la lectura anticipada es especialmente beneficioso en el UFS de Solaris. Si utilizas innodb_​flush_​method=​O_DIRECT, desactivarás automáticamente la lectura anticipada.

Algunos sistemas de archivos no admiten funciones que podrías necesitar. Por ejemplo, la compatibilidad con la E/S directa puede ser importante si utilizas el método de descarga O_DIRECT para InnoDB. Además, algunos sistemas de archivos gestionan un gran número de unidades subyacentes mejor que otros; XFS suele ser mucho mejor en esto que ext3, por ejemplo. Por último, si piensas utilizar instantáneas del Gestor de Volúmenes Lógicos (LVM) para inicializar réplicas o hacer copias de seguridad, debes comprobar que el sistema de archivos elegido y la versión de LVM funcionan bien juntos.

La Tabla 4-2 resume en las características de algunos sistemas de archivos comunes.

Tabla 4-2. Características comunes de los sistemas de archivos
Sistema de archivos Sistema operativo Diario Grandes directorios
ext3 GNU/Linux Opcional Opcional/parcial
ext4 GNU/Linux
Sistema de Archivos en Diario (JFS) GNU/Linux No
NTFS Windows
ReiserFS GNU/Linux
UFS (Solaris) Solaris Sintonizable
UFS (FreeBSD) FreeBSD No Opcional/parcial
UFS2 FreeBSD No Opcional/parcial
XFS GNU/Linux
ZFS GNU/Linux, Solaris, FreeBSD

Nosotros solemos recomendar el uso del sistema de archivos XFS. El sistema de archivos ext3 tiene demasiadas limitaciones graves, como su único mutex por nodo, y un mal comportamiento, como vaciar todos los bloques sucios de todo el sistema de archivos en fsync() en lugar de sólo los bloques sucios de un archivo. El sistema de archivos ext4 es una opción aceptable, aunque ha habido cuellos de botella de rendimiento en versiones específicas del núcleo que deberías investigar antes de comprometerte con él.

Al considerar cualquier sistema de archivos para una base de datos, es bueno tener en cuenta cuánto tiempo lleva disponible, lo maduro que es y lo probado que está en entornos de producción. Los bits del sistema de archivos son el nivel más bajo de integridad de los datos que tienes en una base de datos.

Elegir un Programador de Colas de Disco

En GNU/Linux, el programador de colas determina el orden en que las peticiones a un dispositivo de bloque se envían realmente al dispositivo subyacente. Por defecto es Cola Completamente Justa, o cfq. Está bien para un uso casual en portátiles y ordenadores de sobremesa, donde ayuda a evitar la inanición de E/S, pero es terrible para los servidores. Provoca tiempos de respuesta muy pobres bajo los tipos de carga de trabajo que genera MySQL, porque estanca innecesariamente algunas peticiones en la cola.

Puedes ver qué programadores están disponibles y cuál está activo con el siguiente comando:

$ cat /sys/block/sda/queue/scheduler
noop deadline [cfq]

Debes sustituir sda por el nombre del dispositivo del disco que te interesa. En nuestro ejemplo, los corchetes indican qué programador está en uso para este dispositivo. Las otras dos opciones son adecuadas para hardware de clase servidor, y en la mayoría de los casos funcionan casi igual de bien. El programador noop es adecuado para dispositivos que realizan su propia programación entre bastidores, como las controladoras RAID de hardware y las redes de área de almacenamiento (SAN), y deadline está bien tanto para controladoras RAID como para discos conectados directamente. Nuestras pruebas de rendimiento muestran muy poca diferencia entre ambos. Lo principal es utilizar cualquier cosa menos cfq, que puede causar graves problemas de rendimiento.

Memoria e intercambio

MySQL funciona mejor con una gran cantidad de memoria asignada. Como aprendimos en el Capítulo 1, InnoDB utiliza la memoria como caché para evitar el acceso al disco. Esto significa que el rendimiento del sistema de memoria puede tener un impacto directo en la rapidez con la que se sirven las consultas. Incluso hoy en día, una de las mejores formas de garantizar un acceso más rápido a la memoria ha sido sustituir el asignador de memoria integrado en (glibc) por uno externo como tcmalloc o jemalloc. Numerosas pruebas comparativas2 han demostrado que ambos ofrecen un mejor rendimiento y una menor fragmentación de la memoria en comparación con glibc.

El intercambio se produce cuando el sistema operativo escribe parte de la memoria virtual en el disco porque no tiene suficiente memoria física para contenerla. El intercambio es transparente para los procesos que se ejecutan en el sistema operativo. Sólo el sistema operativo sabe si una determinada dirección de memoria virtual está en la memoria física o en el disco.

Cuando utiliza discos SSD, la penalización de rendimiento no es tan acusada como solía serlo con los HDD. Aún así, debes evitar activamente el intercambio, aunque sólo sea para evitar escrituras innecesarias que pueden acortar la vida útil total del disco. También puedes considerar la posibilidad de no utilizar swap, lo que evita totalmente el potencial, pero te pone en una situación en la que quedarte sin memoria puede provocar la finalización del proceso.

En GNU/Linux, puedes monitorizar el intercambio con vmstat (mostramos algunos ejemplos en la siguiente sección). Tienes que fijarte en la actividad de E/S de la swap, de la que se informa en las columnas si y so, más que en el uso de la swap, del que se informa en la columna swpd. La columna swpd puede mostrar procesos que se han cargado pero no se están utilizando, lo que no es realmente problemático. Nos gusta que los valores de las columnas si y so sean 0, y sin duda deben ser inferiores a 10 bloques por segundo.

En casos extremos, una asignación excesiva de memoria puede hacer que el sistema operativo se quede sin espacio de intercambio. Si esto ocurre, la falta de memoria virtual resultante puede bloquear MySQL. Pero incluso si no se queda sin espacio de intercambio, un intercambio muy activo puede hacer que todo el sistema operativo deje de responder, hasta el punto de que ni siquiera puedas entrar y matar el proceso MySQL. A veces, el núcleo de Linux puede incluso colgarse por completo cuando se queda sin espacio de intercambio. Te recomendamos que ejecutes tus bases de datos sin utilizar espacio de intercambio en absoluto. El disco sigue siendo un orden de magnitud más lento que la RAM, y esto evita todos los dolores de cabeza mencionados aquí.

Otra cosa de que ocurre con frecuencia bajo una presión extrema de memoria virtual es que el proceso "out-of-memory killer" (OOM) entra en acción y mata algo. Con frecuencia se trata de MySQL, pero también puede ser otro proceso como SSH, que puede dejarte con un sistema inaccesible desde la red. Puedes evitarlo configurando el valor oom_adj o oom_score_adj del proceso SSH. Cuando trabajes con servidores de bases de datos dedicados, te recomendamos encarecidamente que identifiques los procesos clave, como MySQL y SSH, y que ajustes de forma proactiva la puntuación de OOM killer para evitar que sean los primeros en ser seleccionados para su finalización.

Puedes resolver la mayoría de los problemas de intercambio configurando correctamente los buffers de MySQL, pero a veces el sistema de memoria virtual del sistema operativo decide intercambiar MySQL de todos modos, a veces relacionado con cómo funciona nonuniform memory access (NUMA)3 en Linux. Esto suele ocurrir cuando el sistema operativo ve mucha E/S de MySQL, por lo que intenta aumentar la caché de archivos para contener más datos. Si no hay suficiente memoria, hay que intercambiar algo, y ese algo puede ser el propio MySQL. Algunas versiones antiguas del núcleo de Linux también tienen prioridades contraproducentes que intercambian cosas cuando no deben, pero esto se ha aliviado un poco en los núcleos más recientes.

Los sistemas operativos suelen permitir cierto control sobre la memoria virtual y la E/S. Mencionamos algunas formas de controlarlos en GNU/Linux. La más básica es cambiar el valor de /proc/sys/vm/swappiness a un valor bajo, como 0 o 1. Esto indica al núcleo que no intercambie a menos que la necesidad de memoria virtual sea extrema. Por ejemplo, aquí tienes cómo comprobar el valor actual:

$ cat /proc/sys/vm/swappiness
60

El valor que se muestra, 60, es el ajuste de intercambio por defecto (el rango es de 0 a 100). Éste es un valor por defecto muy malo para los servidores. Sólo es apropiado para ordenadores portátiles. Los servidores deberían ajustarse a 0:

$ echo 0 > /proc/sys/vm/swappiness

Otra opción es cambiar la forma en que los motores de almacenamiento leen y escriben los datos. Por ejemplo, utilizar innodb_flush_method=O_DIRECT alivia la presión de la E/S. La E/S directa no se almacena en caché, por lo que el sistema operativo no lo ve como una razón para aumentar el tamaño de la caché de archivos. Este parámetro sólo funciona para InnoDB.

Otra opción es utilizar la opción de configuración memlock de MySQL, que bloquea MySQL en memoria. Esto evitará el swapping, pero puede ser peligroso: si no queda suficiente memoria bloqueable, MySQL puede bloquearse cuando intente asignar más memoria. También puede haber problemas si se bloquea demasiada memoria y no queda suficiente para el sistema operativo.

Muchos de los trucos son específicos de una versión del núcleo, así que ten cuidado, sobre todo cuando actualices. En algunas cargas de trabajo, es difícil hacer que el sistema operativo se comporte con sensatez, y tu único recurso puede ser reducir el tamaño de los búferes a valores subóptimos.

Estado del sistema operativo

Tu sistema operativo proporciona herramientas para ayudarte a averiguar qué están haciendo el sistema operativo y el hardware. En esta sección, te mostraremos ejemplos de cómo utilizar dos herramientas ampliamente disponibles, iostat y vmstat. Si tu sistema no proporciona ninguna de estas herramientas, lo más probable es que proporcione algo similar. Por tanto, nuestro objetivo no es convertirte en un experto en el uso de iostat o vmstat, sino simplemente mostrarte qué debes buscar cuando intentes diagnosticar problemas con herramientas como éstas.

En además de estas herramientas, tu sistema operativo puede proporcionar otras, como mpstat o sar. Si te interesan otras partes de tu sistema, como la red, quizá prefieras utilizar herramientas como ifconfig (que muestra cuántos errores de red se han producido, entre otras cosas) o netstat.

Por defecto, vmstat e iostat producen un único informe que muestra los valores medios de varios contadores desde que se inició el servidor, lo que no es muy útil. Sin embargo, puedes dar a ambas herramientas un argumento de intervalo. Esto hace que generen informes incrementales que muestran lo que el servidor está haciendo en este momento, lo que es mucho más relevante. (La primera línea muestra las estadísticas desde que se inició el sistema; puedes ignorarla).

Cómo leer la salida de vmstat

Veamos primero un ejemplo de vmstat en. Para que imprima un nuevo informe cada cinco segundos, informando de los tamaños en megabytes, utiliza el siguiente comando:

$ vmstat -SM 5
procs -------memory------- -swap- -----io---- ---system---- ------cpu-----
 r  b swpd free buff cache  si so    bi    bo     in     cs us sy id wa st
11  0    0 2410    4 57223   0  0  9902 35594 122585 150834 10  3 85  1  0
10  2    0 2361    4 57273   0  0 23998 35391 124187 149530 11  3 84  2  0

Puedes detener vmstat con Ctrl-C. La salida que veas depende de tu sistema operativo, así que puede que necesites leer la página del manual para averiguarlo.

Como hemos dicho antes, aunque pedimos una salida incremental, la primera línea de valores muestra los promedios desde que se arrancó el servidor. La segunda línea muestra lo que está ocurriendo en este momento, y las líneas siguientes mostrarán lo que ocurre a intervalos de cinco segundos. Las columnas están agrupadas por una de las siguientes cabeceras:

procs
La columna r muestra cuántos procesos están esperando tiempo de CPU. La columna b muestra cuántos están en reposo ininterrumpido, lo que generalmente significa que están esperando E/S (disco, red, entrada de usuario, etc.).
memoria
La columna swpd muestra cuántos bloques se intercambian a disco (paginados). Las tres columnas restantes muestran cuántos bloques están free (no utilizados), cuántos se utilizan para búferes (buff) y cuántos se utilizan para el sistema operativo cache.
intercambiar
Estas columnas muestran la actividad de intercambio: cuántos bloques por segundo está intercambiando el sistema operativo hacia dentro (desde el disco) y hacia fuera (al disco). Es mucho más importante monitorizarlas que la columna swpd. Nos gusta ver si y so en 0 la mayor parte del tiempo, y definitivamente no nos gusta ver más de 10 bloques por segundo. Las ráfagas también son malas.
io
Estas columnas muestran cuántos bloques por segundo se leen en (bi) y se escriben en (bo) dispositivos de bloques. Esto suele reflejar la E/S de disco.
sistema
Estas columnas muestran el número de interrupciones por segundo (in) y el número de cambios de contexto por segundo (cs).
cpu
Estas columnas muestran los porcentajes del tiempo total de CPU dedicado a ejecutar código de usuario (no del núcleo), ejecutar código del sistema (del núcleo), inactividad y espera de E/S. Una posible quinta columna (st) muestra el porcentaje "robado" a una máquina virtual si utilizas la virtualización. Esto se refiere al tiempo durante el cual algo era ejecutable en la máquina virtual, pero el hipervisor eligió ejecutar otra cosa en su lugar. Si la máquina virtual no quiere ejecutar nada y el hipervisor ejecuta otra cosa, eso no cuenta como tiempo robado.

La salida de vmstat depende del sistema, por lo que debes leer la página de manual vmstat(8) de tu sistema si el tuyo tiene un aspecto diferente al del ejemplo que hemos mostrado.

Cómo leer la salida de iostat

Pasemos ahora a iostat. Por defecto, muestra parte de la misma información sobre el uso de la CPU que vmstat. Sin embargo, normalmente sólo nos interesan las estadísticas de E/S, por lo que utilizaremos el siguiente comando para mostrar únicamente las estadísticas ampliadas de los dispositivos:

$ iostat -dxk 5
Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s 
sda 0.00 0.00 1060.40 3915.00 8483.20 42395.20 

avgrq-sz avgqu-sz await r_await w_await svctm %util
 20.45 3.68 0.74 0.57 0.78 0.20 98.22

Al igual que con vmstat, el primer informe muestra los promedios desde que se arrancó el servidor (generalmente lo omitimos para ahorrar espacio), y los siguientes informes muestran promedios incrementales. Hay una línea por dispositivo.

Hay varias opciones que muestran u ocultan columnas. La documentación oficial es un poco confusa, y tuvimos que indagar en el código fuente para averiguar qué se mostraba realmente. Esto es lo que muestra cada columna:

rrqm/s y wrqm/s
El número de peticiones de lectura y escritura fusionadas puestas en cola por segundo. Fusionadas significa que el sistema operativo tomó varias peticiones lógicas de la cola y las agrupó en una única petición al dispositivo real.
r/s y w/s
El número de peticiones de lectura y escritura enviadas al dispositivo por segundo.
rkB/s y wkB/s
El número de kilobytes leídos y escritos por segundo.
avgrq-sz
El tamaño de la petición en sectores.
avgqu-sz
El número de solicitudes en espera en la cola del dispositivo.
await
El número de milisegundos pasados en la cola del disco.
r_await y w_await
El tiempo medio en milisegundos para que las peticiones de lectura emitidas al dispositivo sean atendidas, tanto para lecturas como para escrituras, respectivamente. Esto incluye el tiempo que pasan las peticiones en cola y el tiempo empleado en atenderlas.
svctm
El número de milisegundos empleados en atender las peticiones, excluyendo el tiempo de espera en cola.
%util4
El porcentaje de tiempo durante el cual estuvo activa al menos una petición. Esta denominación es muy confusa. No es la utilización del dispositivo, si estás familiarizado con la definición estándar de utilización en la teoría de colas. Un dispositivo con más de un disco duro (como un controlador RAID) debería ser capaz de soportar una concurrencia superior a 1, pero %util nunca superará el 100% a menos que haya un error de redondeo en las matemáticas utilizadas para calcularlo. En consecuencia, no es una buena indicación de la saturación del dispositivo, contrariamente a lo que dice la documentación, salvo en el caso especial de que estés mirando un único disco duro físico.

Puedes utilizar la salida para deducir algunos datos sobre el subsistema de E/S de una máquina. Una métrica importante es el número de peticiones servidas simultáneamente. Como las lecturas y escrituras son por segundo y la unidad del tiempo de servicio es la milésima de segundo, puedes utilizar la ley de Little para deducir la siguiente fórmula del número de peticiones concurrentes que atiende el dispositivo:

concurrency = (r/s + w/s) * (svctm/1000)

Si se introducen los números de muestra anteriores en la fórmula de concurrencia, se obtiene una concurrencia de aproximadamente 0,995. Esto significa que, de media, el dispositivo atendió menos de una petición a la vez durante el intervalo de muestreo.

Otras herramientas útiles

Hemos mostrado vmstat e iostat porque están ampliamente disponibles, y vmstat suele venir instalado por defecto en muchos sistemas operativos tipo Unix. Sin embargo, cada una de estas herramientas tiene sus limitaciones, como unidades de medida confusas, muestreos a intervalos que no se corresponden con el momento en que el sistema operativo actualiza las estadísticas y la imposibilidad de ver todas las métricas a la vez. Si estas herramientas no satisfacen tus necesidades, quizá te interesen dstat o collectl.

En también nos gusta utilizar mpstat para observar las estadísticas de la CPU; proporciona una idea mucho mejor de cómo se comportan las CPU individualmente, en lugar de agruparlas todas. A veces esto es muy importante cuando estás diagnosticando un problema. Puede que blktrace también te resulte útil cuando examines el uso de E/S del disco.

Percona escribió su propio sustituto de iostat llamado pt-diskstats. Forma parte de Percona Toolkit. Aborda algunas de las quejas sobre iostat, como la forma en que presenta las lecturas y escrituras de forma agregada y la falta de visibilidad de la concurrencia. También es interactivo y se maneja mediante pulsaciones de teclas, por lo que puedes ampliarlo y reducirlo, cambiar la agregación, filtrar dispositivos y mostrar y ocultar columnas. Es una forma estupenda de trocear una muestra de estadísticas de disco, que puedes recopilar con un simple script de shell aunque no tengas instalada la herramienta. Puedes capturar muestras de la actividad del disco y enviarlas por correo electrónico o guardarlas para su posterior análisis.

Por último, perf, el perfilador de Linux de, es una herramienta inestimable para inspeccionar lo que ocurre a nivel del sistema operativo. Puedes utilizar perf para inspeccionar información general sobre el sistema operativo, como por ejemplo por qué el núcleo está utilizando tanto la CPU. También puedes inspeccionar IDs de procesos específicos, permitiéndote ver cómo MySQL está interactuando con el sistema operativo. Inspeccionar el rendimiento del sistema es una inmersión muy profunda, por lo que recomendamos Systems Performance, Segunda Edición de Brendan Gregg (Pearson) como excelente lectura complementaria.

Resumen

Elegir y configurar el hardware para MySQL, y configurar MySQL para el hardware, no es un arte místico. En general, necesitas las mismas habilidades y conocimientos que para la mayoría de los demás fines. Sin embargo, hay algunas cosas específicas de MySQL que debes saber.

Lo que solemos sugerir a la mayoría de la gente es encontrar un buen equilibrio entre rendimiento y coste. En primer lugar, nos gusta utilizar servidores "commodity", por muchas razones. Por ejemplo, si tienes problemas con un servidor y necesitas dejarlo fuera de servicio mientras intentas diagnosticarlo, o si simplemente quieres intentar cambiarlo por otro servidor como forma de diagnóstico, esto es mucho más fácil de hacer con un servidor de 5.000 $ que con uno que cueste 50.000 $ o más. MySQL también suele adaptarse mejor -tanto por el software en sí como por las cargas de trabajo típicas que ejecuta- al hardware básico.

Los cuatro recursos fundamentales que necesita MySQL son CPU, memoria, disco y recursos de red. La red no suele aparecer como un cuello de botella grave muy a menudo, pero las CPU, la memoria y los discos sí que lo hacen. El equilibrio entre velocidad y cantidad depende realmente de la carga de trabajo, y debes esforzarte por conseguir un equilibrio entre rapidez y cantidad en la medida en que lo permita tu presupuesto. Cuanta más concurrencia esperes, más deberías apoyarte en más CPUs para acomodar tu carga de trabajo.

La relación entre CPU, memoria y discos es intrincada, y los problemas en un área suelen aparecer en otra. Antes de dedicar recursos a un problema, pregúntate si no deberías dedicarlos a otro problema. Si tienes problemas de E/S, ¿necesitas más capacidad de E/S o sólo más memoria? La respuesta depende del tamaño del conjunto de trabajo, que es el conjunto de datos que se necesita con más frecuencia durante un periodo determinado.

Dispositivos de estado sólido son excelentes para mejorar el rendimiento general del servidor y, en general, deberían ser el estándar para las bases de datos en la actualidad, especialmente para las cargas de trabajo OLTP. La única razón para seguir utilizando discos duros es en sistemas con un presupuesto extremadamente limitado o en los que necesites una cantidad asombrosamente alta de espacio en disco, del orden de petabytes en una situación de almacenamiento de software de datos.

En cuanto al sistema operativo, sólo hay unas pocas cosas importantes que debes hacer bien, sobre todo relacionadas con el almacenamiento, las redes y la gestión de la memoria virtual. Si utilizas GNU/Linux, como la mayoría de los usuarios de MySQL, te sugerimos que utilices el sistema de archivos XFS de y que configures el swappiness y el programador de colas de disco con valores adecuados para un servidor. Hay algunos parámetros de red que puede que necesites cambiar, y puede que desees ajustar algunas otras cosas (como desactivar SELinux), pero esos cambios son cuestión de preferencia.

1 Haiku popular: No es DNS. Es imposible que sea DNS. Era DNS.

2 Consulta las entradas del blog "Impacto de los asignadores de memoria en el rendimiento de MySQL" y "Pruebas de uso de memoria de MySQL (o Percona)" para ver las comparaciones.

3 Para más información, consulta esta entrada del blog.

4 El RAID por software, como MD/RAID, puede no mostrar la utilización de la propia matriz RAID.

Get MySQL de Alto Rendimiento, 4ª Edición now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.