Acabei de fazer uma nova instalação do XAMPP. Quando abri o PHPMyAdmin pela primeira vez, notei que era extremamente lento. Não fazia sentido que no localhost levasse quase 5 segundos para cada página abrir. Fiz um pequeno caso de teste para afastar a culpa do 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);
O script acima leva apenas cerca de 3 segundos para ser executado (embora tenha levado mais de 8 segundos para carregar na primeira vez que o executei).
Em seguida, para verificar se foi culpa do PDO, tentei usar mysql_connect
:
$con = mysql_connect("localhost", "root", "");
mysql_select_db("mysql", $con);
$result = mysql_query('SELECT host,user,password FROM user;');
Leva exatamente o tempo necessário para terminar.
Eu pensei que era culpa do PHP no começo, mas o código PHP e os arquivos estáticos são servidos mais rapidamente do que posso clicar em Atualizar. Testei o PHP executando este pequeno script:
header("Content-Type: text/plain");
for($i = 0; $i < 5000; $i++)
{
echo sha1(rand()) . "\n";
}
5.000 sha1
cálculos e a página ainda é exibida mais rapidamente do que posso atualizar minha janela.
Então eu achei que era culpa do MySQL. Mas, novamente, não foi preciso muito teste para descobrir que o MySQL está funcionando mais rápido do que eu preciso. Usando o cliente MySQL CLI, a consulta de seleção do usuário nem leva um tempo mensurável - é feita antes mesmo de eu deixar a tecla de retorno.
O problema deve ser a conexão do PHP ao MySQL - isso é o que eu pude argumentar. Eu posso encontrar muitas coisas sobre o PHP ser lento ou o MySQL lento, mas nada sobre o PHP + MySQL extremamente lento.
Obrigado a quem puder me ajudar a resolver isso!
Estou usando o XAMPP 1.8.0 para win32 ( Link para download )
Versão do PHP: 5.4.4
Versão do MySQL: 14.14
EDIT: Após o tempo, verifica-se que é a função de conexão que está demorando tanto:
$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);
Saída:
Tempo de conexão: 1.006148 Tempo da consulta: 0.000247
O que pode fazer com que o PHP gaste muito tempo se conectando ao banco de dados? O cliente CLI, HeidiSQL e MySQL Workbench se conectam instantaneamente
Respostas:
Pode ser que o seu mysql tente executar a consulta rev-dns sempre que você se conectar? tente adicionar ao my.cnf, seção mysqld: skip-name-resolve .
fonte
Isso foi tirado quase literalmente da minha resposta aqui , mas eu sei que nos desaprovamos em respostas somente para links no SO, então imagino que vocês também :-)
Se você está tendo esse problema e está usando uma versão do Windows anterior ao Windows 7, provavelmente esta não é a resposta para o seu problema.
Por que isso está acontecendo?
A causa desse problema é IPv4 vs IPv6.
Quando você usa um nome de host em vez de um endereço IP, o cliente MySQL executa primeiro uma
AAAA
pesquisa de host (IPv6) para o nome e tenta esse endereço primeiro se resolver com êxito o nome para um endereço IPv6. Se uma das etapas falhar (resolução de nome ou conexão), ela retornará ao IPv4, executando umaA
pesquisa e tentando este host.O que isso significa na prática é que, se a
localhost
pesquisa do IPv6 for bem-sucedida, mas o MySQL não estiver vinculado ao loopback do IPv6, será necessário aguardar um ciclo de tempo limite da conexão antes que ocorra o fallback do IPv4 e a conexão tenha êxito.Isso não foi um problema anterior ao Windows 7, porque a
localhost
resolução foi feita através do arquivo hosts e veio pré-configurada apenas127.0.0.1
- ela não veio com sua contraparte do IPv6::1
.Desde o Windows 7, no entanto, a
localhost
resolução está incorporada no resolvedor de DNS, pelos motivos descritos aqui . Isso significa que a pesquisa do IPv6 agora terá êxito - mas o MySQL não está vinculado a esse endereço IPv6, portanto a conexão falhará e você verá o atraso descrito nesta pergunta.Isso é bom. Apenas me diga como consertar já!
Você tem poucas opções. Olhando pela Internet, a "solução" geral parece ser o uso explícito do endereço IP, e não o nome, mas existem algumas razões para não fazer isso, tanto relacionadas à portabilidade, quanto sem dúvida importantes:
Se você mover seu script para outra máquina que suporte apenas IPv6, seu script não funcionará mais.
Se você mover seu script para um ambiente de hospedagem baseado em * nix, a string mágica
localhost
significaria que o cliente MySQL preferiria usar um soquete Unix se um estiver configurado, isso é mais eficiente que a conectividade baseada em loopback IPEles parecem muito importantes?
Eles não são. Você deve projetar seu aplicativo para que esse tipo de coisa seja definido em um arquivo de configuração. Se você mover seu script para outro ambiente, é provável que outras coisas também precisem ser configuradas.
Em resumo, usar o endereço IP não é a melhor solução, mas é provavelmente uma solução aceitável.
Então, qual é a melhor solução?
A melhor maneira seria alterar o endereço de ligação que o servidor MySQL usa. No entanto, isso não é tão simples quanto se pode gostar. Ao contrário do Apache, Nginx e quase todos os outros aplicativos de serviços de rede sãos já criados, o MySQL suporta apenas um único endereço de ligação, portanto, não é apenas o caso de adicionar outro. Felizmente, os sistemas operacionais suportam um pouco de mágica aqui, para que possamos permitir que o MySQL use IPv4 e IPv6 simultaneamente.
Você precisa estar executando o MySQL 5.5.3 ou posterior e iniciar o MySQL com o
--bind-address=
argumento de linha de comando. Você tem quatro opções de documentos , dependendo do que você deseja fazer:Aquele com quem você provavelmente está familiarizado e o que você provavelmente (efetivamente) está usando
0.0.0.0
,. Isso se liga a todos os endereços IPv4 disponíveis na máquina. Na verdade, isso provavelmente não é a melhor coisa a se fazer, mesmo que você não se importe com o IPv6, pois ele sofre os mesmos riscos de segurança que::
.Um endereço IPv4 ou IPv6 explícito (por exemplo
127.0.0.1
ou::1
para loopback). Isso liga o servidor a esse endereço e somente a esse endereço.A corda mágica
::
. Isso ligará o MySQL a todos os endereços da máquina, tanto os endereços de loopback quanto os da interface física, no modo IPv4 e IPv6. Isso é potencialmente um risco de segurança, apenas faça isso se você precisar do MySQL para aceitar conexões de hosts remotos.Use um endereço IPv6 mapeado para IPv4 . Esse é um mecanismo especial incorporado ao IPv6 para compatibilidade com versões anteriores durante a transição 4 -> 6, e permite a ligação a um endereço IPv4 específico e seu equivalente ao IPv6. É pouco provável que seja útil a você para algo que não seja o endereço de "loopback duplo"
::ffff:127.0.0.1
. Essa é provavelmente a melhor solução para a maioria das pessoas, vinculando apenas o loopback, mas permitindo conexões IPv4 e IPv6.Preciso modificar o arquivo hosts?
NÃO . Não modifique o arquivo hosts. O resolvedor de DNS sabe com o que fazer
localhost
, redefini-lo na melhor das hipóteses não terá efeito e, na pior das hipóteses, confundir o inferno com o resolvedor.Que tal
--skip-name-resolve
?Isso também pode resolver o problema, por um motivo relacionado, mas um pouco diferente.
Sem essa opção de configuração, o MySQL tentará resolver todos os endereços IP da conexão do cliente com um nome de host por meio de uma
PTR
consulta DNS. Se o seu servidor MySQL já estiver habilitado para usar o IPv6, mas as conexões ainda estiverem demorando muito, pode ser porque o registro DNS (PTR
) reverso não está configurado corretamente.Desabilitar a resolução de nomes corrigirá esse problema, mas ele tem outras ramificações, principalmente porque agora todas as permissões de acesso configuradas para usar um nome DNS na
Host
condição falharão.Se você fizer isso, precisará configurar todas as suas concessões para usar endereços IP em vez de nomes.
fonte
::1
. Infelizmente,::ffff:127.0.0.1
continuei me dando um atraso de 1 segundo (independentemente de usarskip-name-resolve
ou não), alguma idéia do porquê? (no Windows 8.1)Normalmente, quando o IPv6 está ativado nas conexões do servidor com o MySQL,
localhost
são extremamente lentos.Alterar o endereço do servidor mysql no script para
127.0.0.1
resolver o problema.fonte
localhost
que o resolvedor DNS para a razão que @DaveRandom ligada a: serverfault.com/questions/4689/...localhost
. Eu tive o mesmo problema de atraso para um endereço de servidor no formulárioxx.xxxx.xxxxx.xxxxx.com
. Depois que alterei o nome do servidor para o seu endereço IP, o problema desapareceu.Bem, é bastante óbvio qual é o motivo. PHP realmente bom em algumas coisas, mas não na tradução direta de 'localhost' para '127.0.0.1'. Você deve tentar isso, reduzirá muito o tempo de carregamento geral da página do site, porque impede o PHP de verificar seu arquivo HOSTS e o que não está fazendo para obter o endereço IP real atrás de 'localhost'
fonte
Adicionar esta linha ao seu arquivo hosts resolveu o problema para mim
Resposta detalhada pode ser encontrada neste tópico: /programming/13584360/php-with-mysql-is-slow
fonte
Você também pode eliminar a desaceleração da consulta fazendo um pequeno ajuste na sua variável de conexão db (que, esperançosamente, está em um arquivo separado dos scripts para portabilidade). Altere o valor do host para "127.0.0.1" em vez de "localhost". Isso ignora a longa pesquisa de DNS do host local.
Espero que isto ajude!
fonte