El historial de transacciones de Innodb a menudo esconde «deudas» peligrosas

En muchas cargas de trabajo intensivas en secuencias de comandos de Innodb/XtraDB, es posible que observe una acumulación de «deuda» oculta y peligrosa: un «historial» de transacciones sin purgar que, si no se controla con el tiempo, provocará una regresión del rendimiento. liberar espacio y causar una interrupción. Hablemos de dónde viene y qué puede hacer para evitar tener problemas.

Avances técnicos: InnoDB es un motor MVCC, lo que significa que mantiene múltiples versiones de filas en la base de datos, y cuando las filas se eliminan o actualizan, no se eliminan inmediatamente de la base de datos, sino que se mantienen durante algún tiempo, hasta que se puedan eliminar. Para la mayoría de las cargas de trabajo de OLTP, se pueden eliminar segundos después de que se haya realizado el cambio. En algunos casos, incluso si necesita conservarse durante un largo período de tiempo, si hay transacciones antiguas ejecutándose en el sistema, es posible que aún deba mantener un estado de base de datos antiguo. Dado que MySQL 5.6 Innodb tiene uno o más «hilos de purga» que eliminan datos antiguos Puerto eliminarse, incluso si no pueden hacerlo lo suficientemente rápido para cargas de trabajo con escritura muy intensiva.

¿Realmente sucede? Empecé a analizar este problema en función de algunas inquietudes de los clientes y, para mi sorpresa, pude hacer que la historia creciera rápidamente utilizando la carga de trabajo básica de «actualización» de sysbench. Es mayormente fácil con la falla innodb_purge_threads = 1 parámetro sino también con innodb_purge_threads = 8 crece bastante rápido.

Si echamos un vistazo a la velocidad de purga (que proviene de la tabla de métricas de innodb), podemos ver que la purga está muy hambrienta por el proceso activo simultáneo de sysbench y se acelerará mucho cuando finalice:

Ahora, para ser sincero, no es una situación fácil ingresar a la mayoría de las cargas de trabajo con transacciones cortas cuando el espacio cancelado se almacena en la purga de memoria y se puede mantener. Sin embargo, si el espacio Deshacer está fuera del grupo de búfer, la velocidad de purga puede disminuir drásticamente y es posible que el sistema ya no pueda mantenerla. ¿Cómo pudo pasar esto? Hay 2 variantes comunes…

Transacciones a largo plazo: Si tiene una transacción larga, por ejemplo mysqldump, en la tabla más grande, la purga se detendrá mientras se ejecuta la transacción y se acumulará una gran cantidad de historial. Si hay suficiente presión de E/S, parte del espacio cancelado se eliminará del grupo de búfer.

Reinicie MySQL: Incluso con un historial modesto, reiniciar MySQL lo borrará de la memoria y hará que la purga se vincule a IO. Esto es seguro si no está utilizando InnoDB Buffer Pool para guardar y recargar.

¿Cómo verifica si su espacio UNDO está almacenado en caché correctamente? En Percona Server puedo usar los siguientes comandos:

segundo

) Esto muestra cuál es el tamaño total del espacio eliminado ahora, 1,7 GB, con menos de 100 MB de caché en el tamaño del grupo de búfer… Estos son algunos gráficos de consultas simultáneas de Ejecución intensa durante una carga de trabajo más liviana en la que se pudo mantener la depuración. En este caso, utilicé la «inyección» de referencia en la configuración de sysbench

segundo
)

Lo que podemos ver en esos gráficos es que la purga de InnoDB inicialmente avanza a una velocidad lo suficientemente rápida como para mantener el flujo de transacciones, sin embargo, a medida que se estabiliza la demanda complicada, se detiene la purga y cuando se realiza la demanda, la velocidad de purga se ajusta al nuevo nivel mucho más bajo en el que ya no es capaz de mantener la carga de trabajo. Ahora, hay un reconocimiento de este problema y hay opciones con él. innodb_max_purge_lag y

innodb_max_purge_lag_delay

para establecer la duración máxima del historial después de alcanzar qué retraso se inyectará para declaraciones DML hasta una cantidad específica de microsegundos. Desafortunadamente, no está muy bien diseñado para usarse con aplicaciones reales. Los problemas que le veo a su diseño son dos…

Mirando la historia total: Si lo piensa, hay 2 tipos de registros en el historial: hay registros que se pueden depurar y otros que no se pueden depurar porque son necesarios para una transacción activa. Es perfecto para tener muchos registros en el historial, si se están ejecutando transacciones largas; no es la causa del problema o la sobrecarga, mientras esperamos qué «historial purgable» debería ser bajo la mayor parte del tiempo.

