1. Introducción
Hace unos días recibí un email de mi proveedor de hosting, indicándome que uno de mis proyectos estaba consumiendo una gran parte de los recursos del servidor de la base de datos, que comparto con otros clientes.
Bueno, uno de los motivos era que gracias a mi trabajo de posicionamiento en Google, el trafico de este proyecto había aumentado considerablemente.
Debido al aumento del numero de transacciones, recién salió a luz que alguna componente del proyecto no estaba funcionando bien.
Pero como saber que era lo que estaba sucediendo en el servidor?
2. Monitoreo
Una forma de investigar lo que estaba sucediendo en el servidor era colocar mensajes de Debug, pero en un sistema que esta en producción, o como ahora se acostumbra a decir live, no era posible.
La única forma era entonces monitorear directamente la base de datos de MySQL para encontrar el origen del problema.
Buscando un poco en la red, encontré en el blog de Ajaxian la herramienta que estaba necesitando. Un monitor de MySQL en Ajax (AjaxMyTop) que muestra periódicamente el estado actual de todas las conexiones a una base de datos. Es una herramienta muy sencilla que recién se esta comenzando a desarrollar (versión 0.1) pero que tiene un gran futuro.
Revisando los resultados del monitor, pude descubrir 2 casos interesantes:
- Cuando los usuarios accesaban a algunas páginas (justamente aquellas que están en las primeras posiciones de Google), no todas las conexiones a la base de datos se cerraban al terminar el proceso del web server.De esta manera, en muy corto tiempo, el número de conexiones abiertas crecía rápidamente antes de que los timeouts del servidor pudiesen actuar. En las horas pico, el servidor tenia unas 4000 pageviews por hora, es decir unos 66 pageviews por segundo.
- Cuando las páginas del proyecto, que estaban ahora en las primeras posiciones de Google eran accesadas, se podía observar en el monitor que el número de conexiones a la base de datos aumentaba desmesuradamente. En las horas pico, esto causaba que mi proyecto consumiera una gran parte de los recursos del servidor de la base de datos.
4. Solución
En el caso 1. el problema estaba claro: En algún lugar del código yo no había cerrado la conexión a la base de datos. Este error fue resuelto rápidamente.
El caso 2. era más difícil de resolver. Aquí no me quedo mas que realizar pruebas en mi sistema local, colocando mensajes de Debug en una de las páginas que era mas accesada por los usuarios.
Después de un análisis profundo de todos los accesos a la base de datos, me di cuenta que la programación con objetos y a alto nivel puede ser en algunos casos muy peligrosa: En muchos lugares del código de PHP usaba funciones de una clase, que al parecer sencillas de usar, realizaban cada vez conexiones a la base de datos. De esta manera cada acceso a esta página web generaba 33 conexiones a la base de datos. Esto significaba unas 2178 conexiones a la DB por segundo en las horas pico.
La solución a este problema fue obtener los datos que se necesitan de la DB al inicio y colocarlos en una variable global para que puedan ser usada posteriormente por la clase anteriormente mencionada. De esta manera se pudo reducir el número de las conexiones a la DB en mas de un 60%.
5. Recomendaciones
Como conclusión de esta experiencia, que fue causada por haber logrado una de mis metas: Aumentar el trafico en uno de mis proyectos, puedo dar las siguientes recomendaciones para webs de alto trafico:
1. Las conexiones a la base de datos deben ser lo mas cortas posible. Se debe evitar llamar a otras funciones que no sean accesos a la base de datos durante una conexión:
– Abrir conexion a la DB ( mysql_connect() , mysql_select_db())
– Ejecutar query ( mysql_query() )
– Cerrar conexión de inmediato (mysql_close() )
2. En caso de que se necesiten datos de un registro o varios registros de la DB en diferentes partes de la página, se debe crear una variable global, obtener los datos desde la DB al inicio y luego usar solamente la variable global.
3. Durante el desarrollo de las páginas web se debe revisar continuamente los recursos que se usan al llamar las diferentes funciones.
4. Hacer pruebas de carga generando un trafico artificial. Esto se puede realizar con un pequeño script en PHP que escanee con alta frequencia la página a testear. Parlamente se puede analizar con un monitor el rendimiento de la base de datos y del mismo web server.
Artículos relacionados
– Monitorear MySQL
– Rendimiento en MySQL
El programa me parece una maravilla, el primro que he visto y la verdad muy bueno, no me puedo ni imaginar lo que harán en su versión 1.0, pero ahora me surge una duda, lo corrí para ver que pasaba con mi DB y tengo muchas conexiones en «sleep», como puedo solventar esto? Las conexiones son cerradas al no estar ciendo usadas, sin embargo se mantiene el sleep de MySQl, gracias de antemano
Juan,
Siempre debes tener en cuenta que la lista que muestra el monitor es un snapshot, es decir una foto instantánea del estado de tu DB en un momento dado.
En el caso de que no tengas visitantes, teoréticamente debería aparecer solo un proceso con la información show processlist que es monitor mismo.
1. La mayoría del tiempo de una conexión a la DB también debería tener el estado sleep, ya que un acceso a la DB dura solamente unos milisegundos. Esos accesos se ven de vez en cuando con la info SELECT, UPDATE, etc.
2. En caso de que una conexión muestre por mucho tiempo una función a la DB, entonces existe un deadlock o algún problema en tu programa. Eso tienes que corregir.
3. En caso de que una conexión muestre por mucho tiempo sleep (con un valor grande de time) significa que esa conexión no ha sido cerrada correctamente. Eso también tienes que corregir.
La mejor forma de analizar y corregir los programas ya la he descrito en el artículo.
Si esto es como dices, por qué entonces servidores como dreamhost aconsejan que no se cierre y se abran conexiones a cada momento, y que se abran de modo persistente?
http://us2.php.net/manual/en/features.persistent-connections.php
http://us2.php.net/manual/en/function.mysql-pconnect.php
http://wiki.dreamhost.com/index.php/MySQL_and_PHP
O por lo menos asà lo he entendido yo.
Se necesitan permisos especiales de Mysql para usar la aplicación AjaxMyTop. Estos permisos no los dan en proveedores de hosting normalmente…
Esto está basado en la aplicación para consola mytop. Lo único que hacen aquí es ponerle una GUI web.
La aplicación se basa en la información generada por el comando «Query show full processlist» de Mysql, el cual necesita permisos especiales para funcionar.
Luis,
Como tu mencionas, mytop es una herramienta para consola que se ha sido inspirada por la función top de Linux. Solo funciona mediante una conexión telnet o SSH. La mayoría de los webmasters no cuentan con este tipo de accesos a los servidores web.
Por el contrario, AjaxMyTop se puede usar desde cualquier browser.
pues yo lo he instalado en mi site http://www.cheapbarcelonahotels.co.uk/ y aunque esta correctamente instalado no veo el flujo de conexiones