Intereting Posts
Как отобразить или просмотреть загруженное изображение после отправки на PHP без сохранения базы данных? Как округлить до ближайшей тысячи? Как суммировать N количество времени (формат ЧЧ: ММ)? передать переменную javascript в php mysql select query Как изменить порядок сообщений по количеству просмотров, а не по дате в wordpress Переместить значение атрибута title в значение атрибута класса в HTML-коде file_get_contents с включенной информацией о хешах PHP SoapClient __getFunctions () возвращает типы UNKNOWN Является ли php-сессия неизменной от пользователя? Исключено исключение «PPConnectionException» в адаптивном платежном платежном платеже PayPal Создание пользовательских конечных точек WordPress fgetcsv не корректно считывает файл csv, который сохраняется в системе linux php: поиск электронной почты, которая поддерживает очередь сообщений Навигация по ajax не работает после перезаписи htaccess Как отслеживать, где настройки umask php5-fpm исходят из ubuntu

PDO: сервер MySQL ушел

У меня есть сценарий, который выполняет много ночной работы в ночное время.

Он использует подготовленный PDO оператор, который выполняется в цикле.

Первые несколько работают нормально, но потом я добираюсь до точки, где все они терпят неудачу с ошибкой: «Сервер MySQL ушел».

Мы запускаем MySQL 5.0.77.

Версия PHP 5.2.12

Остальная часть сайта работает нормально.

Solutions Collecting From Web of "PDO: сервер MySQL ушел"

В.5.2.9. В сервере MySQL ушел раздел руководства MySQL содержит список возможных причин этой ошибки.

Может быть, вы находитесь в одной из таких ситуаций? – Особенно учитывая, что вы выполняете длительную операцию, точка wait_timeout может быть интересной …

Скорее всего, вы отправили пакет на сервер, длина которого превышает максимально допустимый пакет.

Когда вы пытаетесь вставить BLOB, который превышает максимальный размер пакета вашего сервера, даже на локальном сервере вы увидите, что «сервер MySQL ушел» на стороне клиента, и «Ошибка 1153» Получил пакет, превышающий «max_allowed_packet» байты в журнал сервера (если включена регистрация ошибок). Чтобы исправить это, вам нужно решить, что такое размер самого большого BLOB, который вы когда-либо вставляете, и установите max_allowed_packet в my.ini соответственно, например:

 [mysqld] ... max_allowed_packet = 200M ... 

У меня была та же проблема, когда администрация сервера хостинга убивает соединение, если есть тайм-аут.

Поскольку я использовал запрос в большей части, я написал код, который вместо использования класса PDO мы можем включить ниже класс и заменить имя класса на «ConnectionManagerPDO». Я просто завернул класс PDO.

 final class ConnectionManagerPDO { private $dsn; private $username; private $passwd; private $options; private $db; private $shouldReconnect; const RETRY_ATTEMPTS = 3; public function __construct($dsn, $username, $passwd, $options = array()) { $this->dsn = $dsn; $this->username = $username; $this->passwd = $passwd; $this->options = $options; $this->shouldReconnect = true; try { $this->connect(); } catch (PDOException $e) { throw $e; } } /** * @param $method * @param $args * @return mixed * @throws Exception * @throws PDOException */ public function __call($method, $args) { $has_gone_away = false; $retry_attempt = 0; try_again: try { if (is_callable(array($this->db, $method))) { return call_user_func_array(array($this->db, $method), $args); } else { trigger_error("Call to undefined method '{$method}'"); /* * or * * throw new Exception("Call to undefined method."); * */ } } catch (\PDOException $e) { $exception_message = $e->getMessage(); if ( ($this->shouldReconnect) && strpos($exception_message, 'server has gone away') !== false && $retry_attempt <= self::RETRY_ATTEMPTS ) { $has_gone_away = true; } else { /* * What are you going to do with it... Throw it back.. FIRE IN THE HOLE */ throw $e; } } if ($has_gone_away) { $retry_attempt++; $this->reconnect(); goto try_again; } } /** * Connects to DB */ private function connect() { $this->db = new PDO($this->dsn, $this->username, $this->passwd, $this->options); /* * I am manually setting to catch error as exception so that the connection lost can be handled. */ $this->db->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION ); } /** * Reconnects to DB */ private function reconnect() { $this->db = null; $this->connect(); } } 

