Too many connections, Slow Queries y Locks

Este es un caso que me he encontrado ya varias veces y, al menos la primera vez, fue complicado de diagnosticar.

Todo empieza porque detectamos (vía monitorización o porque llama el cliente, uff), que el contenido que se muestra en una wed desde base de datos... no aparece.

Al ojear los logs de Apache en error_log vemos trazas tal que:

[Thu Sep 04 17:15:53 2008] [error] [client 74.6.*.*] PHP Warning:  mysql_select_db() [<a href='function.mysql-select-db'>function.mysql-select-db</a>]: Too many connections in /var/www/html/whatever.php on line X

Lo primero a comprobar es, vía access_log, si tenemos muchas peticiones simultáneas, pero... sorpresa: ¡no hay!

Por defecto MySQL tiene configuradas 100 conexiones simultáneas, que en general suele ser un buen valor para la mayoría de los casos.

Entonces, si tenemos pocas peticiones y, por lo tanto, pocas consultas a la base de datos, ¿qué es lo que está acabando con nuestro MySQL?

Bueno, el caso más habitual que me encuentro es un foro PhpBB2 (uff, lo sé :D) con tablas que tienden a degradarse por cómo está diseñado el sistema para las búsquedas en el foro. Se abusa de la indexación de palabras buscadas, y nos encontramos con tablas de más de 20 millones de filas.

La clave para el diagnóstico es ejecutar un SHOW PROCESSLIST;, y ver el siguiente resultado:

+--------+--------+-----------+--------+---------+------+----------------------+------------------------------------------------------------------------------------------------------+
| Id     | User   | Host      | db     | Command | Time | State                | Info                                                                                                 |
+--------+--------+-----------+--------+---------+------+----------------------+------------------------------------------------------------------------------------------------------+
| 383506 | bd_clientu | localhost | bd_client | Query   |  729 | Copying to tmp table | SELECT m.word_id 
				FROM phpbb_search_wordmatch m, phpbb_search_wordlist w 
				WHERE w.word_text  | 
| 383526 | bd_clientu | localhost | bd_client | Query   |  237 | Copying to tmp table | SELECT m.word_id 
				FROM phpbb_search_wordmatch m, phpbb_search_wordlist w 
				WHERE w.word_text  | 
| 383535 | bd_clientu | localhost | bd_client | Query   |  228 | Copying to tmp table | SELECT m.word_id 
				FROM phpbb_search_wordmatch m, phpbb_search_wordlist w 
				WHERE w.word_text  | 
| 383541 | bd_clientu | localhost | bd_client | Query   |  149 | Copying to tmp table | SELECT m.word_id 
				FROM phpbb_search_wordmatch m, phpbb_search_wordlist w 
				WHERE w.word_text  | 
| 383542 | bd_clientu | localhost | bd_client | Query   |  148 | Copying to tmp table | SELECT m.word_id 
				FROM phpbb_search_wordmatch m, phpbb_search_wordlist w 
				WHERE w.word_text  | 
| 383572 | bd_clientu | localhost | bd_client | Query   | 2511 | Sending data         | INSERT INTO phpbb_search_wordmatch (post_id, word_id, title_match) 
				SELECT 152262, word_id, 1  
 | 
| 383574 | bd_clientu | localhost | bd_client | Query   | 2511 | Locked               | INSERT INTO phpbb_search_wordmatch (post_id, word_id, title_match)
                                SELECT 152263, word_id, 1
 |
[... etc ...]
| 384946 | root   | localhost | NULL   | Query   |    0 | NULL                 | SHOW PROCESSLIST                                                                                     | 
+--------+--------+-----------+--------+---------+------+----------------------+------------------------------------------------------------------------------------------------------+
100 rows in set (0.00 sec)

Con lo que ahí tenemos nuestras 100 conexiones ocupadas ;). He recortado la salida, porque hay muchas entradas como la que he destacado, y la clave está en rojo.

En este foro una búsqueda lleva implícita un SELECT y un INSERT, siendo ambas operaciones lentas en una tabla muy grande.

En este caso el problema es que bots de spammers entran en el foro y hacen gran cantidad de búsquedas de forma que nuestra tabla degradada (recordemos que hablamos de millones de registros) satura el servidor de bases de datos, lo que acaba en una auténtica denegación de servicio :(.

Las solución inmediata pasa por aumentar el número máximo de conexiones para MySQL (en my.cnf, max-connections en el apartado [mysqld]), confiando que el servidor aguante así el tirón, pero lo más probable es que el problema se vuelva a producir con el tiempo.

Para arreglarlo de verdad, se podría evitar el acceso de los bots, pedir que el usuario del foro esté registrado para hacer búsquedas, o simplemente cambiar de aplicación para el foro (aunque esto último no es justo, porque me he encontrado con el mismo problema con software que disfruta de mucha mejor consideración en la comunidad y que se supone de gran calidad...).


Publicidad

Aviso: Los siguientes comentarios pertenecen a las personas que los han enviado.
El administrador de este sitio web no es responsable de los mismos.

[comentarios] Hay 4 comentarios:

Gravatar
06/09/2008 09:24:51
Captchas
por Peibol (IP: 212.183.243.*)
Comentario de Peibol
Otra forma de evitar los bots spammers es incluír un mecanismo de filtro por captchas ( http://es.wikipedia.org/wiki/Captcha http://www.phpbb.com/community/viewtopic.php?t=382890) que por lo visto lo hay para phpbb, de esta forma los bots no serán capaces de ejecutar ninguna consulta con lo que no será necesario aumentar las conexiones ni el stress del servidor.

Salu2
Gravatar
07/09/2008 07:44:08
captchas...
por juanjo (IP: 212.145.193.*)
Comentario de juanjo
el tema de los captchas es un mal necesario, eso está claro .Es mucho más cómodo que obligar a la gente a registrarse para enviar comentarios.

saludos crack
Gravatar
08/09/2008 02:04:18
mytop
por sepp0 (IP: 190.190.23.*)
Comentario de sepp0
Hay un programa que te puede ser de mucha ayuda para este tipo de cosas, se llama 'mytop'.

Saludos!
Gravatar
13/09/2008 09:12:03
registrarse para buscar..
por Peibol (IP: 212.183.243.*)
Comentario de Peibol
Buff.... registrarse para buscar o comentar... que pereza... buena forma de echar a la gente de un sitio :P

Salu2

! Esta entrada no permite nuevos comentarios.

Los comentarios se bloquean automáticamente tras 15 días desde la publicación del artículo.

Si deseas comentar algo relacionado con el texto, puedes enviarme un e-mail.