2

タブ区切りファイルを含むフォルダーをステップスルーし、それらを行ごとに解析し、データをmysqlデータベースに挿入するphpスクリプトがあります。サーバーのセキュリティ制限のために LOAD TABLE を使用できず、構成ファイルにアクセスできません。スクリプトは、1 つまたは 2 つの小さなファイルを解析するのに問題なく動作しますが、複数の大きなファイルを処理すると 500 エラーが発生します。エラーに関連するメッセージを含むエラー ログはないようです。少なくとも、ホスティング プロバイダーがアクセスを許可したものはありません。以下はコードです。私は、私がする必要があることを別の方法で行うための提案も受け付けています。最終的には、このスクリプトを約 30 分ごとに起動して、新しいデータを挿入し、終了したらファイルを削除するようにしたいと考えています。

編集: フィルが提案した変更を行った後、スクリプトはまだ失敗しますが、エラーログに次のメッセージが表示されるようになりました "mod_fcgid: read data timeout in 120 seconds", スクリプトがタイムアウトしているように見える.タイムアウト設定?

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

1 に答える 1

1

最初に行うことは、準備済みステートメントを使用することです (PDO を使用)。

関数を使用して、mysql_query()すべての挿入に対して新しいステートメントを作成しているため、許可されている制限を超えている可能性があります。

プリペアド ステートメントを使用する場合、1 つのステートメントのみが作成され、データベース サーバー上でコンパイルされます。

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

このスクリプトをスケジュールに従って実行することを考慮して、Web サーバーを完全に避け、cron またはホストが提供するスケジュール サービスを使用して CLI 経由でスクリプトを実行します。これにより、Web サーバーで構成されたタイムアウトを回避できます。

于 2010-11-18T03:47:10.693 に答える