manera de evitar que las consultas esperen el bloqueo a nivel de tabla

10

Hemos encontrado un problema después de mover la base de datos de nuestro cliente a un servidor adicional. Esto debería haber tenido efectos positivos en el rendimiento del sitio, pero hay un problema con el bloqueo de la tabla en MyISAM. (He oído hablar de usar InnoDB en lugar de MyISAM, pero no podemos cambiar el motor en el futuro cercano).
Podríamos detectarlo en una consulta de actualización que se realiza cuando un moderador activa un comentario en el sitio del artículo. Este es el proceso:

  • Se procesa la consulta de actualización SET status = 1 WHERE id = 5(se establece el índice)
  • los archivos en caché de la página se eliminan

En este punto, toda la página se vuelve lenta. La base de datos está ocupada por minutos. Busqué la lista de procesos varias veces y vi unas 60 entradas de diferentes consultas de selección, que estaban todas en el estado esperando el bloqueo a nivel de tabla .

1. No entiendo por qué esta actualización en la tabla article_commentspuede afectar las declaraciones de selección para que la tabla articleespere el bloqueo a nivel de tabla. En la lista de procesos, casi todas las consultas en espera eran de esta tabla. He leído sobre el hecho de que se prefieren las actualizaciones / inserciones a las selecciones y que esto puede causar tales problemas, pero la tabla de artículos en sí no se actualiza cuando se activan los comentarios, por lo que las selecciones no deberían esperar. ¿Entendí mal eso?
2. ¿Hay algo además de cambiar a InnoDB para evitar este comportamiento o al menos para obtener un mejor equilibrio? Estoy muy irritado por el hecho de que este problema no apareció antes de mover la base de datos al nuevo servidor. Supongo que hay una mala configuración, pero no sé cómo identificarme.

32bitfloat
fuente
1
Habilite el registro general y observe las declaraciones JOIN entre estas tablas. Cuando SELECCIONA, crea un BLOQUEO DE LECTURA implícito. Dado que MYISAM no admite el bloqueo de NIVEL DE FILA, se bloquea en el nivel de la mesa. Probablemente sea el caso de que este bloqueo ocurriera en el servidor anterior pero nadie estaba mirando. Compare su línea my.cnf para la línea entre hosts y especialmente asegúrese de que su key_buffer esté sintonizado correctamente.
randomx
Tuvimos varios otros problemas de rendimiento en el servidor anterior y, a menudo, vimos la lista de procesos. Hubo principalmente muchos procesos de suspensión, pero nunca notamos los que esperaban (vi esta información en general la primera vez en este nuevo servidor). Mi compañero copió el antiguo my.cnf y ajustó los valores al nuevo hardware existente, pero no había muchas entradas. También comparé los resultados de "MOSTRAR VARIABLES" pero realmente no sabía qué buscar. Revisaremos el buffer de mañana mañana, gracias por tu comentario.
32bitfloat
Recientemente tuvimos un problema similar. Inicialmente nuestro key_buffer_sizeestaba configurado para 1GB. Aumentar eso para 10GBreducir el problema.
Haluk
@ Rick James, gracias. Me salvaste muchos problemas hoy. ¿Tienes una lista de deseos en Amazon o en otro lugar? :) Configuré query_cache_limit en 1024. No hay ningún problema de bloqueo ahora. Lo hice en variables al principio desde el cliente mysql. establecer global query_cache_limit = 1024; Ahora lo escribiré en my.cnf. Esta solución me dio tiempo para planificar la migración innodb sin ningún tipo de estrés, así que gracias.

Respuestas:

8

MyISAM Storage Engine es muy conocido por realizar bloqueos de tabla completos para cualquier DML (INSERTOS, ACTUALIZACIONES, DELETES). InnoDB definitivamente resolvería ese problema a largo plazo.

Escribí sobre los pros y los contras de usar MyISAM vs InnoDB

Con respecto a su pregunta actual, aquí hay un posible escenario:

  • articley article_commentsson ambas tablas MyISAM
  • article_commentstiene uno o más índices con statusuna columna
  • Las actualizaciones de la página de índice article_commentsse almacenan en caché en MyISAM Key Buffer (dimensionado por key_buffer_size ), lo que hace que las páginas de índice antiguas salgan de MyISAM Key Buffer
  • Tiene consultas SELECT que realizan uniones entre articleyarticle_comments

En mi escenario sugerido, los SELECT contra la articletabla pueden retrasarse para permitir escrituras debido a que tienen que esperar para article_commentsestar libres de cualquier DML (en este caso, un UPDATE)

RolandoMySQLDBA
fuente
Gracias por su respuesta (y los enlaces), su escenario es real. No me di cuenta de que la mayoría de los artículos seleccionados se unieron a la tabla de comentarios (o, en otras palabras, vi las declaraciones incompletas en la lista de procesos de phpmyadmin). ¿Conoces una solución a corto plazo para evitar las múltiples consultas de espera? Ya lo intenté con "UPDATE LOW_PRIORITY" en la declaración específica, pero eso no hizo cambios notables. Realmente cambiaremos a innodb en el futuro, pero me pregunto si actualmente hay una manera de mejorar.
32bitfloat
La solución definitiva: convertir tablas a InnoDB. Vea mi publicación dba.stackexchange.com/a/9422/877 sobre cómo convertir todo MyISAM en InnoDB
RolandoMySQLDBA
7

En este punto, toda la página se vuelve lenta. La base de datos está ocupada por minutos.

¿Hueles como si tuvieras una gran Query_cache?

mysql> SHOW VARIABLES LIKE 'query_cache%';
+------------------------------+----------+
| Variable_name                | Value    |
+------------------------------+----------+
| query_cache_limit            | 1048576  |
| query_cache_min_res_unit     | 4096     |
| query_cache_size             | 16777216 | -- Not over 50M
| query_cache_type             | DEMAND   | -- Only if using SQL_CACHE
| query_cache_wlock_invalidate | OFF      |
+------------------------------+----------+

Para sistemas de producción con muchas escrituras, también puede desactivar el query_cache.

Todas las entradas en query_cache para la tabla dada se purgan cuando se produce una escritura en esa tabla. Cuanto más grande es el control de calidad, más lenta es esta tarea.

MyISAM utiliza bloqueos de "nivel de tabla". Las lecturas y escrituras no pueden ocurrir al mismo tiempo (en la misma tabla). Crudo, pero efectivo.

Rick James
fuente
1
Bueno, sí. Tenemos aproximadamente 64 millones de caché. Gracias por esta información que era nueva para mí, sin embargo, teníamos el mismo valor en el antiguo servidor donde no notamos los bloqueos de la tabla. Ya hemos comenzado a mudarnos a InnoDB, pero este hecho sigue siendo un misterio ...
32bitfloat