MySQL kļūda "Can't connect to local MySQL server through socket" (kļūda 2002) nozīmē, ka klients tajā pašā datorā mēģināja atvērt MySQL Unix socket failu un tas neizdevās. Praksē iemeslu ir tikai daži: serveris nedarbojas, tas darbojas, bet tā socket ir citur, vai klientam nav atļauts atvērt šo failu. Skaitlis iekavās ziņojuma beigās pasaka, ko pārbaudīt vispirms.
Tipisks ziņojums:
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)
Kāpēc "localhost" nozīmē socket
Unix sistēmās MySQL klients var pieslēgties divos veidos: caur Unix socket failu failu sistēmā vai caur TCP/IP. Saskaņā ar MySQL rokasgrāmatu socket fails tiek izmantots, ja jūs nenorādāt resursdatora nosaukumu vai norādāt īpašo nosaukumu localhost. Tātad mysql -h localhost portu 3306 nemaz neaiztiek, bet mysql -h 127.0.0.1 gan. Šī viena detaļa izskaidro daudz mulsinošu situāciju: "ports ir atvērts, bet localhost nestrādā" ir socket problēma, nevis tīkla problēma.
Kļūda 2002 ir socket gadījums. Ja klients ietu caur TCP, jūs redzētu kļūdu 2003, "Can't connect to MySQL server on 'host:port'". Abi ziņojumi nāk no klienta bibliotēkas libmysql/errmsg.cc, un pēdējais skaitlis iekavās ir operētājsistēmas kļūdas kods.
Nolasiet skaitli iekavās
Tās ir parastas Linux errno vērtības, un tās uzreiz sašaurina meklēšanu:
(2) ENOENT šajā ceļā nav faila: serveris nedarbojas vai ceļš ir nepareizs
(13) EACCES fails vai tā direktorija šim OS lietotājam nav pieejama
(111) ECONNREFUSED socket fails eksistē, bet neviens serveris to neklausās
- (2) ir visbiežākais. Vai nu mysqld nedarbojas, vai tas izveidoja savu socket citā ceļā, nekā meklē klients.
- (13) ir par tiesībām: socket fails vai kāda no tā vecākdirektorijām nav pieejama lietotājam, kas palaiž klientu. Sistēmās ar SELinux rokasgrāmata norāda arī uz savu SELinux sadaļu.
- (111) parasti nozīmē palikušu socket failu: ceļš eksistē, bet process, kam tas piederēja, vairs nedarbojas, parasti pēc avārijas.
Četras pārbaudes, kas atrod cēloni
# 1. Vai serveris vispār darbojas?
systemctl status mysql # vai mysqld, atkarībā no pakotnes
ps aux | grep [m]ysqld
# 2. Kuru socket serveris patiesībā klausās?
ss -xlp | grep mysql
# 3. Kuru socket mēģina izmantot klients?
my_print_defaults client mysql
mysql --print-defaults
# 4. Ko serveris saka par sevi (caur TCP)?
mysql -h 127.0.0.1 -P 3306 -u root -p -e "SELECT @@socket, @@port, @@skip_networking"
- Nav mysqld procesa nozīmē, ka tā vispār nav socket problēma. Serveris nedarbojas, un īstais jautājums ir, kāpēc. Pirms jebko restartējat, paskatieties kļūdu žurnālā (komandas zem saraksta).
- Serveris klausās citu socket.
ss -xlpparāda īsto ceļu. Salīdziniet to ar ceļu kļūdas ziņojumā. - Klients lasa citu konfigurāciju.
my_print_defaults client mysqlizdrukā opcijas, komysqlklients saņem no opciju failu grupām[client]un[mysql](skatiet my_print_defaults dokumentāciju). Nepareizasocket=rinda tur vai tās trūkums ir ierastais vaininieks. - Pajautājiet serverim. Ja TCP ir ieslēgts,
@@socketparāda, kur serveris novietoja failu. Ja@@skip_networkingir 1, TCP ir izslēgts un socket ir vienīgā ieeja.
journalctl -u mysql -n 100 --no-pager
tail -n 100 /var/log/mysql/error.log # Debian/Ubuntu pakotnes
tail -n 100 /var/log/mysqld.log # bieži RPM sistēmās
Ja serveris nedarbojas, tipiski iemesli žurnālā ir pilns disks, InnoDB atkopšanas kļūda, nepareiza opcija tikko rediģētā konfigurācijas failā vai serveris, ko apturējis OOM killer. Restartēšana, neizlasot žurnālu, bieži vienkārši atkārto avāriju.
Kur atrodas socket
Iekompilētais noklusējums sistēmas mainīgajam socket ir /tmp/mysql.sock, un rokasgrāmata piebilst, ka dažos distribūcijas formātos direktorija ir cita, piemēram, /var/lib/mysql RPM pakotnēm. Debian/Ubuntu pakotnes, kas būvētas no paša MySQL pirmkoda, failā mysqld.cnf iestata /var/run/mysqld/mysqld.sock. Tāpēc kļūda tik bieži parādās pēc kādām izmaiņām:
- tarball, pašbūvēta versija vai otra instance izmanto
/tmp/mysql.sock, bet klienta konfigurācija norāda uz distribūcijas ceļu, vai otrādi; - kāds nomainīja
socket=sadaļā[mysqld], bet ne[client]; - tīrīšanas darbs izdzēsa
/tmp/mysql.sock. Rokasgrāmata min tieši šo gadījumu un iesaka vai nu salabot darbu, vai pārvietot socket ārpus/tmp.
Pastāvīgs risinājums ir ierakstīt to pašu ceļu abās grupās:
# /etc/mysql/my.cnf vai /etc/my.cnf: serverim un klientiem jāsakrīt
[mysqld]
socket = /var/run/mysqld/mysqld.sock
[client]
socket = /var/run/mysqld/mysqld.sock
Rokasgrāmatas lapa par socket failu min arī citus veidus, kā klientiem pateikt ceļu: opciju --socket un vides mainīgo MYSQL_UNIX_PORT. Vienreizējam savienojumam vai kamēr vēl izmeklējat, der jebkurš no tiem:
mysql --socket=/var/lib/mysql/mysql.sock -u root -p # norādiet socket skaidri
mysql -h 127.0.0.1 --protocol=TCP -u app -p # apejiet socket, izmantojiet TCP
MYSQL_UNIX_PORT=/var/lib/mysql/mysql.sock mysqldump ... # vides mainīgais
Pāreja uz TCP ne vienmēr ir neitrāla. Serveris var piemeklēt citu kontu, un spraudnis auth_socket, kas autentificē klientus, kuri pieslēdzas caur Unix socket failu, caur TCP jūs vispār neielaidīs. Ja root izmanto auth_socket, paturiet socket un salabojiet ceļu. Ja savienojums izdodas, bet pieteikšanās ne, tā ir cita kļūda; skatiet mūsu ceļvedi par MySQL kļūdu 1045.
Pazudusi direktorija pēc pārstartēšanas
Mūsdienu distribūcijās ar systemd /var/run ir saite uz /run, kas atrodas atmiņā un pēc katras ielādes ir tukša. Oficiālais Debian/Ubuntu serviss to atrisina: tā pirmsstarta skripts failā mysql-helpers izveido /var/run/mysqld ar īpašnieku mysql un režīmu 0755, ja tās nav. Ja mysqld startējat citādi, ar roku, no pielāgota unit faila vai konteinerā, šo direktoriju neviens neizveido, un serveris tur nevar izveidot savu socket. Pārbaudiet to un izveidojiet tāpat:
ls -ld /var/run/mysqld /var/run/mysqld/mysqld.sock
# oficiālais Debian/Ubuntu serviss izveido direktoriju pirms starta:
install -d -m0755 -o mysql -g mysql /var/run/mysqld
PHP, konteineri un citi klienti
PHP lietotnes to pašu problēmu ziņo kā SQLSTATE[HY000] [2002]. PDO_MYSQL dokumentācija paskaidro, kāpēc: Unix sistēmās resursdatora nosaukums localhost liek savienojumam iet caur domēna socket, un ar mysqlnd noklusējuma ceļš nāk no pdo_mysql.default_socket, kura dokumentētā vērtība ir /tmp/mysql.sock, lai gan PHP būvējumā kompilēšanas laikā var būt iestatīts cits noklusējums. Salabojiet to php.ini vai norādiet socket DSN virknē:
; php.ini
pdo_mysql.default_socket = /var/run/mysqld/mysqld.sock
mysqli.default_socket = /var/run/mysqld/mysqld.sock
// vai DSN virknē
$pdo = new PDO('mysql:unix_socket=/var/run/mysqld/mysqld.sock;dbname=app', $user, $pass);
Konteineros tas pats noteikums izraisa citu kļūmi. Lietotnes konteiners, kas pieslēdzas localhost, meklē socket failu savā failu sistēmā, kur tā nav. Izmantojiet datubāzes servisa resursdatora nosaukumu vai IP, kas iet caur TCP, vai apzināti piemontējiet socket direktoriju konteinerā.
Ja savienojumi sākumā strādā un tad pārtrūkst vaicājumu vidū, tā arī nav 2002; šo gadījumu apskata "MySQL server has gone away".
Galvenās atziņas
- Kļūda 2002 ir lokāla socket savienojuma kļūme. Unix sistēmās
localhostnozīmē socket;127.0.0.1nozīmē TCP. - Nolasiet errno iekavās: (2) serveris nedarbojas vai nepareizs ceļš, (13) tiesības, (111) palicis socket bez servera aiz tā.
- Ja mysqld nedarbojas, pirms restartēšanas izlasiet kļūdu žurnālu. Socket ir tikai simptoms.
- Ierakstiet to pašu
socket=sadaļās[mysqld]un[client], un norādiet uz to PHPdefault_socket. - Pāreja uz TCP ir ātrs apvedceļš, bet
auth_socketkonti strādā tikai caur socket.