Concéntrese en el tamaño en lugar del tipo de cambio:

Peor aún, la prevención de explosiones de historial mantiene el valor actual para inyectar un retraso y no cada vez que crece o disminuye. Estos conjuntos significan que los casos de transacciones largas que compiten con las cargas de trabajo de OLTP se manejan muy mal: hasta que el historial alcanza el máximo especificado, el sistema se activará a toda marcha, retrasando todas las declaraciones al máximo posible, hasta que la historia regrese por debajo del máximo. umbral. Así es como se ve en los gráficos: Como se puede ver en el último gráfico, tenemos el

purga_dml_delay_usec aumentando a 10000us (configuración máxima I) incluso cuando no se puede realizar una purga (vea que la línea azul está en cero). En realidad, solo comienza a trabajar en la historia cuando se completa la gran demanda y realmente libera los descansos cuando se completa la purga. En este caso, el rendimiento del sistema se redujo más de 5 veces cuando el retraso estaba activo, lo que no funcionó para la mayoría de los sistemas del mundo real.

Pensamientos de diseño: Entonces, ¿qué cambiaría en el diseño de purga de la configuración? Me gustaría ver una mejor configuración predeterminada que debería incluir varios cables de purga y un retraso de purga (mejorado). Encontraré una manera de medir no solo el tamaño de la historia, sino también el tamaño de la historia purgable y el retraso básico de la purga basado en ella. También hágalo en función del cambio en lugar del umbral: hágalo lo suficientemente largo como para que la historia se reduzca gradualmente. También en función del tamaño del espacio vacío en lugar de la cantidad de transacciones (que pueden variar en tamaño), podría ser más conveniente y fácil de ajustar automáticamente. Probablemente también podamos hacerlo mejor en términos de limpieza del espacio de la memoria caché, similar a Insertar búfer, me gustaría mantener en la memoria hasta el 10% del tamaño del grupo de búfer mientras elimino de la memoria caché algo que sabe que necesita mucho. pronto es. mal negocio, además de considerar si existe una forma de lectura anticipada que pueda funcionar para deshacer la lectura previa del espacio que se necesita. Ahora lo probé y ni la lectura lineal ni la aleatoria parecen ayudar a sacarlo del disco con menos E/S aleatoria.

Pensamientos prácticos: Independientemente de las mejoras que recibamos de la purga, tenemos los sistemas MySQL y Percona Server 5.6 funcionando durante muchos años. Entonces, ¿qué pasos prácticos podemos tomar para manejar mejor la historia de la purga? Monitor: Asegúrese de monitorear y gráficos

innodb_history_list_length. Si usa transacciones grandes, configure alertas lo suficientemente altas, pero no las deje sin marcar. Configurar Colocar innodb_purge_threads = 8 o algún otro valor si está escribiendo una carga de trabajo intensiva. Considere jugar con innodb_max_purge_lag y

innodb_max_purge_lag_delay pero cuidado, tal como se concibe realmente, puede hacer que el sirviente se arrodille. En su lugar, puede considerar usarlo de forma interactiva, cambiándolos como opciones de tiempo de ejecución si ve el crecimiento de la lista de historial sin verificación, equilibrando los requisitos de carga de trabajo actuales con los recursos destinados a la purga.

Dejar purgar antes de cerrar: En muchos casos, encontré que el rendimiento de la purga era muy bajo después de reiniciar MySQL Server debido al almacenamiento en caché. Por lo tanto, el mejor enfoque podría ser simplemente eliminar la carga de trabajo del servidor MySQL antes de apagarlo para permitir que se elimine el historial excepcionalmente completo, y solo después de apagarlo. Si el servidor falla, es posible que desee considerar dejar un drenaje completo antes de devolverle el tráfico. Usar la precarga del grupo de búfer de Innodb Usar innodb_buffer_pool_dump_at_shutdown = encendido y

innodb_buffer_pool_load_at_startup = activado para asegurarse de que el espacio cancelado esté precargado en el grupo de búfer al inicio. PD Si te preguntas de dónde vienen los gráficos que usé, estos son nuestros

Percona Cloud Tools: una forma muy conveniente de análisis como este que permite el acceso a todas las variables de estado de MySQL, métricas de InnoDB, toneladas de métricas del sistema operativo y más.

Author: Ing. Luis

A lo largo de conocer Windows y otros sistemas operativos me eh encontrado con diversos tipos de error, ahora brindo soluciones según mi experiencia-

Deja un comentario