解决“MySQL服务器已经消失”的错误

时间:2011-12-31 17:53:07

标签: mysql connection phpmyadmin php

我在PHP中编写了一些代码,用于返回.edu域中的html内容。这里给出简要介绍:Errors regarding Web Crawler in PHP

当抓取的链接数量很少(大约40个URL)时爬虫工作正常,但是在这个数字之后我得到“MySQL服务器已经消失”错误。

我将html内容存储为MySQL表中的longtext,我不知道为什么错误在至少40-50次插入后到达。

对此方面的任何帮助表示高度赞赏。

请注意我已经更改了wait_timeout和max_allowed_pa​​cket来容纳我的查询和php代码,现在我不知道该怎么做。请帮助我。

5 个答案:

答案 0 :(得分:12)

您可能倾向于通过在查询之前“ping”mysql服务器来处理此问题。这是一个坏主意。有关原因的更多信息,请查看此SO帖子:Should I ping mysql server before each query?

处理此问题的最佳方法是在try/catch块中包装查询并捕获任何数据库异常,以便您可以适当地处理它们。这在长时间运行和/或守护程序类型的脚本中尤为重要。所以,这是一个非常基本的例子,使用“连接管理器”来控制对数据库连接的访问​​:

class DbPool {

    private $connections = array();

    function addConnection($id, $dsn) {
        $this->connections[$id] = array(
            'dsn' => $dsn,
            'conn' => null
        );
    }

    function getConnection($id) {
        if (!isset($this->connections[$id])) {
            throw new Exception('Invalid DB connection requested');
        } elseif (isset($this->connections[$id]['conn'])) {
            return $this->connections[$id]['conn'];
        } else {
            try {
                // for mysql you need to supply user/pass as well
                $conn = new PDO($dsn);

                // Tell PDO to throw an exception on error
                // (like "MySQL server has gone away")
                $conn->setAttribute(
                    PDO::ATTR_ERRMODE,
                    PDO::ERRMODE_EXCEPTION
                );
                $this->connections[$id]['conn'] = $conn;

                return $conn;
            } catch (PDOException $e) {
                return false;
            }
        }
    }

    function close($id) {
        if (!isset($this->connections[$id])) {
            throw new Exception('Invalid DB connection requested');
        }
        $this->connections[$id]['conn'] = null;
    }


}


class Crawler {

    private $dbPool;

    function __construct(DbPool $dbPool) {
        $this->dbPool = $dbPool;
    }

    function crawl() {
        // craw and store data in $crawledData variable
        $this->save($crawledData);
    }

    function saveData($crawledData) {
        if (!$conn = $this->dbPool->getConnection('write_conn') {
            // doh! couldn't retrieve DB connection ... handle it
        } else {
            try {
                // perform query on the $conn database connection
            } catch (Exception $e) {
                $msg = $e->getMessage();
                if (strstr($msg, 'MySQL server has gone away') {
                    $this->dbPool->close('write_conn');
                    $this->saveData($val);
                } else {
                    // some other error occurred
                }
            }
        }
    }
}

答案 1 :(得分:4)

我有another answer处理我认为类似的问题,它需要一个类似的答案。基本上,您可以使用mysql_ping()函数在插入之前测试连接。在MySQL 5.0.14之前,mysql_ping()会自动重新连接服务器,但现在您必须构建自己的重新连接逻辑。类似的东西对你有用:

function check_dbconn($connection) {
    if (!mysql_ping($connection)) {
        mysql_close($connection);
        $connection = mysql_connect('server', 'username', 'password');
        mysql_select_db('db',$connection);
    } 
    return $connection;
}

foreach($array as $value) {
    $dbconn = check_dbconn($dbconn);
    $sql="insert into collected values('".$value."')";
    $res=mysql_query($sql, $dbconn);
    //then some extra code.
}

答案 2 :(得分:2)

我在使用Mysql connector 5.X时遇到“Mysql服务器已消失”错误,将dll替换为最后一个版本解决了问题。

答案 3 :(得分:0)

您是否打开了一个数据库连接并重新使用它?它有可能是一个简单的超时吗?通过为每个读/写操作(IE联系人.edu,获取文本,打开数据库,写文本,关闭数据库,重复)打开新的数据库连接可能会更好。

另外你是如何使用手柄的?它是否有可能出现错误并因此而“消失”?

答案 4 :(得分:0)

那么这就是我现在根据rdlowrey的建议做的事情,我想这也是对的。

public function url_db_html($sourceLink = NULL, $source) {
    $source = mysql_real_escape_string($source);

    $query = "INSERT INTO html (id, sourceLink, sourceCode)
            VALUES (NULL,('$sourceLink') , ('$source'))";

    try {
        if(mysql_query($query, $this->connection)==FALSE) {
            $msg = mysql_errno($this->connection) . ": " . mysql_error($this->connection);
            throw new DbException($msg);
        }           
    } catch (DbException $e) {
        echo "<br><br>Catched!!!<br><br>";
        if(strstr($e->getMessage(), 'MySQL server has gone away')) {
            $this->connection = mysql_connect("localhost", "root", "");
            mysql_select_db("crawler1", $this->connection);
        }
    }
}

因此,一旦查询无法执行,脚本将跳过它,但会确保重新建立连接。

但是,当遇到.jpg,.bmp,.pdf等文件时,我的网络抓取工具会崩溃。有没有办法跳过包含这些扩展名的网址。我正在使用preg_match,并提供了pdf和doc来匹配。但我希望函数跳过所有包含扩展名的链接,如mp3,pdf等。这可能吗?