23 votos

Conectar a MySQL desde PHP es muy lento

Acabo de hacer una nueva instalación de XAMPP. Al abrirlo por primera vez PHPMyAdmin me di cuenta de que era extremadamente lento. No tenía sentido que en localhost, se debe tomar alrededor de 5 segundos por cada página que desea abrir. He hecho una pequeña prueba de echar la culpa fuera de PHPMyAdmin:

$con = new PDO("mysql:host=localhost;dbname=mysql", "root", "");
$statement = $con->query('SELECT host,user,password FROM user;');
$users = $statement->fetchAll(PDO::FETCH_ASSOC);

El script de arriba solo tarda unos 3 segundos para correr (a pesar de que tomó cerca de 8 segundos en cargar la primera vez que me corría.)

A continuación, para comprobar si es de PDO culpa he intentado utilizar mysql_connect lugar:

$con = mysql_connect("localhost", "root", "");
mysql_select_db("mysql", $con);
$result = mysql_query('SELECT host,user,password FROM user;');

Toma exactamente el tiempo para terminar.

Pensé que era de PHP, fallo en primera, pero el código PHP y archivos estáticos se sirven más ágil de lo que me puede hacer clic en actualizar. He probado PHP mediante la ejecución de este pequeño script:

header("Content-Type: text/plain");

for($i = 0; $i < 5000; $i++)
{
    echo sha1(rand()) . "\n";
}

5000 sha1 cálculos y la página se muestra más ágil de lo que puedo actualizar mi ventana.

Entonces pensé que era de MySQL culpa. Pero de nuevo, no tuvo muchas pruebas para averiguar que MySQL es el trabajo más rápido de lo que yo necesito. El uso de MySQL, el cliente CLI que el usuario seleccione consulta no tomar medibles tiempo se hace antes he incluso dejar la tecla de retorno.

El tema debe ser de PHP de conexión a MySQL - que es como he sido capaz de razón. Puedo encontrar un montón de cosas acerca de PHP lento o MySQL ser lento, pero nada acerca de PHP+MySQL ser extremadamente lento.

Gracias a alguien que me pueda ayudar a solucionar esto!


Estoy usando XAMPP 1.8.0 para win32 (link de Descarga)
Versión de PHP: 5.4.4
Versión de MySQL: 14.14


EDIT: Después de cierto tiempo, resulta que es la función de conexión que tomando tanto tiempo:

$time = microtime(true);

$con = mysql_connect("localhost", "root", "");
mysql_select_db("mysql", $con);

$con_time = microtime(true);

$result = mysql_query('SELECT host,user,password FROM user;');

$sel_time = microtime(true);

printf("Connect time: %f\nQuery time: %f\n",
       $con_time-$time,
       $sel_time-$con_time);

Salida:

Tiempo de conexión: 1.006148
Tiempo de consulta: 0.000247

¿Qué puede causar PHP para pasar a hacer mucho a la hora de conectar a la base de datos? El cliente CLI, HeidiSQL y MySQL workbench conectar al instante

34voto

DaveRandom Puntos 527

Esto está tomado casi textualmente de mi respuesta aquí, pero sé que fruncir el ceño en el enlace-sólo respuestas en TAN así que me imagino que ustedes hacen así :-)

Si usted tiene este problema y utilizando una versión de Windows anterior a Windows 7, probablemente esta no sea la respuesta a tu problema.

¿Por qué está sucediendo esto?

La causa de este problema es IPv4 vs IPv6.

Cuando se utiliza un nombre de host en lugar de una dirección IP, el cliente de MySQL se ejecuta en primer lugar un AAAA (IPv6) host de búsqueda para el nombre, y se trata de esta dirección en primer lugar si se resuelve correctamente el nombre a una dirección IPv6. Si se produce un error (o de resolución de nombre de conexión) se reserva para IPv4, ejecutar un A de búsqueda y tratando de este host lugar.

Lo que esto significa en la práctica es que si el IPv6 localhost de búsqueda tiene éxito, pero MySQL no está vinculada a la de bucle invertido de IPv6, será necesario esperar un tiempo de espera de conexión ciclo antes de que el IPv4 retroceso se produce y la conexión se realiza correctamente.

Esto no era un problema antes de Windows 7, porque localhost resolución se realiza a través del archivo hosts, y llegó preconfigurado con sólo 127.0.0.1 - que no venga con su contraparte para IPv6 ::1.

Desde Windows 7, sin embargo, localhost resolución está integrado en la resolución de DNS, por las razones indicadas aquí. Esto significa que el IPv6 búsqueda de ahora va a suceder - pero MySQL no está obligado a que las direcciones IPv6, por lo que la conexión fallará, y usted verá el retraso descritos en esta pregunta.

Que Agradable. Sólo dime cómo solucionarlo ya!

Usted tiene un par de opciones. Mirando alrededor de la internet, el general "solución" parece ser el uso de la dirección IP de forma explícita en lugar de el nombre, pero hay un par de razones para no hacerlo, ambos relacionados con la portabilidad, tanto que podría decirse que no es importante:

  • Si usted mueve su guión a otra máquina que sólo es compatible con IPv6, el script no funcionará más.

  • Si usted mueve su secuencia de comandos *nix basado en el entorno de hosting, la magia de la cadena de localhost significaría que el cliente de MySQL prefiere el uso de un socket de Unix, si se ha configurado, esto es más eficiente que la IP de loopback basado en la conectividad

