2010-11-18 7 views
2

Ich habe ein PHP-Skript, das durch einen Ordner mit tabulatorgetrennten Dateien, Parsen sie Zeile für Zeile und Einfügen der Daten in eine MySQL-Datenbank. Ich kann LOAD TABLE aufgrund von Sicherheitseinschränkungen auf meinem Server nicht verwenden und habe keinen Zugriff auf die Konfigurationsdateien. Das Skript funktioniert prima bei der Analyse von 1 oder 2 kleineren Dateien, aber wenn ich mit mehreren großen Dateien arbeite, bekomme ich einen Fehler von 500. Es scheint keine Fehlerprotokolle zu geben, die Nachrichten bezüglich des Fehlers enthalten, zumindest keine, auf die mein Hosting-Provider Zugriff hat. Unten ist der Code, ich bin auch offen für Vorschläge für alternative Möglichkeiten zu tun, was ich tun muss. Letztendlich möchte ich dieses Skript alle 30 Minuten oder so abfeuern, neue Daten einfügen und die Dateien löschen, wenn Sie fertig sind.500 Fehler nach einer Menge von mysql_query Anrufe in PHP

EDIT: Nach der Änderung Phil schlug vor, das Skript noch immer fehl, aber ich habe jetzt die folgende Meldung in meinem Fehlerprotokoll "mod_fcgid: Daten-Timeout in 120 Sekunden lesen", sieht aus wie das Skript Timeout ist, keine Ahnung wo Ich kann die Timeout-Einstellung ändern?

$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>"; 
} 

Antwort

1

Als erstes würde ich vorbereitete Anweisungen (mit PDO) verwenden.

Mit der Funktion mysql_query() erstellen Sie eine neue Anweisung für jede Einfügung, und Sie überschreiten möglicherweise das zulässige Limit.

Wenn Sie eine vorbereitete Anweisung verwenden, wird nur eine Anweisung erstellt und auf dem Datenbankserver kompiliert.

Beispiel

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>"; 
} 

Betrachtet man dieses Skript auf einem Zeitplan ausgeführt werden soll, würde ich den Web-Server vollständig vermeiden und das Skript über die CLI mit dem Cron oder was auch immer Scheduling-Dienst Ihres Host bietet laufen. Dies wird Ihnen helfen, jedes auf dem Webserver konfigurierte Timeout zu vermeiden.

+0

Es sieht so aus, als würde es mehr Zeilen verarbeiten, bevor es jetzt versagt, aber am Ende gibt es immer noch den Fehler 500, bevor es alle Dateien analysiert. Das heißt, mein Fehlerprotokoll enthält jetzt eine nützliche Nachricht. "mod_fcgid: Daten-Timeout in 120 Sekunden lesen" Eine schnelle Google-Suche hat keine Lösung ergeben, aber ich werde weiter suchen. –

+0

Sieht aus wie es ist wahrscheinlich Apache-Timeout für CGI-Skripte. Wenn Sie dieses Skript nach einem Zeitplan ausführen möchten, würde ich den Webserver vollständig vermeiden und das Skript über die Befehlszeilenschnittstelle ausführen, indem Sie Cron oder einen beliebigen Zeitplanungsdienst Ihres Hosts verwenden. – Phil

+0

Ja, ich denke du hast Recht. Vielen Dank. Wenn Sie das als Antwort angeben, werde ich es akzeptieren. –