2010-11-18 26 views
2

J'ai un script PHP qui traverse un dossier contenant des fichiers délimités par des tabulations, en les analysant ligne par ligne et en insérant les données dans une base de données mysql. Je ne peux pas utiliser LOAD TABLE en raison des restrictions de sécurité sur mon serveur et je n'ai pas accès aux fichiers de configuration. Le script fonctionne très bien en analysant 1 ou 2 fichiers plus petits mais lorsque je travaille avec plusieurs fichiers volumineux, je reçois une erreur de 500. Il ne semble pas y avoir de journaux d'erreurs contenant des messages relatifs à l'erreur, au moins aucun que mon fournisseur d'hébergement me donne accès. Ci-dessous le code, je suis également ouvert aux suggestions pour d'autres façons de faire ce que je dois faire. En fin de compte, je veux que ce script se déclenche toutes les 30 minutes environ, en insérant de nouvelles données et en supprimant les fichiers lorsque vous avez terminé. EDIT: Après avoir fait les changements que Phil a suggéré, le script échoue toujours mais j'ai maintenant le message suivant dans mon journal d'erreurs "mod_fcgid: lire le timeout des données en 120 secondes", ressemble au script Je peux changer le paramètre de délai d'expiration?500 erreur après beaucoup d'appels mysql_query dans php

$folder = opendir($dir); 
    while (($file = readdir($folder)) !== false) { 
     $filepath = $dir . "/" . $file; 

     //If it is a file and ends in txt, parse it and insert the records into the db 
     if (is_file($filepath) && substr($filepath, strlen($filepath) - 3) == "txt") { 
      uploadDataToDB($filepath, $connection); 
     } 
    } 

function uploadDataToDB($filepath, $connection) { 
    ini_set('display_errors', 'On'); 
    error_reporting(E_ALL); 
    ini_set('max_execution_time', 300); 

    $insertString = "INSERT INTO dirty_products values("; 

    $count = 1; 

    $file = @fopen($filepath, "r"); 

    while (($line = fgets($file)) !== false) { 
     $values = ""; 
     $valueArray = explode("\t", $line); 
     foreach ($valueArray as $value) { 
      //Escape single quotes 
      $value = str_replace("'", "\'", $value); 
      if ($values != "") 
       $values = $values . ",'" . $value . "'"; 
      else 
       $values = "'" . $value . "'"; 
     } 

     mysql_query($insertString . $values . ")", $connection); 
     $count++; 
    } 

    fclose($file); 

    echo "Count: " . $count . "</p>"; 
} 

Répondre

1

La première chose que je ferais est d'utiliser des instructions préparées (en utilisant PDO). Avec la fonction mysql_query(), vous créez une nouvelle instruction pour chaque insertion et vous pouvez dépasser la limite autorisée.

Si vous utilisez une instruction préparée, une seule instruction est créée et compilée sur le serveur de base de données.

Exemple

function uploadDataToDB($filepath, $connection) { 
    ini_set('display_errors', 'On'); 
    error_reporting(E_ALL); 
    ini_set('max_execution_time', 300); 

    $db = new PDO(/* DB connection parameters */); 
    $stmt = $db->prepare('INSERT INTO dirty_products VALUES (
         ?, ?, ?, ?, ?, ?)'); 
    // match number of placeholders to number of TSV fields 

    $count = 1; 

    $file = @fopen($filepath, "r"); 

    while (($line = fgets($file)) !== false) { 
     $valueArray = explode("\t", $line); 
     $stmt->execute($valueArray); 
     $count++; 
    } 

    fclose($file); 
    $db = null; 

    echo "Count: " . $count . "</p>"; 
} 

Considérant que vous voulez exécuter ce script sur un calendrier, il faut éviter le serveur web entièrement et exécutez le script via la CLI en utilisant cron ou quel que soit le service planification de votre hôte fournit. Cela vous aidera à éviter tout délai d'attente configuré sur le serveur Web.

+0

Il semble que l'on pourrait traiter plus de lignes avant d'échouer maintenant, mais à la fin il donne toujours l'erreur 500 avant d'avoir fini d'analyser tous les fichiers. Cela dit, mon journal des erreurs contient maintenant un message utile. "mod_fcgid: lire le timeout des données en 120 secondes" Une recherche rapide sur google n'a pas trouvé de solution, mais je continuerai à chercher. –

+0

On dirait que c'est probablement le délai d'Apache pour les scripts CGI. Étant donné que vous voulez exécuter ce script selon un calendrier, j'éviterais complètement le serveur Web et exécuterais le script via l'interface CLI en utilisant cron ou tout autre service de planification fourni par votre hôte. – Phil

+0

Ouais je pense que tu as raison. Merci. Si vous mettez cela comme réponse, je l'accepterai. –