Suenan bastante importante, aunque?

Ellos no están. Usted debe ser el diseño de su aplicación, por lo que este tipo de cosa se define en un archivo de configuración. Si usted mueve su script a otro entorno, las posibilidades son otras cosas será necesario configurar así.

En resumen, el uso de la dirección IP no es la mejor solución, pero es más probable que uno aceptable.

Así que ¿cuál es la mejor solución?

La mejor manera sería cambiar el enlace de direcciones que el servidor MySQL utiliza. Sin embargo, esto no es tan simple como a uno le gustaría. A diferencia de Apache, Nginx y casi todos los otros sane de red de la aplicación de servicio de la historia, MySQL sólo admite una sola enlazar dirección, así que no es sólo un caso de la adición de otro. Afortunadamente, sin embargo, los sistemas operativos compatibles con un poco de magia aquí, para que podamos habilitar MySQL para utilizar IPv4 e IPv6 simultáneamente.

Usted necesita estar ejecutando MySQL 5.5.3 o más tarde, y debes comenzar a MySQL con el --bind-address= argumento de línea de comandos. Tienes 4 opcionesdocs, dependiendo de lo que quieres hacer:

  • El que usted probablemente está familiarizado con, y el uno que es más probable (efectivamente) el uso de, 0.0.0.0. Esto se une a todas las direcciones IPv4 disponibles en la máquina. En realidad, esto no es probablemente la mejor cosa a hacer, incluso si usted no se preocupan acerca de IPv6, ya que sufre los mismos riesgos de seguridad como ::.

  • Una explícita dirección IPv4 o IPv6 (por ejemplo 127.0.0.1 o ::1 de bucle). Esto se une el servidor para que la dirección y sólo esa dirección.

  • La magia de la cadena de ::. Esto se unen MySQL para cada dirección en la máquina, tanto de bucle invertido y física de la interfaz de direcciones en IPv4 y IPv6 modo. Este es un riesgo de seguridad potencial, sólo haga esto si usted necesita MySQL para aceptar conexiones desde el host remoto.

  • El uso de una IPv4-mapped IPv6 dirección. Este es un mecanismo especial construido en IPv6 para la compatibilidad hacia atrás durante el 4 -> 6 de transición, y se permite enlazar a una determinada dirección IPv4 y IPv6 equivalente. Esto es muy poco probable que sea útil para otra cosa que el "doble bucle" dirección ::ffff:127.0.0.1. Esta es probablemente la mejor solución para la mayoría de las personas, sólo vinculante para el bucle, pero permitiendo tanto para IPv4 como para IPv6 conexiones.

Necesito modificar el archivo hosts?

NO. No modificar el archivo de hosts. La resolución de DNS no sabe qué hacer con localhost, la redefinición de que a lo mejor no tienen ningún efecto, y en el peor de confundir el infierno de la resolución.

¿Qué acerca de la --skip-name-resolve?

Esto también puede solucionar el problema, para una ligeramente diferente pero relacionado razón.

Sin esta opción de configuración, MySQL intentará resolver todas las de conexión de cliente de direcciones IP a un nombre de host a través de una PTR consulta DNS. Si su servidor MySQL ya está habilitado para el uso de IPv6, pero las conexiones son todavía de tomar un largo tiempo, puede ser debido a la inversa de DNS (PTR) de registro no está configurado correctamente.

La desactivación de la resolución de nombres va a solucionar este problema, pero tiene otras ramificaciones, en particular, que cualquier permisos de acceso configurado para utilizar un nombre DNS en el Host condición de error.

Si usted va a hacer esto, usted tendrá que configurar todas las subvenciones para el uso de direcciones IP en lugar de nombres.

19voto

Steve Mould Puntos 141

Puede ser que tu mysql intenta ejecutar rev-consulta de dns cada vez que se conecte? trate de añadir a mi.cnf, sección mysqld: skip-name-resolve.

13voto

Doug Puntos 214

Por lo general, cuando IPv6 está habilitado en el servidor de conexiones a MySQL usando localhost son extremadamente lentos.

Cambiar el servidor de mysql dirección en la secuencia de comandos a 127.0.0.1 soluciona el problema.

1voto

Xesau Puntos 11
mysql_connect("localhost", "root", "");

Bueno, es bastante obvio cuál es la razón. PHP realmente bueno en algunas cosas, pero no en una traducción directa de 'localhost' en '127.0.0.1'. Usted debe tratar de que, lo que realmente le baje su sitio web global de carga de la página el tiempo, ya sea porque tiene PHP de nuevo a partir de la comprobación de su archivo de HOSTS y qué no hacer para obtener la dirección IP real detrás de 'localhost'

EnMiMaquinaFunciona.com

EnMiMaquinaFunciona es una comunidad de administradores de sistemas en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros sysadmin, hacer tus propias preguntas o resolver las de los demás.

Powered by: