Устранение ошибок "сервер MySQL ушел"

Я написал код на PHP, который возвращает html-контент из доменов .edu. Здесь приводится краткое введение: Ошибки в отношении веб-искателя в PHP

Искатель отлично работает, когда количество ссылок на обход небольших (около 40 URL-адресов), но после этого числа я получаю сообщение "сервер MySQL ушел".

Я храню html-содержимое как longtext в таблицах MySQL, и я не понимаю, почему ошибка появляется после как минимум 40-50 вставок.

Любая помощь в этом отношении высоко ценится.

Обратите внимание, что я уже изменил wait_timeout и max_allowed_packet для размещения моих запросов и php-кода, и теперь я не знаю, что делать. Пожалуйста, помогите мне в этом отношении.

Ответ 1

Возможно, вы склонны справляться с этой проблемой, "пинговая" сервер mysql перед запросом. Это плохая идея. Для получения дополнительной информации о том, почему, проверьте это сообщение SO: Должен ли я ping сервер mysql перед каждым запросом?

Лучший способ справиться с проблемой - обернуть запросы внутри блоков 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
                }
            }
        }
    }
}

Ответ 2

У меня есть другой ответ, который касается того, что, по моему мнению, является аналогичной проблемой, и для этого потребуется аналогичный ответ. В принципе, вы можете использовать функцию 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.
}

Ответ 3

Я столкнулся с ошибкой "Ошибка сервера Mysql" при использовании Mysql connector 5.X, заменив dll на последнюю версию, решив проблему.

Ответ 4

Вы открываете одно соединение с БД и повторно используете его? Возможно ли, что это простой тайм-аут? Вам может быть лучше, если открыть новое соединение с БД для каждой операции чтения/записи (IE contact.edu, получить текст, открыть БД, написать текст, закрыть db, повторить).

Также как вы используете ручку? Возможно ли, что он ошибся и "ушел" по этой причине?

Ответ 5

Ну, вот что я делаю сейчас на основе предложения 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);
        }
    }
}

Итак, как только запрос не будет выполнен, script пропустит его, но будет убедиться, что соединение восстановлено.

Однако мой веб-искатель сбой, когда встречаются файлы, такие как .jpg,.bmp,.pdf и т.д. Есть ли способ пропустить эти URL-адреса, содержащие эти расширения. Я использую preg_match и дал pdf и doc для соответствия. Тем не менее, я хочу, чтобы функция пропускала все ссылки, содержащие расширения, такие как mp3, pdf и т.д. Возможно ли это?