В данном посте я заведу речь о, как в последствии оказалось, весьма наболевшей проблеме связанной с MySQL сервером установленным на машину под управлением операционной системы на базе ядра Linux. Для её решения мне пришлось убить не мало времени, но я всё же таки разобрался в чём же было дело и с радостью поделюсь секретом с Вами.
Итак проблема следующего характера: есть выделенный web сервер с (в моём случае) операционной системой Linux Ubuntu и всё прилегающее естественно, т.е. Apache, PHP и этот злосчастный MySQL. И в один прекрасный момент, СУБД MySQL выдаёт примерно следующее сообщение об ошибке при запуске: Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)
. В самом конце, в скобочках, код ошибки, который меняется по ходу решения проблемы. Во всяком случае «вначале пути», как правило, это двойка, позже были и 13-ый код и 111-ый и т.д. То, что это локальный сервер можете не смущаться, так было именно в моём случае т.к. СУБД MySQL была установлена на локальный ПК, там же где и web сервер Apache, естественно, что в сообщении может фигурировать и не локальный хост, это не столь важно. Так вот, что мы имеем? Сообщение об ошибке, которое говорит: «Не могу соединиться с локальным MySQL сервером через сокет '/var/run/mysqld/mysqld.sock' (2)
«.
При этом файлы логов СУБД либо пусты, либо ничего дельного не сообщают по сути проблемы. Напомню на всякий случай, что лежат они в следующих местах:
/var/log/mysql.log
/var/log/mysql.err
/var/log/mysql/error.log
но это нам не понадобится.
Значит сейчас можно попробовать посмотреть объяснение системной ошибки через утилиту perror
набрав в консоли следующее: perror 2
Кстати так же можно почитать информацию и про другие ошибки, которые могут встретиться на пути. В общем давайте идти дальше. Что же делать? Очевидно, что проблема с сокетом, который располагается по следующему адресу: /var/run/mysqld/mysqld.sock
Т.е. MySQL демон не может подключиться к Unix-сокету. А такое может произойти по 3-ём причинам:
- Его просто физически нет (не создан);
- Кто-то его уже занял;
- MySQL пользователь не может получить доступ к сокету по правам доступа.
Для проверки 2-ого варианта можно попробовать узнать, а не занимает ли кто-то этот файл?
sudo lsof /var/run/mysqld/mysqld.sock
В результате можем получить нечто подобное:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME mysqld 1299 mysql 6u unix 0xf688b840 0t0 7877 /var/run/mysqld/mysqld.sock
сразу видно, кто занял сокет. Или же получаем следующее:
... lsof: status error on /run/mysqld/mysqld.sock: No such file or directory ...
— т.е. файл просто отсутствует.
В первом случае всё понятно — отключаем приложение, занявшее нужный сокет, либо лезем в конфиг MySQL и ставим другой сокет.
Во втором случае надо создать сокет и/или сделать его доступным для mysql, для этого выполняем следующие действия (описываю построчно):
- Создаём директорию, в которой должен лежать файл сокета:
sudo mkdir /var/run/mysqld
Она может быть уже создана, тогда получите такое сообщение: «mkdir: cannot create directory `/var/run/mysqld’: File exists;».
- Создаём сам сокет командой mkfifo.
sudo mkfifo /var/run/mysqld/mysqld.sock
Хотя сокет является тоже файлом, создавать его можно только специальной программой «mkfifo».
- Рекурсивно устанавливаем владельцем папки mysql (и всего её содержимого) пользователя mysql:
sudo chown -R mysql /var/run/mysqld
После чего пытаемся запустить/рестартануть MySQL сервер.
В моём случае на этом всё не закончилось. Я для гарантии и большей проверки решил ещё и ребутнуть весь физический сервер. После чего увидел, что при попытке старта СУБД MySQL файл сокета почему то не создаётся. Сделал вывод, что у пользователя от которого работает сервер MySQL нет прав, другого быть не может. Пошёл в эту директорию и ещё раз сам вручную создал нужный сокет, заново дал необходимые права на папку. После этого последовала 13-ая ошибка, которая говорит, что у MySQL недостаточно прав на сокет, что бы его использовать в своих целях. Решил явно дать общие свободные права для всех так:
chmod 0777 /var/run/mysqld/mysqld.sock
Теперь ошибка сменилась на 111-ую, что говорит о запрете доступа. В общем тут меня вообще накрыло, уже не знал, что и делать. Казалось бы всё перепробовал. Поиски по интернету перешли уже далеко за русскоязычный раздел, но толку было мало. Всё, тупик.
И как вы думаете в чём же оказалось дело? В простой и банальной нехватки места на жёстком диске! Да! Кто бы мог подумать. При помощи команд ls
, df
и du
просматриваем свободное/занятое место на hard drive’e вашего сервера баз данных и делаем соответствующие выводы. Скорее всего причина может крыться именно здесь. Лично у меня файлы логов были очень большие. В общем почистил место и всё завелось как прежде. Проблема решена.
Итак давайте подведём итог. Куда смотреть в первую очередь и на, что обращать внимание.
Смотрим на коды ошибок, расшифровываем при помощи утилиты perror
.
Следим за сокетом расположенным по адресу: /var/run/mysqld/mysqld.sock
.
Если надо то создаём его вручную командой mkfifo /var/run/mysqld/mysqld.sock
(от рута естественно)
Поглядываем за правами mysql пользователя, он должен иметь полные права на этот файл. Если требуется, то так же меняем вручную командами chmod
и chown
.
Можно так же заглянуть в журналы логов MySQL, они тут:
/var/log/mysql.log
/var/log/mysql.err
/var/log/mysql/error.log
Все файлы сокетов можно найти командой find / -type s
Ну и в крайнем случае может понадобится заглянуть в конфигурационный файл СУБД MySQL, он тут: /etc/mysql/my.cnf
. Там есть директивы, которые устанавливают файл сокета. Выглядит примерно так:
[mysqld] datadir=/usr/local/mysql/data socket=/var/lib/mysql/mysql.sock [mysql.server] user=mysql basedir=/usr/local/mysql ... [client] socket=/var/lib/mysql/mysql.sock
Если потребуется, то сокет для MySQL так же можно установить так: mysql --socket=/var/lib/mysql/mysql.sock
, что бы лишний раз не лазить в my.cnf
.
Для старта/рестарта сервера баз данных используем следующий синтаксис:
sudo /etc/init.d/mysqld start sudo /etc/init.d/mysqld stop sudo /etc/init.d/mysqld restart
а не такой:
service mysql start service mysql stop service mysql restart
Т.е. используем скрипт инициализации, а не команду service. Это не одно и тоже! Надёжнее так как я рекомендую.
Можно попробовать создать символьную ссылку таким образом: ln -s /tmp/mysql.sock /var/lib/mysql/mysql.sock
для исключения проблем с правами доступа. Т.е. файл сокета будет храниться во временной папке, но ссылка на него будет из папки mysql.
У пользователя mysql так же должны быть права на папку /tmp
(настройки по умолчанию), если не определена другая временная папка.
Надеюсь у вас получилось. Спасибо за внимание.