Ошибка PHP Warning: Error while sending QUERY packet, с таким я столкнулся, когда написал демона на PHP, который в самом начале подключается к базе, а потом ждет задачки из RabbitMQ и выполняет их на базе MariaDB.
Если у вас умирающий скрипт, который некоторое время подумает, а потом снова к базе обращается и может произойти отключение в этот момент, то нужно в my.cnf прибавить таймаут, например, сделать его пару минут
wait_timeout = 120
Но у меня таймаут может быть хоть триста дней, для этого я решил наоборот его убавить, чтобы отловить этот момент и да, если выполняю запросы к базе, то все отлично, отсчитываю 10 сек, снова выполняю и скрипт вылетает, т.к. соединение с базой уже отвалилось. Нужно тут уже сам скрипт подпиливать.
У меня свой класс для работы базы на mysqli, конечно, первым делом подумал о том, что можно проверку соединения делать в момент запроса, но не добавит ли нам это лишних затрат по времени, когда например надо 5 миллионов записей в базу залить, там даже индексы и те добавляют некоторую задержку и я сперва забивал базу данными, потом индексировал поля.
Лучшим решением будет проверка соединения в момент запуска функции, а функция моя чаще выполняет 2-3 запроса и делает это за доли секунды.
Итак, скрипт висит на фоне, висит так пару суток, тут к нему прилетает запрос от Rabbit, он запускает функцию обработки, которая некоторые данные цепляет из базы и тут перед выполнением наших запросиков надо бы проверить соединение и переподключиться...
class DB {
public $l,
$db_name,
$last_res,
$cnt = 0,
$debug=0,
$last_rows;
private $c = []; //connect config
public function connect(&$c)
{
if (isset($c['socket']) && !empty($c['socket']))
@$this->l = new mysqli(NULL, $c['user'], $c['pass'], $c['db_name'], NULL, $c['socket']);
else
@$this->l = new mysqli($c['host'], $c['user'], $c['pass'], $c['db_name']);
if ($this->l->connect_errno)
{
http_response_code(503);
exit("ERROR CONNECT DB");
}
}
function __construct(&$c) {
$this->connect($c);
$this->c = &$c;
}
public function check_conn ()
{
if ($this->l->ping()===false)
{
//проверим еще раз не переподключился ли он автоматом
if ($this->l->ping()===false)
$this->connect($this->c);
}
}
//тут еще дофига методов, но я их не покажу
}
$l
- это у нас переменная $mysqli
Я дважды проверил через $mysql->ping
, т.к. в некоторых ситуациях в момент выполнения этой функции происходит автоматический реконнект, по умолчанию оно отключено, и даже если включено, то mysqlnd игнорит...