Тогда использование может начать использовать вышеуказанный класс, как и в PDO.

 try { $db = new ConnectionManagerPDO("mysql:host=localhost;dbname=dummy_test", "root", ""); $query = $db->query("select * from test"); $query->setFetchMode(PDO::FETCH_ASSOC); } catch(PDOException $e){ /* handle the exception throw in ConnectionManagerPDO */ } 

Попробуйте использовать PDO::setAttribute(PDO::ATTR_EMULATE_PREPARES, true) на экземплярах вашего модуля. Не знаю, что это поможет, но без данных журнала все, что я получил.

Вероятно, что ваше соединение было убито (например, wait_timeout или другой поток, выдающий команду KILL), сервер разбился или вы каким-то образом нарушили протокол mysql.

Последнее, вероятно, будет ошибкой в ​​PDO, что весьма вероятно, если вы используете подготовленные на сервере заявления или многорезультаты (подсказка: Do not)

Крушение сервера необходимо будет исследовать; посмотрите журналы сервера.

Если вы все еще не знаете, что происходит, используйте сетевой упаковщик (например, tcpdump), чтобы выгрузить содержимое соединения.

Вы также можете включить общий журнал запросов – но делайте это очень осторожно в процессе производства.

Nathan H, ниже – это php-класс для повторного подключения pdo + пример использования кода. Скриншот прилагается.

 <?php # set errors reporting level error_reporting(E_ALL ^ E_NOTICE ^ E_WARNING); # set pdo connection include('db.connection.pdo.php'); /* # this is "db.connection.pdo.php" content define('DB_HOST', 'localhost'); define('DB_NAME', ''); define('DB_USER', ''); define('DB_PWD', ''); define('DB_PREFIX', ''); define('DB_SHOW_ERRORS', 1); # connect to db try { $dbh = new PDO('mysql:host='.DB_HOST.';dbname='.DB_NAME, DB_USER, DB_PWD); $dbh->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC); $dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, TRUE); $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); } catch(PDOException $e) { # echo $e->getMessage()."<br />"; # exit; exit("Site is temporary unavailable."); # } */ $reconnection = new PDOReconnection($dbh); $reconnection->getTimeout(); echo $dbh->query('select 1')->fetchColumn(); echo PHP_EOL; echo 'sleep 10 seconds..'.PHP_EOL; sleep(10); $dbh = $reconnection->checkConnection(); echo $dbh->query('select 1')->fetchColumn(); echo PHP_EOL; echo 'sleep 35 seconds..'.PHP_EOL; sleep(35); $dbh = $reconnection->checkConnection(); echo $dbh->query('select 1')->fetchColumn(); echo PHP_EOL; echo 'sleep 55 seconds..'.PHP_EOL; sleep(55); $dbh = $reconnection->checkConnection(); echo $dbh->query('select 1')->fetchColumn(); echo PHP_EOL; echo 'sleep 300 seconds..'.PHP_EOL; sleep(300); $dbh = $reconnection->checkConnection(); echo $dbh->query('select 1')->fetchColumn(); echo PHP_EOL; # ************************************************************************************************* # Class for PDO reconnection class PDOReconnection { private $dbh; # constructor public function __construct($dbh) { $this->dbh = $dbh; } # ************************************************************************************************* # get mysql variable "wait_timeout" value public function getTimeout() { $timeout = $this->dbh->query('show variables like "wait_timeout"')->fetch(); # print_r($timeout); echo '========================'.PHP_EOL.'mysql variable "wait_timeout": '.$timeout['Value'].' seconds.'.PHP_EOL.'========================'.PHP_EOL; } # ************************************************************************************************* # check mysql connection public function checkConnection() { try { $this->dbh->query('select 1')->fetchColumn(); echo 'old connection works..'.PHP_EOL.'========================'.PHP_EOL; } catch (PDOException $Exception) { # echo 'there is no connection.'.PHP_EOL; $this->dbh = $this->reconnect(); echo 'connection was lost, reconnect..'.PHP_EOL.'========================'.PHP_EOL; } return $this->dbh; } # ************************************************************************************************* # reconnect to mysql public function reconnect() { $dbh = new PDO('mysql:host=' . DB_HOST . ';dbname=' . DB_NAME, DB_USER, DB_PWD); $dbh->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC); $dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, TRUE); $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); return $dbh; } } # /Class for PDO reconnection # ************************************************************************************************* в <?php # set errors reporting level error_reporting(E_ALL ^ E_NOTICE ^ E_WARNING); # set pdo connection include('db.connection.pdo.php'); /* # this is "db.connection.pdo.php" content define('DB_HOST', 'localhost'); define('DB_NAME', ''); define('DB_USER', ''); define('DB_PWD', ''); define('DB_PREFIX', ''); define('DB_SHOW_ERRORS', 1); # connect to db try { $dbh = new PDO('mysql:host='.DB_HOST.';dbname='.DB_NAME, DB_USER, DB_PWD); $dbh->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC); $dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, TRUE); $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); } catch(PDOException $e) { # echo $e->getMessage()."<br />"; # exit; exit("Site is temporary unavailable."); # } */ $reconnection = new PDOReconnection($dbh); $reconnection->getTimeout(); echo $dbh->query('select 1')->fetchColumn(); echo PHP_EOL; echo 'sleep 10 seconds..'.PHP_EOL; sleep(10); $dbh = $reconnection->checkConnection(); echo $dbh->query('select 1')->fetchColumn(); echo PHP_EOL; echo 'sleep 35 seconds..'.PHP_EOL; sleep(35); $dbh = $reconnection->checkConnection(); echo $dbh->query('select 1')->fetchColumn(); echo PHP_EOL; echo 'sleep 55 seconds..'.PHP_EOL; sleep(55); $dbh = $reconnection->checkConnection(); echo $dbh->query('select 1')->fetchColumn(); echo PHP_EOL; echo 'sleep 300 seconds..'.PHP_EOL; sleep(300); $dbh = $reconnection->checkConnection(); echo $dbh->query('select 1')->fetchColumn(); echo PHP_EOL; # ************************************************************************************************* # Class for PDO reconnection class PDOReconnection { private $dbh; # constructor public function __construct($dbh) { $this->dbh = $dbh; } # ************************************************************************************************* # get mysql variable "wait_timeout" value public function getTimeout() { $timeout = $this->dbh->query('show variables like "wait_timeout"')->fetch(); # print_r($timeout); echo '========================'.PHP_EOL.'mysql variable "wait_timeout": '.$timeout['Value'].' seconds.'.PHP_EOL.'========================'.PHP_EOL; } # ************************************************************************************************* # check mysql connection public function checkConnection() { try { $this->dbh->query('select 1')->fetchColumn(); echo 'old connection works..'.PHP_EOL.'========================'.PHP_EOL; } catch (PDOException $Exception) { # echo 'there is no connection.'.PHP_EOL; $this->dbh = $this->reconnect(); echo 'connection was lost, reconnect..'.PHP_EOL.'========================'.PHP_EOL; } return $this->dbh; } # ************************************************************************************************* # reconnect to mysql public function reconnect() { $dbh = new PDO('mysql:host=' . DB_HOST . ';dbname=' . DB_NAME, DB_USER, DB_PWD); $dbh->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC); $dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, TRUE); $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); return $dbh; } } # /Class for PDO reconnection # ************************************************************************************************* . <?php # set errors reporting level error_reporting(E_ALL ^ E_NOTICE ^ E_WARNING); # set pdo connection include('db.connection.pdo.php'); /* # this is "db.connection.pdo.php" content define('DB_HOST', 'localhost'); define('DB_NAME', ''); define('DB_USER', ''); define('DB_PWD', ''); define('DB_PREFIX', ''); define('DB_SHOW_ERRORS', 1); # connect to db try { $dbh = new PDO('mysql:host='.DB_HOST.';dbname='.DB_NAME, DB_USER, DB_PWD); $dbh->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC); $dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, TRUE); $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); } catch(PDOException $e) { # echo $e->getMessage()."<br />"; # exit; exit("Site is temporary unavailable."); # } */ $reconnection = new PDOReconnection($dbh); $reconnection->getTimeout(); echo $dbh->query('select 1')->fetchColumn(); echo PHP_EOL; echo 'sleep 10 seconds..'.PHP_EOL; sleep(10); $dbh = $reconnection->checkConnection(); echo $dbh->query('select 1')->fetchColumn(); echo PHP_EOL; echo 'sleep 35 seconds..'.PHP_EOL; sleep(35); $dbh = $reconnection->checkConnection(); echo $dbh->query('select 1')->fetchColumn(); echo PHP_EOL; echo 'sleep 55 seconds..'.PHP_EOL; sleep(55); $dbh = $reconnection->checkConnection(); echo $dbh->query('select 1')->fetchColumn(); echo PHP_EOL; echo 'sleep 300 seconds..'.PHP_EOL; sleep(300); $dbh = $reconnection->checkConnection(); echo $dbh->query('select 1')->fetchColumn(); echo PHP_EOL; # ************************************************************************************************* # Class for PDO reconnection class PDOReconnection { private $dbh; # constructor public function __construct($dbh) { $this->dbh = $dbh; } # ************************************************************************************************* # get mysql variable "wait_timeout" value public function getTimeout() { $timeout = $this->dbh->query('show variables like "wait_timeout"')->fetch(); # print_r($timeout); echo '========================'.PHP_EOL.'mysql variable "wait_timeout": '.$timeout['Value'].' seconds.'.PHP_EOL.'========================'.PHP_EOL; } # ************************************************************************************************* # check mysql connection public function checkConnection() { try { $this->dbh->query('select 1')->fetchColumn(); echo 'old connection works..'.PHP_EOL.'========================'.PHP_EOL; } catch (PDOException $Exception) { # echo 'there is no connection.'.PHP_EOL; $this->dbh = $this->reconnect(); echo 'connection was lost, reconnect..'.PHP_EOL.'========================'.PHP_EOL; } return $this->dbh; } # ************************************************************************************************* # reconnect to mysql public function reconnect() { $dbh = new PDO('mysql:host=' . DB_HOST . ';dbname=' . DB_NAME, DB_USER, DB_PWD); $dbh->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC); $dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, TRUE); $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); return $dbh; } } # /Class for PDO reconnection # ************************************************************************************************* 

У меня была точно такая же проблема. Я решил эту проблему, сделав unset в объекте PDO вместо того, чтобы установить его в NULL.

Например:

 function connectdb($dsn,$username,$password,$driver_options) { try { $dbh = new PDO($dsn,$username,$password,$driver_options); return $dbh; } catch(PDOException $e) { print "DB Error: ".$e->getMessage()."<br />"; die(); } } function closedb($dbh) { unset($dbh); // use this line instead of $dbh = NULL; } с function connectdb($dsn,$username,$password,$driver_options) { try { $dbh = new PDO($dsn,$username,$password,$driver_options); return $dbh; } catch(PDOException $e) { print "DB Error: ".$e->getMessage()."<br />"; die(); } } function closedb($dbh) { unset($dbh); // use this line instead of $dbh = NULL; } 

Кроме того, настоятельно рекомендуется отключить все ваши объекты PDO. Это включает переменные, содержащие подготовленные операторы.

 $pdo = new PDO( $dsn, $config['username'], $config['password'], array( PDO::ATTR_PERSISTENT => true, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION ) ); 

попробуй это. Он может работать