【问题标题】:500 error after a lot of mysql_query calls in php在 php 中调用大量 mysql_query 后出现 500 错误
【发布时间】:2010-11-18 03:19:07
【问题描述】:

我有一个 php 脚本,它遍历包含制表符分隔文件的文件夹,逐行解析它们并将数据插入 mysql 数据库。由于服务器上的安全限制,我无法使用 LOAD TABLE,而且我无权访问配置文件。该脚本可以很好地解析 1 或 2 个较小的文件,但是在处理多个大文件时出现 500 错误。似乎没有任何错误日志包含与错误有关的消息,至少我的托管服务提供商没有让我访问。下面是代码,我也愿意接受有关我需要做的替代方法的建议。最终我希望这个脚本每 30 分钟左右触发一次,插入新数据并在完成后删除文件。

编辑:在进行 Phil 建议的更改后,脚本仍然失败,但我现在在错误日志中显示以下消息“mod_fcgid:120 秒内读取数据超时”,看起来脚本正在超时,不知道我在哪里可以更改超时设置吗?

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

【问题讨论】:

    标签: php mysql explode fgets


    【解决方案1】:

    我要做的第一件事是使用准备好的语句(使用 PDO)。

    使用mysql_query() 函数,您正在为每个插入创建一个新语句,您可能会超出允许的限制。

    如果使用准备好的语句,则在数据库服务器上只创建和编译一条语句。

    例子

    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 服务器中配置的任何超时。

    【讨论】:

    • 看起来它现在可能会在失败之前处理更多行,但最后它仍然会在解析所有文件之前给出 500 错误。也就是说,我的错误日志现在包含一条有用的消息。 "mod_fcgid: read data timeout in 120 seconds" 快速谷歌搜索没有找到解决方案,但我会继续寻找。
    • 看起来可能是 Apache 对 CGI 脚本的超时。考虑到您想按计划运行此脚本,我将完全避免使用 Web 服务器,并使用 cron 或您的主机提供的任何调度服务通过 CLI 运行脚本。
    • 是的,我认为你是对的。谢谢。如果你把它作为答案,我会接受。
    猜你喜欢
    • 1970-01-01
    • 2012-10-24
    • 2016-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-05
    • 1970-01-01
    相关资源
    最近更新 更多