Mi aplicación MySQL experimenta bajo rendimiento al ejecutar algunas consultas UPDATE
, INSERT
y DELETE
. En esta pregunta, solo hablaré de un particular UPDATE
, porque es suficiente para demostrar el problema:¿Puede la latencia de I/O causar una ACTUALIZACIÓN simple para tomar segundos en MySQL?
UPDATE projects SET ring = 5 WHERE id = 1
Este UPDATE
es por lo general lo suficientemente rápido, alrededor de 0,2 ms, pero de vez en cuando (lo suficiente como para ser un problema) tarda varios segundos. He aquí un extracto del registro (mirar la cuarta línea):
~ (0.000282) UPDATE `projects` SET `ring` = 5 WHERE `id` = 1
~ (0.000214) UPDATE `projects` SET `ring` = 6 WHERE `id` = 1
~ (0.000238) UPDATE `projects` SET `ring` = 7 WHERE `id` = 1
~ (3.986502) UPDATE `projects` SET `ring` = 8 WHERE `id` = 1
~ (0.000186) UPDATE `projects` SET `ring` = 9 WHERE `id` = 1
~ (0.000217) UPDATE `projects` SET `ring` = 0 WHERE `id` = 1
~ (0.000162) UPDATE `projects` SET `ring` = 1 WHERE `id` = 1
projects
es una tabla InnoDB con 6 columnas de tipos INT
y VARCHAR
, 17 filas y un índice en id
. Sucede con otras tablas también, pero aquí me estoy enfocando en esta. Al tratar de resolver el problema, me aseguré de que las consultas fueran todas secuenciales, así que esto es , no es un problema de bloqueo. El UPDATE
anterior se ejecuta en el contexto de una transacción. Otro información en el servidor:
- VPS con 4 GB de RAM (1 GB fue), el espacio libre en disco 12 GB
- CentoOS 5,8 (5,7)
- MySQL 5.5.10 (era 5.0.x)
El bit "was" anterior significa que no funcionó antes o después de la actualización.
Lo que he probado hasta ahora, en vano:
- Configuración
innodb_flush_log_at_trx_commit
a 0, 1 ó 2 - Configuración
innodb_locks_unsafe_for_binlog
dentro o fuera de - Configuración
timed_mutexes
dentro o fuera de - Cambiando
innodb_flush_method
de forma predeterminada aO_DSYNC
oO_DIRECT
- El aumento
innodb_buffer_pool_size
del valor predeterminado a 600M y luego a 3000M - El aumento
innodb_log_file_size
del valor predeterminado a 128M - la compilación de MySQL desde el código fuente
- Correr
SHOW PROCESSLIST
, que me informa de que el estado es "actualización" - Correr
SHOW PROFILE ALL
, que dice que casi todo el tiempo se gastó en "actualizar" y que, dentro de ese paso, no se gastaba tanto tiempo en ciclos de CPU y había muchos cambios de contexto voluntarios (como 30) - Monitoreando
SHOW STATUS
para ver cambios enInnodb_buffer_pool_pages_dirty
. Puede haber alguna relación entre las páginas sucias que se vacían y las consultas lentas, pero la correlación no es clara.
Luego decidí verificar la latencia de E/S del sistema con ioping
.Esta es mi primera VPS, por lo Me sorprendió ver este resultado:
4096 bytes from . (vzfs /dev/vzfs): request=1 time=249.2 ms
4096 bytes from . (vzfs /dev/vzfs): request=2 time=12.3 ms
4096 bytes from . (vzfs /dev/vzfs): request=3 time=110.5 ms
4096 bytes from . (vzfs /dev/vzfs): request=4 time=232.8 ms
4096 bytes from . (vzfs /dev/vzfs): request=5 time=294.4 ms
4096 bytes from . (vzfs /dev/vzfs): request=6 time=704.7 ms
4096 bytes from . (vzfs /dev/vzfs): request=7 time=1115.0 ms
4096 bytes from . (vzfs /dev/vzfs): request=8 time=209.7 ms
4096 bytes from . (vzfs /dev/vzfs): request=9 time=64.2 ms
4096 bytes from . (vzfs /dev/vzfs): request=10 time=396.2 ms
Bastante irregular, diría.
Una vez dicho todo esto, pregunto:
Puede ser latencia en ocasiones matar el rendimiento de E/S de MySQL? Siempre pensé que, cuando ejecutaba un
UPDATE
, el hilo que se encargaba de esa conexión no iba a vaciar datos en el disco ni esperar a tal enrojecimiento; volvería inmediatamente y el enrojecimiento sería hecho por otro hilo en otro momento.Si no puede ser E/S de disco, ¿hay algo más que pueda probar, salvo alquilar un servidor dedicado?
¿Es el COMPROMISO el que tarda 5 segundos o la ACTUALIZACIÓN real? –
El actual 'ACTUALIZACIÓN'. –
'UPDATE' debería normalmente, como dices, no estar al ras en el disco, solo' COMMIT' vaciará el registro mientras se ejecuta en tu hilo (y innodb_flush_log_at_trx_commit = 0 debería desactivarlo) Tu latencia de E/S es definitivamente fuera de control (!), pero a menos que la carga sea lo suficientemente alta como para no permitir el almacenamiento en caché de la tabla de 17 filas para leer, no puedo ver cómo sería la causa de este problema exacto. –