чатгпт "просит" кое-что пофиксить...
Posted: Thu Feb 12, 2026 5:00 pm
Игрался с гпт на предмет периодически возникающих ошибок такого рода: 2026-02-12 11:20:34 :: 2006 :: MySQL server has gone away :: SELECT name, value FROM rot_settings WHERE name IN ('ftp_host', 'ftp_user', 'ftp_password', 'ftp_path', 'ftp_url' )
Вот, что он мне в итоге выдал:
сперва попросил показать mysql.php
Если скинешь mysql.php — я тебе под него сделаю точечный патч, без «колхоза» и риска сломать проект.
я показал, вот ниже вердикт... но сходу внедрять это как-то боязно, хотел бы сперва обсудить с разработчиком, так сказать... так как, вам оно всё же виднее)) Ну, а если совет действительно толковый (выгядит всё логично на мой дилетантский взгляд), то может просто это в ап добавить?
Главная проблема в твоём mysql.php
У тебя вообще нет автопереподключения при потере соединения.
Да, есть:
function db_ping($link = 'db_link') {
global $$link;
if (!mysqli_ping($$link)) {
return false;
}
return true;
}
Но он НИГДЕ НЕ ИСПОЛЬЗУЕТСЯ в db_query.
То есть:
соединение умерло
$db_link остался
mysqli_query() → 2006
дальше db_error → лог
Вторая серьёзная проблема: persistent connections
В db_connect:
$db_server = (isset($connect_config["db_persistent"]) and $connect_config["db_persistent"])
? ('p:' . $connect_config["db_server"])
: $connect_config["db_server"];
Если в конфиге:
db_persistent = true
→ ты используешь persistent connections (p:).
С cron + долгие процессы = ЗЛО.
MySQL может закрыть persistent socket → PHP получает труп.
Это классический источник 2006.
Третья проблема: db_query не ловит 2006
В while ($tries < 3) ты ретраишь только:
1205 (lock wait timeout)
1213 (deadlock)
А 2006 — нет.
То есть reconnect не делается.
Правильное решение (минимальный безопасный патч)
Мы:
Проверяем ping перед запросом
При 2006 → reconnect + repeat
Не ломаем архитектуру
🛠 Вставь в mysql.php (1 раз — и забудешь)
ШАГ 1. Найди функцию db_query
И в начале, после:
if (!$$link) {
ВСТАВЬ:
ВСТАВИТЬ СЮДА:
// --- AUTO RECONNECT ---
if (!mysqli_ping($$link)) {
mysqli_close($$link);
$$link = db_connect($link);
}
В итоге будет так:
if (!$$link) {
...
}
// AUTO RECONNECT
if (!mysqli_ping($$link)) {
mysqli_close($$link);
$$link = db_connect($link);
}
ШАГ 2. Добавь обработку 2006 в retry
Найди:
if (!$result and (mysqli_errno($$link) == 1205 or mysqli_errno($$link) == 1213) ) {
ЗАМЕНИ на:
if (
!$result and (
mysqli_errno($$link) == 1205 ||
mysqli_errno($$link) == 1213 ||
mysqli_errno($$link) == 2006
)
) {
И внутрь добавь reconnect:
if (mysqli_errno($$link) == 2006) {
mysqli_close($$link);
$$link = db_connect($link);
}
В итоге:
if (
!$result and (
mysqli_errno($$link) == 1205 ||
mysqli_errno($$link) == 1213 ||
mysqli_errno($$link) == 2006
)
) {
if (mysqli_errno($$link) == 2006) {
mysqli_close($$link);
$$link = db_connect($link);
}
$tries++;
sleep(1);
continue;
}
ОБЯЗАТЕЛЬНО проверь config.php
Найди:
db_persistent
Если есть:
true
СДЕЛАЙ:
false
или удали вообще.
Для cron — persistent противопоказан.
Почему это решит проблему навсегда
После патча:
умер сокет → reconnect
MySQL рестарт → reconnect
network glitch → reconnect
cron висел 40 минут → reconnect
→ никаких 2006.
Дополнительный апгрейд (по желанию)
В db_connect можно добавить:
mysqli_options($$link, MYSQLI_OPT_CONNECT_TIMEOUT, 5);
Перед connect — защита от зависаний.
Итог
Твоя ошибка — архитектурная, не серверная.
Причина:
Нет reconnect
Возможно persistent
Нет retry на 2006
Решение:
ping
reconnect
retry
Вот, что он мне в итоге выдал:
сперва попросил показать mysql.php
Если скинешь mysql.php — я тебе под него сделаю точечный патч, без «колхоза» и риска сломать проект.
я показал, вот ниже вердикт... но сходу внедрять это как-то боязно, хотел бы сперва обсудить с разработчиком, так сказать... так как, вам оно всё же виднее)) Ну, а если совет действительно толковый (выгядит всё логично на мой дилетантский взгляд), то может просто это в ап добавить?
У тебя вообще нет автопереподключения при потере соединения.
Да, есть:
function db_ping($link = 'db_link') {
global $$link;
if (!mysqli_ping($$link)) {
return false;
}
return true;
}
То есть:
соединение умерло
$db_link остался
mysqli_query() → 2006
дальше db_error → лог
В db_connect:
$db_server = (isset($connect_config["db_persistent"]) and $connect_config["db_persistent"])
? ('p:' . $connect_config["db_server"])
: $connect_config["db_server"];
Если в конфиге:
db_persistent = true
→ ты используешь persistent connections (p:).
MySQL может закрыть persistent socket → PHP получает труп.
Это классический источник 2006.
В while ($tries < 3) ты ретраишь только:
1205 (lock wait timeout)
1213 (deadlock)
А 2006 — нет.
То есть reconnect не делается.
Мы:
🛠 Вставь в mysql.php (1 раз — и забудешь)
И в начале, после:
if (!$$link) {
ВСТАВЬ:
// --- AUTO RECONNECT ---
if (!mysqli_ping($$link)) {
mysqli_close($$link);
$$link = db_connect($link);
}
В итоге будет так:
if (!$$link) {
...
}
// AUTO RECONNECT
if (!mysqli_ping($$link)) {
mysqli_close($$link);
$$link = db_connect($link);
}
Найди:
if (!$result and (mysqli_errno($$link) == 1205 or mysqli_errno($$link) == 1213) ) {
ЗАМЕНИ на:
if (
!$result and (
mysqli_errno($$link) == 1205 ||
mysqli_errno($$link) == 1213 ||
mysqli_errno($$link) == 2006
)
) {
И внутрь добавь reconnect:
if (mysqli_errno($$link) == 2006) {
mysqli_close($$link);
$$link = db_connect($link);
}
В итоге:
if (
!$result and (
mysqli_errno($$link) == 1205 ||
mysqli_errno($$link) == 1213 ||
mysqli_errno($$link) == 2006
)
) {
if (mysqli_errno($$link) == 2006) {
mysqli_close($$link);
$$link = db_connect($link);
}
$tries++;
sleep(1);
continue;
}
Найди:
db_persistent
Если есть:
true
false
или удали вообще.
Для cron — persistent противопоказан.
После патча:
→ никаких 2006.
В db_connect можно добавить:
mysqli_options($$link, MYSQLI_OPT_CONNECT_TIMEOUT, 5);
Перед connect — защита от зависаний.
Твоя ошибка — архитектурная, не серверная.
Причина:
Решение: