Ir para conteúdo

POWERED BY:

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

kmachado

Evitar que loop consuma o servidor?

Recommended Posts

Olá amigos

 

Eu tenho um script que execulta um while para fazer a atualização de registros em um banco de dados.

 

eu limitei o loop até dez registros, ok, no inicio ele tava atualizando os 10 registros numa boa, só que com o passar do tempo, toda vez que execulto o script, mesmo com o limit em 10, o loop vai dimuinuindo a repetiçao sendo que agora só ta girando 3 vezes, ou seja, apenas 3 registros são atualizados? O que pode ser isso, e como resolver.

Compartilhar este post


Link para o post
Compartilhar em outros sites

mostre o teu script, se não fica praticamente impossível de adivinharmos.

Compartilhar este post


Link para o post
Compartilhar em outros sites

mostre o teu script, se não fica praticamente impossível de adivinharmos.

 


<?php


if(!file_exists('reral_1.php')){
      		header("Location: ../../index.php");
	exit;
}



require"../../conexao.php";
include_once('../simple_html_dom.php');

$sql = mysql_query("select * from anuncio where permissao != 'S' limit 10");
$sql2 = mysql_query("select * from anuncio where permissao != 'S'");
$qtd_n = mysql_num_rows($sql2);

while($registro = mysql_fetch_array($sql)){


$cod = $registro['codigo'];
$quarto = $registro['n_quartos'];

$html = file_get_html('http://www.siteexterno.com.br?id='.$cod');

foreach($html->find('.description') as $descricao) {

$troca = array("Ã" , "Ç", "Â", "²", "Ã", "Ã", "Ó", "É", "°");
$replace = array("Í", "Ç", "Â", "²", "Ã", "Á", "Ó", "É", "°");
  	$descricao = strip_tags($descricao);
$desc = str_replace($troca, $replace, $descricao);
$desc = trim($desc);
$desc = mysql_real_escape_string($desc);



$busca_suite = preg_split("/[sS][uU][iíIÍ][tT][eE]/", $desc);
$num = count($busca_suite);
$busca_suite = trim($busca_suite[0]);

if($num > 1 && $quarto != 0){
	$busca_qtd = explode(" ", $busca_suite);
	$qtd_suite  = $busca_qtd[count($busca_qtd)-1];
	if($qtd_suite == 'UMA'){
		$qtd_suite = 1;
	}
	$qtd_suite = (int)$qtd_suite;
	$quarto = $quarto - $qtd_suite;
}
else{
	$qtd_suite = 0;
}

$sql_altera = mysql_query("UPDATE anuncio SET  descricao = '$desc', n_quartos = '$quarto', n_suite = '$qtd_suite', permissao = 'S' WHERE codigo = '$cod'") or die (mysql_error());





}


}


echo '.$qtd_n.'<br/>	
<a href="captura_reralfase2.php">fazer novamente</a>';

unset($qtd_n);
unset($qtd_suite);
unset($sql_altera);
unset($quarto);
unset($busca_suite);
unset($num);
unset($sql);
unset($sql2);
unset($qtd_n);
unset($troca);
unset($replace);
unset($desc);
unset($busca_qtd);
unset($sql_altera);
unset($descricao);
unset($registro);
unset($html);



?>


Compartilhar este post


Link para o post
Compartilhar em outros sites

cara... essa rotina que você faz, é para "corrigir" erros de INSERT, ne?!

 

Corrija o INSERT logo..

Compartilhar este post


Link para o post
Compartilhar em outros sites

cara... essa rotina que você faz, é para "corrigir" erros de INSERT, ne?!

 

Corrija o INSERT logo..

 

tbm, mas principalmente para achar pedaços de informações dentro da string.

 

exemplo:

eu recebo uma string "vende-se casa com 3 suítes" então eu preciso achar apenas o '3' e inserir no banco de dados

Compartilhar este post


Link para o post
Compartilhar em outros sites

Isso! mas faz isso na hora do INSERT. Pois ai, você vai rodar 1 coisa de cada vez.

 

E não ter que ficar varrendo o banco, corrigindo informações.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Isso! mas faz isso na hora do INSERT. Pois ai, você vai rodar 1 coisa de cada vez.

 

E não ter que ficar varrendo o banco, corrigindo informações.

 

:ermm: humm... mas como procederia então, fale mais a respeito

 

e com relação ao consumo do servidor

 

Caraca... deu uma mensagem aqui "MySQL server has gone away"

Compartilhar este post


Link para o post
Compartilhar em outros sites
MySQL server has gone away

estourou o limite de conexões ou querys...

 

qual versão do mysql está usando ?

 

 

outra questão é, faça conforme o Bruno sugeriu, que é o correto..

 

agora no seu caso, para corrigir os dados, dei uma lida rápida no script que postou.

 

pelo que entendi é possível fazer isso usando somente SQL.. não tem necessidade de usar o php.

Compartilhar este post


Link para o post
Compartilhar em outros sites

E se você executar todos os updates com uma só consulta?

 

No loop, apenas concatene as strings

$sql_altera .= "UPDATE anuncio SET  descricao = '$desc', n_quartos = '$quarto', n_suite = '$qtd_suite', permissao = 'S' WHERE codigo = '$cod';\n";

 

Fora do loop, execute tudo de uma vez:

$altera = mysql_query($sql_altera) or die (mysql_error());

Compartilhar este post


Link para o post
Compartilhar em outros sites

aquele trecho do str_replace, strip_tags, etc... é possível criar funções equivalentes no próprio mysql

Compartilhar este post


Link para o post
Compartilhar em outros sites

Eu tentei assim mas está dando erro de sintaxe. Acho que é pq o comando UPDATE está se repetindo, mas tbm não sei como ficaria.

 

oque ta acontecendo é que as variaveis estão morrendo dentro do loop foreach. assim o update fica vazio com eu arranjo isso?

Compartilhar este post


Link para o post
Compartilhar em outros sites

Coloque o nome da tag que tem a classe 'description'. Se for um DIV, coloque:

$html->find('div.description')

 

Isso talvez melhore a velocidade...

 

 

Quanto às variáveis aí, tem que debugar.

O que eu acho que está acontecendo é que alguns desses caracteres mal encodados está passando, você não previu eles no str_replace e eles estão passando direto para o seu SQL, e isso pode estar causando erro. Tente usar mysql_escape_string.

 

Mas é bom debugar também:

 

Instale o Xdebug se ainda não o tiver.

 

Antes do foreach, coloque:

echo "<h1>Debug</h1>";
$i = 0;

 

 

comente a linha que tem $sql_altera e coloque o seguinte antes do fechamento do foreach:

echo "<hr />I: {$i}<br />\n";
"$desc$quarto$qtd_suite$cod
var_dump();
$i++;

Compartilhar este post


Link para o post
Compartilhar em outros sites

outra dica,

 

algo que consome muito do servidor, principalmente hd, são os arquivos de log

 

no arquivo de configuração do mysql, se possuir acesso, configure-o para criar rotatividade num período mais curto.

 

exemplo

log-bin=mysql-bin
expire_logs_days = 10

 

caso esteja no linux, no syslog, desative o log de processos desnecessários.

mantenha no nível critico

Compartilhar este post


Link para o post
Compartilhar em outros sites

Galera!

 

depois de vários testes :upset:

O que eu percebi foi que na verdade as variáveis do foreach estavam vazias porque o loop foreach não estava "girando", dessa forma elas não estava sendo "alimentadas" com as informações, a questão é: por que o foreach não girou.

 

hipótese: como o foreach depende da array $html que busca seu conteudo em um servidor externo, o que eu acho é que o servidor externo "percebeu" muitas requisições simultaneas e limitou o acesso.

 

Como eu percebi isso: o que eu percebi é que no inicio quando eu usei o script o foreach girava 10 x, exatamente como o while (isso porque a array $html só tem um elemento) que está limtado a 10 registros, mas a medida que eu "disparava" o script o while continuava rodando as 10X mas o foreach diminuia gradativamente o giro, até o memento que não girou mais(mesmo com o while girando normalmente). Então passei umas duas horas sem executar o script, após duas horas eu execultei o script novamente e o foreach voltou a girar 10x de novo, e toda vez que execulto o script seguidamente, o foreach vai gradadivamente reduzindo o número de giros.

Compartilhar este post


Link para o post
Compartilhar em outros sites

há algum motivo específico para continuar fazendo esses laços de repetião com o php ?

 

isso que está tentando fazer pode ser feito com 2 ou 3 linhas de comando sql sem uso de php e tampouco sem precisar fazer loop algum.. dependendo da quantidade de registros, a excução terminará em alguns segundos ou até menos que 1 segundo.

 

após corrigir, deve fazer tratamento das strings no momento do insert conforme já sugerido;

Compartilhar este post


Link para o post
Compartilhar em outros sites

A função file_get_html usa file_get_contents para pegar o conteúdo da página externa. Essa função retorna false em caso de erro, então você deve verificar isso e armazenar os códigos que não obtiveram sucesso em um array.

 

---

Obs. à parte: O ideal seria usar cURL, pois aí você poderia verificar se a resposta é um 200 (OK), um 404 (Not found),um Forbidden (403), etc.

---

 

 

Seria mais ou menos o seguinte:

 

 

 

Coloque isso antes do loop while:

$context = array(
     'http'=>array(
       'method'=>"GET",
       'header'=>"Accept-language: en\r\n" .
                 "User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; es-AR; rv:1.9.2.23) Gecko/20110921 Ubuntu/10.10 (maverick) Firefox/3.6.23"
     )
);

// Array onde serão armazenados os códigos que falharam
$fail_cods = array();

 

Dentro do while, no lugar de file_get_html, use o seguinte:

$content = file_get_contents('http://www.siteexterno.com.br?id=' . $cod, false, $context);

if (!$content) {
 $fail_cods []= $cod;
 sleep(1); // OPCIONAL: Esperar 1 segundo para continuar?
 continue;
}

// Essa função é do Simple DOM HTML, serve para processar a partir de uma string, ao invés de carregar o arquivo.
$html = str_get_html($content);

// não se esqueça de usar mysql_escape_string antes de colocar as variáveis no SQL

 

Após terminar o laço foreach, use o seguinte para limpar a memória:

$html->clear();

 

Observe que pode haver algum erro de sintaxe no código acima pois eu digitei aqui direto no campo de postagem do fórum e não verifiquei a sintaxe.

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.