Устранение ошибок «сервер MySQL исчез» - PullRequest
16 голосов
/ 31 декабря 2011

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

Программа-обходчик работает нормально, когда количество ссылок для сканирования небольшое (около 40 URL-адресов), но после этого числа появляется сообщение об ошибке «Сервер MySQL исчез».

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

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

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

Ответы [ 5 ]

13 голосов
/ 31 декабря 2011

Вы можете быть склонны решить эту проблему, "пингуя" сервер mysql перед запросом. Это плохая идея. Подробнее о том, почему, проверьте этот пост SO: Должен ли я пинговать сервер 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
                }
            }
        }
    }
}
4 голосов
/ 31 декабря 2011

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

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

0 голосов
/ 01 января 2012

Ну, это то, что я делаю сейчас, основываясь на предложении 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 и т. д.Есть ли способ пропустить те URL, содержащие эти расширения.Я использую preg_match и дал pdf и doc для соответствия.Тем не менее, я хочу, чтобы функция пропускала все ссылки, содержащие расширения, такие как mp3, pdf и т. Д. Возможно ли это?

0 голосов
/ 31 декабря 2011

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

Кроме того, как вы используете ручку? Возможно ли, что он совершил ошибку и «ушел» по этой причине?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...