Назад | Перейти на главную страницу

Периодические ошибки подключения к MySQL

Я недавно получал эти ошибки на моем сервере:

mysql_connect() [function.mysql-connect ]: 
   Can't connect to MySQL server on 'xxx.xxx.xxx.xxx' (4)

Я не думаю, что это проблема с учетными данными, поскольку имя пользователя, пароль, IP-адрес хоста и имя базы данных считываются из конфигурации плоского файла и сохраняются в константе PHP. Кроме того, мой журнал ошибок сообщает мне, что используемые учетные данные на самом деле те, что указаны в конфигурации.

Я попытался найти это в Google, и один из них указывает мне на max_connections вопрос. Этот сайт все еще находится в стадии бета-тестирования, и количество одновременных пользователей не превышает 10. Я посмотрел значение max_connections и это на 2048

Версия MySQL - 5.0.91, а сервер - Gentoo Linux (это то, что version_comment говорит). Файл сокета находится в /var/run/mysqld/mysqld.sock и порт 3306

Что меня действительно беспокоит, так это то, что эта ошибка кажется прерывистой. Я действительно не могу это уловить, когда пытаюсь воспроизвести. Кто-то сказал с одного сайта, что индекс ошибок (4) означает прерванные системные вызовы.

Означает ли это, что я могу отклонить ошибку как ошибку моего веб-хоста, а не скрипта PHP?

Попробуйте проверить, не превышаете ли вы максимальное количество открытых файлов при вводе dmesg и наблюдая за ошибкой "Слишком много открытых файлов".

Если вы его превышаете, вам придется увеличить лимиты, установленные системой, изменив /etc/security/limits.conf с этим заявлением:


mysql           soft    nofile          2048
mysql           hard    nofile          4096

Где 2048 и 4096 - максимальное количество файлов, которое может открыть пользователь mysql. (Сюда входят все файловые дескрипторы, такие как сокеты)

Если ваша строка подключения является именем узла сервера и требует DNS, убедитесь, что это не промежуточное медленное разрешение DNS, вызывающее тайм-аут при попытке подключения. Используйте localhost, если это уместно. При необходимости запустите локальный DNS. Короткое замыкание в файле LMHOSTS, если необходимо. Полностью устраните необходимость в DNS и при необходимости укажите IP-адрес. Все, что нужно, чтобы не зависеть от внешнего, иногда медленного DNS-поиска имени сервера в строке подключения.

Иногда со строкой подключения все в порядке; иногда разрешение DNS периодически оказывается слишком медленным. Это может быть одной из причин периодических проблем с подключением.

Пример: предположим, что у вас есть облачный экземпляр, на котором размещены и mysql, и apache, но иногда вы запускаете сайт на локальной машине DevO. Таким образом, в строке подключения вы используете полное имя узла сервера, поэтому сайт «работает» либо с сайта развертывания, либо с вашей машины Devo. Может случиться так, что он никогда не выходит из строя на вашей машине Dev (потому что DNS вашей машины Dev всегда блестит), но вы получаете прерывистые проблемы с подключением на развернутом сайте (потому что, даже если экземпляр mysql расположен вместе, ваша строка подключения по-прежнему нуждается в чтобы DNS был разрешен обратно к самому себе, но DNS на вашем облачном экземпляре иногда не так блестит. Это немного раздражает, потому что в развернутом экземпляре экземпляр mysql на самом деле является локальным. Но на самом деле даже не суть - суть действительно , разница между временем отклика DNS вашего компьютера DevOps во всех условиях нагрузки и таким же в облачном экземпляре. Так что упростите задачу в облачном экземпляре. Ошибка не будет выглядеть так: «DNS был слишком медленным», даже если это является первопричиной.

Вы можете копать дальше, используя mysql_error () и mysql_errno ()-функции, но насколько я могу судить, ваши предположения верны.

В качестве короткого исправления ошибки (которую я обычно использую в своих веб-приложениях) является повторное подключение с логированием через две секунды:

$i = 0;
if ($i < 3 && ($db = mysql_connect(...)) == false) {
    trigger_error('Could not connect to ...', E_USER_WARNING);
    $i++;
    sleep(2);
}
if (!$db)
    die('Could not connect to ... for 3 times with a 2 second dely - giving up');

Поскольку посещаемость сайта низкая, вы можете подумать о запуске tcpdump на сервере в файл и настройте свой php-скрипт на отправку вам предупреждения в случае сбоя соединения. Скопируйте файл tcpdump в свой локальный ящик и проанализируйте сбой подключения через WireShark.

Вы также должны проверять журналы mysql-daemon и системные журналы в вашей системе во время сбоя на наличие аномалий.

Имейте в виду, что при регистрации вашего трафика будет регистрироваться все содержимое трафика, включая пароли и другую конфиденциальную информацию, что может нарушать политику или законы компании. Вы должны стереть tcpdump-файл после деактивации ведения журнала, чтобы не позволять конфиденциальной информации оставаться на сервере и передавать файлы через ssh или любое другое подходящее зашифрованное соединение.